Drawing table view cell when drag and drop - objective-c

I have dragged an item into my tableview object.
When the dragged item hover over an item in tableview,
the item is redrawn with selection background. The image is as under
The row of the tableview is not selected, when i checked selectedRow method.
My requirement is when an item hover any item i should control its selection
and the background selection thereof.
Thanks,
iSight

To 'control' the selection of a TableViewCell when 'hovering' over such an item you will have to call this method:
- (NSIndexPath *)indexPathForRowAtPoint:(CGPoint)point
It's a method from the UITableView Class and uses the local coordinate system of your tableView. As is mentioned in the Apple Doc: http://developer.apple.com/library/ios/#documentation/uikit/reference/UITableView_Class/Reference/Reference.html
When the method is called you will have a NSIndexPath returned. With it you can select the cell/item at that particular path.
Mind, selecting a path manually doesn't call the didSelectRowAtIndexPath delegate-method so if you want a certain method called from that delegate you will have to do that manually as well!
This method is prolly called from the touchedDidMove method (where you also do the drag&drop) so getting the point needed for the method shouldn't be a problem for you.
You will figure it out :)
Good luck.

Related

Get the representedObject values of NSCollectionViewItem NSButton click

I have read some questions and I find some very confusing and I don't really know if they answer my question.
I have an NSCollectionView implemented and connected to a Core Data context, everything shows correctly.
Now what I have is buttons in the view prototype, and when I click this buttons I need to get the value of the representedObject of that cloned view.
I have read and read and some parts are confusing to me, so I'm looking for a simple explanation.
Thank you for your time.
An action method takes one argument:
- (IBAction) collectionViewButtonClicked:(id)sender {
}
That sender is the control or other UI element (e.g., menu item) that sent the message.
With that argument, when your action method gets called, you know which button was clicked.
A button is a kind of control, and every control is backed by at least one cell. Cells have represented objects, too.
So, first, set the represented object of your button's cell to the collection view item that owns the button. (You can do this in the nib editor.) Then, in your action method, get the button's cell, then the cell's represented object (which is the item), then the item's represented object.
If the representedObject outlet doesn't show up in the nib editor, you probably have the button selected, not its cell. I recommend opening the nib editor's outline view using the button in the lower-left and then never, ever closing it.

UITableView: How to revert a user input

I have a UITableView with a couple items and I've added a cell that says "No More Items" to the bottom of the UITableView list. I'm preventing the "NMI" cell from being re-ordered, but I can still take one of the other items and drag it underneath the "NMI" cell.
When my view tells me: tableView:moveRowAtIndexPath:toIndexPath, I don't modify the model and reorder the array of items. However, even if I don't modify the model, the UITableView still reflects the new order.
What I'm looking for is a method to reject the UITableView's change. So when tableView says "hey the user is moving this row to the end of the list, you should update the model," the controller can respond and say "wait, that row can't be moved to the end of the list. don't do that"
Try using this delegate method to check if reordering is allowed or not.
- (BOOL)tableView:(NSTableView *)tableView shouldReorderColumn:(NSInteger)columnIndex toColumn:(NSInteger)newColumnIndex

Adding properties to UIControls without subclassing

