#include "oscontrol_osx.inl"
#include "osgui_osx.inl"
#include "oscolor.inl"
#include "oslabel_osx.inl"
#include "osbutton_osx.inl"
#include "oscombo_osx.inl"
#include "osedit_osx.inl"
#include "ospanel_osx.inl"
#include "ospopup_osx.inl"
#include "osprogress_osx.inl"
#include "osslider_osx.inl"
#include "ossplit_osx.inl"
#include "ostext_osx.inl"
#include "osupdown_osx.inl"
#include "osview_osx.inl"
#include "osweb_osx.inl"
#include "oswindow_osx.inl"
#include "../osgui.inl"
#include "../oscontrol.inl"
#include <draw2d/color.h>
#include <draw2d/font.h>
#include <draw2d/image.h>
#include <sewer/cassert.h>
#include <sewer/ptr.h>
#include <sewer/unicode.h>
#if !defined(__MACOS__)
#error This file is only for OSX
#endif
void _oscontrol_init(NSView *control)
{
[control setHidden:YES];
}
void _oscontrol_origin_in_screen_coordinates(const NSRect *frame, CGFloat *x, CGFloat *y)
{
NSSize screen_size;
cassert_no_null(frame);
cassert_no_null(x);
cassert_no_null(y);
screen_size = [[NSScreen mainScreen] frame].size;
*x = frame->origin.x;
*y = screen_size.height - frame->origin.y - frame->size.height;
}
static ___INLINE NSTextAlignment i_text_alignment(const align_t halign)
{
#if defined(MAC_OS_X_VERSION_10_12) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_12
switch (halign)
{
case ekLEFT:
return NSTextAlignmentLeft;
case ekCENTER:
return NSTextAlignmentCenter;
case ekJUSTIFY:
return NSTextAlignmentJustified;
case ekRIGHT:
return NSTextAlignmentRight;
cassert_default();
}
return NSTextAlignmentLeft;
#else
switch (halign)
{
case ekLEFT:
return NSLeftTextAlignment;
case ekCENTER:
return NSCenterTextAlignment;
case ekJUSTIFY:
return NSJustifiedTextAlignment;
case ekRIGHT:
return NSRightTextAlignment;
cassert_default();
}
return NSLeftTextAlignment;
#endif
}
NSTextAlignment _oscontrol_text_alignment(const align_t halign)
{
return i_text_alignment(halign);
}
static ___INLINE NSControlSize i_control_size(const gui_size_t size)
{
#if defined(MAC_OS_X_VERSION_10_12) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_12
switch (size)
{
case ekGUI_SIZE_MINI:
return NSControlSizeMini;
case ekGUI_SIZE_SMALL:
return NSControlSizeSmall;
case ekGUI_SIZE_REGULAR:
return NSControlSizeRegular;
cassert_default();
}
#else
switch (size)
{
case ekGUI_SIZE_MINI:
return NSMiniControlSize;
case ekGUI_SIZE_SMALL:
return NSSmallControlSize;
case ekGUI_SIZE_REGULAR:
return NSRegularControlSize;
cassert_default();
}
#endif
return (NSControlSize)UINT32_MAX;
}
void _oscontrol_size_from_font(NSCell *cell, const Font *font)
{
gui_size_t size = _osgui_size_font(font_size(font));
[cell setControlSize:i_control_size(size)];
}
void _oscontrol_cell_set_control_size(NSCell *cell, const gui_size_t size)
{
cassert_no_null(cell);
[cell setControlSize:i_control_size(size)];
}
NSControlSize _oscontrol_control_size(const gui_size_t size)
{
return i_control_size(size);
}
void _oscontrol_cell_set_image(NSCell *cell, const Image *image)
{
cassert_no_null(cell);
if (image != NULL)
[cell setImage:cast(image_native(image), NSImage)];
else
[cell setImage:nil];
}
void _oscontrol_tooltip_set(NSView *view, const char_t *text)
{
cassert_no_null(view);
if (text != NULL)
{
NSString *str = [[NSString alloc] initWithUTF8String:cast_const(text, char)];
[view setToolTip:str];
[str release];
}
else
{
[view setToolTip:nil];
}
}
NSColor *_oscontrol_color(const color_t color)
{
return _oscolor_NSColor(color);
}
color_t _oscontrol_from_NSColor(NSColor *color)
{
return _oscolor_from_NSColor(color);
}
static NSColor *i_control_color(NSControl *control, const color_t color)
{
if ([control isEnabled] == YES)
{
if (color == kCOLOR_TRANSPARENT)
{
if ([control isKindOfClass:[NSTextField class]])
{
#if defined(MAC_OS_X_VERSION_10_10) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_10
return [NSColor labelColor];
#else
return [NSColor controlTextColor];
#endif
}
else
{
return [NSColor controlTextColor];
}
}
else
{
return _oscontrol_color(color);
}
}
else
{
return [NSColor disabledControlTextColor];
}
}
static NSDictionary *i_text_attribs(NSControl *control, const align_t align, const color_t color, const uint32_t fstyle, NSFont *font)
{
id keys[5];
id objects[5];
keys[0] = NSUnderlineStyleAttributeName;
keys[1] = NSStrikethroughStyleAttributeName;
keys[2] = NSParagraphStyleAttributeName;
keys[3] = NSForegroundColorAttributeName;
keys[4] = NSFontAttributeName;
objects[0] = (fstyle & ekFUNDERLINE) ? kUNDERLINE_STYLE_SINGLE : kUNDERLINE_STYLE_NONE;
objects[1] = (fstyle & ekFSTRIKEOUT) ? kUNDERLINE_STYLE_SINGLE : kUNDERLINE_STYLE_NONE;
switch (align)
{
case ekLEFT:
case ekJUSTIFY:
objects[2] = kLEFT_PARAGRAPH_STYLE;
break;
case ekRIGHT:
objects[2] = kRIGHT_PARAGRAPH_STYLE;
break;
case ekCENTER:
objects[2] = kCENTER_PARAGRAPH_STYLE;
break;
cassert_default();
}
objects[3] = i_control_color(control, color);
objects[4] = font;
return [NSDictionary dictionaryWithObjects:objects forKeys:keys count:5];
}
void _oscontrol_init_textattr(OSTextAttr *attr)
{
cassert_no_null(attr);
attr->font = _osgui_create_default_font();
attr->color = kCOLOR_TRANSPARENT;
attr->align = ekLEFT;
attr->mark = UINT32_MAX;
}
void _oscontrol_remove_textattr(OSTextAttr *attr)
{
cassert_no_null(attr);
ptr_destopt(font_destroy, &attr->font, Font);
}
static void i_update_text(NSControl *control, const OSTextAttr *attrs, NSString *str)
{
NSCell *cell = [control cell];
uint32_t fstyle = font_style(attrs->font);
cassert_no_null(control);
cassert_no_null(attrs);
if (str == nil)
{
if ([cell isKindOfClass:[NSButtonCell class]])
str = [cell title];
else
str = [cell stringValue];
}
{
NSFont *font = cast(font_native(attrs->font), NSFont);
NSDictionary *dict = i_text_attribs(control, attrs->align, attrs->color, fstyle, font);
NSAttributedString *astr = [[NSAttributedString alloc] initWithString:str attributes:dict];
NSMutableDictionary *mdict = nil;
NSMutableAttributedString *mastr = nil;
if (attrs->mark != UINT32_MAX && (fstyle & ekFUNDERLINE) == 0)
{
mdict = [[NSMutableDictionary alloc] initWithDictionary:dict];
[mdict setValue:kUNDERLINE_STYLE_SINGLE forKey:NSUnderlineStyleAttributeName];
mastr = [[NSMutableAttributedString alloc] initWithAttributedString:astr];
[mastr setAttributes:mdict range:NSMakeRange(attrs->mark, 1)];
}
[cell setFont:font];
if ([cell isKindOfClass:[NSButtonCell class]])
[(NSButtonCell *)cell setAttributedTitle:mastr != nil ? mastr : astr];
else
[cell setAttributedStringValue:mastr != nil ? mastr : astr];
[astr release];
if (mdict != nil)
[mdict release];
if (mastr != nil)
[mastr release];
}
}
void _oscontrol_set_text(NSControl *control, const OSTextAttr *attrs, const char_t *text)
{
NSString *str = [[NSString alloc] initWithUTF8String:cast_const(text, char)];
i_update_text(control, attrs, str);
[str release];
}
void _oscontrol_set_font(NSControl *control, OSTextAttr *attrs, const Font *font)
{
cassert_no_null(attrs);
if (font_equals(attrs->font, font) == FALSE)
{
font_destroy(&attrs->font);
attrs->font = font_copy(font);
i_update_text(control, attrs, nil);
}
}
void _oscontrol_set_align(NSControl *control, OSTextAttr *attrs, const align_t align)
{
cassert_no_null(attrs);
if (attrs->align != align)
{
attrs->align = align;
i_update_text(control, attrs, nil);
}
}
void _oscontrol_set_text_color(NSTextField *control, OSTextAttr *attrs, const color_t color)
{
cassert_no_null(attrs);
attrs->color = color;
i_update_text(control, attrs, nil);
}
void _oscontrol_attach_to_parent(NSView *control, NSView *parent)
{
cassert_no_null(control);
cassert_no_null(parent);
[parent addSubview:control];
}
void _oscontrol_detach_from_parent(NSView *control, NSView *parent)
{
cassert_no_null(control);
cassert_no_null(parent);
cassert([control superview] == parent);
[control removeFromSuperviewWithoutNeedingDisplay];
}
void _oscontrol_set_visible(NSView *object, const bool_t visible)
{
cassert_no_null(object);
[object setHidden:!(BOOL)visible];
}
void _oscontrol_set_enabled(NSControl *object, const bool_t enabled)
{
cassert_no_null(object);
if ([object isEnabled] != (BOOL)enabled)
[object setEnabled:(BOOL)enabled];
}
void _oscontrol_get_size(const NSView *object, real32_t *width, real32_t *height)
{
NSSize size;
cassert_no_null(object);
cassert_no_null(width);
cassert_no_null(height);
size = [object frame].size;
*width = (real32_t)size.width;
*height = (real32_t)size.height;
}
void _oscontrol_get_origin(const NSView *object, real32_t *x, real32_t *y)
{
NSRect rect;
cassert_no_null(object);
cassert_no_null(x);
cassert_no_null(y);
rect = [object frame];
if (*x < 0.f)
{
NSView *parent = [object superview];
cassert(*y < 0.f);
cassert(FALSE);
while (parent != nil)
{
NSRect parent_rect = [parent frame];
rect.origin.x += parent_rect.origin.x;
rect.origin.y += parent_rect.origin.y;
parent = [parent superview];
}
{
NSRect wframe = NSMakeRect(0.f, 0.f, 100.f, 100.f);
wframe = [object.window frameRectForContentRect:wframe];
rect.origin.y += wframe.size.height - 100.f;
}
{
NSRect window_rect = [object.window frame];
CGFloat origin_x, origin_y;
_oscontrol_origin_in_screen_coordinates(&window_rect, &origin_x, &origin_y);
*x = (real32_t)(origin_x + rect.origin.x);
*y = (real32_t)(origin_y + rect.origin.y);
}
}
else
{
*x = (real32_t)rect.origin.x;
*y = (real32_t)rect.origin.y;
}
}
#if defined(__ASSERTS__)
static BOOL i_check_control_frame(NSView *object)
{
cassert_no_null(object);
if ([object superview] == nil)
return YES;
if ([object window] == nil)
return YES;
if ([[object window] contentView] == object)
return YES;
{
NSRect parent_frame;
NSRect object_frame;
parent_frame = [[object superview] frame];
object_frame = [object frame];
cassert(parent_frame.origin.x >= 0.f);
cassert(parent_frame.origin.y >= 0.f);
cassert(parent_frame.size.width >= 0.f);
cassert(parent_frame.size.height >= 0.f);
cassert(object_frame.origin.x >= 0.f);
cassert(object_frame.origin.y >= 0.f);
}
return YES;
}
#endif
void _oscontrol_set_frame(NSView *object, const real32_t x, const real32_t y, const real32_t width, const real32_t height)
{
cassert_no_null(object);
if (__TRUE_EXPECTED(x >= 0.f))
{
[object setFrame:NSMakeRect((CGFloat)x, (CGFloat)y, (CGFloat)width, (CGFloat)height)];
}
else
{
cassert(y < 0.f);
[object setFrameSize:NSMakeSize((CGFloat)width, (CGFloat)height)];
}
cassert(i_check_control_frame(object) == YES);
}
static gui_type_t i_oscontrol_type(NSView *object)
{
cassert_no_null(object);
if (_oslabel_is(object) == YES)
return ekGUI_TYPE_LABEL;
if (_osbutton_is(object) == YES)
return ekGUI_TYPE_BUTTON;
if (_ospopup_is(object) == YES)
return ekGUI_TYPE_POPUP;
if (_osedit_is(object) == YES)
return ekGUI_TYPE_EDITBOX;
if (_oscombo_is(object) == YES)
return ekGUI_TYPE_COMBOBOX;
if (_osslider_is(object) == YES)
return ekGUI_TYPE_SLIDER;
if (_osupdown_is(object) == YES)
return ekGUI_TYPE_UPDOWN;
if (_osprogress_is(object) == YES)
return ekGUI_TYPE_PROGRESS;
if (_ostext_is(object) == YES)
return ekGUI_TYPE_TEXTVIEW;
if (_osweb_is(object) == YES)
return ekGUI_TYPE_WEBVIEW;
if (_ossplit_is(object) == YES)
return ekGUI_TYPE_SPLITVIEW;
if (_osview_is(object) == YES)
return ekGUI_TYPE_CUSTOMVIEW;
if (_ospanel_is(object) == YES)
return ekGUI_TYPE_PANEL;
return ENUM_MAX(gui_type_t);
}
OSControl *_oscontrol_from_nsview(NSView *object)
{
gui_type_t type = i_oscontrol_type(object);
if (type != ENUM_MAX(gui_type_t))
return cast(object, OSControl);
return NULL;
}
gui_type_t _oscontrol_type(const OSControl *control)
{
gui_type_t type = ENUM_MAX(gui_type_t);
cassert_no_null(control);
cassert([cast(control, NSObject) isKindOfClass:[NSView class]] == YES);
type = i_oscontrol_type(cast(control, NSView));
cassert(type != ENUM_MAX(gui_type_t));
return type;
}
OSControl *_oscontrol_parent(const OSControl *control)
{
cassert_no_null(control);
cassert([cast(control, NSObject) isKindOfClass:[NSView class]] == YES);
return cast([cast(control, NSView) superview], OSControl);
}
void _oscontrol_frame(const OSControl *control, OSFrame *rect)
{
real32_t x, y, w, h;
cassert_no_null(control);
cassert_no_null(rect);
cassert([cast(control, NSObject) isKindOfClass:[NSView class]] == YES);
_oscontrol_get_origin(cast(control, NSView), &x, &y);
_oscontrol_get_size(cast(control, NSView), &w, &h);
rect->left = (int32_t)x;
rect->top = (int32_t)y;
rect->right = rect->left + (int32_t)w;
rect->bottom = rect->top + (int32_t)h;
}
void _oscontrol_set_can_focus(OSControl *control, const bool_t can_focus)
{
unref(control);
unref(can_focus);
}
OSWidget *_oscontrol_focus_widget(const OSControl *control)
{
cassert_no_null(control);
cassert([cast(control, NSObject) isKindOfClass:[NSView class]] == YES);
if (_osview_is(cast(control, NSView)) == YES)
return cast(_osview_focus_widget(cast(control, NSView)), OSWidget);
return cast(control, OSWidget);
}
bool_t _oscontrol_widget_visible(const OSWidget *widget)
{
cassert_no_null(widget);
return (bool_t) ![cast(widget, NSView) isHidden];
}
bool_t _oscontrol_widget_enable(const OSWidget *widget)
{
cassert_no_null(widget);
if ([(NSObject *)widget isKindOfClass:[NSControl class]] == YES)
return (bool_t)[cast(widget, NSControl) isEnabled];
else
return TRUE;
}