1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
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;
}
|