Switched from NSPopover for the TextField.Invalid() warning on Mac OS X to a custom window subclass.
This commit is contained in:
parent
83f423a43e
commit
a9961feb2c
|
@ -7,7 +7,7 @@
|
|||
#define toNSButton(x) ((NSButton *) (x))
|
||||
#define toNSTextField(x) ((NSTextField *) (x))
|
||||
#define toNSView(x) ((NSView *) (x))
|
||||
#define toNSPopover(x) ((NSPopover *) (x))
|
||||
#define toNSWindow(x) ((NSWindow *) (x))
|
||||
#define toNSBox(x) ((NSBox *) (x))
|
||||
|
||||
@interface goControlDelegate : NSObject <NSTextFieldDelegate> {
|
||||
|
@ -168,18 +168,18 @@ void textFieldSetText(id t, char *text)
|
|||
|
||||
id textfieldOpenInvalidPopover(id textfield, char *reason)
|
||||
{
|
||||
NSPopover *popover;
|
||||
id popover;
|
||||
|
||||
popover = (NSPopover *) newWarningPopover(reason);
|
||||
[popover showRelativeToRect:NSZeroRect ofView:toNSView(textfield) preferredEdge:NSMaxYEdge];
|
||||
popover = newWarningPopover(reason);
|
||||
warningPopoverShow(popover, textfield);
|
||||
NSBeep();
|
||||
return (id) popover;
|
||||
}
|
||||
|
||||
void textfieldCloseInvalidPopover(id popover)
|
||||
{
|
||||
[toNSPopover(popover) close];
|
||||
[toNSPopover(popover) release];
|
||||
[toNSWindow(popover) orderOut:toNSWindow(popover)];
|
||||
[toNSWindow(popover) release];
|
||||
}
|
||||
|
||||
id newLabel(void)
|
||||
|
|
|
@ -145,5 +145,6 @@ extern void openFile(id, void *);
|
|||
|
||||
/* warningpopover_darwin.m */
|
||||
extern id newWarningPopover(char *);
|
||||
extern void warningPopoverShow(id, id);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -48,7 +48,6 @@ func (t *textfield) OnChanged(f func()) {
|
|||
|
||||
func (t *textfield) Invalid(reason string) {
|
||||
// TODO disable animations if reason is still valid
|
||||
// TODO don't steal focus
|
||||
if t.invalid != nil {
|
||||
C.textfieldCloseInvalidPopover(t.invalid)
|
||||
t.invalid = nil
|
||||
|
|
|
@ -3,6 +3,48 @@
|
|||
#include "objc_darwin.h"
|
||||
#include <Cocoa/Cocoa.h>
|
||||
|
||||
// We would be able to just use plain old NSPopover here, but alas that steals focus.
|
||||
// NSPopovers are intended for interactive content, and Apple seems to be diligent in enforcing this rule, as the known techniques for preventing a NSPopover from stealing focus no longer work in 10.9.
|
||||
// Let's just fake it with a window.
|
||||
|
||||
// TODO
|
||||
// - doesn't get hidden properly when asked to order out
|
||||
// - doesn't get hidden when changing first responders
|
||||
// - doesn't get hidden when switching between programs/shown again
|
||||
// - doesn't animate or have a transparent background; probably should
|
||||
|
||||
@interface goWarningPopover : NSWindow
|
||||
@end
|
||||
|
||||
@implementation goWarningPopover
|
||||
|
||||
- (id)init
|
||||
{
|
||||
self = [super initWithContentRect:NSZeroRect
|
||||
styleMask:NSBorderlessWindowMask
|
||||
backing:NSBackingStoreBuffered
|
||||
defer:YES];
|
||||
[self setOpaque:NO];
|
||||
// [self setAlphaValue:0.1];
|
||||
[self setHasShadow:YES];
|
||||
[self setExcludedFromWindowsMenu:YES];
|
||||
[self setMovableByWindowBackground:NO];
|
||||
[self setLevel:NSPopUpMenuWindowLevel];
|
||||
return self;
|
||||
}
|
||||
|
||||
- (BOOL)canBecomeKeyWindow
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (BOOL)canBecomeMainWindow
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@interface goWarningView : NSView {
|
||||
@public
|
||||
NSImageView *icon;
|
||||
|
@ -65,14 +107,24 @@ id newWarningPopover(char *text)
|
|||
[wv addSubview:wv->label];
|
||||
[wv sizeToFitAndArrange];
|
||||
|
||||
NSPopover *popover;
|
||||
NSViewController *vc;
|
||||
goWarningPopover *popover;
|
||||
|
||||
vc = [NSViewController new];
|
||||
[vc setView:wv];
|
||||
popover = [NSPopover new];
|
||||
[popover setContentViewController:vc];
|
||||
popover = [[goWarningPopover alloc] init]; // explicitly use our initializer
|
||||
[[popover contentView] addSubview:wv];
|
||||
[popover setContentSize:[wv frame].size];
|
||||
|
||||
return (id) popover;
|
||||
}
|
||||
|
||||
void warningPopoverShow(id popover, id control)
|
||||
{
|
||||
goWarningPopover *p = (goWarningPopover *) popover;
|
||||
NSView *v = (NSView *) control;
|
||||
NSRect vr;
|
||||
NSPoint vo;
|
||||
|
||||
vr = [v convertRect:[v frame] toView:nil];
|
||||
vo = [[v window] convertRectToScreen:vr].origin;
|
||||
[p setFrameOrigin:NSMakePoint(vo.x, vo.y - [p frame].size.height)];
|
||||
[p orderFront:p];
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue