NSStepper in NSTableCellView has no effect - objective-c

I’m using a regular (not subclassed) NSTableCellView in a view-based table view. It has the initial image and text field views. I added an NSStepper to the view.
The text field is bound to tableCellView.objectValue.quantity.
The stepper’s value is bound to tableCellView.objectValue.quantity too.
The problem is that when running the app, when I click the stepper it doesn’t seem to get the mouse event, neither arrow gets highlighted, the value is not incremented or decremented.
If I set the double action of the table view it gets triggered if I double-click the stepper as if it was transparent.
What am I missing?
Thanks!

You should look at the documentation but easiest is that you need to subclass NSTableView and override this method to validate the proposed first responder. As the document states NSTableViews disallow some controls to be used unless the row is first selected. Even then it still may discard some.
- (BOOL)validateProposedFirstResponder:(NSResponder *)responder forEvent:(NSEvent *)event {
return YES;
}

Further to the correct answer from Robert Payne, with Swift you could add an extension to NSTableView and not subclass it.
extension NSTableView {
override public func validateProposedFirstResponder(responder: NSResponder, forEvent event: NSEvent?) -> Bool {
return true
}
}
And I'd like to emphasis that it's the NSTableView not the NSTableViewCell.

Related

Next key view of NSTextView find bar

Suppose there is a window which has two NSTextViews in it, and each of them uses the findBar.
The problem is that after closing one find bar (finishing the finding) the cursor jumps to the other textView, i.e. the focus does not return the the textView for which the find operation originated.
Please, does anyone know how to make it return to the original view?
This is a screenshot of one simple setup:
You can assign the nextKeyView property in StoryBoards (see image below) to assign where you want to the focus to "jump", otherwise, if you need to assign the nextKeyView property programmatically (when the view is initialized), you can do so using the nextKeyView property available via the NSView class. Both methods are hinted at below:
1. Assign the nextKeyView programmatically via this property
#property(assign) NSView *nextKeyView;
2. Or you can assign the nextKeyView in storyboards
Hope this helps!
Set the nextKeyView property of the text field back to the original view.
You can create the subclass of textview and mention the same inside your interface builder->Custom class and inside your custom textview class override the below method:-
-(BOOL)becomeFirstResponder
{
return YES;
}

Xcode - setFocus on a text field, becomeFirstResponder isn't enough

