Mouseover in NSTableView - objective-c

I'm having trouble creating a mouseover function with an NSTableView. The idea is that (if the feature is selected in prefs) placing the mouse pointer above a particular row in an NSTabelView will display a small popup window with additional information regarding the entry in that particular row. The effect should not be immediate (as e.g. highliting a button when rolling over it), but come with a delay of a few seconds.
So far, I have implemented this functionality using the tooltip delegate method, but this does not allow for customization of the window and does not work well (layout wise) if more than 1-3 rows of info need to be displayed.
In Hillegass' book it is suggested that one uses the mouseEntered/mouseExited methods for rollovers, but as far as I can tell this works with pre-defined areas of a window and not rows in a table view.
Does anyone have any suggestions?
Gregor Tomasevic,
Sweden

You're on the right track with -mouseEntered: and -mouseExited:.
Look into NSView's -addTrackingRect:owner:userData:assumeInside: and -removeTrackingRect: methods. You can either set up your tableView to create trackingRects for every row that's in there whenever the contents of the tableView change, or alternatively, set up/update one tracking area on the entire tableView whenever -tile or another layout related method is called.

Related

NSTableView: Displaying An Expanded Row (Resizing on the Fly)

OK. I looked through the suggestions (which often answer my questions before I ask). I haven't found what I need.
I know that I'm doing something wrong. I do this all the time in iOS (UIKit), but tables in NS (Mac) are pretty darn different from UIKit.
I have a view-based NSTableView. Each row has exactly 1 column. This column has a view with a header (21 points high), and an expanded view (the row is 420 points high). There is a disclosure triangle on the left of the header that toggles these two modes.
The controller is also the table datasource and delegate. I have the row height callback returning the correct values for the view.
The header displays fine. I set the row heights to 21, and only the headers are shown. This clips the main view.
When a disclosure triangle is toggled, a row expands its height to reveal the entire view:
Simple enough, eh?
The problem is that B is not displayed. I just get a blank (However, A is correctly displayed). The items are there, just not being displayed. The table row is the correct height (this can be verified by using alternating row colors).
I've tried setting setNeedsLayout/Draw on the views.
Any clues on what I may be doing wrong?
I'm willing to bet that I'm doing something boneheaded, and I'll keep looking into this.
Using noteHeighOfRowsWithIndexesChanged:? It's an NSTableView function, not a delegate function.
In the documentation for the delegate function tableView:heightOfRow it declares:
Although table views may cache the returned values, you should ensure that this method is efficient. When you change a row's height you must invalidate the existing row height by calling noteHeightOfRowsWithIndexesChanged:. NSTableView automatically invalidates its entire row height cache when reloadData and noteNumberOfRowsChanged are called.
As it mentions, NSTableView's reloadData is often the lazy way to fix your sort of issue as well.
Your table controller shouldn't need the setsNeeds[whatever] methods you tried.
Also, speaking of disclosure triangles and such, on OSX there is a NSTableView subclass called NSOutlineView that handles item expansion if you mangle your data into a poorly documented tree format. I actually wouldn't recommend it if your data's not a natural tree, but you should be aware of it, even if its API sucks. Oh, and the expansion when clicking the disclosure triangle is animated.

VoiceOver reading twice each element - Inconsistent Behavior

I am working on Accessibility. I am using XIB file and I enabled all the views which need to be read by voiceover.Now the issue is first cell in tableview is reading twice by the voiceover. That happens only first time. I have multiple cells in tableview. But Voiceover reading first cell that too first time. If I swipe to next cells and come to the first cell again it reads only once.
Its very Inconsistent behavior. I could not able to find out the problem. I tried by passing nil values to both accessibilityLabel and accessibilityValue of the cells. But no impact on the Issue.When I disable the accessibility from the XIB file and enable it by programmatically also, but no Use.
Any Suggestions on this would be helpful.
You positing the UIAccessbilitypostnotification for the table with (Screenchange notification), will leads to read twice.
Dont post screenchange notification for Table view. UIKit will handle that by default.

How can I make command-A select all the NSTextView text in rows in an NSTableView?

