Validating a drag to an NSCollectionView isn't reflected visually - cocoa

I have an NSCollectionView that I want to accept items dragged from elsewhere in my application.
I implement collectionView:validateDrop:proposedIndex:dropOperation: and collectionView:acceptDrop:index:dropOperation: in the collectionview's delegate and register for the appropriate dragged types. Both methods get called fine when I drag the appropriate types, but I don't get a blue focus ring over the collectionview indicating a valid drag.
Have tried both the collection view and its containing scroll view on Default and External settings for the focus ring. Both are just the standard non-derived Cocoa classes. Wondered if there was anything else I should try. Surely it isn't necessary to subclass NSCollectionView for this?
Thanks
Chris

Focus rings are not typically the correct way to provide feedback about drag destinations. Every view does it slightly differently. NSTextView shows the insertion bar. NSTableView shows a blue line in between rows for Before drop operations, and shows a bezel around the row for On drop operations. (See NSTableViewDropOperation)
NSCollectionView shows a "gap" between existing subviews to show where the items will be dropped for Before drop operations, and it will set the selected property on NSCollectionViewItem to YES for On drop operations. (Note: NSCollectionViewItem doesn't do anything by default to visibly represent the selected property. You must implement that yourself.)
Since NSCollectionView's feedback uses existing subviews only, it appears there isn't any feedback at all for empty NSCollectionView's. You would need to subclass to provide this behavior yourself. You could also file a bug to request that NSCollectionView do this itself.

Related

What is the appropriate UI set up for messaging functionality?

I have an app which allows users to send messages to each. The process is accomplished by saving the sent messages in a local SQLite database, while actually sending the messages to a database and using push notifications to send the message to the recipient's SQLite database. The set up I have works fine. However, what I am confused about is how to set up the actual interactive UI for the user (I am using XCode). I figured it should be a UITableView with each table cell representing a message. However, with this approach I run into a few requirements:
Variable TextView Sizes
Just as with regular iOS messaging, the TextView's size needs to be variable, adjusting its dimensions to fit all of the text in each message. I do not know how to accomplish this. I have a general understanding of how to generally vary sizes, but no clue how to dynamically have it based on the text within that view.
Variable TextView Positions
Again, just as with regular iOS messaging, the textview needs to be offset to either the right or left side depending on whether the sender was the user or who the are conversing with, respectively. I also do not know how to do this, because it changes the center of the textview.
Non-selectability
Xcode allows cells to be pressed. Handling what happens after this selection can be achieved by the didSelectRowatIndexPath tableView function. I can simply not implement this, but clicking on the cell causes it to turn darker to indicate it has been pressed. I would like to eliminate this while retaining the ability to, say, select some of the text and copy and paste it or whatever (just like messaging works normally on your phone).
Other Approaches?
This is the real meat of the question. I have considered the above approach because that is all that I have been able to come up with based on my limited experience with XCode UI elements. If there is a better approach (perhaps even a pod or framework) for this purpose I would love to hear it. I do not need the messaging UI to look amazing, just clean and crisp.
I suggest the following:
Variable TextView Sizes:
I assume you do use auto layout. If you don’t yet, please consider using it since it make life much easier!
If you use a UITableView, you can adjust the height of its UITableViewCells dynamically, depending on the actual content by using self-sizing cells. You can find a tutorial how to do this here.
Variable TextView Positions:
I assume you have a UITextView within a table view cell. In this case, you have to set auto layout constraints to the borders of the cell’s contentView. If you define a custom subclass of a UITableViewCell, you can define in this class 2 IBOutlet properties that are linked to say the left and the right layout constraints (e.g. var leftLayoutConstraint: NSLayoutConstraint). Then, you can set the constraint’s constant property as required when the cell is laid out, i.e. in the layoutSubviews function of the custom table view cell.
Non-selectability:
I am not sure what you mean by „I can simply not implement this“. Please make sure that you set the delegate property of the UITableView to the view controller where you want to handle cell selection. Selecting a cell changes the cells color by default, but you can change this: In the storyboard, select your table view’s prototype cell, and open Xcode’s utility pane (top rightmost button). Under „Table view cell“ you find „Selection“ that you can set to „None“.
I hope this helps!

How to call NSScrollView autoscroll-method programmatically

I have simple chat application with text messages view-based NSTableView as you can see at the picture below.
Each message contains NSTextView instance having height to fit all the text.
All I need is to start NSScrollView (which NSTableView-instance is enclosed by) autoscrolling while the user selecting text dragging mouse far enough. Unfortunately, autoscrolling doesn't appear. In case of dragging somewhere outside of the text views all succeed.
I tried to call autoscroll:-method directly by simply push NSEvent-instance from NSTextView-subclass "mouse dragged"-event (like in example from this article):
- (void)mouseDragged:(NSEvent *)event
{
[self.scrollView autoscroll:event];
}
As I've overrode all the mouse events and implemented all the text selecting, this method often invokes. But the autoscrolling doesn't seem to work.
UPDATE
I figured out that before calling -autoscroll:-method there must be -mouseDown: of the same object. But it breaks my text selecting mechanism. The point even not in being first responder, there must be nothing but the mouseDown:-method.
Normally, a text view is within a scroll view of its own. Even if that's big enough to show all of the text without scrolling, it's still there. A call of -autoscroll: on anything within that scroll view (possibly including that scroll view itself?) will just try to scroll that scroll view, not the scroll view that contains the table view.
Try calling -autoscroll: on a view higher up in the hierarchy. Either self.scrollView.superview, the table cell view, or the table view.
Note, though, that the table view's scroll view will keep scrolling even after the cell view containing the text view is fully on-screen. In fact, it may keep scrolling it so far that it's off the screen in the other direction. Basically, it doesn't know that you're trying to select within the text view so it doesn't know to stop when the selection extends all the way to the edge of the text view.
Another approach might be to try to use a "bare" text view with no enclosing scroll view. I don't think IB will let you do that, so you'd have to do it programmatically. Bare text views don't play well with auto layout, though.

How to correctly add NSComboBox to view-based NSTableView in Interface Builder

I'm basically asking how do you correctly add a Combo Box to a Table View with correct layout i.e. so that appears as if you were adding a ComboBox cell to a cell-based Table View. Currently when I add it to the Table Cell View it doesn't fit (bottom half chopped off) and doesn't behave as its supposed i.e. focus ring is messed up, arrows messed up, not aligned correctly.
I have searched the net couple of times over and funny enough I haven't found an answer to this question. If I don't find a solution I might have return to good old cell-based table views.
If the combo box doesn't fit, you need to increase the height of the NSTableCellView. This is done in Interface Builder or, if implemented, in the NSTableViewDelegate method tableView:heightOfRow:.

Is there a concept of viewcontroller containment in NSViewController

In iOS, you have a concept of View Containment, is there such things in OSX?
Basically I want to create multiple nsviewcontroller each managing a specific view. I'd have a MasterViewController with a menu on the left (like ITunes), each time the user click on an item on the left, it would load the correct nsviewcontroller to display it's view.
Any tips to achieve what I need is appreciated
Thanks,
As of OSX 10.10 there is, watch Storyboards and Controllers on OS X.
Comment.
NSViewController did basically nothing (other that load NIBs) for years, I'm glad to see that it finally got from attention. Certain people in the Cocoa crowd here have a snotty attitude about the view controller programming style; I've asked questions like this before and had the "are you a iOS newbie coming to Cocoa" response. That's something that I never understood, it's a great model for containment, and reuse.
The main difference between OS X and iOS is that on an iOS device you have only one "window". On OS X there are desktops that can contain many windows that you can view and interact with at the same time.
In general, it sounds like you are trying to create an NSWindow that contains a single-column NSTableView for your list of choices on the left, and some other view that will display the detail of the selection on the right. It's common to place these within a vertical NSSplitView so the user can adjust their relative widths, but they could also stand on their own, as two separate subviews within the window's main view.
You typically use an NSArrayController to manage the list contents and track which particular item is selected. For your detail view on the right, you would use a single NSView with NSControl subviews that display values bound to the array controller's selected object.
If the data structure varies among your objects, swap in or show/hide various subviews as needed for the different types of data the particular selected object represents. You can use the "Conditionally Sets Hidden" binding option to automatically hide controls for which there is no applicable keyed value.
Alternatively, if there's a fixed number of objects in your list and their structures are all quite different from one another, then you may wish to use a tabless NSTabView that has a separate tab with its own custom view for each of your objects. Observe when the selection changes in your list, and select the appropriate tab accordingly.

Setting a custom tab order in a Cocoa application

I have a window with two columns of fields. On the left, there is an NSTableView and an NSTokenField, and on the right, there are two NSTextFields. I want the tab order to go down the left, then down the right. (So the order should be NSTableView, NSTokenField, NSTextField, NSTextField in my window.) However, Cocoa appears to be determining its own preferred order, going from the top to the bottom. The NSTokenField is positioned lower in the window than any other control, so it will always tab from NSTableView, to the right NSTextFields, then back to the bottom left NSTokenField.
I have tried following this section of the Apple developer documentation called Enable Tabbing Between Text Fields and dragging nextKeyView in Interface Builder between the fields in the order that I want. This seems to have absolutely zero effect on the tab order, and from what I can tell, Cocoa appears to still use its default detecting method to choose a tab order.
Any ideas? My target is 10.6+.
Make sure that you also set the initialFirstResponder outlet of the window to the first field (the table view in this case).
Sounds like you're going to have to do it programmatically:
Register for controlTextDidEndEditing notifications, identify the field by tag, and then call makeFirstResponder:fieldOfYourChoice on the window. And/or use an IBAction on the field, identifying it by sender, and call makeFirstResponder.

Resources