From bf411e787e8c20d55e0351fe463e8619f226ddf5 Mon Sep 17 00:00:00 2001 From: Pietro Gagliardi Date: Sun, 15 May 2016 20:51:33 -0400 Subject: [PATCH] Implemented uiColorButton on OS X. --- common/controlsigs.h | 1 + darwin/GNUfiles.mk | 1 + darwin/colorbutton.m | 148 +++++++++++++++++++++++++++++++++++++++++ darwin/main.m | 2 + darwin/uipriv_darwin.h | 3 + test/page10.c | 8 +-- ui.h | 2 +- 7 files changed, 160 insertions(+), 5 deletions(-) create mode 100644 darwin/colorbutton.m diff --git a/common/controlsigs.h b/common/controlsigs.h index 598e7342..dc984329 100644 --- a/common/controlsigs.h +++ b/common/controlsigs.h @@ -4,6 +4,7 @@ #define uiBoxSignature 0x426F784C #define uiButtonSignature 0x42746F6E #define uiCheckboxSignature 0x43686B62 +#define uiColorButtonSignature 0x436F6C42 #define uiComboboxSignature 0x436F6D62 #define uiDateTimePickerSignature 0x44545069 #define uiEntrySignature 0x456E7472 diff --git a/darwin/GNUfiles.mk b/darwin/GNUfiles.mk index 1ddbeebc..810ddd16 100644 --- a/darwin/GNUfiles.mk +++ b/darwin/GNUfiles.mk @@ -8,6 +8,7 @@ MFILES += \ darwin/box.m \ darwin/button.m \ darwin/checkbox.m \ + darwin/colorbutton.m \ darwin/combobox.m \ darwin/control.m \ darwin/datetimepicker.m \ diff --git a/darwin/colorbutton.m b/darwin/colorbutton.m new file mode 100644 index 00000000..47f8511e --- /dev/null +++ b/darwin/colorbutton.m @@ -0,0 +1,148 @@ +// 15 may 2016 +#import "uipriv_darwin.h" + +@interface colorButton : NSColorWell { + uiColorButton *libui_b; + BOOL libui_changing; +} +- (id)initWithFrame:(NSRect)frame libuiColorButton:(uiColorButton *)b; +- (void)deactivateOnClose:(NSNotification *)note; +- (void)libuiColor:(double *)r g:(double *)g b:(double *)b a:(double *)a; +- (void)libuiSetColor:(double)r g:(double)g b:(double)b a:(double)a; +@end + +// only one may be active at one time +static colorButton *activeColorButton = nil; + +struct uiColorButton { + uiDarwinControl c; + colorButton *button; + void (*onChanged)(uiColorButton *, void *); + void *onChangedData; +}; + +@implementation colorButton + +- (id)initWithFrame:(NSRect)frame libuiColorButton:(uiColorButton *)b +{ + self = [super initWithFrame:frame]; + if (self) { + // the default color is white; set it to black first (see -setColor: below for why we do it first) + [self libuiSetColor:0.0 g:0.0 b:0.0 a:1.0]; + + self->libui_b = b; + self->libui_changing = NO; + } + return self; +} + +- (void)activate:(BOOL)exclusive +{ + if (activeColorButton != nil) + activeColorButton->libui_changing = YES; + [NSColorPanel setPickerMask:NSColorPanelAllModesMask]; + [[NSColorPanel sharedColorPanel] setShowsAlpha:YES]; + [super activate:YES]; + activeColorButton = self; + // TODO try setWorksWhenModal (I'd need a color well there) + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(deactivateOnClose:) + name:NSWindowWillCloseNotification + object:[NSColorPanel sharedColorPanel]]; +} + +- (void)deactivate +{ + [super deactivate]; + activeColorButton = nil; + if (!self->libui_changing) + [[NSColorPanel sharedColorPanel] orderOut:nil]; + [[NSNotificationCenter defaultCenter] removeObserver:self + name:NSWindowWillCloseNotification + object:[NSColorPanel sharedColorPanel]]; + self->libui_changing = NO; +} + +- (void)deactivateOnClose:(NSNotification *)note +{ + [self deactivate]; +} + +- (void)setColor:(NSColor *)color +{ + uiColorButton *b = self->libui_b; + + [super setColor:color]; + // this is called by NSColorWell's init, so we have to guard + if (b != nil) + (*(b->onChanged))(b, b->onChangedData); +} + +- (void)libuiColor:(double *)r g:(double *)g b:(double *)b a:(double *)a +{ + NSColor *rgba; + CGFloat cr, cg, cb, ca; + + // the given color may not be an RGBA color, which will cause the -getRed:green:blue:alpha: call to throw an exception + // TODO device RGB space? + rgba = [[self color] colorUsingColorSpaceName:NSCalibratedRGBColorSpace]; + [rgba getRed:&cr green:&cg blue:&cb alpha:&ca]; + *r = cr; + *g = cg; + *b = cb; + *a = ca; + // rgba will be autoreleased since it isn't a new or init call +} + +- (void)libuiSetColor:(double)r g:(double)g b:(double)b a:(double)a +{ + // TODO does this set the panel color? does it send a signal? + [self setColor:[NSColor colorWithRed:r green:g blue:b alpha:a]]; +} + +@end + +uiDarwinControlAllDefaults(uiColorButton, button) + +// we do not want color change events to be sent to any controls other than the color buttons +// see main.m for more details +BOOL colorButtonInhibitSendAction(SEL sel, id from, id to) +{ + if (sel != @selector(changeColor:)) + return NO; + return ![to isKindOfClass:[colorButton class]]; +} + +static void defaultOnChanged(uiColorButton *b, void *data) +{ + // do nothing +} + +void uiColorButtonColor(uiColorButton *b, double *r, double *g, double *bl, double *a) +{ + [b->button libuiColor:r g:g b:bl a:a]; +} + +void uiColorButtonSetColor(uiColorButton *b, double r, double g, double bl, double a) +{ + [b->button libuiSetColor:r g:g b:bl a:a]; +} + +void uiColorButtonOnChanged(uiColorButton *b, void (*f)(uiColorButton *, void *), void *data) +{ + b->onChanged = f; + b->onChangedData = data; +} + +uiColorButton *uiNewColorButton(void) +{ + uiColorButton *b; + + uiDarwinNewControl(uiColorButton, b); + + b->button = [[colorButton alloc] initWithFrame:NSZeroRect libuiColorButton:b]; + + uiColorButtonOnChanged(b, defaultOnChanged, NULL); + + return b; +} diff --git a/darwin/main.m b/darwin/main.m index bd939d4a..fa0e5782 100644 --- a/darwin/main.m +++ b/darwin/main.m @@ -18,6 +18,8 @@ static BOOL canQuit = NO; // it turns out NSFontManager also sends changeFont: through this; let's inhibit that here too (see fontbutton.m) - (BOOL)sendAction:(SEL)sel to:(id)to from:(id)from { + if (colorButtonInhibitSendAction(sel, from, to)) + return NO; if (fontButtonInhibitSendAction(sel, from, to)) return NO; return [super sendAction:sel to:to from:from]; diff --git a/darwin/uipriv_darwin.h b/darwin/uipriv_darwin.h index 2bfaaf20..2afded8f 100644 --- a/darwin/uipriv_darwin.h +++ b/darwin/uipriv_darwin.h @@ -110,3 +110,6 @@ extern void doDrawText(CGContextRef c, CGFloat cheight, double x, double y, uiDr extern BOOL fontButtonInhibitSendAction(SEL sel, id from, id to); extern BOOL fontButtonOverrideTargetForAction(SEL sel, id from, id to, id *override); extern void setupFontPanel(void); + +// colorbutton.m +extern BOOL colorButtonInhibitSendAction(SEL sel, id from, id to); diff --git a/test/page10.c b/test/page10.c index 69191860..0262c815 100644 --- a/test/page10.c +++ b/test/page10.c @@ -6,7 +6,7 @@ static uiEntry *textString; static uiFontButton *textFontButton; -static uiFontButton *textColorButton; +static uiColorButton *textColorButton; static uiEntry *textWidth; static uiButton *textApply; static uiCheckbox *addLeading; @@ -28,7 +28,7 @@ static void handlerDraw(uiAreaHandler *a, uiArea *area, uiAreaDrawParams *dp) { uiDrawTextFont *font; uiDrawTextLayout *layout; - double, r, g, b, a; + double r, g, b, al; font = uiFontButtonFont(textFontButton); @@ -39,10 +39,10 @@ static void handlerDraw(uiAreaHandler *a, uiArea *area, uiAreaDrawParams *dp) uiDrawTextLayoutSetColor(layout, 8, 14, 1, 0, 0.5, 0.5); - uiColorButtonColor(textColorButton, &r, &g, &b, &a); + uiColorButtonColor(textColorButton, &r, &g, &b, &al); uiDrawTextLayoutSetColor(layout, 14, 18, - r, g, b, a); + r, g, b, al); uiDrawText(dp->Context, 10, 10, layout); uiDrawFreeTextLayout(layout); diff --git a/ui.h b/ui.h index 935c09a1..3968f01c 100644 --- a/ui.h +++ b/ui.h @@ -593,7 +593,7 @@ _UI_EXTERN uiFontButton *uiNewFontButton(void); typedef struct uiColorButton uiColorButton; #define uiColorButton(this) ((uiColorButton *) (this)) _UI_EXTERN void uiColorButtonColor(uiColorButton *b, double *r, double *g, double *bl, double *a); -_UI_EXTERN void uiColorButtonSetColor(uiColorButton *b, double r, double g, double b, double a); +_UI_EXTERN void uiColorButtonSetColor(uiColorButton *b, double r, double g, double bl, double a); _UI_EXTERN void uiColorButtonOnChanged(uiColorButton *b, void (*f)(uiColorButton *, void *), void *data); _UI_EXTERN uiColorButton *uiNewColorButton(void);