I have embedded UIButtons in my TableViewCells. In order to track which cell the button belongs to, I would like to add an NSIndexPath property to UIButton. I do not want to subclass a UIButton. Is there a way I can do this with categories?
EDIT: I believe the idea of setting tags will not work if I have multiple sections in the table view. Another approach of accessing the button's superview's superview to determine the cell seems more like a hack. Looking for a cleaner way of doing this.
There are several approaches. If you just really need a single number rather than a full index path, you can use setTag:. It's inflexible, but it's readily available.
The next best solution is associative references. These can hang data onto any object, with proper memory management. I usually create a category that adds a property implemented using objc_setAssociatedObject and objc_getAssociatedObject.
You can find out which cell a clicked button was in without having to associate tags or index paths with the buttons, which can get messy when re-using cells. Tags do work with sectioned tables but you have to mess about with numbers, e.g. 10001 is section 1, row 1, so you've got to convert at one end and convert back at the other, too fragile for my liking.
A nicer method is to use UITableView's indexPathForRowAtPoint: method. When your button's action is activated (assuming the target is in your table view controller:
CGPoint point = [sender convertPoint:sender.center toView:self.tableView];
NSIndexPath *path = [self.tableView indexPathForRowAtPoint:point];
sender here is cast to UIButton.
In order to track which cell the button belongs to
You already know which cell the button belongs to: it's the cell that the button is a subview of.
Start with a reference to the button. (If you are the button, this is self. If you're the button's target for its action, then when the button is tapped and emits an action message, it passes itself along as parameter to the action message, usually called sender.)
Look up the view hierarchy (superview) to find the UIViewTableCell containing the button.
UIView* v = theButton;
while (![v isKindOfClass: [UITableViewCell class]]) v = v.superview;
Now you can do whatever you like with that info. For example, you seem to want an NSIndexPath; then call -[UITableView indexPathForCell:].

mouseover detection in NSTableView's NSCell?

I am wanting to change the text background color on a tableview's cell when it is hovered upon, similar to how AddressBook "highlights" the label of a contact's element when you mouseover the label names. However I cannot figure out how to accomplish...
detecting a mouseover on a particular NSCell and...
After detecting the cell his hovered upon, highlighting the text in that cell (not highlighting the entire row as if the user selected that row)
As NSCell is not a subclass of NSView this seems to be a very difficult task.
Any example of this or explanation on how this might be done would be greatly appreciated.
Thanks!
I actually got it working using another method. I got it from the example posted here... http://www.cocoadev.com/index.pl?NSTableViewRollover
https://web.archive.org/web/20111013060111/http://cocoadev.com/index.pl?NSTableViewRollover
Instead of using NSCell's tracking mechanism, I am tracking mouseEntered/mouseExited and mouseMoved within my subclassed NSTableView.
When the tableview awakeFromNib method is called, I create a trackingRect from the visible portion of the tableview
I have a BOOL ivar that is set to YES when the mouse is within the tracking area(mouseEntered) and NO when it is not (mouseExited)
Within the mouseMoved method, I determine the current row the mouse cursor is on and set it to an NSInteger ivar and then call the tableview's setNeedsDisplayInRect: passing the rect of the row that the mouse is on.
I also override resetCursorRects to remove the old tracking rect and add a new one...this method is called when the tableview is scrolled upon so that it's tracking the latest visible rect.
Finally in my tableview's delegate, I determine the selected row (by retrieving the row index from the NSInteger ivar of the table view and change the cell's text color (or anything you want) if the currently drawn cell matches the row the mouse cursor is on. All this is done in the delegate method: tableView:(NSTableView *)aTableView willDisplayCell:(id)aCell forTableColumn:(NSTableColumn *)aTableColumn row:(NSInteger)rowIndex
I hope this helps others, as this was a bit tricky. It is also probably important to make sure that tableview is the firstResponder when the view loads, just makes things a bit more streamlined and cleaner.
Btw, is there a way to make a specific control in a view always be the firstResponder with nothing else possible as being the firstResponder? Even a method such as the iPhones... viewWillAppear method will help as I could set the first responder each time the view is visible...but i'm not aware of such a method on the Mac.
Overall, it's not a simple task as you noticed.
To track the mouse in an NSCell, subclass NSCell and override
-[NSCell startTrackingAt:inView:]
and
-[NSCell stopTracking:at:inView:mouseIsUp:]
Once you've detected the mouse is tracking inside a cell, you can find out which cell you are in the table with [tableView rowAtPoint:point] and [tableView columnAtPoint:point], and then find your frame with [tableView frameOfCellAtColumn:column row:row]
Then, you can change the way your cell is drawn by changing some property of the cell or changing the way it's drawn directly by overriding drawInteriorWithFrame:inView:.
Here's documentation on subclassing NSCell:
http://developer.apple.com/mac/library/documentation/cocoa/conceptual/ControlCell/Tasks/SubclassingNSCell.html
I achieved something similar by making use of addGlobalMonitorForEventsMatchingMask: handler: of NSEvent within my NSTableView subclass for the NSMouseMovedMask. using this along with columnAtPoint and rowAtPoint of NSTableView I was able to figure out if the position of the mouse was within a given cell.
Using this information I was able to bring up a PopOver when the mouse was over a particular cell.

Saving reference to UITableViewCell

I have 5 cells in a tableview that are all custom. Meaning, I've created a xib with a tableviewcell and created a corresponding cellController. The xib has two labels named name and size. The user taps a row, triggering didSelectRowAtIndexPath. From there a timer is started. At some point the timer finishes. Here I need to assign text to the selected cell's name label. How do I get the selected cell reference and keep it for assigning? Or, is there a better way to do it?
The UITableView instance method
-(UITableViewCell*) cellForRowAtIndexPath: (NSIndexPath*)indexPath
will allow you to get a pointer to the cell.
Simply store the row+section info from NSIndexPath argument of the didSelectRowAtIndexPath event. Then, when the timer finishes, build a new NSIndexPath and call cellForRowAtIndexPath. Also be prepared for it to return nil if the cell is no longer in view.