# HG changeset patch # User bsmith@81767d24-ef19-dc11-ae90-00e081727c95 # Date 1617499436 0 # Node ID 4a353a83b2e4022f7dae25eb899d3c167f1a9922 # Parent d88928a854369d2af8d52bd66a6b93aa6c038007 iOS: Initial attempt at implementing check and radio boxes using SF Symbols. diff -r d88928a85436 -r 4a353a83b2e4 ios/dw.m --- a/ios/dw.m Sat Apr 03 21:25:25 2021 +0000 +++ b/ios/dw.m Sun Apr 04 01:23:56 2021 +0000 @@ -5,7 +5,7 @@ * (C) 2011-2021 Brian Smith * (C) 2011-2018 Mark Hessling * - * Requires 10.0 or later. + * Requires 13.0 or later. * clang -g -o dwtest -D__IOS__ -I. dwtest.c ios/dw.m -framework UIKit -framework WebKit -framework Foundation -framework UserNotifications */ #import @@ -1327,19 +1327,26 @@ } @end +#define _DW_BUTTON_TYPE_NORMAL 0 +#define _DW_BUTTON_TYPE_CHECK 1 +#define _DW_BUTTON_TYPE_RADIO 2 + /* Subclass for a button type */ @interface DWButton : UIButton { void *userdata; - UIButtonType buttonType; DWBox *parent; + int type, state; } -(void *)userdata; -(void)setUserdata:(void *)input; -(void)buttonClicked:(id)sender; --(UIButtonType)buttonType; -(void)setParent:(DWBox *)input; -(DWBox *)parent; +-(int)type; +-(void)setType:(int)input; +-(int)state; +-(void)setState:(int)input; @end @implementation DWButton @@ -1347,11 +1354,77 @@ -(void)setUserdata:(void *)input { userdata = input; } -(void)buttonClicked:(id)sender { + /* Toggle the button */ + if(type == _DW_BUTTON_TYPE_CHECK) + [self setState:(state ? FALSE : TRUE)]; + else if(type == _DW_BUTTON_TYPE_RADIO) + [self setState:TRUE]; + _dw_event_handler(self, nil, 8); -} --(UIButtonType)buttonType { return buttonType; } + + /* If it is a radio button, uncheck all the other radio buttons in the box */ + if(type == _DW_BUTTON_TYPE_RADIO) + { + DWBox *viewbox = [self parent]; + Box *thisbox = [viewbox box]; + int z; + + for(z=0;zcount;z++) + { + if(thisbox->items[z].type != TYPEBOX) + { + id object = thisbox->items[z].hwnd; + + if([object isMemberOfClass:[DWButton class]]) + { + DWButton *button = object; + + if(button != self && [button type] == _DW_BUTTON_TYPE_RADIO) + { + [button setState:FALSE]; + } + } + } + } + } +} -(void)setParent:(DWBox *)input { parent = input; } -(DWBox *)parent { return parent; } +-(int)type { return type; } +-(void)setType:(int)input { type = input; [self updateImage]; } +-(void)updateImage +{ + UIImage *image = nil; + + switch(type) + { + case _DW_BUTTON_TYPE_CHECK: + { + + if(state) + image = [UIImage systemImageNamed:@"checkbox.square"]; + else + image = [UIImage systemImageNamed:@"square"]; + } + break; + case _DW_BUTTON_TYPE_RADIO: + { + if(state) + image = [UIImage systemImageNamed:@"largecircle.fill.circle"]; + else + image = [UIImage systemImageNamed:@"circle"]; + } + break; + } + if(image) + { + CGSize size = [image size]; + [self setImage:image forState:UIControlStateNormal]; + [self setTitleEdgeInsets:UIEdgeInsetsMake(0,size.width,0,0)]; + } +} +-(int)state { return state; } +-(void)setState:(int)input { state = input; [self updateImage]; } -(void)dealloc { UserData *root = userdata; _dw_remove_userdata(&root, NULL, TRUE); dw_signal_disconnect_by_window(self); [super dealloc]; } @end @@ -3143,31 +3216,24 @@ id object = _dw_text_handle(handle); /* Handle all the different button types */ - if([ object isKindOfClass:[ UIButton class ] ]) - { - switch([object buttonType]) - { - default: - { - UIImage *image = (UIImage *)[object image]; - - if(image) - { - /* Image button */ - CGSize size = [image size]; - thiswidth = (int)size.width; - thisheight = (int)size.height; - } - else - { - /* Text button */ - nsstr = [[object titleLabel] text]; - - extrawidth = 8; - extraheight = 4; - } - break; - } + if([ object isMemberOfClass:[ DWButton class ] ]) + { + UIImage *image = (UIImage *)[object image]; + + if(image) + { + /* Image button */ + CGSize size = [image size]; + extrawidth = (int)size.width; + extraheight = (int)size.height; + } + /* Text button */ + nsstr = [[object titleLabel] text]; + + if(nsstr && [nsstr length] > 0) + { + extrawidth += 8; + extraheight += 4; } } /* If the control is an entryfield set width to 150 */ @@ -3844,7 +3910,7 @@ DW_FUNCTION_RESTORE_PARAM2(text, const char *, cid, ULONG) { DWButton *button = _dw_internal_button_new(text, cid); - /* TODO: Customize to be a radio button https://github.com/DavydLiu/DLRadioButton */ + [button setType:_DW_BUTTON_TYPE_RADIO]; DW_FUNCTION_RETURN_THIS(button); } @@ -3996,7 +4062,7 @@ DW_FUNCTION_RESTORE_PARAM2(text, const char *, cid, ULONG) { DWButton *button = _dw_internal_button_new(text, cid); - /* TODO: Switch to UISwitch control with text */ + [button setType:_DW_BUTTON_TYPE_CHECK]; DW_FUNCTION_RETURN_THIS(button); } @@ -4005,14 +4071,17 @@ * Parameters: * handle: Handle to the checkbox to be queried. */ -int API dw_checkbox_get(HWND handle) +DW_FUNCTION_DEFINITION(dw_checkbox_get, int, HWND handle) +DW_FUNCTION_ADD_PARAM1(handle) +DW_FUNCTION_RETURN(dw_checkbox_get, int) +DW_FUNCTION_RESTORE_PARAM1(handle, HWND) { DWButton *button = handle; + int retval = FALSE; + if([button state]) - { - return TRUE; - } - return FALSE; + retval = TRUE; + DW_FUNCTION_RETURN_THIS(retval); } /* @@ -4021,19 +4090,14 @@ * handle: Handle to the checkbox to be queried. * value: TRUE for checked, FALSE for unchecked. */ -void API dw_checkbox_set(HWND handle, int value) -{ -#if 0 /* TODO: Convert to UISwitch */ +DW_FUNCTION_DEFINITION(dw_checkbox_set, void, HWND handle, int value) +DW_FUNCTION_ADD_PARAM2(handle, value) +DW_FUNCTION_NO_RETURN(dw_checkbox_set) +DW_FUNCTION_RESTORE_PARAM2(handle, HWND, value, int) +{ DWButton *button = handle; - if(value) - { - [button setState:DWControlStateValueOn]; - } - else - { - [button setState:DWControlStateValueOff]; - } -#endif + [button setState:value]; + DW_FUNCTION_RETURN_NOTHING; } /* Internal common function to create containers and listboxes */