comparison ios/dw.m @ 2422:4a353a83b2e4

iOS: Initial attempt at implementing check and radio boxes using SF Symbols.
author bsmith@81767d24-ef19-dc11-ae90-00e081727c95
date Sun, 04 Apr 2021 01:23:56 +0000
parents d88928a85436
children b4cb136b5222
comparison
equal deleted inserted replaced
2421:d88928a85436 2422:4a353a83b2e4
3 * A GTK like implementation of the iOS GUI 3 * A GTK like implementation of the iOS GUI
4 * 4 *
5 * (C) 2011-2021 Brian Smith <brian@dbsoft.org> 5 * (C) 2011-2021 Brian Smith <brian@dbsoft.org>
6 * (C) 2011-2018 Mark Hessling <mark@rexx.org> 6 * (C) 2011-2018 Mark Hessling <mark@rexx.org>
7 * 7 *
8 * Requires 10.0 or later. 8 * Requires 13.0 or later.
9 * clang -g -o dwtest -D__IOS__ -I. dwtest.c ios/dw.m -framework UIKit -framework WebKit -framework Foundation -framework UserNotifications 9 * clang -g -o dwtest -D__IOS__ -I. dwtest.c ios/dw.m -framework UIKit -framework WebKit -framework Foundation -framework UserNotifications
10 */ 10 */
11 #import <Foundation/Foundation.h> 11 #import <Foundation/Foundation.h>
12 #import <UIKit/UIKit.h> 12 #import <UIKit/UIKit.h>
13 #import <WebKit/WebKit.h> 13 #import <WebKit/WebKit.h>
1325 [view setFrame:frame]; 1325 [view setFrame:frame];
1326 [view windowResized:frame.size]; 1326 [view windowResized:frame.size];
1327 } 1327 }
1328 @end 1328 @end
1329 1329
1330 #define _DW_BUTTON_TYPE_NORMAL 0
1331 #define _DW_BUTTON_TYPE_CHECK 1
1332 #define _DW_BUTTON_TYPE_RADIO 2
1333
1330 /* Subclass for a button type */ 1334 /* Subclass for a button type */
1331 @interface DWButton : UIButton 1335 @interface DWButton : UIButton
1332 { 1336 {
1333 void *userdata; 1337 void *userdata;
1334 UIButtonType buttonType;
1335 DWBox *parent; 1338 DWBox *parent;
1339 int type, state;
1336 } 1340 }
1337 -(void *)userdata; 1341 -(void *)userdata;
1338 -(void)setUserdata:(void *)input; 1342 -(void)setUserdata:(void *)input;
1339 -(void)buttonClicked:(id)sender; 1343 -(void)buttonClicked:(id)sender;
1340 -(UIButtonType)buttonType;
1341 -(void)setParent:(DWBox *)input; 1344 -(void)setParent:(DWBox *)input;
1342 -(DWBox *)parent; 1345 -(DWBox *)parent;
1346 -(int)type;
1347 -(void)setType:(int)input;
1348 -(int)state;
1349 -(void)setState:(int)input;
1343 @end 1350 @end
1344 1351
1345 @implementation DWButton 1352 @implementation DWButton
1346 -(void *)userdata { return userdata; } 1353 -(void *)userdata { return userdata; }
1347 -(void)setUserdata:(void *)input { userdata = input; } 1354 -(void)setUserdata:(void *)input { userdata = input; }
1348 -(void)buttonClicked:(id)sender 1355 -(void)buttonClicked:(id)sender
1349 { 1356 {
1357 /* Toggle the button */
1358 if(type == _DW_BUTTON_TYPE_CHECK)
1359 [self setState:(state ? FALSE : TRUE)];
1360 else if(type == _DW_BUTTON_TYPE_RADIO)
1361 [self setState:TRUE];
1362
1350 _dw_event_handler(self, nil, 8); 1363 _dw_event_handler(self, nil, 8);
1351 } 1364
1352 -(UIButtonType)buttonType { return buttonType; } 1365 /* If it is a radio button, uncheck all the other radio buttons in the box */
1366 if(type == _DW_BUTTON_TYPE_RADIO)
1367 {
1368 DWBox *viewbox = [self parent];
1369 Box *thisbox = [viewbox box];
1370 int z;
1371
1372 for(z=0;z<thisbox->count;z++)
1373 {
1374 if(thisbox->items[z].type != TYPEBOX)
1375 {
1376 id object = thisbox->items[z].hwnd;
1377
1378 if([object isMemberOfClass:[DWButton class]])
1379 {
1380 DWButton *button = object;
1381
1382 if(button != self && [button type] == _DW_BUTTON_TYPE_RADIO)
1383 {
1384 [button setState:FALSE];
1385 }
1386 }
1387 }
1388 }
1389 }
1390 }
1353 -(void)setParent:(DWBox *)input { parent = input; } 1391 -(void)setParent:(DWBox *)input { parent = input; }
1354 -(DWBox *)parent { return parent; } 1392 -(DWBox *)parent { return parent; }
1393 -(int)type { return type; }
1394 -(void)setType:(int)input { type = input; [self updateImage]; }
1395 -(void)updateImage
1396 {
1397 UIImage *image = nil;
1398
1399 switch(type)
1400 {
1401 case _DW_BUTTON_TYPE_CHECK:
1402 {
1403
1404 if(state)
1405 image = [UIImage systemImageNamed:@"checkbox.square"];
1406 else
1407 image = [UIImage systemImageNamed:@"square"];
1408 }
1409 break;
1410 case _DW_BUTTON_TYPE_RADIO:
1411 {
1412 if(state)
1413 image = [UIImage systemImageNamed:@"largecircle.fill.circle"];
1414 else
1415 image = [UIImage systemImageNamed:@"circle"];
1416 }
1417 break;
1418 }
1419 if(image)
1420 {
1421 CGSize size = [image size];
1422 [self setImage:image forState:UIControlStateNormal];
1423 [self setTitleEdgeInsets:UIEdgeInsetsMake(0,size.width,0,0)];
1424 }
1425 }
1426 -(int)state { return state; }
1427 -(void)setState:(int)input { state = input; [self updateImage]; }
1355 -(void)dealloc { UserData *root = userdata; _dw_remove_userdata(&root, NULL, TRUE); dw_signal_disconnect_by_window(self); [super dealloc]; } 1428 -(void)dealloc { UserData *root = userdata; _dw_remove_userdata(&root, NULL, TRUE); dw_signal_disconnect_by_window(self); [super dealloc]; }
1356 @end 1429 @end
1357 1430
1358 /* Subclass for a progress type */ 1431 /* Subclass for a progress type */
1359 @interface DWPercent : UIProgressView 1432 @interface DWPercent : UIProgressView
3141 int thiswidth = 1, thisheight = 1, extrawidth = 0, extraheight = 0; 3214 int thiswidth = 1, thisheight = 1, extrawidth = 0, extraheight = 0;
3142 NSString *nsstr = nil; 3215 NSString *nsstr = nil;
3143 id object = _dw_text_handle(handle); 3216 id object = _dw_text_handle(handle);
3144 3217
3145 /* Handle all the different button types */ 3218 /* Handle all the different button types */
3146 if([ object isKindOfClass:[ UIButton class ] ]) 3219 if([ object isMemberOfClass:[ DWButton class ] ])
3147 { 3220 {
3148 switch([object buttonType]) 3221 UIImage *image = (UIImage *)[object image];
3149 { 3222
3150 default: 3223 if(image)
3151 { 3224 {
3152 UIImage *image = (UIImage *)[object image]; 3225 /* Image button */
3153 3226 CGSize size = [image size];
3154 if(image) 3227 extrawidth = (int)size.width;
3155 { 3228 extraheight = (int)size.height;
3156 /* Image button */ 3229 }
3157 CGSize size = [image size]; 3230 /* Text button */
3158 thiswidth = (int)size.width; 3231 nsstr = [[object titleLabel] text];
3159 thisheight = (int)size.height; 3232
3160 } 3233 if(nsstr && [nsstr length] > 0)
3161 else 3234 {
3162 { 3235 extrawidth += 8;
3163 /* Text button */ 3236 extraheight += 4;
3164 nsstr = [[object titleLabel] text];
3165
3166 extrawidth = 8;
3167 extraheight = 4;
3168 }
3169 break;
3170 }
3171 } 3237 }
3172 } 3238 }
3173 /* If the control is an entryfield set width to 150 */ 3239 /* If the control is an entryfield set width to 150 */
3174 else if([object isKindOfClass:[ UITextField class ]]) 3240 else if([object isKindOfClass:[ UITextField class ]])
3175 { 3241 {
3842 DW_FUNCTION_ADD_PARAM2(text, cid) 3908 DW_FUNCTION_ADD_PARAM2(text, cid)
3843 DW_FUNCTION_RETURN(dw_radiobutton_new, HWND) 3909 DW_FUNCTION_RETURN(dw_radiobutton_new, HWND)
3844 DW_FUNCTION_RESTORE_PARAM2(text, const char *, cid, ULONG) 3910 DW_FUNCTION_RESTORE_PARAM2(text, const char *, cid, ULONG)
3845 { 3911 {
3846 DWButton *button = _dw_internal_button_new(text, cid); 3912 DWButton *button = _dw_internal_button_new(text, cid);
3847 /* TODO: Customize to be a radio button https://github.com/DavydLiu/DLRadioButton */ 3913 [button setType:_DW_BUTTON_TYPE_RADIO];
3848 DW_FUNCTION_RETURN_THIS(button); 3914 DW_FUNCTION_RETURN_THIS(button);
3849 } 3915 }
3850 3916
3851 /* 3917 /*
3852 * Create a new slider window (widget) to be packed. 3918 * Create a new slider window (widget) to be packed.
3994 DW_FUNCTION_ADD_PARAM2(text, cid) 4060 DW_FUNCTION_ADD_PARAM2(text, cid)
3995 DW_FUNCTION_RETURN(dw_checkbox_new, HWND) 4061 DW_FUNCTION_RETURN(dw_checkbox_new, HWND)
3996 DW_FUNCTION_RESTORE_PARAM2(text, const char *, cid, ULONG) 4062 DW_FUNCTION_RESTORE_PARAM2(text, const char *, cid, ULONG)
3997 { 4063 {
3998 DWButton *button = _dw_internal_button_new(text, cid); 4064 DWButton *button = _dw_internal_button_new(text, cid);
3999 /* TODO: Switch to UISwitch control with text */ 4065 [button setType:_DW_BUTTON_TYPE_CHECK];
4000 DW_FUNCTION_RETURN_THIS(button); 4066 DW_FUNCTION_RETURN_THIS(button);
4001 } 4067 }
4002 4068
4003 /* 4069 /*
4004 * Returns the state of the checkbox. 4070 * Returns the state of the checkbox.
4005 * Parameters: 4071 * Parameters:
4006 * handle: Handle to the checkbox to be queried. 4072 * handle: Handle to the checkbox to be queried.
4007 */ 4073 */
4008 int API dw_checkbox_get(HWND handle) 4074 DW_FUNCTION_DEFINITION(dw_checkbox_get, int, HWND handle)
4075 DW_FUNCTION_ADD_PARAM1(handle)
4076 DW_FUNCTION_RETURN(dw_checkbox_get, int)
4077 DW_FUNCTION_RESTORE_PARAM1(handle, HWND)
4009 { 4078 {
4010 DWButton *button = handle; 4079 DWButton *button = handle;
4080 int retval = FALSE;
4081
4011 if([button state]) 4082 if([button state])
4012 { 4083 retval = TRUE;
4013 return TRUE; 4084 DW_FUNCTION_RETURN_THIS(retval);
4014 }
4015 return FALSE;
4016 } 4085 }
4017 4086
4018 /* 4087 /*
4019 * Sets the state of the checkbox. 4088 * Sets the state of the checkbox.
4020 * Parameters: 4089 * Parameters:
4021 * handle: Handle to the checkbox to be queried. 4090 * handle: Handle to the checkbox to be queried.
4022 * value: TRUE for checked, FALSE for unchecked. 4091 * value: TRUE for checked, FALSE for unchecked.
4023 */ 4092 */
4024 void API dw_checkbox_set(HWND handle, int value) 4093 DW_FUNCTION_DEFINITION(dw_checkbox_set, void, HWND handle, int value)
4025 { 4094 DW_FUNCTION_ADD_PARAM2(handle, value)
4026 #if 0 /* TODO: Convert to UISwitch */ 4095 DW_FUNCTION_NO_RETURN(dw_checkbox_set)
4096 DW_FUNCTION_RESTORE_PARAM2(handle, HWND, value, int)
4097 {
4027 DWButton *button = handle; 4098 DWButton *button = handle;
4028 if(value) 4099 [button setState:value];
4029 { 4100 DW_FUNCTION_RETURN_NOTHING;
4030 [button setState:DWControlStateValueOn];
4031 }
4032 else
4033 {
4034 [button setState:DWControlStateValueOff];
4035 }
4036 #endif
4037 } 4101 }
4038 4102
4039 /* Internal common function to create containers and listboxes */ 4103 /* Internal common function to create containers and listboxes */
4040 HWND _dw_cont_new(ULONG cid, int multi) 4104 HWND _dw_cont_new(ULONG cid, int multi)
4041 { 4105 {