diff options
Diffstat (limited to 'src/libui_sdl/libui/darwin/fontbutton.m')
-rw-r--r-- | src/libui_sdl/libui/darwin/fontbutton.m | 218 |
1 files changed, 218 insertions, 0 deletions
diff --git a/src/libui_sdl/libui/darwin/fontbutton.m b/src/libui_sdl/libui/darwin/fontbutton.m new file mode 100644 index 0000000..22bc646 --- /dev/null +++ b/src/libui_sdl/libui/darwin/fontbutton.m @@ -0,0 +1,218 @@ +// 14 april 2016 +#import "uipriv_darwin.h" + +@interface fontButton : NSButton { + uiFontButton *libui_b; + NSFont *libui_font; +} +- (id)initWithFrame:(NSRect)frame libuiFontButton:(uiFontButton *)b; +- (void)updateFontButtonLabel; +- (IBAction)fontButtonClicked:(id)sender; +- (void)activateFontButton; +- (void)deactivateFontButton:(BOOL)activatingAnother; +- (void)deactivateOnClose:(NSNotification *)note; +- (uiDrawTextFont *)libuiFont; +@end + +// only one may be active at one time +static fontButton *activeFontButton = nil; + +struct uiFontButton { + uiDarwinControl c; + fontButton *button; + void (*onChanged)(uiFontButton *, void *); + void *onChangedData; +}; + +@implementation fontButton + +- (id)initWithFrame:(NSRect)frame libuiFontButton:(uiFontButton *)b +{ + self = [super initWithFrame:frame]; + if (self) { + self->libui_b = b; + + // imitate a NSColorWell in appearance + [self setButtonType:NSPushOnPushOffButton]; + [self setBordered:YES]; + [self setBezelStyle:NSShadowlessSquareBezelStyle]; + + // default font values according to the CTFontDescriptor reference + // this is autoreleased (thanks swillits in irc.freenode.net/#macdev) + self->libui_font = [[NSFont fontWithName:@"Helvetica" size:12.0] retain]; + [self updateFontButtonLabel]; + + // for when clicked + [self setTarget:self]; + [self setAction:@selector(fontButtonClicked:)]; + } + return self; +} + +- (void)dealloc +{ + // clean up notifications + if (activeFontButton == self) + [self deactivateFontButton:NO]; + [self->libui_font release]; + [super dealloc]; +} + +- (void)updateFontButtonLabel +{ + NSString *title; + + title = [NSString stringWithFormat:@"%@ %g", + [self->libui_font displayName], + [self->libui_font pointSize]]; + [self setTitle:title]; +} + +- (IBAction)fontButtonClicked:(id)sender +{ + if ([self state] == NSOnState) + [self activateFontButton]; + else + [self deactivateFontButton:NO]; +} + +- (void)activateFontButton +{ + NSFontManager *sfm; + + sfm = [NSFontManager sharedFontManager]; + if (activeFontButton != nil) + [activeFontButton deactivateFontButton:YES]; + [sfm setTarget:self]; + [sfm setSelectedFont:self->libui_font isMultiple:NO]; + [sfm orderFrontFontPanel:self]; + activeFontButton = self; + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(deactivateOnClose:) + name:NSWindowWillCloseNotification + object:[NSFontPanel sharedFontPanel]]; + [self setState:NSOnState]; +} + +- (void)deactivateFontButton:(BOOL)activatingAnother +{ + NSFontManager *sfm; + + sfm = [NSFontManager sharedFontManager]; + [sfm setTarget:nil]; + if (!activatingAnother) + [[NSFontPanel sharedFontPanel] orderOut:self]; + activeFontButton = nil; + [[NSNotificationCenter defaultCenter] removeObserver:self + name:NSWindowWillCloseNotification + object:[NSFontPanel sharedFontPanel]]; + [self setState:NSOffState]; +} + +- (void)deactivateOnClose:(NSNotification *)note +{ + [self deactivateFontButton:NO]; +} + +- (void)changeFont:(id)sender +{ + NSFontManager *fm; + NSFont *old; + uiFontButton *b = self->libui_b; + + fm = (NSFontManager *) sender; + old = self->libui_font; + self->libui_font = [sender convertFont:self->libui_font]; + // do this even if it returns the same; we don't own anything that isn't from a new or alloc/init + [self->libui_font retain]; + // do this second just in case + [old release]; + [self updateFontButtonLabel]; + (*(b->onChanged))(b, b->onChangedData); +} + +- (NSUInteger)validModesForFontPanel:(NSFontPanel *)panel +{ + return NSFontPanelFaceModeMask | + NSFontPanelSizeModeMask | + NSFontPanelCollectionModeMask; +} + +- (uiDrawTextFont *)libuiFont +{ + return mkTextFontFromNSFont(self->libui_font); +} + +@end + +uiDarwinControlAllDefaults(uiFontButton, button) + +// we do not want font change events to be sent to any controls other than the font buttons +// see main.m for more details +BOOL fontButtonInhibitSendAction(SEL sel, id from, id to) +{ + if (sel != @selector(changeFont:)) + return NO; + return ![to isKindOfClass:[fontButton class]]; +} + +// we do not want NSFontPanelValidation messages to be sent to any controls other than the font buttons when a font button is active +// see main.m for more details +BOOL fontButtonOverrideTargetForAction(SEL sel, id from, id to, id *override) +{ + if (activeFontButton == nil) + return NO; + if (sel != @selector(validModesForFontPanel:)) + return NO; + *override = activeFontButton; + return YES; +} + +// we also don't want the panel to be usable when there's a dialog running; see stddialogs.m for more details on that +// unfortunately the panel seems to ignore -setWorksWhenModal: so we'll have to do things ourselves +@interface nonModalFontPanel : NSFontPanel +@end + +@implementation nonModalFontPanel + +- (BOOL)worksWhenModal +{ + return NO; +} + +@end + +void setupFontPanel(void) +{ + [NSFontManager setFontPanelFactory:[nonModalFontPanel class]]; +} + +static void defaultOnChanged(uiFontButton *b, void *data) +{ + // do nothing +} + +uiDrawTextFont *uiFontButtonFont(uiFontButton *b) +{ + return [b->button libuiFont]; +} + +void uiFontButtonOnChanged(uiFontButton *b, void (*f)(uiFontButton *, void *), void *data) +{ + b->onChanged = f; + b->onChangedData = data; +} + +uiFontButton *uiNewFontButton(void) +{ + uiFontButton *b; + + uiDarwinNewControl(uiFontButton, b); + + b->button = [[fontButton alloc] initWithFrame:NSZeroRect libuiFontButton:b]; + uiDarwinSetControlFont(b->button, NSRegularControlSize); + + uiFontButtonOnChanged(b, defaultOnChanged, NULL); + + return b; +} |