ui/cocoa/MainWindow.m

changeset 108
77254bd6dccb
parent 102
64ded9f6a6c6
child 109
c3dfcb8f0be7
equal deleted inserted replaced
107:b34bd1557c6c 108:77254bd6dccb
28 28
29 #import "MainWindow.h" 29 #import "MainWindow.h"
30 #import "Container.h" 30 #import "Container.h"
31 #import "GridLayout.h" 31 #import "GridLayout.h"
32 #import "../common/object.h" 32 #import "../common/object.h"
33 #import <objc/runtime.h>
34
35 #import "EventData.h"
36 #import "menu.h"
33 37
34 @implementation MainWindow 38 @implementation MainWindow
35 39
36 - (MainWindow*)init:(UiObject*)obj { 40 - (MainWindow*)init:(UiObject*)obj {
37 self.uiobj = obj;
38 NSRect frame = NSMakeRect(300, 200, 600, 500); 41 NSRect frame = NSMakeRect(300, 200, 600, 500);
39 42
40 self = [self initWithContentRect:frame 43 self = [self initWithContentRect:frame
41 styleMask:NSWindowStyleMaskTitled | 44 styleMask:NSWindowStyleMaskTitled |
42 NSWindowStyleMaskResizable | 45 NSWindowStyleMaskResizable |
61 64
62 return self; 65 return self;
63 } 66 }
64 67
65 @end 68 @end
69
70
71
72 @implementation MainWindowController
73
74 - (MainWindowController*)initWithWindow:(UiObject*)obj window:(NSWindow*)window {
75 self = [super initWithWindow:window];
76 _uiobj = obj;
77
78 self.checkItemStates = [[NSMutableDictionary alloc] init];
79 self.radioItems = [[NSMutableDictionary alloc] init];
80
81 // bind all stateful menu items (checkbox, radiobuttons, lists)
82 NSArray *menuBindItems = ui_get_binding_items(); // returns all items that require binding
83 for(MenuItem *item in menuBindItems) {
84 if(item.checkItem || item.radioItem) {
85 // simple check item (ui_menu_toggleitem_create)
86 UiVar *var = uic_widget_var(obj->ctx, obj->ctx, NULL, item.checkItem ? item.checkItem->varname : item.radioItem->varname, UI_VAR_INTEGER);
87 // create the state object for this item/window
88 MenuItemState *state = [[MenuItemState alloc] init];
89 state.mainWindow = self;
90 state.var = var;
91 if(var) {
92 UiInteger *i = var->value;
93 if(item.checkItem) {
94 // bind toggle item
95 state.state = (int)i->value;
96 i->obj = (__bridge void*)state;
97 i->get = ui_menu_check_item_get;
98 i->set = ui_menu_check_item_set;
99 } else {
100 // bind radio item
101 NSMutableArray *rgroup = nil;
102 if(i->obj) {
103 rgroup = (__bridge NSMutableArray*)i->obj;
104 } else {
105 // create a new rgroup array and register it in the window
106 rgroup = [[NSMutableArray alloc] init];
107 NSString *varname = [[NSString alloc] initWithUTF8String:item.radioItem->varname];
108 [_radioItems setObject:rgroup forKey:varname];
109 i->obj = (__bridge void*)rgroup;
110 }
111 i->get = ui_menu_radio_item_get;
112 i->set = ui_menu_radio_item_set;
113 [rgroup addObject:state]; // add this item state to the radio group
114 // i->value can contain a non-zero value, which means a specific radiobutton
115 // should be pre-selected
116 if(i->value == rgroup.count) {
117 state.state = NSControlStateValueOn;
118 }
119 }
120 } else {
121 state.state = 0;
122 }
123 [_checkItemStates setObject:state forKey:item.itemId];
124 }
125 }
126
127 return self;
128 }
129
130 - (void) windowDidLoad {
131 [self.window setNextResponder:self];
132 }
133
134 - (void)menuItemAction:(id)sender {
135 EventData *event = objc_getAssociatedObject(sender, "eventdata");
136 if(event) {
137 event.obj = self.uiobj; // temporary set the event object
138 [event handleEvent:sender];
139 }
140 }
141
142 - (void)menuCheckItemAction:(id)sender {
143 NSMenuItem *menuItem = sender;
144 MenuItem *item = objc_getAssociatedObject(sender, "menuitem");
145 if(!item || !item.checkItem) {
146 return;
147 }
148
149 MenuItemState *state = [_checkItemStates objectForKey:item.itemId];
150 state.state = state.state == NSControlStateValueOff ? NSControlStateValueOn : NSControlStateValueOff;
151 menuItem.state = state.state;
152
153 UiMenuCheckItem *it = item.checkItem;
154 if(it->callback) {
155 UiEvent event;
156 event.obj = _uiobj;
157 event.window = event.obj->window;
158 event.document = event.obj->ctx->document;
159 event.eventdata = state.var ? state.var->value : NULL;
160 event.intval = state.state;
161 it->callback(&event, it->userdata);
162 }
163 }
164
165 - (void)menuRadioItemAction:(id)sender {
166 NSMenuItem *menuItem = sender;
167 MenuItem *item = objc_getAssociatedObject(sender, "menuitem");
168 if(!item || !item.radioItem) {
169 return;
170 }
171
172 UiMenuRadioItem *it = item.radioItem;
173 if(!it->varname) {
174 return;
175 }
176
177 MenuItemState *state = [_checkItemStates objectForKey:item.itemId]; // current state of this menu item
178
179 NSString *varname = [[NSString alloc] initWithUTF8String:it->varname];
180 NSArray *radioGroup = [_radioItems objectForKey:varname];
181 if(!radioGroup) {
182 return;
183 }
184 int index = 1;
185 int value = 0;
186 for(MenuItemState *g in radioGroup) {
187 if(g == state) {
188 menuItem.state = NSControlStateValueOn;
189 g.state = NSControlStateValueOn;
190 value = index;
191 } else {
192 menuItem.state = NSControlStateValueOff;
193 g.state = NSControlStateValueOff;
194 }
195 }
196
197 if(it->callback) {
198 UiEvent event;
199 event.obj = _uiobj;
200 event.window = event.obj->window;
201 event.document = event.obj->ctx->document;
202 event.eventdata = state.var ? state.var->value : NULL;
203 event.intval = value;
204 it->callback(&event, it->userdata);
205 }
206 }
207
208
209 - (BOOL) validateMenuItem:(NSMenuItem *) menuItem {
210 MenuItem *item = objc_getAssociatedObject(menuItem, "menuitem");
211 if(item) {
212 MenuItemState *state = [_checkItemStates objectForKey:item.itemId];
213 if(state) {
214 menuItem.state = state.state;
215 } else {
216 menuItem.state = NSControlStateValueOff;
217 }
218 }
219
220 return YES;
221 }
222
223 @end
224
225 @implementation MenuItemState
226
227 @end
228
229 int64_t ui_menu_check_item_get(UiInteger *i) {
230 MenuItemState *state = (__bridge MenuItemState*)i->obj;
231 i->value = state.state;
232 return i->value;
233 }
234
235 void ui_menu_check_item_set(UiInteger *i, int64_t value) {
236 MenuItemState *state = (__bridge MenuItemState*)i->obj;
237 i->value = value;
238 state.state = (int)value;
239 }
240
241 int64_t ui_menu_radio_item_get(UiInteger *i) {
242 NSArray *rgroup = (__bridge NSArray*)i->obj;
243 i->value = 0;
244 int index = 1;
245 for(MenuItemState *state in rgroup) {
246 if(state.state == NSControlStateValueOn) {
247 i->value = index;
248 break;
249 }
250 index++;
251 }
252 return i->value;
253 }
254
255 void ui_menu_radio_item_set(UiInteger *i, int64_t value) {
256 NSArray *rgroup = (__bridge NSArray*)i->obj;
257 i->value = 0;
258 int index = 1;
259 for(MenuItemState *state in rgroup) {
260 state.state = value == index;
261 index++;
262 }
263 }

mercurial