At the moment, I trigger a method on 'Did End On Exit' in my app (I'm aware that this may not be the greatest way of doing it but I'm very new to Objective C and Xcode for that matter and I'm simply doing what feels comfortable to me).
This method resigns the firstResponder from the current text field and applies it to a later text field.
The problem I'm facing is that the keyboard covers the next text field so that the use has no idea where the focus is and therefore what they are required to type.
How do I get it so that my keyboard shifts down and actually shows the text box that is currently active? Making something the firstResponder simply doesn't do what I want it to, unless there's part of the implementation I'm missing.
Here's my simple method:
- (IBAction)firstNameNext:(id)sender {
[firstNameTextField resignFirstResponder];
[surnameTextField becomeFirstResponder];
}
Any advice would be super.
Add UIScrollView in your main view then all contents as subview to UIScrollView
Now when specific UITextField needs to be able to visible in view use its delegate like this:
Note: add UITextFieldDelegate in .h file like this
#interface yourViewController : UIViewController<UITextFieldDelegate>
Also bind with File's Owner
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField;
{
if(textField == yourSpecficTextField) //one u want move upwards
{
yourScrollView.contentOffset = CGPointMake(0,200); //required offset
}
... //provide contentOffSet those who needed
return YES;
}
- (void)textFieldDidEndEditing:(UITextField *)textField
{
yourScrollView.contentOffset = CGPointMake(0,0); //make UIScrollView as it was before
}
If you have keyboard input fields that will be covered by the virtual keyboard, then you need to move those fields out from under the virtual keyboard.
The normal way to do this is to have the controller's view be a scrollable view like UIScrollView. Moving Content That Is Located Under the Keyboard gives a very robust way of adjusting your scroll view and ensuring the required field shows.

How do I deselect all table rows in NSOutlineView when clicking in the empty space of the view?

For example when I click on the red dot below:
I want the following deselection to occur:
I set up the view-based NSOutlineView using bindings for both the data source and the selection indexes. So far i've tried to override the TableCellView becomeFirstResponder and also override NSOutlineView's becomeFirstResponder however it seems NSOutlineView never actually gives up first responder status?
Some advice would be very much appreciated!
I found this post on the topic. The solution appears to be in creating a subclass of NSOutlineView and overriding mouseDown: so that you can determine whether the click was on a row or not. When the click is on a row you just dispatch to super. If it's not you send deselectAll: to your NSOutlineView.
I haven't tried it myself but there are various posts around which come up with comparable code.
Use setAction: method of NSOutlineView.
[mOutlineView setAction:#selector(doClick:)];
[mOutlineView setTarget:self];
-(IBAction) doClick:(id)sender;
{
if ([mOutlineView clickedRow] == -1) {
[mOutlineView deselectAll:nil];
}
}
Swift 5. in NSOutlineViewDelegate
func outlineViewSelectionDidChange(_ notification: Notification) {
//1
guard let outlineView = notification.object as? NSOutlineView else {
return
}
outlineView.deselectAll(nil)
}

NSTableView selection & highlights

I have a NSTableView as a very central part of my Application and want it to integrate more with the rest of it. It has only one column (it's a list) and I draw all Cells (normal NSTextFieldCells) myself.
The first problem is the highlighting. I draw the highlight myself and want to get rid of the blue background. I now fill the whole cell with the original background color to hide the blue background, but this looks bad when dragging the cell around. I tried overriding highlight:withFrame:inView: and highlightColorWithFrame:inView: of NSCell but nothing happened. How can I disable automatic highlighting?
I also want all rows/cells to be deselected when I click somewhere outside my NSTableView. Since the background / highlight of the selected cell turns gray there must be an event for this, but I can't find it. I let my cells expand on a double click and may need to undo this. So getting rid of the gray highlight is not enough.
EDIT: I add a subview to the NSTableView when a cell gets double clicked and then resignFirstResponder of the NSTableView gets called. I tried this:
- (BOOL)resignFirstResponder
{
if (![[self subviews] containsObject:[[self window] firstResponder]])
{
[self deselectAll:self];
...
}
return YES;
}
Besides that it's not working I would need to implement this method for all objects in the view hierarchy. Is there an other solution to find out when the first responder leaves a certain view hierarchy?
I wanted to achieve a similar solution (with an NSOutlineView but this has no difference): when clicking inside the outline view BUT not in a row with a cell (for instance at the empty bottom of a source list), I wanted the currently selected row to be deselected. I ended up with this little piece of code that might be of some help.
In a NSOutlineView subclass, I've put:
#implementation ClickOutlineView
- (void)mouseDown:(NSEvent *)theEvent
{
NSPoint pointInWindow = [theEvent locationInWindow];
NSPoint pointInOutlineView = [self convertPoint:pointInWindow toView:nil];
int rowIndex = [self rowAtPoint:pointInOutlineView];
if ([theEvent clickCount] == 1 && rowIndex == -1) {
[self deselectAll:nil];
}
else {
[super mouseDown:theEvent];
}
}
#end
No doubt it's too late to help the question's poster, but this may help others who come across this on Google (as I did).
You can prevent row selection by selecting 'None' in the 'Highlight' drop-down menu, in the attributes inspector in Xcode 4.
There is also an answer on SO here for setting this programmatically.
Overloading -highlight:withFrame:inView: should be correct. How did you do the overload? Does an NSLog() statement indicate that your code is running? You should also look at NSTableView's -highlightSelectionInClipRect:, which may be more convenient for this.
In order to do something (such as unselect the current selection) when the user clicks outside the table view, overload -resignFirstResponder on NSTableView.

NSCollectionViewItem double-click action?

How do I set an action for when a user double clicks an NSCollectionViewItem. NSTableView, for example, has the setDoubleAction method. Is there something similar for NSCollectionView?
Thanks
I know this question is ancient, but it comes up as the third result on Google right now, and I've found a different and very straightforward method that I haven't seen documented elsewhere. (I don't just need to manipulate the represented item, but have more complex work to do in my app.)
NSCollectionView inherits from NSView, so you can simply create a custom subclass and override mouseDown. This is not completely without pitfalls - you need to check the click count, and convert the point from the main window to your collection view's coordinate, before using NSCollectionView's indexPathForItem method:
override func mouseDown(with theEvent: NSEvent) {
if theEvent.clickCount == 2 {
let locationInWindow = theEvent.locationInWindow
let locationInView = convert(locationInWindow, from: NSApplication.shared.mainWindow?.contentView)
if let doubleClickedItem = indexPathForItem(at: locationInView){
// handle double click - I've created a DoubleClickDelegate
// (my collectionView's delegate, but you could use notifications as well)
...
This feels as if I've finally found the method Apple intended to be used - otherwise, there's no reason for indexPathForItem(at:) to exist.
You'd probably want to handle this in your NSCollectionViewItem, rather than the NSCollectionView itself (to work off your NSTableView analogy).