| |
1 /* |
| |
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. |
| |
3 * |
| |
4 * Copyright 2025 Olaf Wintermann. All rights reserved. |
| |
5 * |
| |
6 * Redistribution and use in source and binary forms, with or without |
| |
7 * modification, are permitted provided that the following conditions are met: |
| |
8 * |
| |
9 * 1. Redistributions of source code must retain the above copyright |
| |
10 * notice, this list of conditions and the following disclaimer. |
| |
11 * |
| |
12 * 2. Redistributions in binary form must reproduce the above copyright |
| |
13 * notice, this list of conditions and the following disclaimer in the |
| |
14 * documentation and/or other materials provided with the distribution. |
| |
15 * |
| |
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
| |
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| |
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| |
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
| |
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| |
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| |
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| |
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
| |
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| |
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
| |
26 * POSSIBILITY OF SUCH DAMAGE. |
| |
27 */ |
| |
28 |
| |
29 #import "Toolbar.h" |
| |
30 #import "EventData.h" |
| |
31 #import "image.h" |
| |
32 #import "menu.h" |
| |
33 #import <objc/runtime.h> |
| |
34 |
| |
35 #include "../common/toolbar.h" |
| |
36 |
| |
37 |
| |
38 void ui_toolbar_init(void) { |
| |
39 |
| |
40 } |
| |
41 |
| |
42 |
| |
43 |
| |
44 /* --------------------- UiToolbar --------------------- */ |
| |
45 |
| |
46 @implementation UiToolbar |
| |
47 |
| |
48 - (UiToolbar*) initWithObject:(UiObject*)object { |
| |
49 self = [super initWithIdentifier:@"UiToolbar"]; |
| |
50 _obj = object; |
| |
51 |
| |
52 allowedItems = [[NSMutableArray alloc]initWithCapacity:16]; |
| |
53 defaultItems = [[NSMutableArray alloc]initWithCapacity:16]; |
| |
54 |
| |
55 CxMap *toolbarItems = uic_get_toolbar_items(); |
| |
56 CxMapIterator i = cxMapIteratorKeys(toolbarItems); |
| |
57 cx_foreach(CxHashKey *, key, i) { |
| |
58 NSString *s = [[NSString alloc]initWithBytes:key->data length:key->len encoding:NSUTF8StringEncoding]; |
| |
59 [allowedItems addObject:s]; |
| |
60 } |
| |
61 [allowedItems addObject: NSToolbarFlexibleSpaceItemIdentifier]; |
| |
62 [allowedItems addObject: NSToolbarSpaceItemIdentifier]; |
| |
63 |
| |
64 CxList *tbitems[3]; |
| |
65 tbitems[0] = uic_get_toolbar_defaults(UI_TOOLBAR_LEFT); |
| |
66 tbitems[1] = uic_get_toolbar_defaults(UI_TOOLBAR_CENTER); |
| |
67 tbitems[2] = uic_get_toolbar_defaults(UI_TOOLBAR_RIGHT); |
| |
68 for(int t=0;t<3;t++) { |
| |
69 CxIterator iter = cxListIterator(tbitems[t]); |
| |
70 cx_foreach(char *, name, iter) { |
| |
71 NSString *s = [[NSString alloc] initWithUTF8String:name]; |
| |
72 [defaultItems addObject:s]; |
| |
73 } |
| |
74 } |
| |
75 |
| |
76 [self setDelegate:self]; |
| |
77 [self setAllowsUserCustomization:YES]; |
| |
78 return self; |
| |
79 } |
| |
80 |
| |
81 // implementation of NSToolbarDelegate methods |
| |
82 |
| |
83 - (NSArray *)toolbarAllowedItemIdentifiers:(NSToolbar *)toolbar { |
| |
84 return allowedItems; |
| |
85 } |
| |
86 |
| |
87 - (NSArray *)toolbarDefaultItemIdentifiers:(NSToolbar *)toolbar { |
| |
88 return defaultItems; |
| |
89 } |
| |
90 |
| |
91 - (NSToolbarItem *)toolbar:(NSToolbar *)toolbar |
| |
92 itemForItemIdentifier:(NSString *)itemIdentifier |
| |
93 willBeInsertedIntoToolbar:(BOOL)flag { |
| |
94 CxMap *items = uic_get_toolbar_items(); |
| |
95 UiToolbarItemI *item = cxMapGet(items, itemIdentifier.UTF8String); |
| |
96 if(!item) { |
| |
97 return nil; |
| |
98 } |
| |
99 |
| |
100 switch(item->type) { |
| |
101 default: return nil; |
| |
102 case UI_TOOLBAR_ITEM: { |
| |
103 return ui_nstoolbaritem_create_item(_obj, (UiToolbarItem*)item, itemIdentifier); |
| |
104 } |
| |
105 case UI_TOOLBAR_TOGGLEITEM: { |
| |
106 return ui_nstoolbaritem_create_toggle(_obj, (UiToolbarToggleItem*)item, itemIdentifier); |
| |
107 } |
| |
108 case UI_TOOLBAR_MENU: { |
| |
109 return ui_nstoolbaritem_create_menu(_obj, (UiToolbarMenuItem*)item, itemIdentifier); |
| |
110 } |
| |
111 } |
| |
112 |
| |
113 return nil; |
| |
114 } |
| |
115 |
| |
116 @end |
| |
117 |
| |
118 @implementation UiToolbarToggleEventHandler |
| |
119 |
| |
120 - (UiToolbarToggleEventHandler*)init { |
| |
121 return self; |
| |
122 } |
| |
123 |
| |
124 - (void)handleEvent:(id)sender { |
| |
125 if(_callback == nil) { |
| |
126 return; |
| |
127 } |
| |
128 |
| |
129 UiEvent event; |
| |
130 event.obj = _obj; |
| |
131 event.window = event.obj->window; |
| |
132 event.document = event.obj->ctx->document; |
| |
133 event.eventdata = NULL; |
| |
134 event.eventdatatype = 0; |
| |
135 event.intval = 0; |
| |
136 event.set = ui_get_setop(); |
| |
137 |
| |
138 if([sender isKindOfClass:[NSSegmentedControl class]]) { |
| |
139 NSSegmentedControl *seg = (NSSegmentedControl*)sender; |
| |
140 event.intval = [seg isSelectedForSegment:0]; |
| |
141 } |
| |
142 |
| |
143 _callback(&event, _userdata); |
| |
144 } |
| |
145 |
| |
146 @end |
| |
147 |
| |
148 NSToolbarItem* ui_nstoolbaritem_create_item(UiObject *obj, UiToolbarItem *item, NSString *identifier) { |
| |
149 NSToolbarItem *button = [[NSToolbarItem alloc] initWithItemIdentifier: identifier]; |
| |
150 button.bordered = YES; |
| |
151 |
| |
152 if(item->args.label) { |
| |
153 NSString *label = [[NSString alloc] initWithUTF8String:item->args.label]; |
| |
154 button.paletteLabel = label; |
| |
155 button.label = label; |
| |
156 } |
| |
157 if(item->args.icon) { |
| |
158 button.image = ui_cocoa_named_icon(item->args.icon); |
| |
159 } |
| |
160 |
| |
161 if(item->args.onclick) { |
| |
162 EventData *event = [[EventData alloc] init:item->args.onclick userdata:item->args.onclickdata]; |
| |
163 event.obj = obj; |
| |
164 button.target = event; |
| |
165 button.action = @selector(handleEvent:); |
| |
166 objc_setAssociatedObject(button, "eventdata", event, OBJC_ASSOCIATION_RETAIN); |
| |
167 } |
| |
168 return button; |
| |
169 } |
| |
170 |
| |
171 NSToolbarItem* ui_nstoolbaritem_create_toggle(UiObject *obj, UiToolbarToggleItem *item, NSString *identifier) { |
| |
172 UiToolbarToggleEventHandler *event = [[UiToolbarToggleEventHandler alloc]init]; |
| |
173 event.obj = obj; |
| |
174 event.callback = item->args.onchange; |
| |
175 event.userdata = item->args.onchangedata; |
| |
176 |
| |
177 NSToolbarItem *button = [[NSToolbarItem alloc] initWithItemIdentifier:identifier]; |
| |
178 if(item->args.label) { |
| |
179 NSString *label = [[NSString alloc] initWithUTF8String:item->args.label]; |
| |
180 button.paletteLabel = label; |
| |
181 button.label = label; |
| |
182 } |
| |
183 objc_setAssociatedObject(button, "eventdata", event, OBJC_ASSOCIATION_RETAIN); |
| |
184 |
| |
185 NSSegmentedControl *seg; |
| |
186 if(!item->args.icon) { |
| |
187 NSArray *labels = @[[[NSString alloc] initWithUTF8String:item->args.label]]; |
| |
188 seg = [NSSegmentedControl segmentedControlWithLabels:labels trackingMode:NSSegmentSwitchTrackingSelectAny target:event action:@selector(handleEvent:)]; |
| |
189 button.view = seg; |
| |
190 } else { |
| |
191 NSArray *images = @[ui_cocoa_named_icon(item->args.icon)]; |
| |
192 seg = [NSSegmentedControl segmentedControlWithImages:images trackingMode:NSSegmentSwitchTrackingSelectAny target:event action:@selector(handleEvent:)]; |
| |
193 } |
| |
194 button.view = seg; |
| |
195 |
| |
196 UiVar* var = uic_widget_var(obj->ctx, obj->ctx, NULL, item->args.varname, UI_VAR_INTEGER); |
| |
197 if(var) { |
| |
198 event.var = var; |
| |
199 UiInteger *i = var->value; |
| |
200 if(i->get) { |
| |
201 if(ui_get(i) != 0) { |
| |
202 [seg setEnabled:YES forSegment:0]; |
| |
203 } |
| |
204 |
| |
205 } |
| |
206 i->obj = (__bridge void*)seg; |
| |
207 i->get = ui_toolbar_seg_toggleitem_get; |
| |
208 i->set = ui_toolbar_seg_toggleitem_set; |
| |
209 } |
| |
210 |
| |
211 return button; |
| |
212 } |
| |
213 |
| |
214 int64_t ui_toolbar_seg_toggleitem_get(UiInteger *i) { |
| |
215 NSSegmentedControl *seg = (__bridge NSSegmentedControl*)i->obj; |
| |
216 i->value = [seg isSelectedForSegment:0]; |
| |
217 return i->value; |
| |
218 } |
| |
219 |
| |
220 void ui_toolbar_seg_toggleitem_set(UiInteger *i, int64_t value) { |
| |
221 NSSegmentedControl *seg = (__bridge NSSegmentedControl*)i->obj; |
| |
222 i->value = value; |
| |
223 [seg setSelected:value != 0 forSegment:0]; |
| |
224 } |
| |
225 |
| |
226 NSToolbarItem* ui_nstoolbaritem_create_menu(UiObject *obj, UiToolbarMenuItem *item, NSString *identifier) { |
| |
227 NSMenuToolbarItem *button = [[NSMenuToolbarItem alloc] initWithItemIdentifier: identifier]; |
| |
228 button.bordered = YES; |
| |
229 |
| |
230 if(item->args.label) { |
| |
231 NSString *label = [[NSString alloc] initWithUTF8String:item->args.label]; |
| |
232 button.paletteLabel = label; |
| |
233 button.label = label; |
| |
234 } |
| |
235 if(item->args.icon) { |
| |
236 button.image = ui_cocoa_named_icon(item->args.icon); |
| |
237 } |
| |
238 |
| |
239 NSMenu *menu = [[NSMenu alloc] initWithTitle:@""]; |
| |
240 ui_add_menu_items(obj, menu, 0, &item->menu); |
| |
241 |
| |
242 button.menu = menu; |
| |
243 |
| |
244 return button; |
| |
245 } |