Binding selected radiobox to enabling checkbox in Cocoa - xcode

I haven't worked with Cocoa bindings a lot before, so I would need a little help here.
I have a radio button group ( NSMatrix ) with three buttons and one checkbox.
I want the checkbox to be enabled only when the last radio button is selected.
Found a tutorial online which advised to bind the selected tag property of the radio button group to the enabled property of the checkbox. The last radiobutton needs to have a tag of 1, the others would need to have a tag of 0.
This works great.
The problem is, that if the checkbox is checked and the radiobutton selection is changed, it stays checked although it isn't enabled. I would want that the box gets unchecked when it changes to the disabled state.
Any advise would be appreciated!
Thanks in advance!
Any way to achieve this without any code?

I doubt it's possible to do this without code.
I handle this in the model, using KVO. Code looks something like this:
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if ([#"checkWithInProcess" isEqualToString:keyPath]) {
NSNumber *oldValue = [change objectForKey:NSKeyValueChangeOldKey];
NSNumber *newValue = [change objectForKey:NSKeyValueChangeNewKey];
BOOL oldValueAsBool = (oldValue != (id)[NSNull null]) && oldValue.boolValue;
BOOL newValueAsBool = (newValue != (id)[NSNull null]) && newValue.boolValue;
if (oldValueAsBool && !newValueAsBool) {
// Save the value
savedRecordValueWithInProcess = self.recordValueWithInProcess;
self.recordValueWithInProcess = nil;
} else if (!oldValueAsBool && newValueAsBool) {
// Restore the value or set it to the default
if (savedRecordValueWithInProcess)
self.recordValueWithInProcess = savedRecordValueWithInProcess;
else
self.recordValueWithInProcess = [NSNumber numberWithBool:NO];
savedRecordValueWithInProcess = nil;
}
}
}
And during initialization:
[self addObserver:self
forKeyPath:#"checkWithInProcess"
options:NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew
context:[Characteristic class]];

Related

NSTableView (view based) with custom text colors and correct editing text color

Changing the text color in a view based NSTableView can be accomplished by using a custom table cell view and implement setBackgroundStyle:
- (void)setBackgroundStyle: (NSBackgroundStyle)backgroundStyle {
[super setBackgroundStyle: backgroundStyle];
UICoverageElement *element = self.objectValue;
if (backgroundStyle == NSBackgroundStyleEmphasized) {
self.textField.textColor = NSColor.highlightColor;
} else {
if ([element.value isEqualToString: #"<no name>"]) {
self.textField.textColor = NSColor.tertiaryLabelColor;
} else if ([element.value hasPrefix: #"UI"]) {
self.textField.textColor = typeColor;
} else if ([element.value hasPrefix: #"["] || [element.value hasPrefix: #"{"]) {
self.textField.textColor = objectColor;
} else {
self.textField.textColor = NSColor.textColor;
}
}
}
This works nice and well:
but causes trouble when editing a cell. In this case the field editor obviously takes the current manually set text color (which is white for a selected row) and shows that in a field editor with white background:
Now the question is: how can I set the correct text color when a cell view is being edited?
setBackgroundStyle is not called when editing starts, which makes it impossible to fix that problem in this function. I tried various methods that indicate start of the editing process, but none is called (but are called for standalone text fields). When I do not set the highlightColor then the editor color is correct but the highlight color of a selected row is wrong then.
Honestly, this is one of those things that you'd think would be really simple and straightforward, and it's really unfortunately not.
The only ways to affect the color in the field editor, are to either:
a) Set the color of your text field to the desired color before NSCell's selectWithFrame:... method is called
b) Change the color the text placed into the field editor after selectWithFrame:... is called.
So generally:
a) subclass NSTextFieldCell and set the field's text color back to the usual default before the field editor is set up.
- (void)selectWithFrame:(NSRect)rect inView:(NSView *)controlView editor:(NSText *)textObj delegate:(id)delegate start:(NSInteger)selStart length:(NSInteger)selLength
{
self.textColorWhenNotEditing = self.textColor;
self.textColor = NSColor.controlTextColor;
[super selectWithFrame:rect inView:controlView editor:textObj delegate:delegate start:selStart length:selLength];
}
- (void)endEditing:(NSText *)textObj
{
[super endEditing:textObj];
self.textColor = self.textColorWhenNotEditing;
}
b) Change the field editor directly
- (void)selectWithFrame:(NSRect)rect inView:(NSView *)controlView editor:(NSText *)textObj delegate:(id)delegate start:(NSInteger)selStart length:(NSInteger)selLength
{
[super selectWithFrame:rect inView:controlView editor:textObj delegate:delegate start:selStart length:selLength];
NSMutableDictionary * attribs = [((NSTextView *)textObj).typingAttributes mutableCopy];
attribs[NSForegroundColorAttributeName] = NSColor.controlTextColor;
[((NSTextView *)textObj).textStorage setAttributes:attribs range:NSMakeRange(0, textObj.string.length)];
((NSTextView *)textObj).typingAttributes = attribs;
}
I had previously answered a related question. Not sure if this should be marked as duplicate:
https://stackoverflow.com/a/54217318/217306
The gist is that the text editing mode is handled by a separate object called field editor. You should create a new instance and use it to customize the look during editing for your table.
windowWillReturnFieldEditor delegate method of NSWindow asks which editor to use for editing a client. You create such editor once for your table and return it when the delegate asks for an editor for your table.
- (id)windowWillReturnFieldEditor:(NSWindow *)sender toObject:(id)client {
if (/* client is a textfield or subview in your table */) {
// Create customEditor elsewhere once
// Get row number or data that corresponds to client view
// Cusomize customEditor colors accordingly
return customEditor;
}
return nil; // Use default editor
}

