// 14 april 2016 #import "uipriv_darwin.h" // TODO drag and drop fonts? what other interactions does NSColorWell allow that we can do for fonts? // TODO make position of templates consistent @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; - (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; }; uiDarwinDefineControl( uiFontButton, // type name button // handle ) @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)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; [self setState:NSOnState]; } - (void)deactivateFontButton:(BOOL)activatingAnother { NSFontManager *sfm; sfm = [NSFontManager sharedFontManager]; [sfm setTarget:nil]; if (!activatingAnother) [[NSFontPanel sharedFontPanel] orderOut:self]; activeFontButton = nil; [self setState:NSOffState]; } - (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]; // TODO do we get it back retained? // TODO is it even retained when we get it, regardless of value? if (self->libui_font != old) [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 // 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; } 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; b = (uiFontButton *) uiNewControl(uiFontButtonType()); b->button = [[fontButton alloc] initWithFrame:NSZeroRect libuiFontButton:b]; uiDarwinSetControlFont(b->button, NSRegularControlSize); uiFontButtonOnChanged(b, defaultOnChanged, NULL); uiDarwinFinishNewControl(b, uiFontButton); return b; }