| 28 |
28 |
| 29 #import "window.h" |
29 #import "window.h" |
| 30 |
30 |
| 31 #import "MainWindow.h" |
31 #import "MainWindow.h" |
| 32 #import "WindowManager.h" |
32 #import "WindowManager.h" |
| |
33 #import "BoxContainer.h" |
| |
34 #import "EventData.h" |
| 33 |
35 |
| 34 #import <objc/runtime.h> |
36 #import <objc/runtime.h> |
| 35 |
37 |
| 36 #include "../ui/window.h" |
38 #include "../ui/window.h" |
| 37 #include "../ui/properties.h" |
39 #include "../ui/properties.h" |
| 38 #include "../common/context.h" |
40 #include "../common/context.h" |
| 39 #include "../common/menu.h" |
41 #include "../common/menu.h" |
| 40 #include "../common/toolbar.h" |
42 #include "../common/toolbar.h" |
| |
43 #include "../common/object.h" |
| 41 |
44 |
| 42 #include <cx/mempool.h> |
45 #include <cx/mempool.h> |
| 43 |
46 |
| 44 |
47 |
| 45 static UiObject* create_window(const char *title, BOOL simple, BOOL sidebar) { |
48 static UiObject* create_window(const char *title, BOOL simple, BOOL sidebar, BOOL splitview) { |
| 46 CxMempool *mp = cxMempoolCreateSimple(256); |
49 UiObject *obj = uic_object_new_toplevel(); |
| 47 UiObject *obj = cxCalloc(mp->allocator, 1, sizeof(UiObject)); |
50 |
| 48 obj->ref = 0; |
51 MainWindow *window = [[MainWindow alloc] init:obj withSidebar:sidebar withSplitview:splitview]; |
| 49 |
|
| 50 obj->ctx = uic_context(obj, mp); |
|
| 51 |
|
| 52 MainWindow *window = [[MainWindow alloc] init:obj withSidebar:sidebar]; |
|
| 53 [[WindowManager sharedWindowManager] addWindow:window]; |
52 [[WindowManager sharedWindowManager] addWindow:window]; |
| 54 window.releasedWhenClosed = false; |
53 window.releasedWhenClosed = false; // TODO: we still need a cleanup strategy |
| 55 |
54 |
| 56 obj->wobj = (__bridge void*)window; |
55 obj->wobj = (__bridge void*)window; |
| 57 |
56 |
| 58 MainWindowController *controller = [[MainWindowController alloc] initWithWindow:obj window:window]; |
57 MainWindowController *controller = [[MainWindowController alloc] initWithWindow:obj window:window]; |
| 59 window.windowController = controller; |
58 window.windowController = controller; |
| 62 |
61 |
| 63 return obj; |
62 return obj; |
| 64 } |
63 } |
| 65 |
64 |
| 66 UiObject* ui_window(const char *title, void *window_data) { |
65 UiObject* ui_window(const char *title, void *window_data) { |
| 67 UiObject *obj = create_window(title, FALSE, FALSE); |
66 UiObject *obj = create_window(title, FALSE, FALSE, FALSE); |
| 68 obj->window = window_data; |
67 obj->window = window_data; |
| 69 return obj; |
68 return obj; |
| 70 } |
69 } |
| 71 |
70 |
| 72 UiObject* ui_simple_window(const char *title, void *window_data) { |
71 UiObject* ui_simple_window(const char *title, void *window_data) { |
| 73 UiObject *obj = create_window(title, TRUE, FALSE); |
72 UiObject *obj = create_window(title, TRUE, FALSE, FALSE); |
| 74 obj->window = window_data; |
73 obj->window = window_data; |
| 75 return obj; |
74 return obj; |
| 76 } |
75 } |
| 77 |
76 |
| 78 UiObject* ui_sidebar_window(const char *title, void *window_data) { |
77 UiObject* ui_sidebar_window(const char *title, void *window_data) { |
| 79 UiObject *obj = create_window(title, FALSE, TRUE); |
78 UiObject *obj = create_window(title, FALSE, TRUE, FALSE); |
| 80 obj->window = window_data; |
79 obj->window = window_data; |
| 81 return obj; |
80 return obj; |
| |
81 } |
| |
82 |
| |
83 UiObject* ui_splitview_window(const char *title, UiBool sidebar) { |
| |
84 return create_window(title, FALSE, sidebar, TRUE); |
| 82 } |
85 } |
| 83 |
86 |
| 84 /* --------------------------------- File Dialogs --------------------------------- */ |
87 /* --------------------------------- File Dialogs --------------------------------- */ |
| 85 |
88 |
| 86 void ui_openfiledialog(UiObject *obj, unsigned int mode, ui_callback file_selected_callback, void *cbdata) { |
89 void ui_openfiledialog(UiObject *obj, unsigned int mode, ui_callback file_selected_callback, void *cbdata) { |
| 228 callback(&event, userdata); |
231 callback(&event, userdata); |
| 229 } |
232 } |
| 230 }]; |
233 }]; |
| 231 |
234 |
| 232 } |
235 } |
| |
236 |
| |
237 /* ------------------------------------- Dialog Window ------------------------------------- */ |
| |
238 |
| |
239 @implementation UiDialogWindow |
| |
240 |
| |
241 - (BOOL) getIsVisible { |
| |
242 return self.isVisible; |
| |
243 } |
| |
244 |
| |
245 - (void) setVisible:(BOOL)visible { |
| |
246 //[self makeKeyAndOrderFront:nil]; |
| |
247 if(visible) { |
| |
248 [_parent beginSheet:self completionHandler:^(NSModalResponse returnCode) { |
| |
249 // TODO: close event |
| |
250 }]; |
| |
251 } else { |
| |
252 [self.sheetParent endSheet:self returnCode:NSModalResponseCancel]; |
| |
253 } |
| |
254 } |
| |
255 |
| |
256 - (void)cancelOperation:(id)sender { |
| |
257 [self.sheetParent endSheet:self returnCode:NSModalResponseCancel]; |
| |
258 // TODO: close event |
| |
259 } |
| |
260 |
| |
261 @end |
| |
262 |
| |
263 UiObject *ui_dialog_window_create(UiObject *parent, UiDialogWindowArgs *args) { |
| |
264 UiObject *obj = uic_object_new_toplevel(); |
| |
265 UiDialogWindow *panel = [[UiDialogWindow alloc] initWithContentRect:NSMakeRect(0, 0, args->width, args->height) |
| |
266 styleMask:(NSWindowStyleMaskTitled | |
| |
267 NSWindowStyleMaskClosable | |
| |
268 NSWindowStyleMaskResizable | |
| |
269 NSWindowStyleMaskUtilityWindow) |
| |
270 backing:NSBackingStoreBuffered |
| |
271 defer:NO]; |
| |
272 panel.parent = (__bridge NSWindow*)parent->wobj; |
| |
273 panel.obj = obj; |
| |
274 panel.modal = args->modal; |
| |
275 panel.onclick = args->onclick; |
| |
276 panel.onclickdata = args->onclickdata; |
| |
277 [panel center]; |
| |
278 [[WindowManager sharedWindowManager] addWindow:panel]; |
| |
279 obj->wobj = (__bridge void*)panel; |
| |
280 |
| |
281 NSView *content = panel.contentView; |
| |
282 |
| |
283 // Create a view for the dialog window buttons (lbutton1, lbutton2, rbutton3, rbutton4) |
| |
284 NSView *buttonArea = [[NSView alloc]init]; |
| |
285 buttonArea.translatesAutoresizingMaskIntoConstraints = NO; |
| |
286 [content addSubview:buttonArea]; |
| |
287 [NSLayoutConstraint activateConstraints:@[ |
| |
288 [buttonArea.bottomAnchor constraintEqualToAnchor:content.bottomAnchor constant:-10], |
| |
289 [buttonArea.leadingAnchor constraintEqualToAnchor:content.leadingAnchor constant:10], |
| |
290 [buttonArea.trailingAnchor constraintEqualToAnchor:content.trailingAnchor constant:-10], |
| |
291 [buttonArea.heightAnchor constraintEqualToConstant:20] |
| |
292 ]]; |
| |
293 |
| |
294 NSButton *lbutton1 = nil; |
| |
295 if(args->lbutton1) { |
| |
296 lbutton1 = [[NSButton alloc]init]; |
| |
297 lbutton1.title = [[NSString alloc]initWithUTF8String:args->lbutton1]; |
| |
298 lbutton1.translatesAutoresizingMaskIntoConstraints = NO; |
| |
299 [buttonArea addSubview:lbutton1]; |
| |
300 [NSLayoutConstraint activateConstraints:@[ |
| |
301 [lbutton1.topAnchor constraintEqualToAnchor:buttonArea.topAnchor constant:0], |
| |
302 [lbutton1.leadingAnchor constraintEqualToAnchor:buttonArea.leadingAnchor constant:0] |
| |
303 ]]; |
| |
304 |
| |
305 EventData *event = [[EventData alloc] init:args->onclick userdata:args->onclickdata]; |
| |
306 event.obj = obj; |
| |
307 event.value = 1; |
| |
308 lbutton1.target = event; |
| |
309 lbutton1.action = @selector(handleEvent:); |
| |
310 objc_setAssociatedObject(lbutton1, "eventdata", event, OBJC_ASSOCIATION_RETAIN); |
| |
311 } |
| |
312 NSButton *lbutton2 = nil; |
| |
313 if(args->lbutton2) { |
| |
314 lbutton2 = [[NSButton alloc]init]; |
| |
315 lbutton2.title = [[NSString alloc]initWithUTF8String:args->lbutton2]; |
| |
316 lbutton2.translatesAutoresizingMaskIntoConstraints = NO; |
| |
317 [buttonArea addSubview:lbutton2]; |
| |
318 NSLayoutXAxisAnchor *anchor = lbutton1 != nil ? lbutton1.trailingAnchor : buttonArea.leadingAnchor; |
| |
319 int off = lbutton1 != nil ? 4 : 0; |
| |
320 [NSLayoutConstraint activateConstraints:@[ |
| |
321 [lbutton2.topAnchor constraintEqualToAnchor:buttonArea.topAnchor constant:0], |
| |
322 [lbutton2.leadingAnchor constraintEqualToAnchor:anchor constant:off] |
| |
323 ]]; |
| |
324 |
| |
325 EventData *event = [[EventData alloc] init:args->onclick userdata:args->onclickdata]; |
| |
326 event.obj = obj; |
| |
327 event.value = 2; |
| |
328 lbutton2.target = event; |
| |
329 lbutton2.action = @selector(handleEvent:); |
| |
330 objc_setAssociatedObject(lbutton2, "eventdata", event, OBJC_ASSOCIATION_RETAIN); |
| |
331 } |
| |
332 |
| |
333 NSButton *rbutton4 = nil; |
| |
334 if(args->rbutton4) { |
| |
335 rbutton4 = [[NSButton alloc]init]; |
| |
336 rbutton4.title = [[NSString alloc]initWithUTF8String:args->rbutton4]; |
| |
337 rbutton4.translatesAutoresizingMaskIntoConstraints = NO; |
| |
338 [buttonArea addSubview:rbutton4]; |
| |
339 [NSLayoutConstraint activateConstraints:@[ |
| |
340 [rbutton4.topAnchor constraintEqualToAnchor:buttonArea.topAnchor constant:0], |
| |
341 [rbutton4.trailingAnchor constraintEqualToAnchor:buttonArea.trailingAnchor constant:0] |
| |
342 ]]; |
| |
343 |
| |
344 EventData *event = [[EventData alloc] init:args->onclick userdata:args->onclickdata]; |
| |
345 event.obj = obj; |
| |
346 event.value = 2; |
| |
347 rbutton4.target = event; |
| |
348 rbutton4.action = @selector(handleEvent:); |
| |
349 objc_setAssociatedObject(rbutton4, "eventdata", event, OBJC_ASSOCIATION_RETAIN); |
| |
350 } |
| |
351 NSButton *rbutton3 = nil; |
| |
352 if(args->rbutton3) { |
| |
353 rbutton3 = [[NSButton alloc]init]; |
| |
354 rbutton3.title = [[NSString alloc]initWithUTF8String:args->rbutton3]; |
| |
355 rbutton3.translatesAutoresizingMaskIntoConstraints = NO; |
| |
356 [buttonArea addSubview:rbutton3]; |
| |
357 NSLayoutXAxisAnchor *anchor = rbutton4 != nil ? rbutton4.leadingAnchor : buttonArea.trailingAnchor; |
| |
358 int off = rbutton4 != nil ? -4 : 0; |
| |
359 [NSLayoutConstraint activateConstraints:@[ |
| |
360 [rbutton3.topAnchor constraintEqualToAnchor:buttonArea.topAnchor constant:0], |
| |
361 [rbutton3.trailingAnchor constraintEqualToAnchor:anchor constant:off] |
| |
362 ]]; |
| |
363 |
| |
364 EventData *event = [[EventData alloc] init:args->onclick userdata:args->onclickdata]; |
| |
365 event.obj = obj; |
| |
366 event.value = 2; |
| |
367 rbutton3.target = event; |
| |
368 rbutton3.action = @selector(handleEvent:); |
| |
369 objc_setAssociatedObject(rbutton3, "eventdata", event, OBJC_ASSOCIATION_RETAIN); |
| |
370 } |
| |
371 switch(args->default_button) { |
| |
372 default: break; |
| |
373 case 1: if(lbutton1 != nil) lbutton1.keyEquivalent = @"\r"; break; |
| |
374 case 2: if(lbutton2 != nil) lbutton2.keyEquivalent = @"\r"; break; |
| |
375 case 3: if(rbutton3 != nil) rbutton3.keyEquivalent = @"\r"; break; |
| |
376 case 4: if(rbutton4 != nil) rbutton4.keyEquivalent = @"\r"; break; |
| |
377 } |
| |
378 |
| |
379 // space between left and right buttons |
| |
380 NSView *space = [[NSView alloc]init]; |
| |
381 space.translatesAutoresizingMaskIntoConstraints = NO; |
| |
382 [buttonArea addSubview:space]; |
| |
383 NSLayoutXAxisAnchor *leftAnchor = buttonArea.leadingAnchor; |
| |
384 NSLayoutXAxisAnchor *rightAnchor = buttonArea.trailingAnchor; |
| |
385 if(lbutton2 != nil) { |
| |
386 leftAnchor = lbutton2.trailingAnchor; |
| |
387 } else if(lbutton1 != nil) { |
| |
388 leftAnchor = lbutton1.trailingAnchor; |
| |
389 } |
| |
390 |
| |
391 if(rbutton3 != nil) { |
| |
392 rightAnchor = rbutton3.leadingAnchor; |
| |
393 } else if(rbutton4 != nil) { |
| |
394 rightAnchor = rbutton4.leadingAnchor; |
| |
395 } |
| |
396 [NSLayoutConstraint activateConstraints:@[ |
| |
397 [space.topAnchor constraintEqualToAnchor:buttonArea.topAnchor], |
| |
398 [space.leadingAnchor constraintEqualToAnchor:leftAnchor constant:10], |
| |
399 [space.trailingAnchor constraintEqualToAnchor:rightAnchor constant:-10] |
| |
400 ]]; |
| |
401 |
| |
402 // dialog window main content |
| |
403 BoxContainer *vbox = [[BoxContainer alloc] init:NSUserInterfaceLayoutOrientationVertical spacing:0]; |
| |
404 vbox.translatesAutoresizingMaskIntoConstraints = NO; |
| |
405 [content addSubview:vbox]; |
| |
406 |
| |
407 [NSLayoutConstraint activateConstraints:@[ |
| |
408 [vbox.topAnchor constraintEqualToAnchor:content.topAnchor constant:0], |
| |
409 [vbox.leadingAnchor constraintEqualToAnchor:content.leadingAnchor], |
| |
410 [vbox.trailingAnchor constraintEqualToAnchor:content.trailingAnchor], |
| |
411 [vbox.bottomAnchor constraintEqualToAnchor:buttonArea.topAnchor constant:0] |
| |
412 ]]; |
| |
413 |
| |
414 UiContainerX *container = ui_create_container(obj, vbox); |
| |
415 vbox.container = container; |
| |
416 uic_object_push_container(obj, container); |
| |
417 |
| |
418 return obj; |
| |
419 } |
| |
420 |