Present a sheet from a menu item

I have a Cocoa app that calls a sheet from the main window. This works fine from an NSButton on the main window. However, when I call from a MainMenu item, the sheet shows as a separate window. Is this expected behavior, or just expected from me :) I have studied this question ..
I call the sheet with this code:
-(IBAction) showSettingsSheet:(id)sender {
NSLog(#"%s", __FUNCTION__);
settingsSheetController = [[SettingsSheetController alloc] initWithWindowNibName:#"SettingsSheet"];
[settingsSheetController beginSheetModalForWindow:self.window completionHandler:^(NSUInteger returnCode) {
if (returnCode == kSettingsSheetReturnedOk) {
NSLog(#"Settings Returned ok");
} else if (returnCode == kSettingsSheetReturnedCancel) {
NSLog(#"Settings Returned cancel");
} else {
//self.categoryDisplayString = #"Oops!";
NSLog(#" Ooops");
}
}];
}
UPDATE
This is how the Attributes Inspector is set:
Try like this, if you want to display sheet in a mainmenu then try the below steps:-
Uncheck the visible at launch option inside attribute inspector of window which you want to display as a sheet attached the screenshot as well

button available only when label is not nil

How can I force the user to insert data to the UITEXTFILED that otherwise the button will not work for him.
I thought about:
-(IBAction) signup:(id)sender{
if text.text==nil
///// return?? /////
?
tnx all
I would do like this, first in my ViewDidLoad():
editButton.enabled=NO;
[_myTextFieldaddTarget:self
action:#selector(textFieldDidChange:)
forControlEvents:UIControlEventEditingChanged];
Then i would add an event handler:
-(void) textFieldDidChange{
if (_myTextField.length == 0){
editbutton.enabled=NO;
}else{
editbutton.enabled=YES;
}
}
You can show an UIAlertView when the user push the button if the UITextField is empty :
if (_myTextField.lenght == 0)
// Display Alert

Disable menu items on ApplescriptObjc

I am coding with ApplescriptObjc.
I want to disable a menu item "Preference..." in a function, but I can't do it.
I can disable buttons. Here is the code:
myButton's setEnabled_(false)
So I tried to disable a menu item like a button:
myMenuItem's setEnabled_(false)
I looked at an Apple Reference (https://developer.apple.com/library/mac/documentation/cocoa/reference/ApplicationKit/Protocols/NSMenuValidation_Protocol/Reference/Reference.html), but I couldn't use this reference because I don't understand how to disable it indeed.
- (BOOL)validateMenuItem:(NSMenuItem *)item {
int row = [tableView selectedRow];
if ([item action] == #selector(nextRecord) &&
(row == [countryKeys indexOfObject:[countryKeys lastObject]])) {
return NO;
}
if ([item action] == #selector(priorRecord) && row == 0) {
return NO;
}
return YES;
}
I thought I can use this function in this way:
on validateMenuItem_(myMenuItem)
if myMenuItemIsEnabled = true then
return true
else
return false
end validateMenuItem_
But this doesn't work (no response). How can I disable menu items?
After connecting the menu item to an IB property, use the following code to disable it:
set (myMenuItem's enabled) to false
Where myMenuItem is a property connected to the menu item you wish to disable. You must make sure to uncheck the menu item's menu option called "Auto Enables Items".

NSDatePicker action method not firing

Scenario:
The user is entering a date in an NSDatePicker in its textual form with no stepper (on OS X), and when they hit return on the keyboard, I'd like a message to be sent to the controller.
In an NSTextField, I would just hook the action up in Interface Builder, or set it from code, and when the user hits enter, the action message is sent to the target.
The date picker allows to set an action message and a target, but I can't get the action to fire. When I hit enter in the date picker, the action message does not get called.
Am I doing something wrong, or is there a workaround that I have to use? I would not be adverse to subclassing any of the classes involved, if that is what it takes.
An NSDatePicker will not handle or forward key events triggered by the Return or Enter key.
The solution is to subclass NSDatePicker to get the desired behavior in keyDown:
#import "datePickerClass.h"
#implementation datePickerClass
- (void)keyDown:(NSEvent *)theEvent{
unsigned short n = [theEvent keyCode];
if (n == 36 || n == 76) {
NSLog(#"Return key or Enter key");
// do your action
//
} else {
[super keyDown:theEvent];// normal behavior
}
}
#end
That's it.
Edit : also you can use NSCarriageReturnCharacter and NSEnterCharacter
NSString* const s = [theEvent charactersIgnoringModifiers];
unichar const key = [s characterAtIndex:0];
if (key == NSCarriageReturnCharacter || key == NSEnterCharacter) {

Resources