/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 2012 Olaf Wintermann. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#import "window.h"
#import "menu.h"
#import "toolbar.h"
#import "container.h"
#import <ucx/mempool.h>
#import "../common/context.h"
static int window_default_width = 600;
static int window_default_height = 500;
@implementation UiCocoaWindow
- (UiCocoaWindow*) init: (NSRect)frame object: (UiObject*)obj {
self = [self initWithContentRect:frame
styleMask:NSTitledWindowMask |
NSResizableWindowMask |
NSClosableWindowMask |
NSMiniaturizableWindowMask
backing:NSBackingStoreBuffered
defer:false];
uiobj = obj;
UcxAllocator *allocator = uiobj->ctx->mempool->allocator;
menus = ucx_map_new_a(allocator, 8);
items = ucx_map_new_a(allocator, 64);
return self;
}
- (UiObject*) object {
return uiobj;
}
- (void) setObject:(UiObject*)obj {
uiobj = obj;
}
- (void) setMenuItems:(UcxList*)menuItems {
UcxAllocator *allocator = uiobj->ctx->mempool->allocator;
UCX_FOREACH(elm, menuItems) {
UiStateItem *item = elm->data;
NSMenu *menu = [item->item menu];
// create UiMenuItem which represents an NSMenuItem for a Window
UiMenuItem *windowItem = ucx_mempool_malloc(uiobj->ctx->mempool, sizeof(UiMenuItem));
windowItem->item = item->item;
windowItem->state = 0;
if(item->var) {
// bind value
UiVar *var = uic_connect_var(uiobj->ctx, item->var, UI_VAR_INTEGER);
if(var) {
UiInteger *value = var->value;
value->obj = windowItem;
value->get = ui_menuitem_get;
value->set = ui_menuitem_set;
value = 0;
} else {
// TODO: error
}
}
// add item
UiAbstractMenuItem *abstractItem = malloc(sizeof(UiAbstractMenuItem));
abstractItem->update = ui_update_item;
abstractItem->item_data = windowItem;
UcxList *itemList = ucx_map_get(menus, ucx_key(&menu, sizeof(void*)));
itemList = ucx_list_append_a(allocator, itemList, abstractItem);
ucx_map_put(menus, ucx_key(&menu, sizeof(void*)), itemList);
ucx_map_put(items, ucx_key(&windowItem->item, sizeof(void*)), windowItem);
}
}
- (void) setMenuItemLists:(UcxList*)itemLists {
UcxAllocator *allocator = uiobj->ctx->mempool->allocator;
UCX_FOREACH(elm, itemLists) {
UiMenuItemList *list = elm->data;
UiAbstractMenuItem *abstractItem = malloc(sizeof(UiAbstractMenuItem));
abstractItem->update = ui_update_item_list;
abstractItem->item_data = list;
UcxList *itemList = ucx_map_get(menus, ucx_key(&list->menu, sizeof(void*)));
itemList = ucx_list_append_a(allocator, itemList, abstractItem);
ucx_map_put(menus, ucx_key(&list->menu, sizeof(void*)), itemList);
}
}
- (UiMenuItem*) getMenuItem:(NSMenuItem*)item {
return ucx_map_get(items, ucx_key(&item, sizeof(void*)));
}
- (void) updateMenu:(NSMenu*)menu {
UcxList *itemList = ucx_map_get(menus, ucx_key(&menu, sizeof(void*)));
UCX_FOREACH(elm, itemList) {
UiAbstractMenuItem *item = elm->data;
item->update(self, item->item_data);
}
// update group items
// TODO: use only one loop for all items
int ngroups = 0;
int *groups = ui_active_groups(uiobj->ctx, &ngroups);
NSArray *groupItems = [menu itemArray];
int count = [groupItems count];
for(int i=0;i<count;i++) {
id item = [groupItems objectAtIndex:i];
if([item class] == [UiGroupMenuItem class]) {
[item checkGroups: groups count:ngroups];
}
}
free(groups);
}
@end
/* ------------------------------ public API ------------------------------ */
UiObject* ui_window(char *title, void *window_data) {
UcxMempool *mp = ucx_mempool_new(256);
UiObject *obj = ucx_mempool_calloc(mp, 1, sizeof(UiObject));
obj->ctx = uic_context(obj, mp);
// create native window
NSRect frame = NSMakeRect(
300,
200,
window_default_width,
window_default_height);
/*
UiCocoaWindow *window = [[UiCocoaWindow alloc] initWithContentRect:frame
styleMask:NSTitledWindowMask | NSResizableWindowMask |
NSClosableWindowMask | NSMiniaturizableWindowMask
backing:NSBackingStoreBuffered
defer:false];
*/
UiCocoaWindow *window = [[UiCocoaWindow alloc] init:frame object:obj];
NSString *titleStr = [[NSString alloc] initWithUTF8String:title];
[window setTitle:titleStr];
UiMenuDelegate *menuDelegate = ui_menu_delegate();
[window setMenuItems: [menuDelegate items]];
[window setMenuItemLists: [menuDelegate lists]];
NSToolbar *toolbar = ui_create_toolbar(obj);
[window setToolbar: toolbar];
obj->widget = (NSView*)window;
obj->window = window_data;
obj->container = ui_window_container(obj, window);
return obj;
}
void ui_close(UiObject *obj) {
// TODO
}
char* ui_openfiledialog(UiObject *obj) {
NSOpenPanel* op = [NSOpenPanel openPanel];
if ([op runModal] == NSOKButton) {
NSArray *urls = [op URLs];
NSURL *url = [urls objectAtIndex:0];
const char *str = [[url path] UTF8String];
return (char*)strdup(str);
}
return NULL;
}
char* ui_savefiledialog(UiObject *obj) {
NSSavePanel* sp = [NSSavePanel savePanel];
if ([sp runModal] == NSOKButton) {
NSURL *url = [sp URL];
const char *str = [[url path] UTF8String];
return (char*)strdup(str);
}
return NULL;
}