So if I have an NSView based tableview and inside the views are NSTextViews which are non-editable but selectable...
how can I get that nice functionality of command-A selects all the text? I don't mean row selection. I have row selection disabled for the tableview. I mean highlighting the text in blue so you can copy it to your clipboard. But not just 1 NSTextView's text from one row, all of them from all the rows.
And in addition to command-A click and drag should do this too. But out of the box it seems I can only select one row's text. Here is video showing problem:
https://dl.dropboxusercontent.com/u/2510380/table.mov
(i keep clicking and dragging but can't highlight text on the next row)
here are two mac apps (skype and gabble) that do this:
https://dl.dropboxusercontent.com/u/2510380/skype.mov
and
https://dl.dropboxusercontent.com/u/2510380/gabble.mov
Assuming they are NOT using WebViews with just HTML inside, how do you get this control over the clipboard? i.e. in Skype you select the text and only the conversation is highlighted, not the timestamp of each message. Also the text copied to the clipboard is formatted very nicely. Can you point me in the right direction to reverse engineer skype?
Unfortunately there's no way to do this easily. This is because only ONE control can be the first responder at a time. This means that, though you can have selection in multiple text views, there are several problems:
Only one text view's text will actually be highlighted with the "live" highlight color; the others will have the gray highlight of non-focused controls.
Copy commands will only apply to the first responder text view.
Drag session starts will be initiated from the control the mouse was actually pointing at (irrespective of first responder) and will only drag that control's text.
In a view-based table view, the controls may not even "exist" for a row not currently displayed, so it'll never get the message unless you forcibly create each row, which could be costly for a large table.
Knowing all this, you might be able to "fake it" by having your controller be complicit in a text view and table view subclass's special handling of a select-all message when it's first responder. On receiving this message, the text view subclass can call super then notify the controller (to get its default behavior AND to let you know it happened), at which point the controller can turn around and send the command to all (existing) text views. Highlighting can be spoofed by overriding the text view's drawing and a drag initiation could defer to a delegate (the controller), which would handle writing ALL the strings from your model to the pasteboard (not even touching the text views in possibly-nonexistent row views). The table view subclass would simply pass the same select-all message to the controller without calling super (and even forcibly making sure nothing is selected before returning for good measure).
I hope this helps. If I've forgotten any of your requirements, let me know.
Try like this:-
First create button programatically then write this code after you create button and also write this code in your load method or awakefromnib method.
NSButton *Buttn=// alloc initwithframe;
[Buttn setKeyEquivalentModifierMask:
NSCommandKeyMask];
[Buttn setKeyEquivalent:#"A"];
[Buttn
setAction:#selector(yourmeth:)];
[Buttn setTarget:self];
// now when you press cmd a write
below code in action method
- (void)selectRowIndexes:(NSIndexSet
*)indexes byExtendingSelection:
(BOOL)extend

different tooltip for each image in NSTableView

I have a NSTableViewwith a NSImageCellin it. I would like to add a tooltip that when I hover the image with the mouse i get a tooltip with the Path of the image. What is the best way to do this?
the problems I have are these:
retrive the path of the hovered image
display it in the tooltip
please keep your answers easy, I am a newbie.
---EDIT---
additional info:
myarray.arrangedobjects is what fills the table. it is an array of NSMutableDictionaries. the dictionary has following Keys:
image (the one displayed in the table that i would like to place the tooltip over)
imagepath (the text i would like to display in the tooltip)
filename (is displayed in another cell)
You will need to provide a delegate for the NSTableView and implement this delegate method:
– tableView:toolTipForCell:rect:tableColumn:row:mouseLocation:
You can find the docs for the NSTableViewDelegate protocol here. You need to make sure to plug the delegate into the delegate outlet on the NSTableView using IB. Your method will not be called unless that has been done. Also, it's worth noting that this delegate method is called on demand, not up-front, so it wont get called until you've parked your mouse hovering over a cell. This approach should work for both tables with a data source and tables that use bindings.
I put a trivial example up on GitHub.

NSOutlineView elements remain hopelessly undraggable

I have a program with a NSOutlineView (that supports single selection only) from which I'd like to be able to drag elements. These elements should either be received as text or files: for instance, dropping the item on a TextEdit window should put text, but dropping the item on the Finder should create a file. I don't want anything to be dropped over my outline view, even it it comes from itself. This seems easy enough, but for some reason, I can't get it to work.
I checked the NSOutlineView drag and drop example from Apple, and I came to implement the following methods (plus a few definitely unrelated ones):
-(BOOL)outlineView:shouldSelectItem: // I don't expect to drag unselectable items
-(NSArray*)outlineView:namesOfPromisedFilesDroppedAtDestination:forDraggedItems:
-(BOOL)outlineView:writeItems:toPasteboard:
However, when I try to drag an item from my outline view, nothing happens. Instead, it just changes the selection following the cursor.
I've put breakpoints in the two last methods, and they never get called, so their implementation is not the immediate issue.
I must be missing something really obvious here.
Also, this is not (yet) a problem, but how am I supposed to provide contents to my promised files?
I was being stupid and I implemented the methods in the delegate instead of the data source (the two are distinct in my app). Problem solved!
Are you using a custom table view cell? The result of NSCell's hitTestForEvent:inRect:ofView: determines whether a dragging operation can be initiated. It also determines whether your outlineView:writeItems:toPasteboard: should be called.
This method should return NSCellHitContentArea to initiate a drag, or NSCellHitTrackableArea to extend or change the selection.
A standard text cell returns NSCellHitContentArea when you click on the actual text of the cell, and NSCellHitTrackableArea when you click outside of the text. This produces the drag behavior you see in Finder's table view.
You can override this method and always return NSCellHitContentArea if you want all areas of the cell to initiate a drag operation.
See Hit Testing for more information.