Disable menu items on ApplescriptObjc - cocoa

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".

Related

How to check if a button is checkbox on 64 bit windows?

I'm checking if a button is checkbox of 32bit process on 64bit windows10.
The problem is that I can not distingush checkbox from normal button.
The buttons are different in Window-Detective:
(After I restart the application, even Window-Detective shows it is a button now!)
But the checkbox can't be recognized as checkbox in Spy++
BS_CHECKBOX is not listed.
Code (compiled as 32bit):
TEST_METHOD(ShouldCheckStyle) {
auto styleOfButton = ::GetWindowLongPtr((HWND)0x003F06E8, GWL_STYLE);
auto styleOfCheckbox = ::GetWindowLongPtr((HWND)0x01101642, GWL_STYLE);
auto bsOfButton = styleOfButton & BS_TYPEMASK;
auto bsOfCheckbox = styleOfCheckbox & BS_TYPEMASK;
auto resultOfButton = (bsOfButton == BS_CHECKBOX);
auto resultOfCheckbox = (bsOfCheckbox == BS_CHECKBOX);
auto debugger = 0;
}
Debug output
The code indicates they both have BS_OWNERDRAW. The above behaves the same for the button and the checkbox.
The weird thing is Window-Detective can recognize the style of checkbox. The code is same as I used above. Here's a piece of code:
Window* WindowManager::createWindow(HWND handle) {
WindowClass* windowClass = getWindowClassFor(handle);
String className = windowClass->getName().toLower();
if (className == "button") {
LONG typeStyle = GetWindowLong(handle, GWL_STYLE) & BS_TYPEMASK;
switch (typeStyle) {
case BS_CHECKBOX:
case BS_AUTOCHECKBOX:
case BS_3STATE:
case BS_AUTO3STATE: {
return new CheckBox(handle, windowClass);
}
case BS_RADIOBUTTON:
case BS_AUTORADIOBUTTON: {
return new RadioButton(handle, windowClass);
}
case BS_GROUPBOX: {
return new GroupBox(handle, windowClass);
}
default: {
// If none of the above is true, then the control is just a Button
return new Button(handle, windowClass);
}
}
}
After some discussion, you can use GetWindowText to get the text from each control and compare the specific text.
BS_CHECKBOX cannot be detected from the properties of the "checkbox" control beacuse of BS_OWNERDRAW.
Creates an owner-drawn button. The owner window receives a WM_DRAWITEM
message when a visual aspect of the button has changed. Do not combine
the BS_OWNERDRAW style with any other button styles.
Try the below code:
WCHAR str1[20];
WCHAR str2[] = L"Agree me";
GetWindowText(hwnd_checkbox, str1, 256);
if (_tcscmp(str1, str2) == 0)
{
//it is checkbox
}
else
{
//it isn't checkbox
}
After you get the correct control handle of the checkbox, you can use SendDlgItemMessage or SendMessage to send BM_SETCHECK check message.
SendMessage(hwnd_checkbox, BM_SETCHECK, BST_CHECKED, 0);

Fullscreen NSWindow on Secondary Monitor - Swift

I have seen many posts on this in Obj C. Not too many in swift, and I just can't get it to work. I want to be able to make a window fullscreen on a specific NSScreen. The 'ToggleFullscreen' method isn't the best way because there aren't many options (for external displays). I tried:
// screen is my variable already set
outputWindow!.window!.setFrame(screen.frame, display: true, animate: true)
outputWindow!.window!.styleMask = NSFullScreenWindowMask
outputWindow!.window!.level = Int(CGShieldingWindowLevel())
// the above one doesn't make it fullscreen.
// it has a title bar and shows the menu on the screen.
// then i tried....
fullscreenWindow = NSWindow(contentRect: screen.frame, styleMask:NSBorderlessWindowMask, backing: NSBackingStoreType.Buffered, defer: false, screen: screen)
fullscreenWindow.level = Int(CGShieldingWindowLevel())
fullscreenWindow.makeKeyAndOrderFront(nil)
//that one works on my main display (somewhat). and does nothing on externals.
One thing I noticed with making my own fullscreen is that I get stuck into it. It's not like the OS X fullscreen where you can press esc to escape it. Are there any tricks to this? Thanks
I struggled with getting stuck on fullscreen as well. The reason behind that is using NSBorderlessWindowMask prevents the window from becoming key regardless of sending the makeKeyAndOrderFront: or makeKeyWindow messages to it. In Objective-C, the solution was to implement canBecomeKeyWindow in the subclassed NSWindow.
- (BOOL)canBecomeKeyWindow {
return YES;
}
Now it receives key events after going full screen as well.
This is a pseudo answer:
[in a inherited class of NSWondowController]
var fullscreen:Bool {
set {
if newValue == true {
if fullscreen == true {
return
}
frameOrig = self.window?.frame
self.window?.setFrame((NSScreen.main()?.frame)!, display: true)
}
else {
self.window?.setFrame(frameOrig!, display: true)
}
}
get {
return self.window?.frame == NSScreen.main()?.frame
}
}
I also trapped key events on both the calling-window and fullscreen window and point them to the above function so that toggling is possible. Like so:
[in some viewcontroller]:
override func keyUp(with event: NSEvent) {
switch event.keyCode {
case 53:
debugPrint("ESC - randomviewcontroller")
(randomView.window?.windowController as! RandomWindowController).fullscreen = !(RandomView.window?.windowController as! RandomWindowController).fullscreen;
break
default:
super.keyUp(with: event)
}
}
I think the above can be done much better & smarter... (picked up Swift a month ago...) but as the saying goes: "It worked on my computer!"
Hope it helps.

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

how to make jqgrid advanced search dialog keyboard accessible

Answer in how to enable enter in jqgrid advanced search window describes how to enable enter and other keys in jqgrid advanced search dialog.
After clicking Add group, Add subgrup, Delete rule or Delete group button in advanced search dialog Enter and other keys are still ignored. How set focus to added element or after delete remaining element to enable Enter and other keys?
The current version of the Advanced Searching dialog (see definition of jqFilter in the grid.filter.js) recreate all controls of the dialog on change of someone. See the code of reDraw which looks
this.reDraw = function() {
$("table.group:first",this).remove();
var t = this.createTableForGroup(p.filter, null);
$(this).append(t);
if($.isFunction(this.p.afterRedraw) ) {
this.p.afterRedraw.call(this, this.p);
}
};
How one can see the first line $("table.group:first",this).remove(); delete the content of all filter. The current focus will be lost and one have the problems which you described.
I suggest to fix the code of reDraw using document.activeElement element which was introduced in Internet Explorer originally (at least in IE4) and which is supported now in all web browsers because it's part of HTML5 standard (see here). The element which has focus originally will be destroyed and one will unable to set focus on it later. So I suggest to save the element name of the element and it's classes (like input.add-group or input.add-rule.ui-add) and to find the position of the element on the searching dialog. Later, after the dialog element will be recreated we'll set focus on the element with the same index.
I suggest to change the code of reDraw to the following
this.reDraw = function() {
var activeElement = document.activeElement, selector, $dialog, activeIndex = -1, $newElem, $buttons,
buttonClass,
getButtonClass = function (classNames) {
var arClasses = ['add-group', 'add-rule', 'delete-group', 'delete-rule'], i, n, className;
for (i = 0, n = classNames.length; i < n; i++) {
className = classNames[i];
if ($.inArray(className, arClasses) >= 0) {
return className;
}
}
return null;
};
if (activeElement) {
selector = activeElement.nodeName.toLowerCase();
buttonClass = getButtonClass(activeElement.className.split(' '));
if (buttonClass !== null) {
selector += '.' + buttonClass;
if (selector === "input.delete-rule") {
$buttons = $(activeElement).closest('table.group')
.find('input.add-rule,input.delete-rule');
activeIndex = $buttons.index(activeElement);
if (activeIndex > 0) {
// find the previous "add-rule" button
while (activeIndex--) {
$newElem = $($buttons[activeIndex]);
if ($newElem.hasClass("add-rule")) {
activeElement = $newElem[0];
selector = activeElement.nodeName.toLowerCase() + "." +
getButtonClass(activeElement.className.split(' '));
break;
}
}
}
} else if (selector === "input.delete-group") {
// change focus to "Add Rule" of the parent group
$newElem = $(activeElement).closest('table.group')
.parent()
.closest('table.group')
.find('input.add-rule');
if ($newElem.length > 1) {
activeElement = $newElem[$newElem.length-2];
selector = activeElement.nodeName.toLowerCase() + "." +
getButtonClass(activeElement.className.split(' '));
}
}
$dialog = $(activeElement).closest(".ui-jqdialog");
activeIndex = $dialog.find(selector).index(activeElement);
}
}
$("table.group:first",this).remove();
$(this).append(this.createTableForGroup(this.p.filter, null));
if($.isFunction(this.p.afterRedraw) ) {
this.p.afterRedraw.call(this, this.p);
}
if (activeElement && activeIndex >=0) {
$newElem = $dialog.find(selector + ":eq(" + activeIndex + ")");
if ($newElem.length>0) {
$newElem.focus();
} else {
$dialog.find("input.add-rule:first").focus();
}
}
};
Like one can see on the next demo the focus in the Searching Dialog stay unchanged after pressing on the "Add subgroup" or "Add rule" buttons. I set it on the "Add rule" buttons of the previous row group in case of pressing "Delete group".
One more demo use jQuery UI style of the buttons and the texts in the buttons (see the answer). After clicking on the "Delete" (rule or group) button I tried to set the focus to the previous "Add Rule" button because setting of the focus on another "Delete" (rule or group) button I find dangerous.
Additionally in the demo I use
afterShowSearch: function ($form) {
var $lastInput = $form.find(".input-elm:last");
if ($lastInput.length > 0) {
$lastInput.focus();
}
}
because it seems me meaningful to set initial focus on the last input field at the dialog opening.
UPDATED: I find additionally meaningful to set focus on the current clicked buttons "Add subgroup", "Add rule" or "Delete group". The advantage one sees in the case it one first click some button with the mouse and then want to continue the work with keyboard. So I suggest to change the line
inputAddSubgroup.bind('click',function() {
to
inputAddSubgroup.bind('click',function(e) {
$(e.target).focus();
To change the line
inputAddRule.bind('click',function() {
to
inputAddRule.bind('click',function(e) {
$(e.target).focus();
and the line
inputDeleteGroup.bind('click',function() {
to
inputDeleteGroup.bind('click',function(e) {
$(e.target).focus();
and the line
ruleDeleteInput.bind('click',function() {
to
ruleDeleteInput.bind('click',function(e) {
$(e.target).focus();

Binding selected radiobox to enabling checkbox in Cocoa

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]];

Resources