aboutsummaryrefslogtreecommitdiff
path: root/src/libui_sdl/libui/darwin/fontbutton.m
diff options
context:
space:
mode:
Diffstat (limited to 'src/libui_sdl/libui/darwin/fontbutton.m')
-rw-r--r--src/libui_sdl/libui/darwin/fontbutton.m218
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;
+}