Initial commit
This commit is contained in:
commit
da448cdfc6
698 changed files with 37867 additions and 0 deletions
47
GNUmakefile
Normal file
47
GNUmakefile
Normal file
|
@ -0,0 +1,47 @@
|
|||
ifeq ($(platform),)
|
||||
hiroflags = $(cppflags) $(flags) -DHIRO_REFERENCE
|
||||
hirolink =
|
||||
endif
|
||||
|
||||
ifeq ($(platform),windows)
|
||||
ifeq ($(hiro),)
|
||||
hiro := windows
|
||||
endif
|
||||
|
||||
ifeq ($(hiro),windows)
|
||||
hiroflags = $(cppflags) $(flags) -DHIRO_WINDOWS
|
||||
hirolink = -lkernel32 -luser32 -lgdi32 -ladvapi32 -lole32 -lcomctl32 -lcomdlg32 -luxtheme -lmsimg32 -lshlwapi
|
||||
endif
|
||||
|
||||
ifeq ($(hiro),gtk)
|
||||
hiroflags = $(cppflags) $(flags) -DHIRO_GTK $(shell pkg-config --cflags gtk+-2.0 gtksourceview-2.0)
|
||||
hirolink = $(shell pkg-config --libs gtk+-2.0 gtksourceview-2.0)
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(platform),macosx)
|
||||
ifeq ($(hiro),)
|
||||
hiro := cocoa
|
||||
endif
|
||||
|
||||
ifeq ($(hiro),cocoa)
|
||||
hiroflags = $(objcppflags) $(flags) -w -DHIRO_COCOA
|
||||
hirolink = -framework Cocoa -framework Carbon
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq ($(filter $(platform),linux bsd),)
|
||||
ifeq ($(hiro),)
|
||||
hiro := gtk
|
||||
endif
|
||||
|
||||
ifeq ($(hiro),gtk)
|
||||
hiroflags = $(cppflags) $(flags) -DHIRO_GTK $(shell pkg-config --cflags gtk+-2.0 gtksourceview-2.0)
|
||||
hirolink = -lX11 $(shell pkg-config --libs gtk+-2.0 gtksourceview-2.0)
|
||||
endif
|
||||
|
||||
ifeq ($(hiro),qt)
|
||||
hiroflags = $(cppflags) $(flags) -DHIRO_QT $(shell pkg-config --cflags QtCore QtGui)
|
||||
hirolink = -lX11 $(shell pkg-config --libs QtCore QtGui)
|
||||
endif
|
||||
endif
|
25
cocoa/action/action.cpp
Normal file
25
cocoa/action/action.cpp
Normal file
|
@ -0,0 +1,25 @@
|
|||
#if defined(Hiro_Action)
|
||||
|
||||
namespace hiro {
|
||||
|
||||
auto pAction::construct() -> void {
|
||||
}
|
||||
|
||||
auto pAction::destruct() -> void {
|
||||
}
|
||||
|
||||
auto pAction::setEnabled(bool enabled) -> void {
|
||||
@autoreleasepool {
|
||||
[cocoaAction setEnabled:enabled];
|
||||
}
|
||||
}
|
||||
|
||||
auto pAction::setVisible(bool visible) -> void {
|
||||
@autoreleasepool {
|
||||
[cocoaAction setHidden:!visible];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
16
cocoa/action/action.hpp
Normal file
16
cocoa/action/action.hpp
Normal file
|
@ -0,0 +1,16 @@
|
|||
#if defined(Hiro_Action)
|
||||
|
||||
namespace hiro {
|
||||
|
||||
struct pAction : pObject {
|
||||
Declare(Action, Object)
|
||||
|
||||
auto setEnabled(bool enabled) -> void override;
|
||||
auto setVisible(bool visible) -> void override;
|
||||
|
||||
NSMenuItem* cocoaAction = nullptr;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
56
cocoa/action/menu-check-item.cpp
Normal file
56
cocoa/action/menu-check-item.cpp
Normal file
|
@ -0,0 +1,56 @@
|
|||
#if defined(Hiro_MenuCheckItem)
|
||||
|
||||
@implementation CocoaMenuCheckItem : NSMenuItem
|
||||
|
||||
-(id) initWith:(hiro::mMenuCheckItem&)menuCheckItemReference {
|
||||
if(self = [super initWithTitle:@"" action:@selector(activate) keyEquivalent:@""]) {
|
||||
menuCheckItem = &menuCheckItemReference;
|
||||
|
||||
[self setTarget:self];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
-(void) activate {
|
||||
menuCheckItem->state.checked = !menuCheckItem->state.checked;
|
||||
auto state = menuCheckItem->state.checked ? NSOnState : NSOffState;
|
||||
[self setState:state];
|
||||
menuCheckItem->doToggle();
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
namespace hiro {
|
||||
|
||||
auto pMenuCheckItem::construct() -> void {
|
||||
@autoreleasepool {
|
||||
cocoaAction = cocoaMenuCheckItem = [[CocoaMenuCheckItem alloc] initWith:self()];
|
||||
pAction::construct();
|
||||
|
||||
setChecked(state().checked);
|
||||
setText(state().text);
|
||||
}
|
||||
}
|
||||
|
||||
auto pMenuCheckItem::destruct() -> void {
|
||||
@autoreleasepool {
|
||||
[cocoaAction release];
|
||||
}
|
||||
}
|
||||
|
||||
auto pMenuCheckItem::setChecked(bool checked) -> void {
|
||||
@autoreleasepool {
|
||||
auto state = checked ? NSOnState : NSOffState;
|
||||
[cocoaAction setState:state];
|
||||
}
|
||||
}
|
||||
|
||||
auto pMenuCheckItem::setText(const string& text) -> void {
|
||||
@autoreleasepool {
|
||||
[cocoaAction setTitle:[NSString stringWithUTF8String:text]];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
24
cocoa/action/menu-check-item.hpp
Normal file
24
cocoa/action/menu-check-item.hpp
Normal file
|
@ -0,0 +1,24 @@
|
|||
#if defined(Hiro_MenuCheckItem)
|
||||
|
||||
@interface CocoaMenuCheckItem : NSMenuItem {
|
||||
@public
|
||||
hiro::mMenuCheckItem* menuCheckItem;
|
||||
}
|
||||
-(id) initWith:(hiro::mMenuCheckItem&)checkItem;
|
||||
-(void) activate;
|
||||
@end
|
||||
|
||||
namespace hiro {
|
||||
|
||||
struct pMenuCheckItem : pAction {
|
||||
Declare(MenuCheckItem, Action)
|
||||
|
||||
auto setChecked(bool checked) -> void;
|
||||
auto setText(const string& text) -> void;
|
||||
|
||||
CocoaMenuCheckItem* cocoaMenuCheckItem = nullptr;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
53
cocoa/action/menu-item.cpp
Normal file
53
cocoa/action/menu-item.cpp
Normal file
|
@ -0,0 +1,53 @@
|
|||
#if defined(Hiro_MenuItem)
|
||||
|
||||
@implementation CocoaMenuItem : NSMenuItem
|
||||
|
||||
-(id) initWith:(hiro::mMenuItem&)menuItemReference {
|
||||
if(self = [super initWithTitle:@"" action:@selector(activate) keyEquivalent:@""]) {
|
||||
menuItem = &menuItemReference;
|
||||
|
||||
[self setTarget:self];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
-(void) activate {
|
||||
menuItem->doActivate();
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
namespace hiro {
|
||||
|
||||
auto pMenuItem::construct() -> void {
|
||||
@autoreleasepool {
|
||||
cocoaAction = cocoaMenuItem = [[CocoaMenuItem alloc] initWith:self()];
|
||||
pAction::construct();
|
||||
|
||||
setIcon(state().icon);
|
||||
setText(state().text);
|
||||
}
|
||||
}
|
||||
|
||||
auto pMenuItem::destruct() -> void {
|
||||
@autoreleasepool {
|
||||
[cocoaAction release];
|
||||
}
|
||||
}
|
||||
|
||||
auto pMenuItem::setIcon(const image& icon) -> void {
|
||||
@autoreleasepool {
|
||||
uint size = 15; //there is no API to retrieve the optimal size
|
||||
[cocoaAction setImage:NSMakeImage(icon, size, size)];
|
||||
}
|
||||
}
|
||||
|
||||
auto pMenuItem::setText(const string& text) -> void {
|
||||
@autoreleasepool {
|
||||
[cocoaAction setTitle:[NSString stringWithUTF8String:text]];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
24
cocoa/action/menu-item.hpp
Normal file
24
cocoa/action/menu-item.hpp
Normal file
|
@ -0,0 +1,24 @@
|
|||
#if defined(Hiro_MenuItem)
|
||||
|
||||
@interface CocoaMenuItem : NSMenuItem {
|
||||
@public
|
||||
hiro::mMenuItem* menuItem;
|
||||
}
|
||||
-(id) initWith:(hiro::mMenuItem&)menuItem;
|
||||
-(void) activate;
|
||||
@end
|
||||
|
||||
namespace hiro {
|
||||
|
||||
struct pMenuItem : pAction {
|
||||
Declare(MenuItem, Action)
|
||||
|
||||
auto setIcon(const image& icon) -> void;
|
||||
auto setText(const string& text) -> void;
|
||||
|
||||
CocoaMenuItem* cocoaMenuItem = nullptr;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
68
cocoa/action/menu-radio-item.cpp
Normal file
68
cocoa/action/menu-radio-item.cpp
Normal file
|
@ -0,0 +1,68 @@
|
|||
#if defined(Hiro_MenuRadioItem)
|
||||
|
||||
@implementation CocoaMenuRadioItem : NSMenuItem
|
||||
|
||||
-(id) initWith:(hiro::mMenuRadioItem&)menuRadioItemReference {
|
||||
if(self = [super initWithTitle:@"" action:@selector(activate) keyEquivalent:@""]) {
|
||||
menuRadioItem = &menuRadioItemReference;
|
||||
|
||||
[self setTarget:self];
|
||||
[self setOnStateImage:[NSImage imageNamed:@"NSMenuRadio"]];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
-(void) activate {
|
||||
menuRadioItem->setChecked();
|
||||
menuRadioItem->doActivate();
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
namespace hiro {
|
||||
|
||||
auto pMenuRadioItem::construct() -> void {
|
||||
@autoreleasepool {
|
||||
cocoaAction = cocoaMenuRadioItem = [[CocoaMenuRadioItem alloc] initWith:self()];
|
||||
pAction::construct();
|
||||
|
||||
if(state().checked) setChecked();
|
||||
setText(state().text);
|
||||
}
|
||||
}
|
||||
|
||||
auto pMenuRadioItem::destruct() -> void {
|
||||
@autoreleasepool {
|
||||
[cocoaAction release];
|
||||
}
|
||||
}
|
||||
|
||||
auto pMenuRadioItem::setChecked() -> void {
|
||||
@autoreleasepool {
|
||||
if(auto group = state().group) {
|
||||
for(auto& weak : group->state.objects) {
|
||||
if(auto object = weak.acquire()) {
|
||||
if(auto self = object->self()) {
|
||||
if(auto p = dynamic_cast<pMenuRadioItem*>(self)) {
|
||||
auto state = this == p ? NSOnState : NSOffState;
|
||||
[p->cocoaAction setState:state];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto pMenuRadioItem::setGroup(sGroup group) -> void {
|
||||
}
|
||||
|
||||
auto pMenuRadioItem::setText(const string& text) -> void {
|
||||
@autoreleasepool {
|
||||
[cocoaAction setTitle:[NSString stringWithUTF8String:text]];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
25
cocoa/action/menu-radio-item.hpp
Normal file
25
cocoa/action/menu-radio-item.hpp
Normal file
|
@ -0,0 +1,25 @@
|
|||
#if defined(Hiro_MenuRadioItem)
|
||||
|
||||
@interface CocoaMenuRadioItem : NSMenuItem {
|
||||
@public
|
||||
hiro::mMenuRadioItem* menuRadioItem;
|
||||
}
|
||||
-(id) initWith:(hiro::mMenuRadioItem&)menuRadioItem;
|
||||
-(void) activate;
|
||||
@end
|
||||
|
||||
namespace hiro {
|
||||
|
||||
struct pMenuRadioItem : pAction {
|
||||
Declare(MenuRadioItem, Action)
|
||||
|
||||
auto setChecked() -> void;
|
||||
auto setGroup(sGroup group) -> void;
|
||||
auto setText(const string& text) -> void;
|
||||
|
||||
CocoaMenuRadioItem* cocoaMenuRadioItem = nullptr;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
20
cocoa/action/menu-separator.cpp
Normal file
20
cocoa/action/menu-separator.cpp
Normal file
|
@ -0,0 +1,20 @@
|
|||
#if defined(Hiro_MenuSeparator)
|
||||
|
||||
namespace hiro {
|
||||
|
||||
auto pMenuSeparator::construct() -> void {
|
||||
@autoreleasepool {
|
||||
cocoaAction = cocoaSeparator = [[NSMenuItem separatorItem] retain];
|
||||
pAction::construct();
|
||||
}
|
||||
}
|
||||
|
||||
auto pMenuSeparator::destruct() -> void {
|
||||
@autoreleasepool {
|
||||
[cocoaAction release];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
13
cocoa/action/menu-separator.hpp
Normal file
13
cocoa/action/menu-separator.hpp
Normal file
|
@ -0,0 +1,13 @@
|
|||
#if defined(Hiro_MenuSeparator)
|
||||
|
||||
namespace hiro {
|
||||
|
||||
struct pMenuSeparator : pAction {
|
||||
Declare(MenuSeparator, Action)
|
||||
|
||||
NSMenuItem* cocoaSeparator = nullptr;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
72
cocoa/action/menu.cpp
Normal file
72
cocoa/action/menu.cpp
Normal file
|
@ -0,0 +1,72 @@
|
|||
#if defined(Hiro_Menu)
|
||||
|
||||
@implementation CocoaMenu : NSMenuItem
|
||||
|
||||
-(id) initWith:(hiro::mMenu&)menuReference {
|
||||
if(self = [super initWithTitle:@"" action:nil keyEquivalent:@""]) {
|
||||
menu = &menuReference;
|
||||
|
||||
cocoaMenu = [[NSMenu alloc] initWithTitle:@""];
|
||||
[self setSubmenu:cocoaMenu];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
-(NSMenu*) cocoaMenu {
|
||||
return cocoaMenu;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
namespace hiro {
|
||||
|
||||
auto pMenu::construct() -> void {
|
||||
@autoreleasepool {
|
||||
cocoaAction = cocoaMenu = [[CocoaMenu alloc] initWith:self()];
|
||||
pAction::construct();
|
||||
|
||||
setIcon(state().icon);
|
||||
setText(state().text);
|
||||
}
|
||||
}
|
||||
|
||||
auto pMenu::destruct() -> void {
|
||||
@autoreleasepool {
|
||||
[[cocoaAction cocoaMenu] release];
|
||||
[cocoaAction release];
|
||||
}
|
||||
}
|
||||
|
||||
auto pMenu::append(sAction action) -> void {
|
||||
@autoreleasepool {
|
||||
if(auto pAction = action->self()) {
|
||||
[[cocoaAction cocoaMenu] addItem:pAction->cocoaAction];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto pMenu::remove(sAction action) -> void {
|
||||
@autoreleasepool {
|
||||
if(auto pAction = action->self()) {
|
||||
[[cocoaAction cocoaMenu] removeItem:pAction->cocoaAction];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto pMenu::setIcon(const image& icon) -> void {
|
||||
@autoreleasepool {
|
||||
uint size = 15; //there is no API to retrieve the optimal size
|
||||
[cocoaAction setImage:NSMakeImage(icon, size, size)];
|
||||
}
|
||||
}
|
||||
|
||||
auto pMenu::setText(const string& text) -> void {
|
||||
@autoreleasepool {
|
||||
[[cocoaAction cocoaMenu] setTitle:[NSString stringWithUTF8String:text]];
|
||||
[cocoaAction setTitle:[NSString stringWithUTF8String:text]];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
27
cocoa/action/menu.hpp
Normal file
27
cocoa/action/menu.hpp
Normal file
|
@ -0,0 +1,27 @@
|
|||
#if defined(Hiro_Menu)
|
||||
|
||||
@interface CocoaMenu : NSMenuItem {
|
||||
@public
|
||||
hiro::mMenu* menu;
|
||||
NSMenu* cocoaMenu;
|
||||
}
|
||||
-(id) initWith:(hiro::mMenu&)menu;
|
||||
-(NSMenu*) cocoaMenu;
|
||||
@end
|
||||
|
||||
namespace hiro {
|
||||
|
||||
struct pMenu : pAction {
|
||||
Declare(Menu, Action)
|
||||
|
||||
auto append(sAction action) -> void;
|
||||
auto remove(sAction action) -> void;
|
||||
auto setIcon(const image& icon) -> void;
|
||||
auto setText(const string& text) -> void;
|
||||
|
||||
CocoaMenu* cocoaMenu = nullptr;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
93
cocoa/application.cpp
Normal file
93
cocoa/application.cpp
Normal file
|
@ -0,0 +1,93 @@
|
|||
#if defined(Hiro_Application)
|
||||
|
||||
@implementation CocoaDelegate : NSObject
|
||||
|
||||
-(NSApplicationTerminateReply) applicationShouldTerminate:(NSApplication*)sender {
|
||||
using hiro::Application;
|
||||
if(Application::state.cocoa.onQuit) Application::Cocoa::doQuit();
|
||||
else Application::quit();
|
||||
return NSTerminateCancel;
|
||||
}
|
||||
|
||||
-(BOOL) applicationShouldHandleReopen:(NSApplication*)application hasVisibleWindows:(BOOL)flag {
|
||||
using hiro::Application;
|
||||
if(Application::state.cocoa.onActivate) Application::Cocoa::doActivate();
|
||||
return NO;
|
||||
}
|
||||
|
||||
-(void) run:(NSTimer*)timer {
|
||||
using hiro::Application;
|
||||
if(Application::state.onMain) Application::doMain();
|
||||
}
|
||||
|
||||
-(void) updateInDock:(NSTimer*)timer {
|
||||
NSArray* windows = [NSApp windows];
|
||||
for(uint n = 0; n < [windows count]; n++) {
|
||||
NSWindow* window = [windows objectAtIndex:n];
|
||||
if([window isMiniaturized]) {
|
||||
[window updateInDock];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
CocoaDelegate* cocoaDelegate = nullptr;
|
||||
|
||||
namespace hiro {
|
||||
|
||||
auto pApplication::run() -> void {
|
||||
//NSTimer* timer = [NSTimer scheduledTimerWithTimeInterval:0.1667 target:cocoaDelegate selector:@selector(updateInDock:) userInfo:nil repeats:YES];
|
||||
|
||||
if(Application::state.onMain) {
|
||||
NSTimer* timer = [NSTimer scheduledTimerWithTimeInterval:0.0 target:cocoaDelegate selector:@selector(run:) userInfo:nil repeats:YES];
|
||||
|
||||
//below line is needed to run application during window resize; however it has a large performance penalty on the resize smoothness
|
||||
//[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSEventTrackingRunLoopMode];
|
||||
}
|
||||
|
||||
@autoreleasepool {
|
||||
[NSApp run];
|
||||
}
|
||||
}
|
||||
|
||||
auto pApplication::pendingEvents() -> bool {
|
||||
bool result = false;
|
||||
@autoreleasepool {
|
||||
NSEvent* event = [NSApp nextEventMatchingMask:NSAnyEventMask untilDate:[NSDate distantPast] inMode:NSDefaultRunLoopMode dequeue:NO];
|
||||
if(event != nil) result = true;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
auto pApplication::processEvents() -> void {
|
||||
@autoreleasepool {
|
||||
while(!Application::state.quit) {
|
||||
NSEvent* event = [NSApp nextEventMatchingMask:NSAnyEventMask untilDate:[NSDate distantPast] inMode:NSDefaultRunLoopMode dequeue:YES];
|
||||
if(event == nil) break;
|
||||
[event retain];
|
||||
[NSApp sendEvent:event];
|
||||
[event release];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto pApplication::quit() -> void {
|
||||
@autoreleasepool {
|
||||
[NSApp stop:nil];
|
||||
NSEvent* event = [NSEvent otherEventWithType:NSApplicationDefined location:NSMakePoint(0, 0) modifierFlags:0 timestamp:0.0 windowNumber:0 context:nil subtype:0 data1:0 data2:0];
|
||||
[NSApp postEvent:event atStart:true];
|
||||
}
|
||||
}
|
||||
|
||||
auto pApplication::initialize() -> void {
|
||||
@autoreleasepool {
|
||||
[NSApplication sharedApplication];
|
||||
cocoaDelegate = [[CocoaDelegate alloc] init];
|
||||
[NSApp setDelegate:cocoaDelegate];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
24
cocoa/application.hpp
Normal file
24
cocoa/application.hpp
Normal file
|
@ -0,0 +1,24 @@
|
|||
#if defined(Hiro_Application)
|
||||
|
||||
@interface CocoaDelegate : NSObject <NSApplicationDelegate> {
|
||||
}
|
||||
-(NSApplicationTerminateReply) applicationShouldTerminate:(NSApplication*)sender;
|
||||
-(BOOL) applicationShouldHandleReopen:(NSApplication*)application hasVisibleWindows:(BOOL)flag;
|
||||
-(void) run:(NSTimer*)timer;
|
||||
-(void) updateInDock:(NSTimer*)timer;
|
||||
@end
|
||||
|
||||
namespace hiro {
|
||||
|
||||
struct pApplication {
|
||||
static auto run() -> void;
|
||||
static auto pendingEvents() -> bool;
|
||||
static auto processEvents() -> void;
|
||||
static auto quit() -> void;
|
||||
|
||||
static auto initialize() -> void;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
73
cocoa/browser-window.cpp
Normal file
73
cocoa/browser-window.cpp
Normal file
|
@ -0,0 +1,73 @@
|
|||
#if defined(Hiro_BrowserWindow)
|
||||
|
||||
namespace hiro {
|
||||
|
||||
auto pBrowserWindow::directory(BrowserWindow::State& state) -> string {
|
||||
string result;
|
||||
|
||||
@autoreleasepool {
|
||||
NSOpenPanel* panel = [NSOpenPanel openPanel];
|
||||
if(state.title) [panel setTitle:[NSString stringWithUTF8String:state.title]];
|
||||
[panel setCanChooseDirectories:YES];
|
||||
[panel setCanChooseFiles:NO];
|
||||
if([panel runModalForDirectory:[NSString stringWithUTF8String:state.path] file:nil] == NSOKButton) {
|
||||
NSArray* names = [panel filenames];
|
||||
const char* name = [[names objectAtIndex:0] UTF8String];
|
||||
if(name) result = name;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
auto pBrowserWindow::open(BrowserWindow::State& state) -> string {
|
||||
string result;
|
||||
|
||||
@autoreleasepool {
|
||||
NSMutableArray* filters = [[NSMutableArray alloc] init];
|
||||
for(auto& rule : state.filters) {
|
||||
string pattern = rule.split("(", 1L)(1).rtrim(")", 1L);
|
||||
if(!pattern.empty()) [filters addObject:[NSString stringWithUTF8String:pattern]];
|
||||
}
|
||||
NSOpenPanel* panel = [NSOpenPanel openPanel];
|
||||
if(state.title) [panel setTitle:[NSString stringWithUTF8String:state.title]];
|
||||
[panel setCanChooseDirectories:NO];
|
||||
[panel setCanChooseFiles:YES];
|
||||
[panel setAllowedFileTypes:filters];
|
||||
if([panel runModalForDirectory:[NSString stringWithUTF8String:state.path] file:nil] == NSOKButton) {
|
||||
NSArray* names = [panel filenames];
|
||||
const char* name = [[names objectAtIndex:0] UTF8String];
|
||||
if(name) result = name;
|
||||
}
|
||||
[filters release];
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
auto pBrowserWindow::save(BrowserWindow::State& state) -> string {
|
||||
string result;
|
||||
|
||||
@autoreleasepool {
|
||||
NSMutableArray* filters = [[NSMutableArray alloc] init];
|
||||
for(auto& rule : state.filters) {
|
||||
string pattern = rule.split("(", 1L)(1).rtrim(")", 1L);
|
||||
if(!pattern.empty()) [filters addObject:[NSString stringWithUTF8String:pattern]];
|
||||
}
|
||||
NSSavePanel* panel = [NSSavePanel savePanel];
|
||||
if(state.title) [panel setTitle:[NSString stringWithUTF8String:state.title]];
|
||||
[panel setAllowedFileTypes:filters];
|
||||
if([panel runModalForDirectory:[NSString stringWithUTF8String:state.path] file:nil] == NSOKButton) {
|
||||
NSArray* names = [panel filenames];
|
||||
const char* name = [[names objectAtIndex:0] UTF8String];
|
||||
if(name) result = name;
|
||||
}
|
||||
[filters release];
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
13
cocoa/browser-window.hpp
Normal file
13
cocoa/browser-window.hpp
Normal file
|
@ -0,0 +1,13 @@
|
|||
#if defined(Hiro_BrowserWindow)
|
||||
|
||||
namespace hiro {
|
||||
|
||||
struct pBrowserWindow {
|
||||
static auto directory(BrowserWindow::State& state) -> string;
|
||||
static auto open(BrowserWindow::State& state) -> string;
|
||||
static auto save(BrowserWindow::State& state) -> string;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
22
cocoa/desktop.cpp
Normal file
22
cocoa/desktop.cpp
Normal file
|
@ -0,0 +1,22 @@
|
|||
#if defined(Hiro_Desktop)
|
||||
|
||||
namespace hiro {
|
||||
|
||||
auto pDesktop::size() -> Size {
|
||||
@autoreleasepool {
|
||||
NSRect primary = [[[NSScreen screens] objectAtIndex:0] frame];
|
||||
return {(int)primary.size.width, (int)primary.size.height};
|
||||
}
|
||||
}
|
||||
|
||||
auto pDesktop::workspace() -> Geometry {
|
||||
@autoreleasepool {
|
||||
auto screen = Desktop::size();
|
||||
NSRect area = [[[NSScreen screens] objectAtIndex:0] visibleFrame];
|
||||
return {(int)area.origin.x, (int)(screen.height() - area.size.height - area.origin.y), (int)area.size.width, (int)area.size.height};
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
12
cocoa/desktop.hpp
Normal file
12
cocoa/desktop.hpp
Normal file
|
@ -0,0 +1,12 @@
|
|||
#if defined(Hiro_Desktop)
|
||||
|
||||
namespace hiro {
|
||||
|
||||
struct pDesktop {
|
||||
static auto size() -> Size;
|
||||
static auto workspace() -> Geometry;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
51
cocoa/font.cpp
Normal file
51
cocoa/font.cpp
Normal file
|
@ -0,0 +1,51 @@
|
|||
#if defined(Hiro_Font)
|
||||
|
||||
namespace hiro {
|
||||
|
||||
auto pFont::size(const Font& font, const string& text) -> Size {
|
||||
@autoreleasepool {
|
||||
if(NSFont* nsFont = create(font)) {
|
||||
return size(nsFont, text);
|
||||
}
|
||||
}
|
||||
return {0, 0};
|
||||
}
|
||||
|
||||
auto pFont::size(NSFont* font, const string& text) -> Size {
|
||||
@autoreleasepool {
|
||||
NSString* cocoaText = [NSString stringWithUTF8String:text];
|
||||
NSDictionary* fontAttributes = [NSDictionary dictionaryWithObjectsAndKeys:font, NSFontAttributeName, nil];
|
||||
NSSize size = [cocoaText sizeWithAttributes:fontAttributes];
|
||||
return {(int)size.width, (int)size.height};
|
||||
}
|
||||
}
|
||||
|
||||
auto pFont::family(const string& family) -> string {
|
||||
if(family == Font::Sans ) return "Lucida Grande";
|
||||
if(family == Font::Serif) return "Georgia";
|
||||
if(family == Font::Mono ) return "Menlo";
|
||||
return "Lucida Grande";
|
||||
}
|
||||
|
||||
auto pFont::create(const Font& font) -> NSFont* {
|
||||
auto fontName = family(font.family());
|
||||
NSString* family = [NSString stringWithUTF8String:fontName];
|
||||
CGFloat size = (float)(font.size() ? font.size() : 8);
|
||||
NSFontTraitMask traits = 0;
|
||||
|
||||
if(font.bold()) traits |= NSBoldFontMask;
|
||||
if(font.italic()) traits |= NSItalicFontMask;
|
||||
|
||||
//note: below properties are not exposed by hiro::Font; traits are saved here for possible future use
|
||||
//if(font.narrow()) traits |= NSNarrowFontMask;
|
||||
//if(font.expanded()) traits |= NSExpandedFontMask;
|
||||
//if(font.condensed()) traits |= NSCondensedFontMask;
|
||||
//if(font.smallCaps()) traits |= NSSmallCapsFontMask;
|
||||
|
||||
size *= 1.5; //scale to point sizes (for consistency with other operating systems)
|
||||
return [[NSFontManager sharedFontManager] fontWithFamily:family traits:traits weight:5 size:size];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
14
cocoa/font.hpp
Normal file
14
cocoa/font.hpp
Normal file
|
@ -0,0 +1,14 @@
|
|||
#if defined(Hiro_Font)
|
||||
|
||||
namespace hiro {
|
||||
|
||||
struct pFont {
|
||||
static auto size(const Font& font, const string& text) -> Size;
|
||||
static auto size(NSFont* font, const string& text) -> Size;
|
||||
static auto family(const string& family) -> string;
|
||||
static auto create(const Font& font) -> NSFont*;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
13
cocoa/group.cpp
Normal file
13
cocoa/group.cpp
Normal file
|
@ -0,0 +1,13 @@
|
|||
#if defined(Hiro_Group)
|
||||
|
||||
namespace hiro {
|
||||
|
||||
auto pGroup::construct() -> void {
|
||||
}
|
||||
|
||||
auto pGroup::destruct() -> void {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
11
cocoa/group.hpp
Normal file
11
cocoa/group.hpp
Normal file
|
@ -0,0 +1,11 @@
|
|||
#if defined(Hiro_Group)
|
||||
|
||||
namespace hiro {
|
||||
|
||||
struct pGroup : pObject {
|
||||
Declare(Group, Object);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
6
cocoa/header.hpp
Normal file
6
cocoa/header.hpp
Normal file
|
@ -0,0 +1,6 @@
|
|||
#define decimal CocoaDecimal
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#import <Carbon/Carbon.h>
|
||||
#undef decimal
|
||||
|
||||
#include <nall/run.hpp>
|
16
cocoa/keyboard.cpp
Normal file
16
cocoa/keyboard.cpp
Normal file
|
@ -0,0 +1,16 @@
|
|||
#if defined(Hiro_Keyboard)
|
||||
|
||||
namespace hiro {
|
||||
|
||||
auto pKeyboard::poll() -> vector<bool> {
|
||||
vector<bool> result;
|
||||
return result;
|
||||
}
|
||||
|
||||
auto pKeyboard::pressed(uint code) -> bool {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
12
cocoa/keyboard.hpp
Normal file
12
cocoa/keyboard.hpp
Normal file
|
@ -0,0 +1,12 @@
|
|||
#if defined(Hiro_Keyboard)
|
||||
|
||||
namespace hiro {
|
||||
|
||||
struct pKeyboard {
|
||||
static auto poll() -> vector<bool>;
|
||||
static auto pressed(uint code) -> bool;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
33
cocoa/layout.cpp
Normal file
33
cocoa/layout.cpp
Normal file
|
@ -0,0 +1,33 @@
|
|||
#if defined(Hiro_Layout)
|
||||
|
||||
namespace hiro {
|
||||
|
||||
auto pLayout::construct() -> void {
|
||||
for(auto& sizable : state().sizables) sizable->construct();
|
||||
}
|
||||
|
||||
auto pLayout::destruct() -> void {
|
||||
for(auto& sizable : state().sizables) sizable->destruct();
|
||||
}
|
||||
|
||||
auto pLayout::setEnabled(bool enabled) -> void {
|
||||
for(auto& sizable : state().sizables) {
|
||||
if(auto self = sizable->self()) self->setEnabled(enabled && sizable->enabled(true));
|
||||
}
|
||||
}
|
||||
|
||||
auto pLayout::setFont(const Font& font) -> void {
|
||||
for(auto& sizable : state().sizables) {
|
||||
if(auto self = sizable->self()) self->setFont(font ? font : sizable->font(true));
|
||||
}
|
||||
}
|
||||
|
||||
auto pLayout::setVisible(bool visible) -> void {
|
||||
for(auto& sizable : state().sizables) {
|
||||
if(auto self = sizable->self()) self->setVisible(visible && sizable->visible(true));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
15
cocoa/layout.hpp
Normal file
15
cocoa/layout.hpp
Normal file
|
@ -0,0 +1,15 @@
|
|||
#if defined(Hiro_Layout)
|
||||
|
||||
namespace hiro {
|
||||
|
||||
struct pLayout : pSizable {
|
||||
Declare(Layout, Sizable);
|
||||
|
||||
auto setEnabled(bool enabled) -> void override;
|
||||
auto setFont(const Font& font) -> void override;
|
||||
auto setVisible(bool visible) -> void override;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
40
cocoa/menu-bar.cpp
Normal file
40
cocoa/menu-bar.cpp
Normal file
|
@ -0,0 +1,40 @@
|
|||
#if defined(Hiro_MenuBar)
|
||||
|
||||
namespace hiro {
|
||||
|
||||
auto pMenuBar::construct() -> void {
|
||||
}
|
||||
|
||||
auto pMenuBar::destruct() -> void {
|
||||
}
|
||||
|
||||
auto pMenuBar::append(sMenu menu) -> void {
|
||||
@autoreleasepool {
|
||||
if(auto parent = _parent()) {
|
||||
if(auto pMenu = menu->self()) {
|
||||
[[parent->cocoaWindow menuBar] addItem:pMenu->cocoaAction];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto pMenuBar::remove(sMenu menu) -> void {
|
||||
@autoreleasepool {
|
||||
if(auto parent = _parent()) {
|
||||
if(auto pMenu = menu->self()) {
|
||||
[[parent->cocoaWindow menuBar] removeItem:pMenu->cocoaAction];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto pMenuBar::_parent() -> maybe<pWindow&> {
|
||||
if(auto parent = self().parentWindow()) {
|
||||
if(auto self = parent->self()) return *self;
|
||||
}
|
||||
return nothing;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
16
cocoa/menu-bar.hpp
Normal file
16
cocoa/menu-bar.hpp
Normal file
|
@ -0,0 +1,16 @@
|
|||
#if defined(Hiro_MenuBar)
|
||||
|
||||
namespace hiro {
|
||||
|
||||
struct pMenuBar : pObject {
|
||||
Declare(MenuBar, Object)
|
||||
|
||||
auto append(sMenu menu) -> void;
|
||||
auto remove(sMenu menu) -> void;
|
||||
|
||||
auto _parent() -> maybe<pWindow&>;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
83
cocoa/message-window.cpp
Normal file
83
cocoa/message-window.cpp
Normal file
|
@ -0,0 +1,83 @@
|
|||
#if defined(Hiro_MessageWindow)
|
||||
|
||||
namespace hiro {
|
||||
|
||||
enum class MessageWindowType : uint { Error, Information, Question, Warning };
|
||||
|
||||
auto MessageWindow_dialog(MessageWindow::State& state, MessageWindowType type) -> MessageWindow::Response {
|
||||
@autoreleasepool {
|
||||
NSAlert* alert = [[[NSAlert alloc] init] autorelease];
|
||||
if(state.title) [alert setMessageText:[NSString stringWithUTF8String:state.title]];
|
||||
[alert setInformativeText:[NSString stringWithUTF8String:state.text]];
|
||||
|
||||
switch(state.buttons) {
|
||||
case MessageWindow::Buttons::Ok:
|
||||
[alert addButtonWithTitle:@"Ok"];
|
||||
break;
|
||||
case MessageWindow::Buttons::OkCancel:
|
||||
[alert addButtonWithTitle:@"Ok"];
|
||||
[alert addButtonWithTitle:@"Cancel"];
|
||||
break;
|
||||
case MessageWindow::Buttons::YesNo:
|
||||
[alert addButtonWithTitle:@"Yes"];
|
||||
[alert addButtonWithTitle:@"No"];
|
||||
break;
|
||||
case MessageWindow::Buttons::YesNoCancel:
|
||||
[alert addButtonWithTitle:@"Yes"];
|
||||
[alert addButtonWithTitle:@"No"];
|
||||
[alert addButtonWithTitle:@"Cancel"];
|
||||
break;
|
||||
}
|
||||
|
||||
switch(type) {
|
||||
case MessageWindowType::Error: [alert setAlertStyle:NSCriticalAlertStyle]; break;
|
||||
case MessageWindowType::Information: [alert setAlertStyle:NSInformationalAlertStyle]; break;
|
||||
case MessageWindowType::Question: [alert setAlertStyle:NSInformationalAlertStyle]; break;
|
||||
case MessageWindowType::Warning: [alert setAlertStyle:NSWarningAlertStyle]; break;
|
||||
}
|
||||
|
||||
NSInteger response = [alert runModal];
|
||||
//[alert beginSheetModalForWindow:parent.p.cocoaWindow modalDelegate:self didEndSelector:@selector(...) contextInfo:nil];
|
||||
|
||||
switch(state.buttons) {
|
||||
case MessageWindow::Buttons::Ok:
|
||||
if(response == NSAlertFirstButtonReturn) return MessageWindow::Response::Ok;
|
||||
break;
|
||||
case MessageWindow::Buttons::OkCancel:
|
||||
if(response == NSAlertFirstButtonReturn) return MessageWindow::Response::Ok;
|
||||
if(response == NSAlertSecondButtonReturn) return MessageWindow::Response::Cancel;
|
||||
break;
|
||||
case MessageWindow::Buttons::YesNo:
|
||||
if(response == NSAlertFirstButtonReturn) return MessageWindow::Response::Yes;
|
||||
if(response == NSAlertSecondButtonReturn) return MessageWindow::Response::No;
|
||||
break;
|
||||
case MessageWindow::Buttons::YesNoCancel:
|
||||
if(response == NSAlertFirstButtonReturn) return MessageWindow::Response::Yes;
|
||||
if(response == NSAlertSecondButtonReturn) return MessageWindow::Response::No;
|
||||
if(response == NSAlertThirdButtonReturn) return MessageWindow::Response::Cancel;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
throw;
|
||||
}
|
||||
|
||||
auto pMessageWindow::error(MessageWindow::State& state) -> MessageWindow::Response {
|
||||
return MessageWindow_dialog(state, MessageWindowType::Error);
|
||||
}
|
||||
|
||||
auto pMessageWindow::information(MessageWindow::State& state) -> MessageWindow::Response {
|
||||
return MessageWindow_dialog(state, MessageWindowType::Information);
|
||||
}
|
||||
|
||||
auto pMessageWindow::question(MessageWindow::State& state) -> MessageWindow::Response {
|
||||
return MessageWindow_dialog(state, MessageWindowType::Question);
|
||||
}
|
||||
|
||||
auto pMessageWindow::warning(MessageWindow::State& state) -> MessageWindow::Response {
|
||||
return MessageWindow_dialog(state, MessageWindowType::Warning);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
14
cocoa/message-window.hpp
Normal file
14
cocoa/message-window.hpp
Normal file
|
@ -0,0 +1,14 @@
|
|||
#if defined(Hiro_MessageWindow)
|
||||
|
||||
namespace hiro {
|
||||
|
||||
struct pMessageWindow {
|
||||
static auto error(MessageWindow::State& state) -> MessageWindow::Response;
|
||||
static auto information(MessageWindow::State& state) -> MessageWindow::Response;
|
||||
static auto question(MessageWindow::State& state) -> MessageWindow::Response;
|
||||
static auto warning(MessageWindow::State& state) -> MessageWindow::Response;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
25
cocoa/monitor.cpp
Normal file
25
cocoa/monitor.cpp
Normal file
|
@ -0,0 +1,25 @@
|
|||
#if defined(Hiro_Monitor)
|
||||
|
||||
namespace hiro {
|
||||
|
||||
auto pMonitor::count() -> uint {
|
||||
@autoreleasepool {
|
||||
return [[NSScreen screens] count];
|
||||
}
|
||||
}
|
||||
|
||||
auto pMonitor::geometry(uint monitor) -> Geometry {
|
||||
@autoreleasepool {
|
||||
NSRect rectangle = [[[NSScreen screens] objectAtIndex:monitor] frame];
|
||||
return {(int)rectangle.origin.x, (int)rectangle.origin.y, (int)rectangle.size.width, (int)rectangle.size.height};
|
||||
}
|
||||
}
|
||||
|
||||
auto pMonitor::primary() -> uint {
|
||||
//on OS X, the primary monitor is always the first monitor
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
13
cocoa/monitor.hpp
Normal file
13
cocoa/monitor.hpp
Normal file
|
@ -0,0 +1,13 @@
|
|||
#if defined(Hiro_Monitor)
|
||||
|
||||
namespace hiro {
|
||||
|
||||
struct pMonitor {
|
||||
static auto count() -> uint;
|
||||
static auto geometry(uint monitor) -> Geometry;
|
||||
static auto primary() -> uint;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
15
cocoa/mouse.cpp
Normal file
15
cocoa/mouse.cpp
Normal file
|
@ -0,0 +1,15 @@
|
|||
#if defined(Hiro_Mouse)
|
||||
|
||||
namespace hiro {
|
||||
|
||||
auto pMouse::position() -> Position {
|
||||
return {0, 0};
|
||||
}
|
||||
|
||||
auto pMouse::pressed(Mouse::Button button) -> bool {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
12
cocoa/mouse.hpp
Normal file
12
cocoa/mouse.hpp
Normal file
|
@ -0,0 +1,12 @@
|
|||
#if defined(Hiro_Mouse)
|
||||
|
||||
namespace hiro {
|
||||
|
||||
struct pMouse {
|
||||
static auto position() -> Position;
|
||||
static auto pressed(Mouse::Button button) -> bool;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
35
cocoa/object.cpp
Normal file
35
cocoa/object.cpp
Normal file
|
@ -0,0 +1,35 @@
|
|||
#if defined(Hiro_Object)
|
||||
|
||||
namespace hiro {
|
||||
|
||||
auto pObject::construct() -> void {
|
||||
}
|
||||
|
||||
auto pObject::destruct() -> void {
|
||||
}
|
||||
|
||||
auto pObject::focused() const -> bool {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto pObject::remove() -> void {
|
||||
}
|
||||
|
||||
auto pObject::reset() -> void {
|
||||
}
|
||||
|
||||
auto pObject::setEnabled(bool enabled) -> void {
|
||||
}
|
||||
|
||||
auto pObject::setFocused() -> void {
|
||||
}
|
||||
|
||||
auto pObject::setFont(const Font& font) -> void {
|
||||
}
|
||||
|
||||
auto pObject::setVisible(bool visible) -> void {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
31
cocoa/object.hpp
Normal file
31
cocoa/object.hpp
Normal file
|
@ -0,0 +1,31 @@
|
|||
#if defined(Hiro_Object)
|
||||
|
||||
namespace hiro {
|
||||
|
||||
struct pObject {
|
||||
pObject(mObject& reference) : reference(reference) {}
|
||||
virtual ~pObject() {}
|
||||
auto self() const -> mObject& { return (mObject&)reference; }
|
||||
auto state() const -> mObject::State& { return self().state; }
|
||||
virtual auto construct() -> void;
|
||||
virtual auto destruct() -> void;
|
||||
|
||||
virtual auto focused() const -> bool;
|
||||
virtual auto remove() -> void;
|
||||
virtual auto reset() -> void;
|
||||
virtual auto setEnabled(bool enabled) -> void;
|
||||
virtual auto setFocused() -> void;
|
||||
virtual auto setFont(const Font& font) -> void;
|
||||
virtual auto setVisible(bool visible) -> void;
|
||||
|
||||
auto locked() const -> bool { return locks != 0; }
|
||||
auto lock() -> void { ++locks; }
|
||||
auto unlock() -> void { --locks; }
|
||||
|
||||
mObject& reference;
|
||||
signed locks = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
60
cocoa/platform.cpp
Normal file
60
cocoa/platform.cpp
Normal file
|
@ -0,0 +1,60 @@
|
|||
#include "platform.hpp"
|
||||
#include "utility.cpp"
|
||||
|
||||
#include "font.cpp"
|
||||
#include "desktop.cpp"
|
||||
#include "monitor.cpp"
|
||||
#include "keyboard.cpp"
|
||||
#include "mouse.cpp"
|
||||
#include "browser-window.cpp"
|
||||
#include "message-window.cpp"
|
||||
|
||||
#include "object.cpp"
|
||||
#include "group.cpp"
|
||||
|
||||
#include "timer.cpp"
|
||||
#include "window.cpp"
|
||||
#include "status-bar.cpp"
|
||||
#include "menu-bar.cpp"
|
||||
#include "popup-menu.cpp"
|
||||
|
||||
#include "action/action.cpp"
|
||||
#include "action/menu.cpp"
|
||||
#include "action/menu-separator.cpp"
|
||||
#include "action/menu-item.cpp"
|
||||
#include "action/menu-check-item.cpp"
|
||||
#include "action/menu-radio-item.cpp"
|
||||
|
||||
#include "sizable.cpp"
|
||||
#include "layout.cpp"
|
||||
|
||||
#include "widget/widget.cpp"
|
||||
#include "widget/button.cpp"
|
||||
#include "widget/canvas.cpp"
|
||||
#include "widget/check-button.cpp"
|
||||
#include "widget/check-label.cpp"
|
||||
#include "widget/combo-button.cpp"
|
||||
#include "widget/combo-button-item.cpp"
|
||||
#include "widget/console.cpp"
|
||||
#include "widget/frame.cpp"
|
||||
#include "widget/hex-edit.cpp"
|
||||
#include "widget/horizontal-scroll-bar.cpp"
|
||||
#include "widget/horizontal-slider.cpp"
|
||||
#include "widget/label.cpp"
|
||||
#include "widget/line-edit.cpp"
|
||||
#include "widget/list-view.cpp"
|
||||
#include "widget/list-view-header.cpp"
|
||||
#include "widget/list-view-column.cpp"
|
||||
#include "widget/list-view-item.cpp"
|
||||
#include "widget/list-view-cell.cpp"
|
||||
#include "widget/progress-bar.cpp"
|
||||
#include "widget/radio-button.cpp"
|
||||
#include "widget/radio-label.cpp"
|
||||
#include "widget/tab-frame.cpp"
|
||||
#include "widget/tab-frame-item.cpp"
|
||||
#include "widget/text-edit.cpp"
|
||||
#include "widget/vertical-scroll-bar.cpp"
|
||||
#include "widget/vertical-slider.cpp"
|
||||
#include "widget/viewport.cpp"
|
||||
|
||||
#include "application.cpp"
|
74
cocoa/platform.hpp
Normal file
74
cocoa/platform.hpp
Normal file
|
@ -0,0 +1,74 @@
|
|||
namespace hiro {
|
||||
struct pFont;
|
||||
struct pWindow;
|
||||
struct pMenu;
|
||||
struct pLayout;
|
||||
struct pWidget;
|
||||
}
|
||||
|
||||
#define Declare(Name, Base) \
|
||||
p##Name(m##Name& reference) : p##Base(reference) {} \
|
||||
auto self() const -> m##Name& { return (m##Name&)reference; } \
|
||||
auto state() const -> m##Name::State& { return self().state; } \
|
||||
auto construct() -> void override; \
|
||||
auto destruct() -> void override; \
|
||||
|
||||
#include "font.hpp"
|
||||
#include "desktop.hpp"
|
||||
#include "monitor.hpp"
|
||||
#include "keyboard.hpp"
|
||||
#include "mouse.hpp"
|
||||
#include "browser-window.hpp"
|
||||
#include "message-window.hpp"
|
||||
|
||||
#include "object.hpp"
|
||||
#include "group.hpp"
|
||||
|
||||
#include "timer.hpp"
|
||||
#include "window.hpp"
|
||||
#include "status-bar.hpp"
|
||||
#include "menu-bar.hpp"
|
||||
#include "popup-menu.hpp"
|
||||
|
||||
#include "action/action.hpp"
|
||||
#include "action/menu.hpp"
|
||||
#include "action/menu-separator.hpp"
|
||||
#include "action/menu-item.hpp"
|
||||
#include "action/menu-check-item.hpp"
|
||||
#include "action/menu-radio-item.hpp"
|
||||
|
||||
#include "sizable.hpp"
|
||||
#include "layout.hpp"
|
||||
|
||||
#include "widget/widget.hpp"
|
||||
#include "widget/button.hpp"
|
||||
#include "widget/canvas.hpp"
|
||||
#include "widget/check-button.hpp"
|
||||
#include "widget/check-label.hpp"
|
||||
#include "widget/combo-button.hpp"
|
||||
#include "widget/combo-button-item.hpp"
|
||||
#include "widget/console.hpp"
|
||||
#include "widget/frame.hpp"
|
||||
#include "widget/hex-edit.hpp"
|
||||
#include "widget/horizontal-scroll-bar.hpp"
|
||||
#include "widget/horizontal-slider.hpp"
|
||||
#include "widget/label.hpp"
|
||||
#include "widget/line-edit.hpp"
|
||||
#include "widget/list-view.hpp"
|
||||
#include "widget/list-view-header.hpp"
|
||||
#include "widget/list-view-column.hpp"
|
||||
#include "widget/list-view-item.hpp"
|
||||
#include "widget/list-view-cell.hpp"
|
||||
#include "widget/progress-bar.hpp"
|
||||
#include "widget/radio-button.hpp"
|
||||
#include "widget/radio-label.hpp"
|
||||
#include "widget/tab-frame.hpp"
|
||||
#include "widget/tab-frame-item.hpp"
|
||||
#include "widget/text-edit.hpp"
|
||||
#include "widget/vertical-scroll-bar.hpp"
|
||||
#include "widget/vertical-slider.hpp"
|
||||
#include "widget/viewport.hpp"
|
||||
|
||||
#undef Declare
|
||||
|
||||
#include "application.hpp"
|
22
cocoa/popup-menu.cpp
Normal file
22
cocoa/popup-menu.cpp
Normal file
|
@ -0,0 +1,22 @@
|
|||
#if defined(Hiro_PopupMenu)
|
||||
|
||||
namespace hiro {
|
||||
|
||||
auto pPopupMenu::construct() -> void {
|
||||
}
|
||||
|
||||
auto pPopupMenu::destruct() -> void {
|
||||
}
|
||||
|
||||
auto pPopupMenu::append(sAction action) -> void {
|
||||
}
|
||||
|
||||
auto pPopupMenu::remove(sAction action) -> void {
|
||||
}
|
||||
|
||||
auto pPopupMenu::setVisible(bool visible) -> void {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
15
cocoa/popup-menu.hpp
Normal file
15
cocoa/popup-menu.hpp
Normal file
|
@ -0,0 +1,15 @@
|
|||
#if defined(Hiro_PopupMenu)
|
||||
|
||||
namespace hiro {
|
||||
|
||||
struct pPopupMenu : pObject {
|
||||
Declare(PopupMenu, Object)
|
||||
|
||||
auto append(sAction action) -> void;
|
||||
auto remove(sAction action) -> void;
|
||||
auto setVisible(bool visible) -> void;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
20
cocoa/sizable.cpp
Normal file
20
cocoa/sizable.cpp
Normal file
|
@ -0,0 +1,20 @@
|
|||
#if defined(Hiro_Sizable)
|
||||
|
||||
namespace hiro {
|
||||
|
||||
auto pSizable::construct() -> void {
|
||||
}
|
||||
|
||||
auto pSizable::destruct() -> void {
|
||||
}
|
||||
|
||||
auto pSizable::minimumSize() const -> Size {
|
||||
return {0, 0};
|
||||
}
|
||||
|
||||
auto pSizable::setGeometry(Geometry geometry) -> void {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
14
cocoa/sizable.hpp
Normal file
14
cocoa/sizable.hpp
Normal file
|
@ -0,0 +1,14 @@
|
|||
#if defined(Hiro_Sizable)
|
||||
|
||||
namespace hiro {
|
||||
|
||||
struct pSizable : pObject {
|
||||
Declare(Sizable, Object)
|
||||
|
||||
virtual auto minimumSize() const -> Size;
|
||||
virtual auto setGeometry(Geometry geometry) -> void;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
53
cocoa/status-bar.cpp
Normal file
53
cocoa/status-bar.cpp
Normal file
|
@ -0,0 +1,53 @@
|
|||
#if defined(Hiro_StatusBar)
|
||||
|
||||
namespace hiro {
|
||||
|
||||
auto pStatusBar::construct() -> void {
|
||||
}
|
||||
|
||||
auto pStatusBar::destruct() -> void {
|
||||
}
|
||||
|
||||
auto pStatusBar::setEnabled(bool enabled) -> void {
|
||||
@autoreleasepool {
|
||||
if(auto parent = _parent()) {
|
||||
[[parent->cocoaWindow statusBar] setEnabled:enabled];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto pStatusBar::setFont(const Font& font) -> void {
|
||||
@autoreleasepool {
|
||||
if(auto parent = _parent()) {
|
||||
[[parent->cocoaWindow statusBar] setFont:pFont::create(font)];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto pStatusBar::setText(const string& text) -> void {
|
||||
@autoreleasepool {
|
||||
if(auto parent = _parent()) {
|
||||
[[parent->cocoaWindow statusBar] setStringValue:[NSString stringWithUTF8String:state().text]];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto pStatusBar::setVisible(bool visible) -> void {
|
||||
@autoreleasepool {
|
||||
if(auto parent = _parent()) {
|
||||
[[parent->cocoaWindow statusBar] setHidden:!visible];
|
||||
parent->setGeometry(parent->state().geometry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto pStatusBar::_parent() -> maybe<pWindow&> {
|
||||
if(auto parent = self().parentWindow()) {
|
||||
if(auto self = parent->self()) return *self;
|
||||
}
|
||||
return nothing;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
18
cocoa/status-bar.hpp
Normal file
18
cocoa/status-bar.hpp
Normal file
|
@ -0,0 +1,18 @@
|
|||
#if defined(Hiro_StatusBar)
|
||||
|
||||
namespace hiro {
|
||||
|
||||
struct pStatusBar : pObject {
|
||||
Declare(StatusBar, Object)
|
||||
|
||||
auto setEnabled(bool enabled) -> void override;
|
||||
auto setFont(const Font& font) -> void override;
|
||||
auto setText(const string& text) -> void;
|
||||
auto setVisible(bool visible) -> void override;
|
||||
|
||||
auto _parent() -> maybe<pWindow&>;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
67
cocoa/timer.cpp
Normal file
67
cocoa/timer.cpp
Normal file
|
@ -0,0 +1,67 @@
|
|||
#if defined(Hiro_Timer)
|
||||
|
||||
@implementation CocoaTimer : NSObject
|
||||
|
||||
-(id) initWith:(hiro::mTimer&)timerReference {
|
||||
if(self = [super init]) {
|
||||
timer = &timerReference;
|
||||
instance = nil;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
-(NSTimer*) instance {
|
||||
return instance;
|
||||
}
|
||||
|
||||
-(void) update {
|
||||
if(instance) {
|
||||
[instance invalidate];
|
||||
instance = nil;
|
||||
}
|
||||
if(timer->enabled()) {
|
||||
instance = [NSTimer
|
||||
scheduledTimerWithTimeInterval:timer->state.interval / 1000.0
|
||||
target:self selector:@selector(run:) userInfo:nil repeats:YES
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
-(void) run:(NSTimer*)instance {
|
||||
if(timer->enabled()) {
|
||||
timer->doActivate();
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
namespace hiro {
|
||||
|
||||
auto pTimer::construct() -> void {
|
||||
@autoreleasepool {
|
||||
cocoaTimer = [[CocoaTimer alloc] initWith:self()];
|
||||
}
|
||||
}
|
||||
|
||||
auto pTimer::destruct() -> void {
|
||||
@autoreleasepool {
|
||||
if([cocoaTimer instance]) [[cocoaTimer instance] invalidate];
|
||||
[cocoaTimer release];
|
||||
}
|
||||
}
|
||||
|
||||
auto pTimer::setEnabled(bool enabled) -> void {
|
||||
@autoreleasepool {
|
||||
[cocoaTimer update];
|
||||
}
|
||||
}
|
||||
|
||||
auto pTimer::setInterval(uint interval) -> void {
|
||||
@autoreleasepool {
|
||||
[cocoaTimer update];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
27
cocoa/timer.hpp
Normal file
27
cocoa/timer.hpp
Normal file
|
@ -0,0 +1,27 @@
|
|||
#if defined(Hiro_Timer)
|
||||
|
||||
@interface CocoaTimer : NSObject {
|
||||
@public
|
||||
hiro::mTimer* timer;
|
||||
NSTimer* instance;
|
||||
}
|
||||
-(id) initWith:(hiro::mTimer&)timer;
|
||||
-(NSTimer*) instance;
|
||||
-(void) update;
|
||||
-(void) run:(NSTimer*)instance;
|
||||
@end
|
||||
|
||||
namespace hiro {
|
||||
|
||||
struct pTimer : pObject {
|
||||
Declare(Timer, Object)
|
||||
|
||||
auto setEnabled(bool enabled) -> void;
|
||||
auto setInterval(uint interval) -> void;
|
||||
|
||||
CocoaTimer* cocoaTimer = nullptr;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
48
cocoa/utility.cpp
Normal file
48
cocoa/utility.cpp
Normal file
|
@ -0,0 +1,48 @@
|
|||
auto NSMakeColor(const hiro::Color& color) -> NSColor* {
|
||||
return [NSColor colorWithRed:(color.red() / 255.0) green:(color.green() / 255.0) blue:(color.blue() / 255.0) alpha:(color.alpha() / 255.0)];
|
||||
}
|
||||
|
||||
auto NSMakeImage(image icon, uint scaleWidth = 0, uint scaleHeight = 0) -> NSImage* {
|
||||
if(!icon) return nil;
|
||||
|
||||
if(scaleWidth && scaleHeight) icon.scale(scaleWidth, scaleHeight);
|
||||
icon.transform(0, 32, 255u << 24, 255u << 0, 255u << 8, 255u << 16); //Cocoa stores images in ABGR format
|
||||
|
||||
//create NSImage from memory
|
||||
NSImage* cocoaImage = [[[NSImage alloc] initWithSize:NSMakeSize(icon.width(), icon.height())] autorelease];
|
||||
NSBitmapImageRep* bitmap = [[[NSBitmapImageRep alloc]
|
||||
initWithBitmapDataPlanes:nil
|
||||
pixelsWide:icon.width() pixelsHigh:icon.height()
|
||||
bitsPerSample:8 samplesPerPixel:4 hasAlpha:YES
|
||||
isPlanar:NO colorSpaceName:NSCalibratedRGBColorSpace
|
||||
bitmapFormat:NSAlphaNonpremultipliedBitmapFormat
|
||||
bytesPerRow:(4 * icon.width()) bitsPerPixel:32
|
||||
] autorelease];
|
||||
memory::copy([bitmap bitmapData], icon.data(), 4 * icon.width() * icon.height());
|
||||
[cocoaImage addRepresentation:bitmap];
|
||||
return cocoaImage;
|
||||
}
|
||||
|
||||
auto DropPathsOperation(id<NSDraggingInfo> sender) -> NSDragOperation {
|
||||
NSPasteboard* pboard = [sender draggingPasteboard];
|
||||
if([[pboard types] containsObject:NSFilenamesPboardType]) {
|
||||
if([sender draggingSourceOperationMask] & NSDragOperationGeneric) {
|
||||
return NSDragOperationGeneric;
|
||||
}
|
||||
}
|
||||
return NSDragOperationNone;
|
||||
}
|
||||
|
||||
auto DropPaths(id<NSDraggingInfo> sender) -> lstring {
|
||||
lstring paths;
|
||||
NSPasteboard* pboard = [sender draggingPasteboard];
|
||||
if([[pboard types] containsObject:NSFilenamesPboardType]) {
|
||||
NSArray* files = [pboard propertyListForType:NSFilenamesPboardType];
|
||||
for(uint n = 0; n < [files count]; n++) {
|
||||
string path = [[files objectAtIndex:n] UTF8String];
|
||||
if(directory::exists(path) && !path.endsWith("/")) path.append("/");
|
||||
paths.append(path);
|
||||
}
|
||||
}
|
||||
return paths;
|
||||
}
|
90
cocoa/widget/button.cpp
Normal file
90
cocoa/widget/button.cpp
Normal file
|
@ -0,0 +1,90 @@
|
|||
#if defined(Hiro_Button)
|
||||
|
||||
@implementation CocoaButton : NSButton
|
||||
|
||||
-(id) initWith:(hiro::mButton&)buttonReference {
|
||||
if(self = [super initWithFrame:NSMakeRect(0, 0, 0, 0)]) {
|
||||
button = &buttonReference;
|
||||
[self setTarget:self];
|
||||
[self setAction:@selector(activate:)];
|
||||
//NSRoundedBezelStyle has a fixed height; which breaks both icons and larger/smaller text
|
||||
[self setBezelStyle:NSRegularSquareBezelStyle];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
-(IBAction) activate:(id)sender {
|
||||
button->doActivate();
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
namespace hiro {
|
||||
|
||||
auto pButton::construct() -> void {
|
||||
@autoreleasepool {
|
||||
cocoaView = cocoaButton = [[CocoaButton alloc] initWith:self()];
|
||||
pWidget::construct();
|
||||
|
||||
setBordered(state().bordered);
|
||||
setIcon(state().icon);
|
||||
setOrientation(state().orientation);
|
||||
setText(state().text);
|
||||
}
|
||||
}
|
||||
|
||||
auto pButton::destruct() -> void {
|
||||
@autoreleasepool {
|
||||
[cocoaView removeFromSuperview];
|
||||
[cocoaView release];
|
||||
}
|
||||
}
|
||||
|
||||
auto pButton::minimumSize() const -> Size {
|
||||
Size size = pFont::size(self().font(true), state().text);
|
||||
|
||||
if(state().orientation == Orientation::Horizontal) {
|
||||
size.setWidth(size.width() + state().icon.width());
|
||||
size.setHeight(max(size.height(), state().icon.height()));
|
||||
}
|
||||
|
||||
if(state().orientation == Orientation::Vertical) {
|
||||
size.setWidth(max(size.width(), state().icon.width()));
|
||||
size.setHeight(size.height() + state().icon.height());
|
||||
}
|
||||
|
||||
return {size.width() + (state().text ? 20 : 8), size.height() + 8};
|
||||
}
|
||||
|
||||
auto pButton::setBordered(bool bordered) -> void {
|
||||
}
|
||||
|
||||
auto pButton::setGeometry(Geometry geometry) -> void {
|
||||
pWidget::setGeometry({
|
||||
geometry.x() - 2, geometry.y() - 2,
|
||||
geometry.width() + 4, geometry.height() + 4
|
||||
});
|
||||
}
|
||||
|
||||
auto pButton::setIcon(const image& icon) -> void {
|
||||
@autoreleasepool {
|
||||
[cocoaView setImage:NSMakeImage(icon)];
|
||||
}
|
||||
}
|
||||
|
||||
auto pButton::setOrientation(Orientation orientation) -> void {
|
||||
@autoreleasepool {
|
||||
if(orientation == Orientation::Horizontal) [cocoaView setImagePosition:NSImageLeft];
|
||||
if(orientation == Orientation::Vertical ) [cocoaView setImagePosition:NSImageAbove];
|
||||
}
|
||||
}
|
||||
|
||||
auto pButton::setText(const string& text) -> void {
|
||||
@autoreleasepool {
|
||||
[cocoaView setTitle:[NSString stringWithUTF8String:text]];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
28
cocoa/widget/button.hpp
Normal file
28
cocoa/widget/button.hpp
Normal file
|
@ -0,0 +1,28 @@
|
|||
#if defined(Hiro_Button)
|
||||
|
||||
@interface CocoaButton : NSButton {
|
||||
@public
|
||||
hiro::mButton* button;
|
||||
}
|
||||
-(id) initWith:(hiro::mButton&)button;
|
||||
-(IBAction) activate:(id)sender;
|
||||
@end
|
||||
|
||||
namespace hiro {
|
||||
|
||||
struct pButton : pWidget {
|
||||
Declare(Button, Widget)
|
||||
|
||||
auto minimumSize() const -> Size override;
|
||||
auto setBordered(bool bordered) -> void;
|
||||
auto setGeometry(Geometry geometry) -> void override;
|
||||
auto setIcon(const image& icon) -> void;
|
||||
auto setOrientation(Orientation orientation) -> void;
|
||||
auto setText(const string& text) -> void;
|
||||
|
||||
CocoaButton* cocoaButton = nullptr;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
208
cocoa/widget/canvas.cpp
Normal file
208
cocoa/widget/canvas.cpp
Normal file
|
@ -0,0 +1,208 @@
|
|||
#if defined(Hiro_Canvas)
|
||||
|
||||
@implementation CocoaCanvas : NSImageView
|
||||
|
||||
-(id) initWith:(hiro::mCanvas&)canvasReference {
|
||||
if(self = [super initWithFrame:NSMakeRect(0, 0, 0, 0)]) {
|
||||
canvas = &canvasReference;
|
||||
[self setEditable:NO]; //disable image drag-and-drop functionality
|
||||
NSTrackingArea* area = [[[NSTrackingArea alloc] initWithRect:[self frame]
|
||||
options:NSTrackingMouseMoved | NSTrackingMouseEnteredAndExited | NSTrackingActiveInKeyWindow | NSTrackingInVisibleRect
|
||||
owner:self userInfo:nil
|
||||
] autorelease];
|
||||
[self addTrackingArea:area];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
-(NSDragOperation) draggingEntered:(id<NSDraggingInfo>)sender {
|
||||
return DropPathsOperation(sender);
|
||||
}
|
||||
|
||||
-(BOOL) performDragOperation:(id<NSDraggingInfo>)sender {
|
||||
lstring paths = DropPaths(sender);
|
||||
if(paths.empty()) return NO;
|
||||
canvas->doDrop(paths);
|
||||
return YES;
|
||||
}
|
||||
|
||||
-(void) mouseButton:(NSEvent*)event down:(BOOL)isDown {
|
||||
if(isDown) {
|
||||
switch([event buttonNumber]) {
|
||||
case 0: return canvas->doMousePress(hiro::Mouse::Button::Left);
|
||||
case 1: return canvas->doMousePress(hiro::Mouse::Button::Right);
|
||||
case 2: return canvas->doMousePress(hiro::Mouse::Button::Middle);
|
||||
}
|
||||
} else {
|
||||
switch([event buttonNumber]) {
|
||||
case 0: return canvas->doMouseRelease(hiro::Mouse::Button::Left);
|
||||
case 1: return canvas->doMouseRelease(hiro::Mouse::Button::Right);
|
||||
case 2: return canvas->doMouseRelease(hiro::Mouse::Button::Middle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
-(void) mouseExited:(NSEvent*)event {
|
||||
canvas->doMouseLeave();
|
||||
}
|
||||
|
||||
-(void) mouseMove:(NSEvent*)event {
|
||||
if([event window] == nil) return;
|
||||
NSPoint location = [self convertPoint:[event locationInWindow] fromView:nil];
|
||||
canvas->doMouseMove({(int)location.x, (int)([self frame].size.height - 1 - location.y)});
|
||||
}
|
||||
|
||||
-(void) mouseDown:(NSEvent*)event {
|
||||
[self mouseButton:event down:YES];
|
||||
}
|
||||
|
||||
-(void) mouseUp:(NSEvent*)event {
|
||||
[self mouseButton:event down:NO];
|
||||
}
|
||||
|
||||
-(void) mouseDragged:(NSEvent*)event {
|
||||
[self mouseMove:event];
|
||||
}
|
||||
|
||||
-(void) rightMouseDown:(NSEvent*)event {
|
||||
[self mouseButton:event down:YES];
|
||||
}
|
||||
|
||||
-(void) rightMouseUp:(NSEvent*)event {
|
||||
[self mouseButton:event down:NO];
|
||||
}
|
||||
|
||||
-(void) rightMouseDragged:(NSEvent*)event {
|
||||
[self mouseMove:event];
|
||||
}
|
||||
|
||||
-(void) otherMouseDown:(NSEvent*)event {
|
||||
[self mouseButton:event down:YES];
|
||||
}
|
||||
|
||||
-(void) otherMouseUp:(NSEvent*)event {
|
||||
[self mouseButton:event down:NO];
|
||||
}
|
||||
|
||||
-(void) otherMouseDragged:(NSEvent*)event {
|
||||
[self mouseMove:event];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
namespace hiro {
|
||||
|
||||
auto pCanvas::construct() -> void {
|
||||
@autoreleasepool {
|
||||
cocoaView = cocoaCanvas = [[CocoaCanvas alloc] initWith:self()];
|
||||
pWidget::construct();
|
||||
|
||||
setDroppable(state().droppable);
|
||||
}
|
||||
}
|
||||
|
||||
auto pCanvas::destruct() -> void {
|
||||
@autoreleasepool {
|
||||
[cocoaView removeFromSuperview];
|
||||
[cocoaView release];
|
||||
}
|
||||
}
|
||||
|
||||
auto pCanvas::minimumSize() const -> Size {
|
||||
if(auto& icon = state().icon) return {(int)icon.width(), (int)icon.height()};
|
||||
return {0, 0};
|
||||
}
|
||||
|
||||
auto pCanvas::setColor(Color color) -> void {
|
||||
update();
|
||||
}
|
||||
|
||||
auto pCanvas::setDroppable(bool droppable) -> void {
|
||||
@autoreleasepool {
|
||||
if(droppable) {
|
||||
[cocoaCanvas registerForDraggedTypes:[NSArray arrayWithObject:NSFilenamesPboardType]];
|
||||
} else {
|
||||
[cocoaCanvas unregisterDraggedTypes];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto pCanvas::setGeometry(Geometry geometry) -> void {
|
||||
pWidget::setGeometry(geometry);
|
||||
update();
|
||||
}
|
||||
|
||||
auto pCanvas::setGradient(Gradient gradient) -> void {
|
||||
update();
|
||||
}
|
||||
|
||||
auto pCanvas::setIcon(const image& icon) -> void {
|
||||
update();
|
||||
}
|
||||
|
||||
auto pCanvas::update() -> void {
|
||||
_rasterize();
|
||||
@autoreleasepool {
|
||||
[cocoaView setNeedsDisplay:YES];
|
||||
}
|
||||
}
|
||||
|
||||
auto pCanvas::_rasterize() -> void {
|
||||
@autoreleasepool {
|
||||
int width = 0;
|
||||
int height = 0;
|
||||
|
||||
if(auto& icon = state().icon) {
|
||||
width = icon.width();
|
||||
height = icon.height();
|
||||
} else {
|
||||
width = pSizable::state().geometry.width();
|
||||
height = pSizable::state().geometry.height();
|
||||
}
|
||||
if(width <= 0 || height <= 0) return;
|
||||
|
||||
if(width != surfaceWidth || height != surfaceHeight) {
|
||||
[cocoaView setImage:nil];
|
||||
[surface release];
|
||||
surface = nullptr;
|
||||
bitmap = nullptr;
|
||||
}
|
||||
|
||||
surfaceWidth = width;
|
||||
surfaceHeight = height;
|
||||
|
||||
if(!surface) {
|
||||
surface = [[[NSImage alloc] initWithSize:NSMakeSize(width, height)] autorelease];
|
||||
bitmap = [[[NSBitmapImageRep alloc]
|
||||
initWithBitmapDataPlanes:nil
|
||||
pixelsWide:width pixelsHigh:height
|
||||
bitsPerSample:8 samplesPerPixel:4 hasAlpha:YES
|
||||
isPlanar:NO colorSpaceName:NSCalibratedRGBColorSpace
|
||||
bitmapFormat:NSAlphaNonpremultipliedBitmapFormat
|
||||
bytesPerRow:(width * 4) bitsPerPixel:32
|
||||
] autorelease];
|
||||
[surface addRepresentation:bitmap];
|
||||
[cocoaView setImage:surface];
|
||||
}
|
||||
|
||||
auto target = (uint32*)[bitmap bitmapData];
|
||||
|
||||
if(auto icon = state().icon) {
|
||||
icon.transform();
|
||||
memory::copy(target, icon.data(), icon.size());
|
||||
} else if(auto& gradient = state().gradient) {
|
||||
auto& colors = gradient.state.colors;
|
||||
image fill;
|
||||
fill.allocate(width, height);
|
||||
fill.gradient(colors[0].value(), colors[1].value(), colors[2].value(), colors[3].value());
|
||||
memory::copy(target, fill.data(), fill.size());
|
||||
} else {
|
||||
uint32 color = state().color.value();
|
||||
for(auto n : range(width * height)) target[n] = color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
48
cocoa/widget/canvas.hpp
Normal file
48
cocoa/widget/canvas.hpp
Normal file
|
@ -0,0 +1,48 @@
|
|||
#if defined(Hiro_Canvas)
|
||||
|
||||
@interface CocoaCanvas : NSImageView {
|
||||
@public
|
||||
hiro::mCanvas* canvas;
|
||||
}
|
||||
-(id) initWith:(hiro::mCanvas&)canvas;
|
||||
-(NSDragOperation) draggingEntered:(id<NSDraggingInfo>)sender;
|
||||
-(BOOL) performDragOperation:(id<NSDraggingInfo>)sender;
|
||||
-(void) mouseButton:(NSEvent*)event down:(BOOL)isDown;
|
||||
-(void) mouseExited:(NSEvent*)event;
|
||||
-(void) mouseMove:(NSEvent*)event;
|
||||
-(void) mouseDown:(NSEvent*)event;
|
||||
-(void) mouseUp:(NSEvent*)event;
|
||||
-(void) mouseDragged:(NSEvent*)event;
|
||||
-(void) rightMouseDown:(NSEvent*)event;
|
||||
-(void) rightMouseUp:(NSEvent*)event;
|
||||
-(void) rightMouseDragged:(NSEvent*)event;
|
||||
-(void) otherMouseDown:(NSEvent*)event;
|
||||
-(void) otherMouseUp:(NSEvent*)event;
|
||||
-(void) otherMouseDragged:(NSEvent*)event;
|
||||
@end
|
||||
|
||||
namespace hiro {
|
||||
|
||||
struct pCanvas : pWidget {
|
||||
Declare(Canvas, Widget)
|
||||
|
||||
auto minimumSize() const -> Size;
|
||||
auto setColor(Color color) -> void;
|
||||
auto setDroppable(bool droppable) -> void;
|
||||
auto setGeometry(Geometry geometry) -> void override;
|
||||
auto setGradient(Gradient gradient) -> void;
|
||||
auto setIcon(const image& icon) -> void;
|
||||
auto update() -> void;
|
||||
|
||||
auto _rasterize() -> void;
|
||||
|
||||
CocoaCanvas* cocoaCanvas = nullptr;
|
||||
NSImage* surface = nullptr;
|
||||
NSBitmapImageRep* bitmap = nullptr;
|
||||
uint surfaceWidth = 0;
|
||||
uint surfaceHeight = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
99
cocoa/widget/check-button.cpp
Normal file
99
cocoa/widget/check-button.cpp
Normal file
|
@ -0,0 +1,99 @@
|
|||
#if defined(Hiro_CheckButton)
|
||||
|
||||
@implementation CocoaCheckButton : NSButton
|
||||
|
||||
-(id) initWith:(hiro::mCheckButton&)checkButtonReference {
|
||||
if(self = [super initWithFrame:NSMakeRect(0, 0, 0, 0)]) {
|
||||
checkButton = &checkButtonReference;
|
||||
|
||||
[self setTarget:self];
|
||||
[self setAction:@selector(activate:)];
|
||||
[self setBezelStyle:NSRegularSquareBezelStyle];
|
||||
[self setButtonType:NSOnOffButton];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
-(IBAction) activate:(id)sender {
|
||||
checkButton->state.checked = [self state] != NSOffState;
|
||||
checkButton->doToggle();
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
namespace hiro {
|
||||
|
||||
auto pCheckButton::construct() -> void {
|
||||
@autoreleasepool {
|
||||
cocoaView = cocoaCheckButton = [[CocoaCheckButton alloc] initWith:self()];
|
||||
pWidget::construct();
|
||||
|
||||
setBordered(state().bordered);
|
||||
setChecked(state().checked);
|
||||
setIcon(state().icon);
|
||||
setOrientation(state().orientation);
|
||||
setText(state().text);
|
||||
}
|
||||
}
|
||||
|
||||
auto pCheckButton::destruct() -> void {
|
||||
@autoreleasepool {
|
||||
[cocoaView removeFromSuperview];
|
||||
[cocoaView release];
|
||||
}
|
||||
}
|
||||
|
||||
auto pCheckButton::minimumSize() const -> Size {
|
||||
Size size = pFont::size(self().font(true), state().text);
|
||||
|
||||
if(state().orientation == Orientation::Horizontal) {
|
||||
size.setWidth(size.width() + state().icon.width());
|
||||
size.setHeight(max(size.height(), state().icon.height()));
|
||||
}
|
||||
|
||||
if(state().orientation == Orientation::Vertical) {
|
||||
size.setWidth(max(size.width(), state().icon.width()));
|
||||
size.setHeight(size.height() + state().icon.height());
|
||||
}
|
||||
|
||||
return {size.width() + (state().text ? 20 : 8), size.height() + 8};
|
||||
}
|
||||
|
||||
auto pCheckButton::setBordered(bool bordered) -> void {
|
||||
}
|
||||
|
||||
auto pCheckButton::setChecked(bool checked) -> void {
|
||||
@autoreleasepool {
|
||||
[cocoaView setState:checked ? NSOnState : NSOffState];
|
||||
}
|
||||
}
|
||||
|
||||
auto pCheckButton::setGeometry(Geometry geometry) -> void {
|
||||
pWidget::setGeometry({
|
||||
geometry.x() - 2, geometry.y() - 2,
|
||||
geometry.width() + 4, geometry.height() + 4
|
||||
});
|
||||
}
|
||||
|
||||
auto pCheckButton::setIcon(const image& icon) -> void {
|
||||
@autoreleasepool {
|
||||
[cocoaView setImage:NSMakeImage(icon)];
|
||||
}
|
||||
}
|
||||
|
||||
auto pCheckButton::setOrientation(Orientation orientation) -> void {
|
||||
@autoreleasepool {
|
||||
if(orientation == Orientation::Horizontal) [cocoaView setImagePosition:NSImageLeft];
|
||||
if(orientation == Orientation::Vertical ) [cocoaView setImagePosition:NSImageAbove];
|
||||
}
|
||||
}
|
||||
|
||||
auto pCheckButton::setText(const string& text) -> void {
|
||||
@autoreleasepool {
|
||||
[cocoaView setTitle:[NSString stringWithUTF8String:text]];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
29
cocoa/widget/check-button.hpp
Normal file
29
cocoa/widget/check-button.hpp
Normal file
|
@ -0,0 +1,29 @@
|
|||
#if defined(Hiro_CheckButton)
|
||||
|
||||
@interface CocoaCheckButton : NSButton {
|
||||
@public
|
||||
hiro::mCheckButton* checkButton;
|
||||
}
|
||||
-(id) initWith:(hiro::mCheckButton&)checkButton;
|
||||
-(IBAction) activate:(id)sender;
|
||||
@end
|
||||
|
||||
namespace hiro {
|
||||
|
||||
struct pCheckButton : pWidget {
|
||||
Declare(CheckButton, Widget)
|
||||
|
||||
auto minimumSize() const -> Size override;
|
||||
auto setBordered(bool bordered) -> void;
|
||||
auto setChecked(bool checked) -> void;
|
||||
auto setGeometry(Geometry geometry) -> void override;
|
||||
auto setIcon(const image& icon) -> void;
|
||||
auto setOrientation(Orientation orientation) -> void;
|
||||
auto setText(const string& text) -> void;
|
||||
|
||||
CocoaCheckButton* cocoaCheckButton = nullptr;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
68
cocoa/widget/check-label.cpp
Normal file
68
cocoa/widget/check-label.cpp
Normal file
|
@ -0,0 +1,68 @@
|
|||
#if defined(Hiro_CheckLabel)
|
||||
|
||||
@implementation CocoaCheckLabel : NSButton
|
||||
|
||||
-(id) initWith:(hiro::mCheckLabel&)checkLabelReference {
|
||||
if(self = [super initWithFrame:NSMakeRect(0, 0, 0, 0)]) {
|
||||
checkLabel = &checkLabelReference;
|
||||
|
||||
[self setTarget:self];
|
||||
[self setAction:@selector(activate:)];
|
||||
[self setButtonType:NSSwitchButton];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
-(IBAction) activate:(id)sender {
|
||||
checkLabel->state.checked = [self state] != NSOffState;
|
||||
checkLabel->doToggle();
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
namespace hiro {
|
||||
|
||||
auto pCheckLabel::construct() -> void {
|
||||
@autoreleasepool {
|
||||
cocoaView = cocoaCheckLabel = [[CocoaCheckLabel alloc] initWith:self()];
|
||||
pWidget::construct();
|
||||
|
||||
setChecked(state().checked);
|
||||
setText(state().text);
|
||||
}
|
||||
}
|
||||
|
||||
auto pCheckLabel::destruct() -> void {
|
||||
@autoreleasepool {
|
||||
[cocoaView removeFromSuperview];
|
||||
[cocoaView release];
|
||||
}
|
||||
}
|
||||
|
||||
auto pCheckLabel::minimumSize() const -> Size {
|
||||
Size size = pFont::size(self().font(true), state().text);
|
||||
return {size.width() + 20, size.height()};
|
||||
}
|
||||
|
||||
auto pCheckLabel::setChecked(bool checked) -> void {
|
||||
@autoreleasepool {
|
||||
[cocoaView setState:checked ? NSOnState : NSOffState];
|
||||
}
|
||||
}
|
||||
|
||||
auto pCheckLabel::setGeometry(Geometry geometry) -> void {
|
||||
pWidget::setGeometry({
|
||||
geometry.x() - 2, geometry.y(),
|
||||
geometry.width() + 4, geometry.height()
|
||||
});
|
||||
}
|
||||
|
||||
auto pCheckLabel::setText(const string& text) -> void {
|
||||
@autoreleasepool {
|
||||
[cocoaView setTitle:[NSString stringWithUTF8String:text]];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
26
cocoa/widget/check-label.hpp
Normal file
26
cocoa/widget/check-label.hpp
Normal file
|
@ -0,0 +1,26 @@
|
|||
#if defined(Hiro_CheckLabel)
|
||||
|
||||
@interface CocoaCheckLabel : NSButton {
|
||||
@public
|
||||
hiro::mCheckLabel* checkLabel;
|
||||
}
|
||||
-(id) initWith:(hiro::mCheckLabel&)checkLabel;
|
||||
-(IBAction) activate:(id)sender;
|
||||
@end
|
||||
|
||||
namespace hiro {
|
||||
|
||||
struct pCheckLabel : pWidget {
|
||||
Declare(CheckLabel, Widget)
|
||||
|
||||
auto minimumSize() const -> Size override;
|
||||
auto setChecked(bool checked) -> void;
|
||||
auto setGeometry(Geometry geometry) -> void;
|
||||
auto setText(const string& text) -> void;
|
||||
|
||||
CocoaCheckLabel* cocoaCheckLabel = nullptr;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
39
cocoa/widget/combo-button-item.cpp
Normal file
39
cocoa/widget/combo-button-item.cpp
Normal file
|
@ -0,0 +1,39 @@
|
|||
#if defined(Hiro_ComboButton)
|
||||
|
||||
namespace hiro {
|
||||
|
||||
auto pComboButtonItem::construct() -> void {
|
||||
}
|
||||
|
||||
auto pComboButtonItem::destruct() -> void {
|
||||
}
|
||||
|
||||
auto pComboButtonItem::setIcon(const image& icon) -> void {
|
||||
}
|
||||
|
||||
auto pComboButtonItem::setSelected() -> void {
|
||||
@autoreleasepool {
|
||||
if(auto parent = _parent()) {
|
||||
[parent->cocoaView selectItemAtIndex:self().offset()];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto pComboButtonItem::setText(const string& text) -> void {
|
||||
@autoreleasepool {
|
||||
if(auto parent = _parent()) {
|
||||
[[parent->cocoaView itemAtIndex:self().offset()] setTitle:[NSString stringWithUTF8String:text]];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto pComboButtonItem::_parent() -> maybe<pComboButton&> {
|
||||
if(auto parent = self().parentComboButton()) {
|
||||
if(auto self = parent->self()) return *self;
|
||||
}
|
||||
return nothing;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
17
cocoa/widget/combo-button-item.hpp
Normal file
17
cocoa/widget/combo-button-item.hpp
Normal file
|
@ -0,0 +1,17 @@
|
|||
#if defined(Hiro_ComboButton)
|
||||
|
||||
namespace hiro {
|
||||
|
||||
struct pComboButtonItem : pObject {
|
||||
Declare(ComboButtonItem, Object)
|
||||
|
||||
auto setIcon(const image& icon) -> void;
|
||||
auto setSelected() -> void;
|
||||
auto setText(const string& text) -> void;
|
||||
|
||||
auto _parent() -> maybe<pComboButton&>;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
81
cocoa/widget/combo-button.cpp
Normal file
81
cocoa/widget/combo-button.cpp
Normal file
|
@ -0,0 +1,81 @@
|
|||
#if defined(Hiro_ComboButton)
|
||||
|
||||
@implementation CocoaComboButton : NSPopUpButton
|
||||
|
||||
-(id) initWith:(hiro::mComboButton&)comboButtonReference {
|
||||
if(self = [super initWithFrame:NSMakeRect(0, 0, 0, 0) pullsDown:NO]) {
|
||||
comboButton = &comboButtonReference;
|
||||
|
||||
[self setTarget:self];
|
||||
[self setAction:@selector(activate:)];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
-(IBAction) activate:(id)sender {
|
||||
if(auto p = comboButton->self()) p->_updateSelected([self indexOfSelectedItem]);
|
||||
comboButton->doChange();
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
namespace hiro {
|
||||
|
||||
auto pComboButton::construct() -> void {
|
||||
@autoreleasepool {
|
||||
cocoaView = cocoaComboButton = [[CocoaComboButton alloc] initWith:self()];
|
||||
pWidget::construct();
|
||||
}
|
||||
}
|
||||
|
||||
auto pComboButton::destruct() -> void {
|
||||
@autoreleasepool {
|
||||
[cocoaView removeFromSuperview];
|
||||
[cocoaView release];
|
||||
}
|
||||
}
|
||||
|
||||
auto pComboButton::append(sComboButtonItem item) -> void {
|
||||
@autoreleasepool {
|
||||
[cocoaView addItemWithTitle:[NSString stringWithUTF8String:item->text()]];
|
||||
}
|
||||
}
|
||||
|
||||
auto pComboButton::minimumSize() const -> Size {
|
||||
auto font = self().font(true);
|
||||
int maximumWidth = 0;
|
||||
for(auto& item : state().items) {
|
||||
maximumWidth = max(maximumWidth, pFont::size(font, item->state.text).width());
|
||||
}
|
||||
Size size = pFont::size(font, " ");
|
||||
return {maximumWidth + 36, size.height() + 6};
|
||||
}
|
||||
|
||||
auto pComboButton::remove(sComboButtonItem item) -> void {
|
||||
@autoreleasepool {
|
||||
[cocoaView removeItemAtIndex:item->offset()];
|
||||
}
|
||||
}
|
||||
|
||||
auto pComboButton::reset() -> void {
|
||||
@autoreleasepool {
|
||||
[cocoaView removeAllItems];
|
||||
}
|
||||
}
|
||||
|
||||
auto pComboButton::setGeometry(Geometry geometry) -> void {
|
||||
pWidget::setGeometry({
|
||||
geometry.x() - 2, geometry.y(),
|
||||
geometry.width() + 4, geometry.height()
|
||||
});
|
||||
}
|
||||
|
||||
auto pComboButton::_updateSelected(signed selected) -> void {
|
||||
for(auto& item : state().items) {
|
||||
item->state.selected = item->offset() == selected;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
29
cocoa/widget/combo-button.hpp
Normal file
29
cocoa/widget/combo-button.hpp
Normal file
|
@ -0,0 +1,29 @@
|
|||
#if defined(Hiro_ComboButton)
|
||||
|
||||
@interface CocoaComboButton : NSPopUpButton {
|
||||
@public
|
||||
hiro::mComboButton* comboButton;
|
||||
}
|
||||
-(id) initWith:(hiro::mComboButton&)comboButton;
|
||||
-(IBAction) activate:(id)sender;
|
||||
@end
|
||||
|
||||
namespace hiro {
|
||||
|
||||
struct pComboButton : pWidget {
|
||||
Declare(ComboButton, Widget)
|
||||
|
||||
auto append(sComboButtonItem item) -> void;
|
||||
auto minimumSize() const -> Size override;
|
||||
auto remove(sComboButtonItem item) -> void;
|
||||
auto reset() -> void;
|
||||
auto setGeometry(Geometry geometry) -> void override;
|
||||
|
||||
auto _updateSelected(signed selected) -> void;
|
||||
|
||||
CocoaComboButton* cocoaComboButton = nullptr;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
46
cocoa/widget/console.cpp
Normal file
46
cocoa/widget/console.cpp
Normal file
|
@ -0,0 +1,46 @@
|
|||
#if defined(Hiro_Console)
|
||||
|
||||
@implementation CocoaConsole : NSScrollView
|
||||
|
||||
-(id) initWith:(phoenix::Console&)consoleReference {
|
||||
if(self = [super initWithFrame:NSMakeRect(0, 0, 0, 0)]) {
|
||||
console = &consoleReference;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
namespace hiro {
|
||||
|
||||
void pConsole::print(string text) {
|
||||
}
|
||||
|
||||
void pConsole::reset() {
|
||||
}
|
||||
|
||||
void pConsole::setBackgroundColor(Color color) {
|
||||
}
|
||||
|
||||
void pConsole::setForegroundColor(Color color) {
|
||||
}
|
||||
|
||||
void pConsole::setPrompt(string prompt) {
|
||||
}
|
||||
|
||||
void pConsole::constructor() {
|
||||
@autoreleasepool {
|
||||
cocoaView = cocoaConsole = [[CocoaConsole alloc] initWith:console];
|
||||
}
|
||||
}
|
||||
|
||||
void pConsole::destructor() {
|
||||
@autoreleasepool {
|
||||
[cocoaView removeFromSuperview];
|
||||
[cocoaView release];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
29
cocoa/widget/console.hpp
Normal file
29
cocoa/widget/console.hpp
Normal file
|
@ -0,0 +1,29 @@
|
|||
#if defined(Hiro_Console)
|
||||
|
||||
@interface CocoaConsole : NSScrollView {
|
||||
@public
|
||||
phoenix::Console* console;
|
||||
}
|
||||
-(id) initWith:(phoenix::Console&)console;
|
||||
@end
|
||||
|
||||
namespace hiro {
|
||||
|
||||
struct pConsole : public pWidget {
|
||||
Console& console;
|
||||
CocoaConsole* cocoaConsole = nullptr;
|
||||
|
||||
void print(string text);
|
||||
void reset();
|
||||
void setBackgroundColor(Color color);
|
||||
void setForegroundColor(Color color);
|
||||
void setPrompt(string prompt);
|
||||
|
||||
pConsole(Console& console) : pWidget(console), console(console) {}
|
||||
void constructor();
|
||||
void destructor();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
87
cocoa/widget/frame.cpp
Normal file
87
cocoa/widget/frame.cpp
Normal file
|
@ -0,0 +1,87 @@
|
|||
#if defined(Hiro_Frame)
|
||||
|
||||
@implementation CocoaFrame : NSBox
|
||||
|
||||
-(id) initWith:(hiro::mFrame&)frameReference {
|
||||
if(self = [super initWithFrame:NSMakeRect(0, 0, 0, 0)]) {
|
||||
frame = &frameReference;
|
||||
|
||||
[self setTitle:@""];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
namespace hiro {
|
||||
|
||||
auto pFrame::construct() -> void {
|
||||
@autoreleasepool {
|
||||
cocoaView = cocoaFrame = [[CocoaFrame alloc] initWith:self()];
|
||||
pWidget::construct();
|
||||
|
||||
setText(state().text);
|
||||
}
|
||||
}
|
||||
|
||||
auto pFrame::destruct() -> void {
|
||||
@autoreleasepool {
|
||||
[cocoaView removeFromSuperview];
|
||||
[cocoaView release];
|
||||
}
|
||||
}
|
||||
|
||||
auto pFrame::append(sLayout layout) -> void {
|
||||
}
|
||||
|
||||
auto pFrame::remove(sLayout layout) -> void {
|
||||
}
|
||||
|
||||
auto pFrame::setEnabled(bool enabled) -> void {
|
||||
pWidget::setEnabled(enabled);
|
||||
if(auto layout = _layout()) layout->setEnabled(layout->self().enabled(true));
|
||||
}
|
||||
|
||||
auto pFrame::setFont(const Font& font) -> void {
|
||||
@autoreleasepool {
|
||||
[cocoaView setTitleFont:pFont::create(font)];
|
||||
}
|
||||
if(auto layout = _layout()) layout->setFont(layout->self().font(true));
|
||||
}
|
||||
|
||||
auto pFrame::setGeometry(Geometry geometry) -> void {
|
||||
bool empty = !state().text;
|
||||
Size size = pFont::size(self().font(true), state().text);
|
||||
pWidget::setGeometry({
|
||||
geometry.x() - 3, geometry.y() - (empty ? size.height() - 2 : 1),
|
||||
geometry.width() + 6, geometry.height() + (empty ? size.height() + 2 : 5)
|
||||
});
|
||||
if(auto layout = state().layout) {
|
||||
layout->setGeometry({
|
||||
geometry.x() + 1, geometry.y() + (empty ? 1 : size.height() - 2),
|
||||
geometry.width() - 2, geometry.height() - (empty ? 1 : size.height() - 1)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
auto pFrame::setText(const string& text) -> void {
|
||||
@autoreleasepool {
|
||||
[cocoaView setTitle:[NSString stringWithUTF8String:text]];
|
||||
}
|
||||
}
|
||||
|
||||
auto pFrame::setVisible(bool visible) -> void {
|
||||
pWidget::setVisible(visible);
|
||||
if(auto layout = _layout()) layout->setVisible(layout->self().visible(true));
|
||||
}
|
||||
|
||||
auto pFrame::_layout() -> maybe<pLayout&> {
|
||||
if(auto layout = state().layout) {
|
||||
if(auto self = layout->self()) return *self;
|
||||
}
|
||||
return nothing;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
30
cocoa/widget/frame.hpp
Normal file
30
cocoa/widget/frame.hpp
Normal file
|
@ -0,0 +1,30 @@
|
|||
#if defined(Hiro_Frame)
|
||||
|
||||
@interface CocoaFrame : NSBox {
|
||||
@public
|
||||
hiro::mFrame* frame;
|
||||
}
|
||||
-(id) initWith:(hiro::mFrame&)frame;
|
||||
@end
|
||||
|
||||
namespace hiro {
|
||||
|
||||
struct pFrame : pWidget {
|
||||
Declare(Frame, Widget)
|
||||
|
||||
auto append(sLayout layout) -> void;
|
||||
auto remove(sLayout layout) -> void;
|
||||
auto setEnabled(bool enabled) -> void override;
|
||||
auto setFont(const Font& font) -> void override;
|
||||
auto setGeometry(Geometry geometry) -> void override;
|
||||
auto setText(const string& text) -> void;
|
||||
auto setVisible(bool visible) -> void override;
|
||||
|
||||
auto _layout() -> maybe<pLayout&>;
|
||||
|
||||
CocoaFrame* cocoaFrame = nullptr;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
52
cocoa/widget/hex-edit.cpp
Normal file
52
cocoa/widget/hex-edit.cpp
Normal file
|
@ -0,0 +1,52 @@
|
|||
#if defined(Hiro_HexEdit)
|
||||
|
||||
@implementation CocoaHexEdit : NSScrollView
|
||||
|
||||
-(id) initWith:(phoenix::HexEdit&)hexEditReference {
|
||||
if(self = [super initWithFrame:NSMakeRect(0, 0, 0, 0)]) {
|
||||
hexEdit = &hexEditReference;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
namespace hiro {
|
||||
|
||||
void pHexEdit::setBackgroundColor(Color color) {
|
||||
}
|
||||
|
||||
void pHexEdit::setColumns(unsigned columns) {
|
||||
}
|
||||
|
||||
void pHexEdit::setForegroundColor(Color color) {
|
||||
}
|
||||
|
||||
void pHexEdit::setLength(unsigned length) {
|
||||
}
|
||||
|
||||
void pHexEdit::setOffset(unsigned offset) {
|
||||
}
|
||||
|
||||
void pHexEdit::setRows(unsigned rows) {
|
||||
}
|
||||
|
||||
void pHexEdit::update() {
|
||||
}
|
||||
|
||||
void pHexEdit::constructor() {
|
||||
@autoreleasepool {
|
||||
cocoaView = cocoaHexEdit = [[CocoaHexEdit alloc] initWith:hexEdit];
|
||||
}
|
||||
}
|
||||
|
||||
void pHexEdit::destructor() {
|
||||
@autoreleasepool {
|
||||
[cocoaView removeFromSuperview];
|
||||
[cocoaView release];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
31
cocoa/widget/hex-edit.hpp
Normal file
31
cocoa/widget/hex-edit.hpp
Normal file
|
@ -0,0 +1,31 @@
|
|||
#if defined(Hiro_HexEdit)
|
||||
|
||||
@interface CocoaHexEdit : NSScrollView {
|
||||
@public
|
||||
phoenix::HexEdit* hexEdit;
|
||||
}
|
||||
-(id) initWith:(phoenix::HexEdit&)hexEdit;
|
||||
@end
|
||||
|
||||
namespace hiro {
|
||||
|
||||
struct pHexEdit : public pWidget {
|
||||
HexEdit& hexEdit;
|
||||
CocoaHexEdit* cocoaHexEdit = nullptr;
|
||||
|
||||
void setBackgroundColor(Color color);
|
||||
void setColumns(unsigned columns);
|
||||
void setForegroundColor(Color color);
|
||||
void setLength(unsigned length);
|
||||
void setOffset(unsigned offset);
|
||||
void setRows(unsigned rows);
|
||||
void update();
|
||||
|
||||
pHexEdit(HexEdit& hexEdit) : pWidget(hexEdit), hexEdit(hexEdit) {}
|
||||
void constructor();
|
||||
void destructor();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
94
cocoa/widget/horizontal-scroll-bar.cpp
Normal file
94
cocoa/widget/horizontal-scroll-bar.cpp
Normal file
|
@ -0,0 +1,94 @@
|
|||
#if defined(Hiro_HorizontalScrollBar)
|
||||
|
||||
@implementation CocoaHorizontalScrollBar : NSScroller
|
||||
|
||||
-(id) initWith:(hiro::mHorizontalScrollBar&)horizontalScrollBarReference {
|
||||
if(self = [super initWithFrame:NSMakeRect(0, 0, 1, 0)]) {
|
||||
horizontalScrollBar = &horizontalScrollBarReference;
|
||||
|
||||
[self setTarget:self];
|
||||
[self setAction:@selector(scroll:)];
|
||||
|
||||
[self setControlSize:NSRegularControlSize];
|
||||
[self setScrollerStyle:NSScrollerStyleLegacy];
|
||||
[self setEnabled:YES];
|
||||
|
||||
[self update];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
-(void) update {
|
||||
double d = 1.0 / horizontalScrollBar->state.length;
|
||||
double f = d * horizontalScrollBar->state.position;
|
||||
|
||||
[self setDoubleValue:f];
|
||||
[self setKnobProportion:d];
|
||||
}
|
||||
|
||||
-(IBAction) scroll:(id)sender {
|
||||
auto& state = horizontalScrollBar->state;
|
||||
|
||||
switch([self hitPart]) {
|
||||
case NSScrollerIncrementLine:
|
||||
case NSScrollerIncrementPage:
|
||||
if(state.position < state.length - 1) state.position++;
|
||||
[self update];
|
||||
break;
|
||||
|
||||
case NSScrollerDecrementLine:
|
||||
case NSScrollerDecrementPage:
|
||||
if(state.position) state.position--;
|
||||
[self update];
|
||||
break;
|
||||
|
||||
case NSScrollerKnob:
|
||||
state.position = [self doubleValue] * state.length;
|
||||
break;
|
||||
}
|
||||
|
||||
horizontalScrollBar->doChange();
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
namespace hiro {
|
||||
|
||||
auto pHorizontalScrollBar::construct() -> void {
|
||||
@autoreleasepool {
|
||||
cocoaView = cocoaHorizontalScrollBar = [[CocoaHorizontalScrollBar alloc] initWith:self()];
|
||||
pWidget::construct();
|
||||
|
||||
setLength(state().length);
|
||||
setPosition(state().position);
|
||||
}
|
||||
}
|
||||
|
||||
auto pHorizontalScrollBar::destruct() -> void {
|
||||
@autoreleasepool {
|
||||
[cocoaView removeFromSuperview];
|
||||
[cocoaView release];
|
||||
}
|
||||
}
|
||||
|
||||
auto pHorizontalScrollBar::minimumSize() const -> Size {
|
||||
@autoreleasepool {
|
||||
return {32, (int)[NSScroller scrollerWidthForControlSize:NSRegularControlSize scrollerStyle:NSScrollerStyleLegacy]};
|
||||
}
|
||||
}
|
||||
|
||||
auto pHorizontalScrollBar::setLength(uint length) -> void {
|
||||
@autoreleasepool {
|
||||
[cocoaView update];
|
||||
}
|
||||
}
|
||||
|
||||
auto pHorizontalScrollBar::setPosition(uint position) -> void {
|
||||
@autoreleasepool {
|
||||
[cocoaView update];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
26
cocoa/widget/horizontal-scroll-bar.hpp
Normal file
26
cocoa/widget/horizontal-scroll-bar.hpp
Normal file
|
@ -0,0 +1,26 @@
|
|||
#if defined(Hiro_HorizontalScrollBar)
|
||||
|
||||
@interface CocoaHorizontalScrollBar : NSScroller {
|
||||
@public
|
||||
hiro::mHorizontalScrollBar* horizontalScrollBar;
|
||||
}
|
||||
-(id) initWith:(hiro::mHorizontalScrollBar&)horizontalScrollBar;
|
||||
-(void) update;
|
||||
-(IBAction) scroll:(id)sender;
|
||||
@end
|
||||
|
||||
namespace hiro {
|
||||
|
||||
struct pHorizontalScrollBar : pWidget {
|
||||
Declare(HorizontalScrollBar, Widget)
|
||||
|
||||
auto minimumSize() const -> Size override;
|
||||
auto setLength(uint length) -> void;
|
||||
auto setPosition(uint position) -> void;
|
||||
|
||||
CocoaHorizontalScrollBar* cocoaHorizontalScrollBar = nullptr;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
67
cocoa/widget/horizontal-slider.cpp
Normal file
67
cocoa/widget/horizontal-slider.cpp
Normal file
|
@ -0,0 +1,67 @@
|
|||
#if defined(Hiro_HorizontalSlider)
|
||||
|
||||
@implementation CocoaHorizontalSlider : NSSlider
|
||||
|
||||
-(id) initWith:(hiro::mHorizontalSlider&)horizontalSliderReference {
|
||||
if(self = [super initWithFrame:NSMakeRect(0, 0, 1, 0)]) {
|
||||
horizontalSlider = &horizontalSliderReference;
|
||||
|
||||
[self setTarget:self];
|
||||
[self setAction:@selector(activate:)];
|
||||
[self setMinValue:0];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
-(IBAction) activate:(id)sender {
|
||||
horizontalSlider->state.position = [self doubleValue];
|
||||
horizontalSlider->doChange();
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
namespace hiro {
|
||||
|
||||
auto pHorizontalSlider::construct() -> void {
|
||||
@autoreleasepool {
|
||||
cocoaView = cocoaHorizontalSlider = [[CocoaHorizontalSlider alloc] initWith:self()];
|
||||
pWidget::construct();
|
||||
|
||||
setLength(state().length);
|
||||
setPosition(state().position);
|
||||
}
|
||||
}
|
||||
|
||||
auto pHorizontalSlider::destruct() -> void {
|
||||
@autoreleasepool {
|
||||
[cocoaView removeFromSuperview];
|
||||
[cocoaView release];
|
||||
}
|
||||
}
|
||||
|
||||
auto pHorizontalSlider::minimumSize() const -> Size {
|
||||
return {48, 20};
|
||||
}
|
||||
|
||||
auto pHorizontalSlider::setGeometry(Geometry geometry) -> void {
|
||||
pWidget::setGeometry({
|
||||
geometry.x() - 2, geometry.y(),
|
||||
geometry.width() + 4, geometry.height()
|
||||
});
|
||||
}
|
||||
|
||||
auto pHorizontalSlider::setLength(uint length) -> void {
|
||||
@autoreleasepool {
|
||||
[cocoaView setMaxValue:length];
|
||||
}
|
||||
}
|
||||
|
||||
auto pHorizontalSlider::setPosition(uint position) -> void {
|
||||
@autoreleasepool {
|
||||
[cocoaView setDoubleValue:position];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
26
cocoa/widget/horizontal-slider.hpp
Normal file
26
cocoa/widget/horizontal-slider.hpp
Normal file
|
@ -0,0 +1,26 @@
|
|||
#if defined(Hiro_HorizontalSlider)
|
||||
|
||||
@interface CocoaHorizontalSlider : NSSlider {
|
||||
@public
|
||||
hiro::mHorizontalSlider* horizontalSlider;
|
||||
}
|
||||
-(id) initWith:(hiro::mHorizontalSlider&)horizontalSlider;
|
||||
-(IBAction) activate:(id)sender;
|
||||
@end
|
||||
|
||||
namespace hiro {
|
||||
|
||||
struct pHorizontalSlider : pWidget {
|
||||
Declare(HorizontalSlider, Widget)
|
||||
|
||||
auto minimumSize() const -> Size override;
|
||||
auto setGeometry(Geometry geometry) -> void;
|
||||
auto setLength(uint length) -> void;
|
||||
auto setPosition(uint position) -> void;
|
||||
|
||||
CocoaHorizontalSlider* cocoaHorizontalSlider = nullptr;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
77
cocoa/widget/label.cpp
Normal file
77
cocoa/widget/label.cpp
Normal file
|
@ -0,0 +1,77 @@
|
|||
#if defined(Hiro_Label)
|
||||
|
||||
@implementation CocoaLabel : NSTextView
|
||||
|
||||
-(id) initWith:(hiro::mLabel&)labelReference {
|
||||
if(self = [super initWithFrame:NSMakeRect(0, 0, 0, 0)]) {
|
||||
label = &labelReference;
|
||||
|
||||
[self setDrawsBackground:NO];
|
||||
[self setEditable:NO];
|
||||
[self setRichText:NO];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
namespace hiro {
|
||||
|
||||
auto pLabel::construct() -> void {
|
||||
@autoreleasepool {
|
||||
cocoaView = cocoaLabel = [[CocoaLabel alloc] initWith:self()];
|
||||
pWidget::construct();
|
||||
|
||||
setAlignment(state().alignment);
|
||||
setText(state().text);
|
||||
}
|
||||
}
|
||||
|
||||
auto pLabel::destruct() -> void {
|
||||
@autoreleasepool {
|
||||
[cocoaView removeFromSuperview];
|
||||
[cocoaView release];
|
||||
}
|
||||
}
|
||||
|
||||
auto pLabel::minimumSize() const -> Size {
|
||||
return pFont::size(self().font(true), state().text);
|
||||
}
|
||||
|
||||
auto pLabel::setAlignment(Alignment alignment) -> void {
|
||||
@autoreleasepool {
|
||||
NSMutableParagraphStyle* paragraphStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
|
||||
paragraphStyle.alignment = NSTextAlignmentCenter;
|
||||
if(alignment.horizontal() < 0.333) paragraphStyle.alignment = NSTextAlignmentLeft;
|
||||
if(alignment.horizontal() > 0.666) paragraphStyle.alignment = NSTextAlignmentRight;
|
||||
[cocoaView setDefaultParagraphStyle:paragraphStyle];
|
||||
}
|
||||
}
|
||||
|
||||
auto pLabel::setGeometry(Geometry geometry) -> void {
|
||||
//NSTextView does not support vertical text centering:
|
||||
//simulate this by adjusting the geometry placement (reduce height, move view down)
|
||||
uint height = pFont::size(self().font(true), state().text).height();
|
||||
auto offset = geometry;
|
||||
|
||||
if(geometry.height() > height) {
|
||||
uint diff = geometry.height() - height;
|
||||
offset.setY(offset.y() + (diff >> 1));
|
||||
offset.setHeight(offset.height() - (diff >> 1));
|
||||
}
|
||||
|
||||
pWidget::setGeometry({
|
||||
offset.x() - 6, offset.y(),
|
||||
offset.width() + 12, offset.height()
|
||||
});
|
||||
}
|
||||
|
||||
auto pLabel::setText(const string& text) -> void {
|
||||
@autoreleasepool {
|
||||
[cocoaView setString:[NSString stringWithUTF8String:text]];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
25
cocoa/widget/label.hpp
Normal file
25
cocoa/widget/label.hpp
Normal file
|
@ -0,0 +1,25 @@
|
|||
#if defined(Hiro_Label)
|
||||
|
||||
@interface CocoaLabel : NSTextView {
|
||||
@public
|
||||
hiro::mLabel* label;
|
||||
}
|
||||
-(id) initWith:(hiro::mLabel&)label;
|
||||
@end
|
||||
|
||||
namespace hiro {
|
||||
|
||||
struct pLabel : pWidget {
|
||||
Declare(Label, Widget)
|
||||
|
||||
auto minimumSize() const -> Size override;
|
||||
auto setAlignment(Alignment alignment) -> void;
|
||||
auto setGeometry(Geometry geometry) -> void override;
|
||||
auto setText(const string& text) -> void;
|
||||
|
||||
CocoaLabel* cocoaLabel = nullptr;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
83
cocoa/widget/line-edit.cpp
Normal file
83
cocoa/widget/line-edit.cpp
Normal file
|
@ -0,0 +1,83 @@
|
|||
#if defined(Hiro_LineEdit)
|
||||
|
||||
@implementation CocoaLineEdit : NSTextField
|
||||
|
||||
-(id) initWith:(hiro::mLineEdit&)lineEditReference {
|
||||
if(self = [super initWithFrame:NSMakeRect(0, 0, 0, 0)]) {
|
||||
lineEdit = &lineEditReference;
|
||||
|
||||
[self setDelegate:self];
|
||||
[self setTarget:self];
|
||||
[self setAction:@selector(activate:)];
|
||||
|
||||
//prevent focus changes from generating activate event
|
||||
[[self cell] setSendsActionOnEndEditing:NO];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
-(void) textDidChange:(NSNotification*)n {
|
||||
lineEdit->doChange();
|
||||
}
|
||||
|
||||
-(IBAction) activate:(id)sender {
|
||||
lineEdit->doActivate();
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
namespace hiro {
|
||||
|
||||
auto pLineEdit::construct() -> void {
|
||||
@autoreleasepool {
|
||||
cocoaView = cocoaLineEdit = [[CocoaLineEdit alloc] initWith:self()];
|
||||
pWidget::construct();
|
||||
|
||||
setBackgroundColor(state().backgroundColor);
|
||||
setEditable(state().editable);
|
||||
setForegroundColor(state().foregroundColor);
|
||||
setText(state().text);
|
||||
}
|
||||
}
|
||||
|
||||
auto pLineEdit::destruct() -> void {
|
||||
@autoreleasepool {
|
||||
[cocoaView removeFromSuperview];
|
||||
[cocoaView release];
|
||||
}
|
||||
}
|
||||
|
||||
auto pLineEdit::minimumSize() const -> Size {
|
||||
Size size = pFont::size(self().font(true), state().text);
|
||||
return {size.width() + 10, size.height() + 8};
|
||||
}
|
||||
|
||||
auto pLineEdit::setBackgroundColor(Color color) -> void {
|
||||
}
|
||||
|
||||
auto pLineEdit::setEditable(bool editable) -> void {
|
||||
@autoreleasepool {
|
||||
[cocoaView setEditable:editable];
|
||||
}
|
||||
}
|
||||
|
||||
auto pLineEdit::setForegroundColor(Color color) -> void {
|
||||
}
|
||||
|
||||
auto pLineEdit::setText(const string& text) -> void {
|
||||
@autoreleasepool {
|
||||
[cocoaView setStringValue:[NSString stringWithUTF8String:text]];
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
auto pLineEdit::text() const -> string {
|
||||
@autoreleasepool {
|
||||
return [[cocoaView stringValue] UTF8String];
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
#endif
|
28
cocoa/widget/line-edit.hpp
Normal file
28
cocoa/widget/line-edit.hpp
Normal file
|
@ -0,0 +1,28 @@
|
|||
#if defined(Hiro_LineEdit)
|
||||
|
||||
@interface CocoaLineEdit : NSTextField <NSTextFieldDelegate> {
|
||||
@public
|
||||
hiro::mLineEdit* lineEdit;
|
||||
}
|
||||
-(id) initWith:(hiro::mLineEdit&)lineEdit;
|
||||
-(void) textDidChange:(NSNotification*)n;
|
||||
-(IBAction) activate:(id)sender;
|
||||
@end
|
||||
|
||||
namespace hiro {
|
||||
|
||||
struct pLineEdit : pWidget {
|
||||
Declare(LineEdit, Widget)
|
||||
|
||||
auto minimumSize() const -> Size override;
|
||||
auto setBackgroundColor(Color color) -> void;
|
||||
auto setEditable(bool editable) -> void;
|
||||
auto setForegroundColor(Color color) -> void;
|
||||
auto setText(const string& text) -> void;
|
||||
|
||||
CocoaLineEdit* cocoaLineEdit = nullptr;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
50
cocoa/widget/list-view-cell.cpp
Normal file
50
cocoa/widget/list-view-cell.cpp
Normal file
|
@ -0,0 +1,50 @@
|
|||
#if defined(Hiro_ListView)
|
||||
|
||||
namespace hiro {
|
||||
|
||||
auto pListViewCell::construct() -> void {
|
||||
}
|
||||
|
||||
auto pListViewCell::destruct() -> void {
|
||||
}
|
||||
|
||||
auto pListViewCell::setAlignment(Alignment alignment) -> void {
|
||||
}
|
||||
|
||||
auto pListViewCell::setBackgroundColor(Color color) -> void {
|
||||
}
|
||||
|
||||
auto pListViewCell::setCheckable(bool checkable) -> void {
|
||||
}
|
||||
|
||||
auto pListViewCell::setChecked(bool checked) -> void {
|
||||
}
|
||||
|
||||
auto pListViewCell::setForegroundColor(Color color) -> void {
|
||||
}
|
||||
|
||||
auto pListViewCell::setIcon(const image& icon) -> void {
|
||||
}
|
||||
|
||||
auto pListViewCell::setText(const string& text) -> void {
|
||||
@autoreleasepool {
|
||||
if(auto pListView = _grandparent()) {
|
||||
[[pListView->cocoaView content] reloadData];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto pListViewCell::_grandparent() -> maybe<pListView&> {
|
||||
if(auto parent = _parent()) return parent->_parent();
|
||||
}
|
||||
|
||||
auto pListViewCell::_parent() -> maybe<pListViewItem&> {
|
||||
if(auto parent = self().parentListViewItem()) {
|
||||
if(auto self = parent->self()) return *self;
|
||||
}
|
||||
return nothing;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
22
cocoa/widget/list-view-cell.hpp
Normal file
22
cocoa/widget/list-view-cell.hpp
Normal file
|
@ -0,0 +1,22 @@
|
|||
#if defined(Hiro_ListView)
|
||||
|
||||
namespace hiro {
|
||||
|
||||
struct pListViewCell : pObject {
|
||||
Declare(ListViewCell, Object)
|
||||
|
||||
auto setAlignment(Alignment alignment) -> void;
|
||||
auto setBackgroundColor(Color color) -> void;
|
||||
auto setCheckable(bool checkable) -> void;
|
||||
auto setChecked(bool checked) -> void;
|
||||
auto setForegroundColor(Color color) -> void;
|
||||
auto setIcon(const image& icon) -> void;
|
||||
auto setText(const string& text) -> void;
|
||||
|
||||
auto _grandparent() -> maybe<pListView&>;
|
||||
auto _parent() -> maybe<pListViewItem&>;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
87
cocoa/widget/list-view-column.cpp
Normal file
87
cocoa/widget/list-view-column.cpp
Normal file
|
@ -0,0 +1,87 @@
|
|||
#if defined(Hiro_ListView)
|
||||
|
||||
namespace hiro {
|
||||
|
||||
auto pListViewColumn::construct() -> void {
|
||||
@autoreleasepool {
|
||||
if(auto listView = _grandparent()) {
|
||||
[listView->cocoaView reloadColumns];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto pListViewColumn::destruct() -> void {
|
||||
@autoreleasepool {
|
||||
if(auto listView = _grandparent()) {
|
||||
[listView->cocoaView reloadColumns];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto pListViewColumn::setActive() -> void {
|
||||
}
|
||||
|
||||
auto pListViewColumn::setAlignment(Alignment alignment) -> void {
|
||||
}
|
||||
|
||||
auto pListViewColumn::setBackgroundColor(Color color) -> void {
|
||||
}
|
||||
|
||||
auto pListViewColumn::setEditable(bool editable) -> void {
|
||||
}
|
||||
|
||||
auto pListViewColumn::setExpandable(bool expandable) -> void {
|
||||
}
|
||||
|
||||
auto pListViewColumn::setFont(const Font& font) -> void {
|
||||
}
|
||||
|
||||
auto pListViewColumn::setForegroundColor(Color color) -> void {
|
||||
}
|
||||
|
||||
auto pListViewColumn::setHorizontalAlignment(double alignment) -> void {
|
||||
}
|
||||
|
||||
auto pListViewColumn::setIcon(const image& icon) -> void {
|
||||
}
|
||||
|
||||
auto pListViewColumn::setResizable(bool resizable) -> void {
|
||||
}
|
||||
|
||||
auto pListViewColumn::setSortable(bool sortable) -> void {
|
||||
}
|
||||
|
||||
auto pListViewColumn::setText(const string& text) -> void {
|
||||
@autoreleasepool {
|
||||
if(auto pListView = _grandparent()) {
|
||||
NSTableColumn* tableColumn = [[pListView->cocoaView content] tableColumnWithIdentifier:[[NSNumber numberWithInteger:self().offset()] stringValue]];
|
||||
[[tableColumn headerCell] setStringValue:[NSString stringWithUTF8STring:text]];
|
||||
[[pListView->cocoaView headerView] setNeedsDisplay:YES];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto pListViewColumn::setVerticalAlignment(double alignment) -> void {
|
||||
}
|
||||
|
||||
auto pListViewColumn::setVisible(bool visible) -> void {
|
||||
}
|
||||
|
||||
auto pListViewColumn::setWidth(signed width) -> void {
|
||||
}
|
||||
|
||||
auto pListViewColumn::_grandparent() -> maybe<pListView&> {
|
||||
if(auto parent = _parent()) return parent->_parent();
|
||||
return nothing;
|
||||
}
|
||||
|
||||
auto pListViewColumn::_parent() -> maybe<pListViewHeader&> {
|
||||
if(auto parent = self().parentListViewHeader()) {
|
||||
if(auto self = parent->self()) return *self;
|
||||
}
|
||||
return nothing;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
30
cocoa/widget/list-view-column.hpp
Normal file
30
cocoa/widget/list-view-column.hpp
Normal file
|
@ -0,0 +1,30 @@
|
|||
#if defined(Hiro_ListView)
|
||||
|
||||
namespace hiro {
|
||||
|
||||
struct pListViewColumn : pObject {
|
||||
Declare(ListViewColumn, Object)
|
||||
|
||||
auto setActive() -> void;
|
||||
auto setAlignment(Alignment alignment) -> void;
|
||||
auto setBackgroundColor(Color color) -> void;
|
||||
auto setEditable(bool editable) -> void;
|
||||
auto setExpandable(bool expandable) -> void;
|
||||
auto setFont(const Font& font) -> void override;
|
||||
auto setForegroundColor(Color color) -> void;
|
||||
auto setHorizontalAlignment(double) -> void;
|
||||
auto setIcon(const image& icon) -> void;
|
||||
auto setResizable(bool resizable) -> void;
|
||||
auto setSortable(bool sortable) -> void;
|
||||
auto setText(const string& text) -> void;
|
||||
auto setVerticalAlignment(double) -> void;
|
||||
auto setVisible(bool visible) -> void override;
|
||||
auto setWidth(signed width) -> void;
|
||||
|
||||
auto _grandparent() -> maybe<pListView&>;
|
||||
auto _parent() -> maybe<pListViewHeader&>;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
38
cocoa/widget/list-view-header.cpp
Normal file
38
cocoa/widget/list-view-header.cpp
Normal file
|
@ -0,0 +1,38 @@
|
|||
#if defined(Hiro_ListView)
|
||||
|
||||
namespace hiro {
|
||||
|
||||
auto pListViewHeader::construct() -> void {
|
||||
}
|
||||
|
||||
auto pListViewHeader::destruct() -> void {
|
||||
}
|
||||
|
||||
auto pListViewHeader::append(sListViewColumn column) -> void {
|
||||
}
|
||||
|
||||
auto pListViewHeader::remove(sListViewColumn column) -> void {
|
||||
}
|
||||
|
||||
auto pListViewHeader::setVisible(bool visible) -> void {
|
||||
@autoreleasepool {
|
||||
if(auto pListView = _parent()) {
|
||||
if(visible) {
|
||||
[[pListView->cocoaView content] setHeaderView:[[[NSTableHeaderView alloc] init] autorelease]];
|
||||
} else {
|
||||
[[pListView->cocoaView content] setHeaderView:nil];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto pListViewHeader::_parent() -> maybe<pListView&> {
|
||||
if(auto parent = self().parentListView()) {
|
||||
if(auto self = parent->self()) return *self;
|
||||
}
|
||||
return nothing;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
17
cocoa/widget/list-view-header.hpp
Normal file
17
cocoa/widget/list-view-header.hpp
Normal file
|
@ -0,0 +1,17 @@
|
|||
#if defined(Hiro_ListView)
|
||||
|
||||
namespace hiro {
|
||||
|
||||
struct pListViewHeader : pObject {
|
||||
Declare(ListViewHeader, Object)
|
||||
|
||||
auto append(sListViewColumn column) -> void;
|
||||
auto remove(sListViewColumn column) -> void;
|
||||
auto setVisible(bool visible) -> void override;
|
||||
|
||||
auto _parent() -> maybe<pListView&>;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
51
cocoa/widget/list-view-item.cpp
Normal file
51
cocoa/widget/list-view-item.cpp
Normal file
|
@ -0,0 +1,51 @@
|
|||
#if defined(Hiro_ListView)
|
||||
|
||||
namespace hiro {
|
||||
|
||||
auto pListViewItem::construct() -> void {
|
||||
}
|
||||
|
||||
auto pListViewItem::destruct() -> void {
|
||||
}
|
||||
|
||||
auto pListViewItem::append(sListViewCell cell) -> void {
|
||||
@autoreleasepool {
|
||||
if(auto listView = _parent()) {
|
||||
[[listView->cocoaView content] reloadData];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto pListViewItem::remove(sListViewCell cell) -> void {
|
||||
@autoreleasepool {
|
||||
if(auto listView = _parent()) {
|
||||
[[listView->cocoaView content] reloadData];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto pListViewItem::setAlignment(Alignment alignment) -> void {
|
||||
}
|
||||
|
||||
auto pListViewItem::setBackgroundColor(Color color) -> void {
|
||||
}
|
||||
|
||||
auto pListViewItem::setFocused() -> void {
|
||||
}
|
||||
|
||||
auto pListViewItem::setForegroundColor(Color color) -> void {
|
||||
}
|
||||
|
||||
auto pListViewItem::setSelected(bool selected) -> void {
|
||||
}
|
||||
|
||||
auto pListViewItem::_parent() -> maybe<pListView&> {
|
||||
if(auto parent = self().parentListView()) {
|
||||
if(auto self = parent->self()) return *self;
|
||||
}
|
||||
return nothing;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
21
cocoa/widget/list-view-item.hpp
Normal file
21
cocoa/widget/list-view-item.hpp
Normal file
|
@ -0,0 +1,21 @@
|
|||
#if defined(Hiro_ListView)
|
||||
|
||||
namespace hiro {
|
||||
|
||||
struct pListViewItem : pObject {
|
||||
Declare(ListViewItem, Object)
|
||||
|
||||
auto append(sListViewCell cell) -> void;
|
||||
auto remove(sListViewCell cell) -> void;
|
||||
auto setAlignment(Alignment alignment) -> void;
|
||||
auto setBackgroundColor(Color color) -> void;
|
||||
auto setFocused() -> void;
|
||||
auto setForegroundColor(Color color) -> void;
|
||||
auto setSelected(bool selected) -> void;
|
||||
|
||||
auto _parent() -> maybe<pListView&>;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
455
cocoa/widget/list-view.cpp
Normal file
455
cocoa/widget/list-view.cpp
Normal file
|
@ -0,0 +1,455 @@
|
|||
#if defined(Hiro_ListView)
|
||||
|
||||
@implementation CocoaListView : NSScrollView
|
||||
|
||||
-(id) initWith:(hiro::mListView&)listViewReference {
|
||||
if(self = [super initWithFrame:NSMakeRect(0, 0, 0, 0)]) {
|
||||
listView = &listViewReference;
|
||||
content = [[CocoaListViewContent alloc] initWithFrame:NSMakeRect(0, 0, 0, 0)];
|
||||
|
||||
[self setDocumentView:content];
|
||||
[self setBorderType:NSBezelBorder];
|
||||
[self setHasVerticalScroller:YES];
|
||||
|
||||
[content setDataSource:self];
|
||||
[content setDelegate:self];
|
||||
[content setTarget:self];
|
||||
[content setDoubleAction:@selector(doubleAction:)];
|
||||
|
||||
[content setAllowsColumnReordering:NO];
|
||||
[content setAllowsColumnResizing:YES];
|
||||
[content setAllowsColumnSelection:NO];
|
||||
[content setAllowsEmptySelection:YES];
|
||||
[content setColumnAutoresizingStyle:NSTableViewLastColumnOnlyAutoresizingStyle];
|
||||
|
||||
font = nil;
|
||||
[self setFont:nil];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
-(void) dealloc {
|
||||
[content release];
|
||||
[font release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
-(CocoaListViewContent*) content {
|
||||
return content;
|
||||
}
|
||||
|
||||
-(NSFont*) font {
|
||||
return font;
|
||||
}
|
||||
|
||||
-(void) setFont:(NSFont*)fontPointer {
|
||||
if(!fontPointer) fontPointer = [NSFont systemFontOfSize:12];
|
||||
[fontPointer retain];
|
||||
if(font) [font release];
|
||||
font = fontPointer;
|
||||
|
||||
uint fontHeight = hiro::pFont::size(font, " ").height();
|
||||
[content setFont:font];
|
||||
[content setRowHeight:fontHeight];
|
||||
[self reloadColumns];
|
||||
}
|
||||
|
||||
-(void) reloadColumns {
|
||||
while([[content tableColumns] count]) {
|
||||
[content removeTableColumn:[[content tableColumns] lastObject]];
|
||||
}
|
||||
|
||||
if(auto listViewHeader = listView->state.header) {
|
||||
for(auto& listViewColumn : listViewHeader->state.columns) {
|
||||
auto column = listViewColumn->offset();
|
||||
|
||||
NSTableColumn* tableColumn = [[NSTableColumn alloc] initWithIdentifier:[[NSNumber numberWithInteger:column] stringValue]];
|
||||
NSTableHeaderCell* headerCell = [[NSTableHeaderCell alloc] initTextCell:[NSString stringWithUTF8String:listViewColumn->state.text]];
|
||||
CocoaListViewCell* dataCell = [[CocoaListViewCell alloc] initWith:*listView];
|
||||
|
||||
[dataCell setEditable:NO];
|
||||
|
||||
[tableColumn setResizingMask:NSTableColumnAutoresizingMask | NSTableColumnUserResizingMask];
|
||||
[tableColumn setHeaderCell:headerCell];
|
||||
[tableColumn setDataCell:dataCell];
|
||||
|
||||
[content addTableColumn:tableColumn];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
-(NSInteger) numberOfRowsInTableView:(NSTableView*)table {
|
||||
return listView->state.items.size();
|
||||
}
|
||||
|
||||
-(id) tableView:(NSTableView*)table objectValueForTableColumn:(NSTableColumn*)tableColumn row:(NSInteger)row {
|
||||
if(auto listViewItem = listView->item(row)) {
|
||||
if(auto listViewCell = listViewItem->cell([[tableColumn identifier] integerValue])) {
|
||||
NSString* text = [NSString stringWithUTF8String:listViewCell->state.text];
|
||||
return @{ @"text":text }; //used by type-ahead
|
||||
}
|
||||
}
|
||||
return @{};
|
||||
}
|
||||
|
||||
-(BOOL) tableView:(NSTableView*)table shouldShowCellExpansionForTableColumn:(NSTableColumn*)tableColumn row:(NSInteger)row {
|
||||
return NO;
|
||||
}
|
||||
|
||||
-(NSString*) tableView:(NSTableView*)table toolTipForCell:(NSCell*)cell rect:(NSRectPointer)rect tableColumn:(NSTableColumn*)tableColumn row:(NSInteger)row mouseLocation:(NSPoint)mouseLocation {
|
||||
return nil;
|
||||
}
|
||||
|
||||
-(void) tableView:(NSTableView*)tableView willDisplayCell:(id)cell forTableColumn:(NSTableColumn*)tableColumn row:(NSInteger)row {
|
||||
[cell setFont:[self font]];
|
||||
}
|
||||
|
||||
-(void) tableViewSelectionDidChange:(NSNotification*)notification {
|
||||
for(auto& listViewItem : listView->state.items) {
|
||||
listViewItem->state.selected = listViewItem->offset() == [content selectedRow];
|
||||
}
|
||||
listView->doChange();
|
||||
}
|
||||
|
||||
-(IBAction) activate:(id)sender {
|
||||
listView->doActivate();
|
||||
}
|
||||
|
||||
-(IBAction) doubleAction:(id)sender {
|
||||
if([content clickedRow] >= 0) {
|
||||
[self activate:self];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation CocoaListViewContent : NSTableView
|
||||
|
||||
-(void) keyDown:(NSEvent*)event {
|
||||
auto character = [[event characters] characterAtIndex:0];
|
||||
if(character == NSEnterCharacter || character == NSCarriageReturnCharacter) {
|
||||
if([self selectedRow] >= 0) {
|
||||
[[self delegate] activate:self];
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
[super keyDown:event];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation CocoaListViewCell : NSCell
|
||||
|
||||
-(id) initWith:(hiro::mListView&)listViewReference {
|
||||
if(self = [super initTextCell:@""]) {
|
||||
listView = &listViewReference;
|
||||
buttonCell = [[NSButtonCell alloc] initTextCell:@""];
|
||||
[buttonCell setButtonType:NSSwitchButton];
|
||||
[buttonCell setControlSize:NSSmallControlSize];
|
||||
[buttonCell setRefusesFirstResponder:YES];
|
||||
[buttonCell setTarget:self];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
//used by type-ahead
|
||||
-(NSString*) stringValue {
|
||||
return [[self objectValue] objectForKey:@"text"];
|
||||
}
|
||||
|
||||
-(void) drawWithFrame:(NSRect)frame inView:(NSView*)view {
|
||||
if(auto listViewItem = listView->item([view rowAtPoint:frame.origin])) {
|
||||
if(auto listViewCell = listViewItem->cell([view columnAtPoint:frame.origin])) {
|
||||
NSColor* backgroundColor = nil;
|
||||
if([self isHighlighted]) backgroundColor = [NSColor alternateSelectedControlColor];
|
||||
else if(!listView->enabled(true)) backgroundColor = [NSColor controlBackgroundColor];
|
||||
else if(auto color = listViewCell->state.backgroundColor) backgroundColor = NSMakeColor(color);
|
||||
else backgroundColor = [NSColor controlBackgroundColor];
|
||||
|
||||
[backgroundColor set];
|
||||
[NSBezierPath fillRect:frame];
|
||||
|
||||
if(listViewCell->state.checkable) {
|
||||
[buttonCell setHighlighted:YES];
|
||||
[buttonCell setState:(listViewCell->state.checked ? NSOnState : NSOffState)];
|
||||
[buttonCell drawWithFrame:frame inView:view];
|
||||
frame.origin.x += frame.size.height + 2;
|
||||
frame.size.width -= frame.size.height + 2;
|
||||
}
|
||||
|
||||
if(listViewCell->state.icon) {
|
||||
NSImage* image = NSMakeImage(listViewCell->state.icon, frame.size.height, frame.size.height);
|
||||
[[NSGraphicsContext currentContext] saveGraphicsState];
|
||||
NSRect targetRect = NSMakeRect(frame.origin.x, frame.origin.y, frame.size.height, frame.size.height);
|
||||
NSRect sourceRect = NSMakeRect(0, 0, [image size].width, [image size].height);
|
||||
[image drawInRect:targetRect fromRect:sourceRect operation:NSCompositeSourceOver fraction:1.0 respectFlipped:YES hints:nil];
|
||||
[[NSGraphicsContext currentContext] restoreGraphicsState];
|
||||
frame.origin.x += frame.size.height + 2;
|
||||
frame.size.width -= frame.size.height + 2;
|
||||
}
|
||||
|
||||
if(listViewCell->state.text) {
|
||||
NSMutableParagraphStyle* paragraphStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
|
||||
paragraphStyle.alignment = NSTextAlignmentCenter;
|
||||
if(listViewCell->state.alignment.horizontal() < 0.333) paragraphStyle.alignment = NSTextAlignmentLeft;
|
||||
if(listViewCell->state.alignment.horizontal() > 0.666) paragraphStyle.alignment = NSTextAlignmentRight;
|
||||
NSColor* foregroundColor = nil;
|
||||
if([self isHighlighted]) foregroundColor = [NSColor alternateSelectedControlTextColor];
|
||||
else if(!listView->enabled(true)) foregroundColor = [NSColor disabledControlTextColor];
|
||||
else if(auto color = listViewCell->state.foregroundColor) foregroundColor = NSMakeColor(color);
|
||||
else foregroundColor = [NSColor textColor];
|
||||
NSString* text = [NSString stringWithUTF8String:listViewCell->state.text];
|
||||
[text drawInRect:frame withAttributes:@{
|
||||
NSBackgroundColorAttributeName:backgroundColor,
|
||||
NSForegroundColorAttributeName:foregroundColor,
|
||||
NSFontAttributeName:hiro::pFont::create(listViewCell->font(true)),
|
||||
NSParagraphStyleAttributeName:paragraphStyle
|
||||
}];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//needed to trigger trackMouse events
|
||||
-(NSUInteger) hitTestForEvent:(NSEvent*)event inRect:(NSRect)frame ofView:(NSView*)view {
|
||||
NSUInteger hitTest = [super hitTestForEvent:event inRect:frame ofView:view];
|
||||
NSPoint point = [view convertPointFromBase:[event locationInWindow]];
|
||||
NSRect rect = NSMakeRect(frame.origin.x, frame.origin.y, frame.size.height, frame.size.height);
|
||||
if(NSMouseInRect(point, rect, [view isFlipped])) {
|
||||
hitTest |= NSCellHitTrackableArea;
|
||||
}
|
||||
return hitTest;
|
||||
}
|
||||
|
||||
//I am unable to get startTrackingAt:, continueTracking:, stopTracking: to work
|
||||
//so instead, I have to run a modal loop on events until the mouse button is released
|
||||
-(BOOL) trackMouse:(NSEvent*)event inRect:(NSRect)frame ofView:(NSView*)view untilMouseUp:(BOOL)flag {
|
||||
if([event type] == NSLeftMouseDown) {
|
||||
NSWindow* window = [view window];
|
||||
NSEvent* nextEvent;
|
||||
while((nextEvent = [window nextEventMatchingMask:(NSLeftMouseDragged | NSLeftMouseUp)])) {
|
||||
if([nextEvent type] == NSLeftMouseUp) {
|
||||
NSPoint point = [view convertPointFromBase:[nextEvent locationInWindow]];
|
||||
NSRect rect = NSMakeRect(frame.origin.x, frame.origin.y, frame.size.height, frame.size.height);
|
||||
if(NSMouseInRect(point, rect, [view isFlipped])) {
|
||||
if(auto listViewItem = listView->item([view rowAtPoint:point])) {
|
||||
if(auto listViewCell = listViewItem->cell([view columnAtPoint:point])) {
|
||||
listViewCell->state.checked = !listViewCell->state.checked;
|
||||
listView->doToggle(listViewCell->instance);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return YES;
|
||||
}
|
||||
|
||||
+(BOOL) prefersTrackingUntilMouseUp {
|
||||
return YES;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
namespace hiro {
|
||||
|
||||
auto pListView::construct() -> void {
|
||||
@autoreleasepool {
|
||||
cocoaView = cocoaListView = [[CocoaListView alloc] initWith:self()];
|
||||
pWidget::construct();
|
||||
|
||||
setAlignment(state().alignment);
|
||||
setBackgroundColor(state().backgroundColor);
|
||||
setBatchable(state().batchable);
|
||||
setBordered(state().bordered);
|
||||
setFont(self().font(true));
|
||||
setForegroundColor(state().foregroundColor);
|
||||
}
|
||||
}
|
||||
|
||||
auto pListView::destruct() -> void {
|
||||
@autoreleasepool {
|
||||
[cocoaView removeFromSuperview];
|
||||
[cocoaView release];
|
||||
}
|
||||
}
|
||||
|
||||
auto pListView::append(sListViewHeader header) -> void {
|
||||
@autoreleasepool {
|
||||
[cocoaView reloadColumns];
|
||||
|
||||
header->setVisible(header->visible());
|
||||
}
|
||||
}
|
||||
|
||||
auto pListView::append(sListViewItem item) -> void {
|
||||
@autoreleasepool {
|
||||
[[cocoaView content] reloadData];
|
||||
}
|
||||
}
|
||||
|
||||
auto pListView::remove(sListViewHeader header) -> void {
|
||||
@autoreleasepool {
|
||||
[cocoaView reloadColumns];
|
||||
}
|
||||
}
|
||||
|
||||
auto pListView::remove(sListViewItem item) -> void {
|
||||
@autoreleasepool {
|
||||
[[cocoaView content] reloadData];
|
||||
}
|
||||
}
|
||||
|
||||
auto pListView::resizeColumns() -> void {
|
||||
@autoreleasepool {
|
||||
if(auto& header = state().header) {
|
||||
vector<int> widths;
|
||||
int minimumWidth = 0;
|
||||
int expandable = 0;
|
||||
for(auto column : range(header->columnCount())) {
|
||||
int width = _width(column);
|
||||
widths.append(width);
|
||||
minimumWidth += width;
|
||||
if(header->column(column).expandable()) expandable++;
|
||||
}
|
||||
|
||||
int maximumWidth = self().geometry().width() - 18; //include margin for vertical scroll bar
|
||||
int expandWidth = 0;
|
||||
if(expandable && maximumWidth > minimumWidth) {
|
||||
expandWidth = (maximumWidth - minimumWidth) / expandable;
|
||||
}
|
||||
|
||||
for(auto column : range(header->columnCount())) {
|
||||
if(auto self = header->state.columns[column]->self()) {
|
||||
int width = widths[column];
|
||||
if(self->state().expandable) width += expandWidth;
|
||||
NSTableColumn* tableColumn = [[cocoaView content] tableColumnWithIdentifier:[[NSNumber numberWithInteger:column] stringValue]];
|
||||
[tableColumn setWidth:width];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto pListView::setAlignment(Alignment alignment) -> void {
|
||||
}
|
||||
|
||||
auto pListView::setBackgroundColor(Color color) -> void {
|
||||
}
|
||||
|
||||
auto pListView::setBatchable(bool batchable) -> void {
|
||||
@autoreleasepool {
|
||||
[[cocoaView content] setAllowsMultipleSelection:(batchable ? YES : NO)];
|
||||
}
|
||||
}
|
||||
|
||||
auto pListView::setBordered(bool bordered) -> void {
|
||||
}
|
||||
|
||||
auto pListView::setEnabled(bool enabled) -> void {
|
||||
pWidget::setEnabled(enabled);
|
||||
@autoreleasepool {
|
||||
[[cocoaView content] setEnabled:enabled];
|
||||
}
|
||||
}
|
||||
|
||||
auto pListView::setFont(const Font& font) -> void {
|
||||
@autoreleasepool {
|
||||
[cocoaView setFont:pFont::create(font)];
|
||||
}
|
||||
}
|
||||
|
||||
auto pListView::setForegroundColor(Color color) -> void {
|
||||
}
|
||||
|
||||
auto pListView::_cellWidth(uint row, uint column) -> uint {
|
||||
uint width = 8;
|
||||
if(auto pListViewItem = self().item(row)) {
|
||||
if(auto pListViewCell = pListViewItem->cell(column)) {
|
||||
if(pListViewCell->state.checkable) {
|
||||
width += 24;
|
||||
}
|
||||
if(auto& icon = pListViewCell->state.icon) {
|
||||
width += icon.width() + 2;
|
||||
}
|
||||
if(auto& text = pListViewCell->state.text) {
|
||||
width += pFont::size(pListViewCell->font(true), text).width();
|
||||
}
|
||||
}
|
||||
}
|
||||
return width;
|
||||
}
|
||||
|
||||
auto pListView::_columnWidth(uint column) -> uint {
|
||||
uint width = 8;
|
||||
if(auto& header = state().header) {
|
||||
if(auto pListViewColumn = header->column(column)) {
|
||||
if(auto& icon = pListViewColumn->state.icon) {
|
||||
width += icon.width() + 2;
|
||||
}
|
||||
if(auto& text = pListViewColumn->state.text) {
|
||||
width += pFont::size(pListViewColumn->font(true), text).width();
|
||||
}
|
||||
}
|
||||
}
|
||||
return width;
|
||||
}
|
||||
|
||||
auto pListView::_width(uint column) -> uint {
|
||||
if(auto& header = state().header) {
|
||||
if(auto width = header->column(column).width()) return width;
|
||||
uint width = 1;
|
||||
if(!header->column(column).visible()) return width;
|
||||
if(header->visible()) width = max(width, _columnWidth(column));
|
||||
for(auto row : range(state().items)) {
|
||||
width = max(width, _cellWidth(row, column));
|
||||
}
|
||||
return width;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
auto pListView::autoSizeColumns() -> void {
|
||||
@autoreleasepool {
|
||||
if(listView.state.checkable) {
|
||||
NSTableColumn* tableColumn = [[cocoaView content] tableColumnWithIdentifier:@"check"];
|
||||
[tableColumn setWidth:20.0];
|
||||
}
|
||||
|
||||
unsigned height = [[cocoaView content] rowHeight];
|
||||
for(unsigned column = 0; column < max(1u, listView.state.headerText.size()); column++) {
|
||||
NSTableColumn* tableColumn = [[cocoaView content] tableColumnWithIdentifier:[[NSNumber numberWithInteger:column] stringValue]];
|
||||
unsigned minimumWidth = pFont::size([[tableColumn headerCell] font], listView.state.headerText(column)).width + 4;
|
||||
for(unsigned row = 0; row < listView.state.text.size(); row++) {
|
||||
unsigned width = pFont::size([cocoaView font], listView.state.text(row)(column)).width + 2;
|
||||
if(listView.state.image(row)(height).empty() == false) width += height + 2;
|
||||
if(width > minimumWidth) minimumWidth = width;
|
||||
}
|
||||
[tableColumn setWidth:minimumWidth];
|
||||
}
|
||||
|
||||
[[cocoaView content] sizeLastColumnToFit];
|
||||
}
|
||||
}
|
||||
|
||||
auto pListView::setSelected(bool selected) -> void {
|
||||
@autoreleasepool {
|
||||
if(selected == false) {
|
||||
[[cocoaView content] deselectAll:nil];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto pListView::setSelection(unsigned selection) -> void {
|
||||
@autoreleasepool {
|
||||
[[cocoaView content] selectRowIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(selection, 1)] byExtendingSelection:NO];
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
#endif
|
71
cocoa/widget/list-view.hpp
Normal file
71
cocoa/widget/list-view.hpp
Normal file
|
@ -0,0 +1,71 @@
|
|||
#if defined(Hiro_ListView)
|
||||
|
||||
@class CocoaListViewContent;
|
||||
|
||||
@interface CocoaListView : NSScrollView <NSTableViewDelegate, NSTableViewDataSource> {
|
||||
@public
|
||||
hiro::mListView* listView;
|
||||
CocoaListViewContent* content;
|
||||
NSFont* font;
|
||||
}
|
||||
-(id) initWith:(hiro::mListView&)listView;
|
||||
-(void) dealloc;
|
||||
-(CocoaListViewContent*) content;
|
||||
-(NSFont*) font;
|
||||
-(void) setFont:(NSFont*)font;
|
||||
-(void) reloadColumns;
|
||||
-(NSInteger) numberOfRowsInTableView:(NSTableView*)table;
|
||||
-(id) tableView:(NSTableView*)table objectValueForTableColumn:(NSTableColumn*)tableColumn row:(NSInteger)row;
|
||||
-(BOOL) tableView:(NSTableView*)table shouldShowCellExpansionForTableColumn:(NSTableColumn*)tableColumn row:(NSInteger)row;
|
||||
-(NSString*) tableView:(NSTableView*)table toolTipForCell:(NSCell*)cell rect:(NSRectPointer)rect tableColumn:(NSTableColumn*)tableColumn row:(NSInteger)row mouseLocation:(NSPoint)mouseLocation;
|
||||
-(void) tableView:(NSTableView*)tableView willDisplayCell:(id)cell forTableColumn:(NSTableColumn*)tableColumn row:(NSInteger)row;
|
||||
-(void) tableViewSelectionDidChange:(NSNotification*)notification;
|
||||
-(IBAction) activate:(id)sender;
|
||||
-(IBAction) doubleAction:(id)sender;
|
||||
@end
|
||||
|
||||
@interface CocoaListViewContent : NSTableView {
|
||||
}
|
||||
-(void) keyDown:(NSEvent*)event;
|
||||
@end
|
||||
|
||||
@interface CocoaListViewCell : NSCell {
|
||||
hiro::mListView* listView;
|
||||
NSButtonCell* buttonCell;
|
||||
}
|
||||
-(id) initWith:(hiro::mListView&)listViewReference;
|
||||
-(NSString*) stringValue;
|
||||
-(void) drawWithFrame:(NSRect)frame inView:(NSView*)view;
|
||||
-(NSUInteger) hitTestForEvent:(NSEvent*)event inRect:(NSRect)frame ofView:(NSView*)view;
|
||||
-(BOOL) trackMouse:(NSEvent*)event inRect:(NSRect)frame ofView:(NSView*)view untilMouseUp:(BOOL)flag;
|
||||
+(BOOL) prefersTrackingUntilMouseUp;
|
||||
@end
|
||||
|
||||
namespace hiro {
|
||||
|
||||
struct pListView : pWidget {
|
||||
Declare(ListView, Widget)
|
||||
|
||||
auto append(sListViewHeader header) -> void;
|
||||
auto append(sListViewItem item) -> void;
|
||||
auto remove(sListViewHeader header) -> void;
|
||||
auto remove(sListViewItem item) -> void;
|
||||
auto resizeColumns() -> void;
|
||||
auto setAlignment(Alignment alignment) -> void;
|
||||
auto setBackgroundColor(Color color) -> void;
|
||||
auto setBatchable(bool batchable) -> void;
|
||||
auto setBordered(bool bordered) -> void;
|
||||
auto setEnabled(bool enabled) -> void override;
|
||||
auto setFont(const Font& font) -> void override;
|
||||
auto setForegroundColor(Color color) -> void;
|
||||
|
||||
auto _cellWidth(uint row, uint column) -> uint;
|
||||
auto _columnWidth(uint column) -> uint;
|
||||
auto _width(uint column) -> uint;
|
||||
|
||||
CocoaListView* cocoaListView = nullptr;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
48
cocoa/widget/progress-bar.cpp
Normal file
48
cocoa/widget/progress-bar.cpp
Normal file
|
@ -0,0 +1,48 @@
|
|||
#if defined(Hiro_ProgressBar)
|
||||
|
||||
@implementation CocoaProgressBar : NSProgressIndicator
|
||||
|
||||
-(id) initWith:(hiro::mProgressBar&)progressBarReference {
|
||||
if(self = [super initWithFrame:NSMakeRect(0, 0, 0, 0)]) {
|
||||
progressBar = &progressBarReference;
|
||||
|
||||
[self setIndeterminate:NO];
|
||||
[self setMinValue:0.0];
|
||||
[self setMaxValue:100.0];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
namespace hiro {
|
||||
|
||||
auto pProgressBar::construct() -> void {
|
||||
@autoreleasepool {
|
||||
cocoaView = cocoaProgressBar = [[CocoaProgressBar alloc] initWith:self()];
|
||||
pWidget::construct();
|
||||
|
||||
setPosition(state().position);
|
||||
}
|
||||
}
|
||||
|
||||
auto pProgressBar::destruct() -> void {
|
||||
@autoreleasepool {
|
||||
[cocoaView removeFromSuperview];
|
||||
[cocoaView release];
|
||||
}
|
||||
}
|
||||
|
||||
auto pProgressBar::minimumSize() const -> Size {
|
||||
return {0, 12};
|
||||
}
|
||||
|
||||
auto pProgressBar::setPosition(uint position) -> void {
|
||||
@autoreleasepool {
|
||||
[cocoaView setDoubleValue:position];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
23
cocoa/widget/progress-bar.hpp
Normal file
23
cocoa/widget/progress-bar.hpp
Normal file
|
@ -0,0 +1,23 @@
|
|||
#if defined(Hiro_ProgressBar)
|
||||
|
||||
@interface CocoaProgressBar : NSProgressIndicator {
|
||||
@public
|
||||
hiro::mProgressBar* progressBar;
|
||||
}
|
||||
-(id) initWith:(hiro::mProgressBar&)progressBar;
|
||||
@end
|
||||
|
||||
namespace hiro {
|
||||
|
||||
struct pProgressBar : pWidget {
|
||||
Declare(ProgressBar, Widget)
|
||||
|
||||
auto minimumSize() const -> Size override;
|
||||
auto setPosition(uint position) -> void;
|
||||
|
||||
CocoaProgressBar* cocoaProgressBar = nullptr;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
114
cocoa/widget/radio-button.cpp
Normal file
114
cocoa/widget/radio-button.cpp
Normal file
|
@ -0,0 +1,114 @@
|
|||
#if defined(Hiro_RadioButton)
|
||||
|
||||
@implementation CocoaRadioButton : NSButton
|
||||
|
||||
-(id) initWith:(hiro::mRadioButton&)radioButtonReference {
|
||||
if(self = [super initWithFrame:NSMakeRect(0, 0, 0, 0)]) {
|
||||
radioButton = &radioButtonReference;
|
||||
|
||||
[self setTarget:self];
|
||||
[self setAction:@selector(activate:)];
|
||||
[self setBezelStyle:NSRegularSquareBezelStyle];
|
||||
[self setButtonType:NSOnOffButton];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
-(IBAction) activate:(id)sender {
|
||||
bool wasChecked = radioButton->state.checked;
|
||||
radioButton->setChecked();
|
||||
if(!wasChecked) radioButton->doActivate();
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
namespace hiro {
|
||||
|
||||
auto pRadioButton::construct() -> void {
|
||||
@autoreleasepool {
|
||||
cocoaView = cocoaRadioButton = [[CocoaRadioButton alloc] initWith:self()];
|
||||
pWidget::construct();
|
||||
|
||||
setBordered(state().bordered);
|
||||
if(state().checked) setChecked();
|
||||
setIcon(state().icon);
|
||||
setOrientation(state().orientation);
|
||||
setText(state().text);
|
||||
}
|
||||
}
|
||||
|
||||
auto pRadioButton::destruct() -> void {
|
||||
@autoreleasepool {
|
||||
[cocoaView removeFromSuperview];
|
||||
[cocoaView release];
|
||||
}
|
||||
}
|
||||
|
||||
auto pRadioButton::minimumSize() const -> Size {
|
||||
Size size = pFont::size(self().font(true), state().text);
|
||||
|
||||
if(state().orientation == Orientation::Horizontal) {
|
||||
size.setWidth(size.width() + state().icon.width());
|
||||
size.setHeight(max(size.height(), state().icon.height()));
|
||||
}
|
||||
|
||||
if(state().orientation == Orientation::Vertical) {
|
||||
size.setWidth(max(size.width(), state().icon.width()));
|
||||
size.setHeight(size.height() + state().icon.height());
|
||||
}
|
||||
|
||||
return {size.width() + (state().text ? 20 : 8), size.height() + 8};
|
||||
}
|
||||
|
||||
auto pRadioButton::setBordered(bool bordered) -> void {
|
||||
}
|
||||
|
||||
auto pRadioButton::setChecked() -> void {
|
||||
@autoreleasepool {
|
||||
if(auto group = state().group) {
|
||||
for(auto& weak : group->state.objects) {
|
||||
if(auto object = weak.acquire()) {
|
||||
if(auto self = object->self()) {
|
||||
if(auto p = dynamic_cast<pRadioButton*>(self)) {
|
||||
auto state = this == p ? NSOnState : NSOffState;
|
||||
[p->cocoaView setState:state];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto pRadioButton::setGeometry(Geometry geometry) -> void {
|
||||
pWidget::setGeometry({
|
||||
geometry.x() - 2, geometry.y() - 2,
|
||||
geometry.width() + 4, geometry.height() + 4
|
||||
});
|
||||
}
|
||||
|
||||
auto pRadioButton::setGroup(sGroup group) -> void {
|
||||
}
|
||||
|
||||
auto pRadioButton::setIcon(const image& icon) -> void {
|
||||
@autoreleasepool {
|
||||
[cocoaView setImage:NSMakeImage(icon)];
|
||||
}
|
||||
}
|
||||
|
||||
auto pRadioButton::setOrientation(Orientation orientation) -> void {
|
||||
@autoreleasepool {
|
||||
if(orientation == Orientation::Horizontal) [cocoaView setImagePosition:NSImageLeft];
|
||||
if(orientation == Orientation::Vertical ) [cocoaView setImagePosition:NSImageAbove];
|
||||
}
|
||||
}
|
||||
|
||||
auto pRadioButton::setText(const string& text) -> void {
|
||||
@autoreleasepool {
|
||||
[cocoaView setTitle:[NSString stringWithUTF8String:text]];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
30
cocoa/widget/radio-button.hpp
Normal file
30
cocoa/widget/radio-button.hpp
Normal file
|
@ -0,0 +1,30 @@
|
|||
#if defined(Hiro_RadioButton)
|
||||
|
||||
@interface CocoaRadioButton : NSButton {
|
||||
@public
|
||||
hiro::mRadioButton* radioButton;
|
||||
}
|
||||
-(id) initWith:(hiro::mRadioButton&)radioButton;
|
||||
-(IBAction) activate:(id)sender;
|
||||
@end
|
||||
|
||||
namespace hiro {
|
||||
|
||||
struct pRadioButton : pWidget {
|
||||
Declare(RadioButton, Widget)
|
||||
|
||||
auto minimumSize() const -> Size override;
|
||||
auto setBordered(bool bordered) -> void;
|
||||
auto setChecked() -> void;
|
||||
auto setGeometry(Geometry geometry) -> void override;
|
||||
auto setGroup(sGroup group) -> void;
|
||||
auto setIcon(const image& icon) -> void;
|
||||
auto setOrientation(Orientation orientation) -> void;
|
||||
auto setText(const string& text) -> void;
|
||||
|
||||
CocoaRadioButton* cocoaRadioButton = nullptr;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
82
cocoa/widget/radio-label.cpp
Normal file
82
cocoa/widget/radio-label.cpp
Normal file
|
@ -0,0 +1,82 @@
|
|||
#if defined(Hiro_RadioLabel)
|
||||
|
||||
@implementation CocoaRadioLabel : NSButton
|
||||
|
||||
-(id) initWith:(hiro::mRadioLabel&)radioLabelReference {
|
||||
if(self = [super initWithFrame:NSMakeRect(0, 0, 0, 0)]) {
|
||||
radioLabel = &radioLabelReference;
|
||||
|
||||
[self setTarget:self];
|
||||
[self setAction:@selector(activate:)];
|
||||
[self setButtonType:NSRadioButton];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
-(IBAction) activate:(id)sender {
|
||||
radioLabel->setChecked();
|
||||
radioLabel->doActivate();
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
namespace hiro {
|
||||
|
||||
auto pRadioLabel::construct() -> void {
|
||||
@autoreleasepool {
|
||||
cocoaView = cocoaRadioLabel = [[CocoaRadioLabel alloc] initWith:self()];
|
||||
pWidget::construct();
|
||||
|
||||
if(state().checked) setChecked();
|
||||
setText(state().text);
|
||||
}
|
||||
}
|
||||
|
||||
auto pRadioLabel::destruct() -> void {
|
||||
@autoreleasepool {
|
||||
[cocoaView removeFromSuperview];
|
||||
[cocoaView release];
|
||||
}
|
||||
}
|
||||
|
||||
auto pRadioLabel::minimumSize() const -> Size {
|
||||
Size size = pFont::size(self().font(true), state().text);
|
||||
return {size.width() + 22, size.height()};
|
||||
}
|
||||
|
||||
auto pRadioLabel::setChecked() -> void {
|
||||
@autoreleasepool {
|
||||
if(auto group = state().group) {
|
||||
for(auto& weak : group->state.objects) {
|
||||
if(auto object = weak.acquire()) {
|
||||
if(auto self = object->self()) {
|
||||
if(auto p = dynamic_cast<pRadioLabel*>(self)) {
|
||||
auto state = this == p ? NSOnState : NSOffState;
|
||||
[p->cocoaView setState:state];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto pRadioLabel::setGeometry(Geometry geometry) -> void {
|
||||
pWidget::setGeometry({
|
||||
geometry.x() - 1, geometry.y(),
|
||||
geometry.width() + 2, geometry.height()
|
||||
});
|
||||
}
|
||||
|
||||
auto pRadioLabel::setGroup(sGroup group) -> void {
|
||||
}
|
||||
|
||||
auto pRadioLabel::setText(const string& text) -> void {
|
||||
@autoreleasepool {
|
||||
[cocoaView setTitle:[NSString stringWithUTF8String:text]];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
27
cocoa/widget/radio-label.hpp
Normal file
27
cocoa/widget/radio-label.hpp
Normal file
|
@ -0,0 +1,27 @@
|
|||
#if defined(Hiro_RadioLabel)
|
||||
|
||||
@interface CocoaRadioLabel : NSButton {
|
||||
@public
|
||||
hiro::mRadioLabel* radioLabel;
|
||||
}
|
||||
-(id) initWith:(hiro::mRadioLabel&)radioLabel;
|
||||
-(IBAction) activate:(id)sender;
|
||||
@end
|
||||
|
||||
namespace hiro {
|
||||
|
||||
struct pRadioLabel : pWidget {
|
||||
Declare(RadioLabel, Widget)
|
||||
|
||||
auto minimumSize() const -> Size override;
|
||||
auto setChecked() -> void;
|
||||
auto setGeometry(Geometry geometry) -> void override;
|
||||
auto setGroup(sGroup group) -> void;
|
||||
auto setText(const string& text) -> void;
|
||||
|
||||
CocoaRadioLabel* cocoaRadioLabel = nullptr;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
49
cocoa/widget/tab-frame-item.cpp
Normal file
49
cocoa/widget/tab-frame-item.cpp
Normal file
|
@ -0,0 +1,49 @@
|
|||
#if defined(Hiro_TabFrame)
|
||||
|
||||
namespace hiro {
|
||||
|
||||
auto pTabFrameItem::construct() -> void {
|
||||
}
|
||||
|
||||
auto pTabFrameItem::destruct() -> void {
|
||||
}
|
||||
|
||||
auto pTabFrameItem::append(sLayout layout) -> void {
|
||||
}
|
||||
|
||||
auto pTabFrameItem::remove(sLayout layout) -> void {
|
||||
}
|
||||
|
||||
auto pTabFrameItem::setClosable(bool closable) -> void {
|
||||
}
|
||||
|
||||
auto pTabFrameItem::setIcon(const image& icon) -> void {
|
||||
}
|
||||
|
||||
auto pTabFrameItem::setMovable(bool movable) -> void {
|
||||
}
|
||||
|
||||
auto pTabFrameItem::setSelected() -> void {
|
||||
@autoreleasepool {
|
||||
if(auto parent = _parent()) {
|
||||
[parent->cocoaView selectTabViewItem:cocoaTabFrameItem];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto pTabFrameItem::setText(const string& text) -> void {
|
||||
@autoreleasepool {
|
||||
[cocoaTabFrameItem setLabel:[NSString stringWithUTF8String:state().text]];
|
||||
}
|
||||
}
|
||||
|
||||
auto pTabFrameItem::_parent() -> maybe<pTabFrame&> {
|
||||
if(auto parent = self().parentTabFrame()) {
|
||||
if(auto self = parent->self()) return *self;
|
||||
}
|
||||
return nothing;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
23
cocoa/widget/tab-frame-item.hpp
Normal file
23
cocoa/widget/tab-frame-item.hpp
Normal file
|
@ -0,0 +1,23 @@
|
|||
#if defined(Hiro_TabFrame)
|
||||
|
||||
namespace hiro {
|
||||
|
||||
struct pTabFrameItem : pObject {
|
||||
Declare(TabFrameItem, Object)
|
||||
|
||||
auto append(sLayout layout) -> void;
|
||||
auto remove(sLayout layout) -> void;
|
||||
auto setClosable(bool closable) -> void;
|
||||
auto setIcon(const image& icon) -> void;
|
||||
auto setMovable(bool movable) -> void;
|
||||
auto setSelected() -> void;
|
||||
auto setText(const string& text) -> void;
|
||||
|
||||
CocoaTabFrameItem* cocoaTabFrameItem = nullptr;
|
||||
|
||||
auto _parent() -> maybe<pTabFrame&>;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
166
cocoa/widget/tab-frame.cpp
Normal file
166
cocoa/widget/tab-frame.cpp
Normal file
|
@ -0,0 +1,166 @@
|
|||
#if defined(Hiro_TabFrame)
|
||||
|
||||
@implementation CocoaTabFrame : NSTabView
|
||||
|
||||
-(id) initWith:(hiro::mTabFrame&)tabFrameReference {
|
||||
if(self = [super initWithFrame:NSMakeRect(0, 0, 0, 0)]) {
|
||||
tabFrame = &tabFrameReference;
|
||||
|
||||
[self setDelegate:self];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
-(void) tabView:(NSTabView*)tabView didSelectTabViewItem:(NSTabViewItem*)tabViewItem {
|
||||
tabFrame->self()->_synchronizeLayout();
|
||||
tabFrame->doChange();
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation CocoaTabFrameItem : NSTabViewItem
|
||||
|
||||
-(id) initWith:(hiro::mTabFrame&)tabFrameReference {
|
||||
if(self = [super initWithIdentifier:nil]) {
|
||||
tabFrame = &tabFrameReference;
|
||||
cocoaTabFrame = tabFrame->self()->cocoaTabFrame;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
-(NSSize) sizeOfLabel:(BOOL)shouldTruncateLabel {
|
||||
NSSize sizeOfLabel = [super sizeOfLabel:shouldTruncateLabel];
|
||||
int selection = [cocoaTabFrame indexOfTabViewItem:self];
|
||||
if(selection >= 0) {
|
||||
if(auto item = tabFrame->item(selection)) {
|
||||
if(item->state.icon) {
|
||||
uint iconSize = hiro::pFont::size(tabFrame->font(true), " ").height();
|
||||
sizeOfLabel.width += iconSize + 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
return sizeOfLabel;
|
||||
}
|
||||
|
||||
-(void) drawLabel:(BOOL)shouldTruncateLabel inRect:(NSRect)tabRect {
|
||||
int selection = [cocoaTabFrame indexOfTabViewItem:self];
|
||||
if(selection >= 0) {
|
||||
if(auto item = tabFrame->item(selection)) {
|
||||
if(item->state.icon) {
|
||||
uint iconSize = hiro::pFont::size(tabFrame->font(true), " ").height();
|
||||
NSImage* image = NSMakeImage(item->state.icon);
|
||||
|
||||
[[NSGraphicsContext currentContext] saveGraphicsState];
|
||||
NSRect targetRect = NSMakeRect(tabRect.origin.x, tabRect.origin.y + 2, iconSize, iconSize);
|
||||
[image drawInRect:targetRect fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1.0 respectFlipped:YES hints:nil];
|
||||
[[NSGraphicsContext currentContext] restoreGraphicsState];
|
||||
|
||||
tabRect.origin.x += iconSize + 2;
|
||||
tabRect.size.width -= iconSize + 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
[super drawLabel:shouldTruncateLabel inRect:tabRect];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
namespace hiro {
|
||||
|
||||
auto pTabFrame::construct() -> void {
|
||||
@autoreleasepool {
|
||||
cocoaView = cocoaTabFrame = [[CocoaTabFrame alloc] initWith:self()];
|
||||
pWidget::construct();
|
||||
|
||||
setNavigation(state().navigation);
|
||||
}
|
||||
}
|
||||
|
||||
auto pTabFrame::destruct() -> void {
|
||||
@autoreleasepool {
|
||||
[cocoaView removeFromSuperview];
|
||||
[cocoaView release];
|
||||
}
|
||||
}
|
||||
|
||||
auto pTabFrame::append(sTabFrameItem item) -> void {
|
||||
@autoreleasepool {
|
||||
if(auto p = item->self()) {
|
||||
p->cocoaTabFrameItem = [[CocoaTabFrameItem alloc] initWith:self()];
|
||||
[p->cocoaTabFrameItem setLabel:[NSString stringWithUTF8String:item->state.text]];
|
||||
[cocoaView addTabViewItem:p->cocoaTabFrameItem];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto pTabFrame::remove(sTabFrameItem item) -> void {
|
||||
@autoreleasepool {
|
||||
if(auto p = item->self()) {
|
||||
[cocoaView removeTabViewItem:p->cocoaTabFrameItem];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto pTabFrame::setEnabled(bool enabled) -> void {
|
||||
pWidget::setEnabled(enabled);
|
||||
for(auto& item : state().items) {
|
||||
if(auto& layout = item->state.layout) {
|
||||
if(auto self = layout->self()) self->setEnabled(layout->enabled(true));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto pTabFrame::setFont(const Font& font) -> void {
|
||||
pWidget::setFont(font);
|
||||
for(auto& item : state().items) {
|
||||
if(auto& layout = item->state.layout) {
|
||||
if(auto self = layout->self()) self->setFont(layout->font(true));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto pTabFrame::setGeometry(Geometry geometry) -> void {
|
||||
pWidget::setGeometry({
|
||||
geometry.x() - 7, geometry.y() - 5,
|
||||
geometry.width() + 14, geometry.height() + 6
|
||||
});
|
||||
geometry.setGeometry({
|
||||
geometry.x() + 1, geometry.y() + 22,
|
||||
geometry.width() - 2, geometry.height() - 32
|
||||
});
|
||||
for(auto& item : state().items) {
|
||||
if(auto& layout = item->state.layout) {
|
||||
layout->setGeometry(geometry);
|
||||
}
|
||||
}
|
||||
_synchronizeLayout();
|
||||
}
|
||||
|
||||
auto pTabFrame::setNavigation(Navigation navigation) -> void {
|
||||
}
|
||||
|
||||
auto pTabFrame::setVisible(bool visible) -> void {
|
||||
pWidget::setVisible(visible);
|
||||
for(auto& item : state().items) {
|
||||
if(auto& layout = item->state.layout) {
|
||||
if(auto self = layout->self()) self->setVisible(layout->visible(true));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto pTabFrame::_synchronizeLayout() -> void {
|
||||
@autoreleasepool {
|
||||
NSTabViewItem* tabViewItem = [cocoaView selectedTabViewItem];
|
||||
int selected = tabViewItem ? [cocoaView indexOfTabViewItem:tabViewItem] : -1;
|
||||
for(auto& item : state().items) {
|
||||
item->state.selected = item->offset() == selected;
|
||||
if(auto& layout = item->state.layout) {
|
||||
if(auto self = layout->self()) self->setVisible(layout->visible(true) && item->selected());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
42
cocoa/widget/tab-frame.hpp
Normal file
42
cocoa/widget/tab-frame.hpp
Normal file
|
@ -0,0 +1,42 @@
|
|||
#if defined(Hiro_TabFrame)
|
||||
|
||||
@interface CocoaTabFrame : NSTabView <NSTabViewDelegate> {
|
||||
@public
|
||||
hiro::mTabFrame* tabFrame;
|
||||
}
|
||||
-(id) initWith:(hiro::mTabFrame&)tabFrame;
|
||||
-(void) tabView:(NSTabView*)tabView didSelectTabViewItem:(NSTabViewItem*)tabViewItem;
|
||||
@end
|
||||
|
||||
@interface CocoaTabFrameItem : NSTabViewItem {
|
||||
@public
|
||||
hiro::mTabFrame* tabFrame;
|
||||
CocoaTabFrame* cocoaTabFrame;
|
||||
}
|
||||
-(id) initWith:(hiro::mTabFrame&)tabFrame;
|
||||
-(NSSize) sizeOfLabel:(BOOL)shouldTruncateLabel;
|
||||
-(void) drawLabel:(BOOL)shouldTruncateLabel inRect:(NSRect)tabRect;
|
||||
@end
|
||||
|
||||
namespace hiro {
|
||||
|
||||
struct pTabFrame : pWidget {
|
||||
Declare(TabFrame, Widget)
|
||||
|
||||
auto append(sTabFrameItem item) -> void;
|
||||
auto remove(sTabFrameItem item) -> void;
|
||||
auto setEnabled(bool enabled) -> void override;
|
||||
auto setFont(const Font& font) -> void override;
|
||||
auto setGeometry(Geometry geometry) -> void override;
|
||||
auto setNavigation(Navigation navigation) -> void;
|
||||
auto setVisible(bool visible) -> void override;
|
||||
|
||||
auto _synchronizeLayout() -> void;
|
||||
|
||||
CocoaTabFrame* cocoaTabFrame = nullptr;
|
||||
vector<CocoaTabFrameItem*> tabs;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
119
cocoa/widget/text-edit.cpp
Normal file
119
cocoa/widget/text-edit.cpp
Normal file
|
@ -0,0 +1,119 @@
|
|||
#if defined(Hiro_TextEdit)
|
||||
|
||||
@implementation CocoaTextEdit : NSScrollView
|
||||
|
||||
-(id) initWith:(hiro::mTextEdit&)textEditReference {
|
||||
if(self = [super initWithFrame:NSMakeRect(0, 0, 0, 0)]) {
|
||||
textEdit = &textEditReference;
|
||||
|
||||
content = [[[NSTextView alloc] initWithFrame:NSMakeRect(0, 0, 0, 0)] autorelease];
|
||||
[content setDelegate:self];
|
||||
[content setRichText:NO];
|
||||
|
||||
[self setBorderType:NSBezelBorder];
|
||||
[self setDocumentView:content];
|
||||
[self configure];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
-(NSTextView*) content {
|
||||
return content;
|
||||
}
|
||||
|
||||
-(void) configure {
|
||||
[content setMinSize:NSMakeSize(0, 0)];
|
||||
[content setMaxSize:NSMakeSize(FLT_MAX, FLT_MAX)];
|
||||
|
||||
[[content textContainer] setContainerSize:NSMakeSize(FLT_MAX, FLT_MAX)];
|
||||
[[content textContainer] setWidthTracksTextView:textEdit->wordWrap()];
|
||||
|
||||
[content setHorizontallyResizable:YES];
|
||||
[content setVerticallyResizable:YES];
|
||||
[content setAutoresizingMask:NSViewNotSizable];
|
||||
|
||||
[self setHasHorizontalScroller:!textEdit->wordWrap()];
|
||||
[self setHasVerticalScroller:YES];
|
||||
}
|
||||
|
||||
-(void) textDidChange:(NSNotification*)notification {
|
||||
textEdit->state.text = [[content string] UTF8String];
|
||||
textEdit->doChange();
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
namespace hiro {
|
||||
|
||||
auto pTextEdit::construct() -> void {
|
||||
@autoreleasepool {
|
||||
cocoaView = cocoaTextEdit = [[CocoaTextEdit alloc] initWith:self()];
|
||||
pWidget::construct();
|
||||
|
||||
setEditable(state().editable);
|
||||
setWordWrap(state().wordWrap);
|
||||
setText(state().text);
|
||||
setCursor(state().cursor);
|
||||
}
|
||||
}
|
||||
|
||||
auto pTextEdit::destruct() -> void {
|
||||
@autoreleasepool {
|
||||
[cocoaView removeFromSuperview];
|
||||
[cocoaView release];
|
||||
}
|
||||
}
|
||||
|
||||
auto pTextEdit::setBackgroundColor(Color color) -> void {
|
||||
}
|
||||
|
||||
auto pTextEdit::setCursor(Cursor cursor) -> void {
|
||||
@autoreleasepool {
|
||||
//todo: handle text selection (cursor.length())
|
||||
string text = [[[cocoaView content] string] UTF8String];
|
||||
auto offset = min(cursor.offset(), text.length());
|
||||
[[cocoaView content] setSelectedRange:NSMakeRange(offset, 0)];
|
||||
}
|
||||
}
|
||||
|
||||
auto pTextEdit::setEditable(bool editable) -> void {
|
||||
@autoreleasepool {
|
||||
[[cocoaView content] setEditable:(editable && self().enabled(true))];
|
||||
}
|
||||
}
|
||||
|
||||
auto pTextEdit::setEnabled(bool enabled) -> void {
|
||||
pWidget::setEnabled(enabled);
|
||||
setEditable(state().editable); //Cocoa lacks NSTextView::setEnabled; simulate via setEnabled()
|
||||
}
|
||||
|
||||
auto pTextEdit::setFont(const Font& font) -> void {
|
||||
@autoreleasepool {
|
||||
[[cocoaView content] setFont:pFont::create(font)];
|
||||
}
|
||||
}
|
||||
|
||||
auto pTextEdit::setForegroundColor(Color color) -> void {
|
||||
}
|
||||
|
||||
auto pTextEdit::setText(const string& text) -> void {
|
||||
@autoreleasepool {
|
||||
[[cocoaView content] setString:[NSString stringWithUTF8String:text]];
|
||||
}
|
||||
}
|
||||
|
||||
auto pTextEdit::setWordWrap(bool wordWrap) -> void {
|
||||
@autoreleasepool {
|
||||
[cocoaView configure];
|
||||
}
|
||||
}
|
||||
|
||||
auto pTextEdit::text() const -> string {
|
||||
@autoreleasepool {
|
||||
return [[[cocoaView content] string] UTF8String];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
34
cocoa/widget/text-edit.hpp
Normal file
34
cocoa/widget/text-edit.hpp
Normal file
|
@ -0,0 +1,34 @@
|
|||
#if defined(Hiro_TextEdit)
|
||||
|
||||
@interface CocoaTextEdit : NSScrollView <NSTextViewDelegate> {
|
||||
@public
|
||||
hiro::mTextEdit* textEdit;
|
||||
NSTextView* content;
|
||||
}
|
||||
-(id) initWith:(hiro::mTextEdit&)textEdit;
|
||||
-(NSTextView*) content;
|
||||
-(void) configure;
|
||||
-(void) textDidChange:(NSNotification*)notification;
|
||||
@end
|
||||
|
||||
namespace hiro {
|
||||
|
||||
struct pTextEdit : pWidget {
|
||||
Declare(TextEdit, Widget)
|
||||
|
||||
auto setBackgroundColor(Color color) -> void;
|
||||
auto setCursor(Cursor cursor) -> void;
|
||||
auto setEditable(bool editable) -> void;
|
||||
auto setEnabled(bool enabled) -> void override;
|
||||
auto setFont(const Font& font) -> void override;
|
||||
auto setForegroundColor(Color color) -> void;
|
||||
auto setText(const string& text) -> void;
|
||||
auto setWordWrap(bool wordWrap) -> void;
|
||||
auto text() const -> string;
|
||||
|
||||
CocoaTextEdit* cocoaTextEdit = nullptr;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
94
cocoa/widget/vertical-scroll-bar.cpp
Normal file
94
cocoa/widget/vertical-scroll-bar.cpp
Normal file
|
@ -0,0 +1,94 @@
|
|||
#if defined(Hiro_VerticalScrollBar)
|
||||
|
||||
@implementation CocoaVerticalScrollBar : NSScroller
|
||||
|
||||
-(id) initWith:(hiro::mVerticalScrollBar&)verticalScrollBarReference {
|
||||
if(self = [super initWithFrame:NSMakeRect(0, 0, 0, 1)]) {
|
||||
verticalScrollBar = &verticalScrollBarReference;
|
||||
|
||||
[self setTarget:self];
|
||||
[self setAction:@selector(scroll:)];
|
||||
|
||||
[self setControlSize:NSRegularControlSize];
|
||||
[self setScrollerStyle:NSScrollerStyleLegacy];
|
||||
[self setEnabled:YES];
|
||||
|
||||
[self update];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
-(void) update {
|
||||
double d = 1.0 / verticalScrollBar->state.length;
|
||||
double f = d * verticalScrollBar->state.position;
|
||||
|
||||
[self setDoubleValue:f];
|
||||
[self setKnobProportion:d];
|
||||
}
|
||||
|
||||
-(IBAction) scroll:(id)sender {
|
||||
auto& state = verticalScrollBar->state;
|
||||
|
||||
switch([self hitPart]) {
|
||||
case NSScrollerIncrementLine:
|
||||
case NSScrollerIncrementPage:
|
||||
if(state.position < state.length - 1) state.position++;
|
||||
[self update];
|
||||
break;
|
||||
|
||||
case NSScrollerDecrementLine:
|
||||
case NSScrollerDecrementPage:
|
||||
if(state.position) state.position--;
|
||||
[self update];
|
||||
break;
|
||||
|
||||
case NSScrollerKnob:
|
||||
state.position = [self doubleValue] * state.length;
|
||||
break;
|
||||
}
|
||||
|
||||
verticalScrollBar->doChange();
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
namespace hiro {
|
||||
|
||||
auto pVerticalScrollBar::construct() -> void {
|
||||
@autoreleasepool {
|
||||
cocoaView = cocoaVerticalScrollBar = [[CocoaVerticalScrollBar alloc] initWith:self()];
|
||||
pWidget::construct();
|
||||
|
||||
setLength(state().length);
|
||||
setPosition(state().position);
|
||||
}
|
||||
}
|
||||
|
||||
auto pVerticalScrollBar::destruct() -> void {
|
||||
@autoreleasepool {
|
||||
[cocoaView removeFromSuperview];
|
||||
[cocoaView release];
|
||||
}
|
||||
}
|
||||
|
||||
auto pVerticalScrollBar::minimumSize() const -> Size {
|
||||
@autoreleasepool {
|
||||
return {(int)[NSScroller scrollerWidthForControlSize:NSRegularControlSize scrollerStyle:NSScrollerStyleLegacy], 32};
|
||||
}
|
||||
}
|
||||
|
||||
auto pVerticalScrollBar::setLength(uint length) -> void {
|
||||
@autoreleasepool {
|
||||
[cocoaView update];
|
||||
}
|
||||
}
|
||||
|
||||
auto pVerticalScrollBar::setPosition(uint position) -> void {
|
||||
@autoreleasepool {
|
||||
[cocoaView update];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
26
cocoa/widget/vertical-scroll-bar.hpp
Normal file
26
cocoa/widget/vertical-scroll-bar.hpp
Normal file
|
@ -0,0 +1,26 @@
|
|||
#if defined(Hiro_VerticalScrollBar)
|
||||
|
||||
@interface CocoaVerticalScrollBar : NSScroller {
|
||||
@public
|
||||
hiro::mVerticalScrollBar* verticalScrollBar;
|
||||
}
|
||||
-(id) initWith:(hiro::mVerticalScrollBar&)verticalScrollBar;
|
||||
-(void) update;
|
||||
-(IBAction) scroll:(id)sender;
|
||||
@end
|
||||
|
||||
namespace hiro {
|
||||
|
||||
struct pVerticalScrollBar : pWidget {
|
||||
Declare(VerticalScrollBar, Widget)
|
||||
|
||||
auto minimumSize() const -> Size override;
|
||||
auto setLength(uint length) -> void;
|
||||
auto setPosition(uint position) -> void;
|
||||
|
||||
CocoaVerticalScrollBar* cocoaVerticalScrollBar = nullptr;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
67
cocoa/widget/vertical-slider.cpp
Normal file
67
cocoa/widget/vertical-slider.cpp
Normal file
|
@ -0,0 +1,67 @@
|
|||
#if defined(Hiro_VerticalSlider)
|
||||
|
||||
@implementation CocoaVerticalSlider : NSSlider
|
||||
|
||||
-(id) initWith:(hiro::mVerticalSlider&)verticalSliderReference {
|
||||
if(self = [super initWithFrame:NSMakeRect(0, 0, 0, 1)]) {
|
||||
verticalSlider = &verticalSliderReference;
|
||||
|
||||
[self setTarget:self];
|
||||
[self setAction:@selector(activate:)];
|
||||
[self setMinValue:0];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
-(IBAction) activate:(id)sender {
|
||||
verticalSlider->state.position = [self doubleValue];
|
||||
verticalSlider->doChange();
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
namespace hiro {
|
||||
|
||||
auto pVerticalSlider::construct() -> void {
|
||||
@autoreleasepool {
|
||||
cocoaView = cocoaVerticalSlider = [[CocoaVerticalSlider alloc] initWith:self()];
|
||||
pWidget::construct();
|
||||
|
||||
setLength(state().length);
|
||||
setPosition(state().position);
|
||||
}
|
||||
}
|
||||
|
||||
auto pVerticalSlider::destruct() -> void {
|
||||
@autoreleasepool {
|
||||
[cocoaView removeFromSuperview];
|
||||
[cocoaView release];
|
||||
}
|
||||
}
|
||||
|
||||
auto pVerticalSlider::minimumSize() const -> Size {
|
||||
return {20, 48};
|
||||
}
|
||||
|
||||
auto pVerticalSlider::setGeometry(Geometry geometry) -> void {
|
||||
pWidget::setGeometry({
|
||||
geometry.x(), geometry.y() - 2,
|
||||
geometry.width(), geometry.height() + 4
|
||||
});
|
||||
}
|
||||
|
||||
auto pVerticalSlider::setLength(uint length) -> void {
|
||||
@autoreleasepool {
|
||||
[cocoaView setMaxValue:length];
|
||||
}
|
||||
}
|
||||
|
||||
auto pVerticalSlider::setPosition(uint position) -> void {
|
||||
@autoreleasepool {
|
||||
[cocoaView setDoubleValue:position];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue