Fix: Editor initially presents at location (0,0) Tweaks: - Added Done button for text fields - Enabled swipe to hide keyboard gesture
1148 lines
52 KiB
Objective-C
1148 lines
52 KiB
Objective-C
#import "Alderis.h"
|
|
#import "Alderis-Swift.h"
|
|
#import "CustomControlsViewController.h"
|
|
#import "DBNumberedSlider.h"
|
|
#import "FileListViewController.h"
|
|
#import "LauncherPreferences.h"
|
|
#import "ios_uikit_bridge.h"
|
|
|
|
#import "customcontrols/ControlDrawer.h"
|
|
#import "customcontrols/ControlLayout.h"
|
|
#import "customcontrols/CustomControlsUtils.h"
|
|
|
|
#include <dlfcn.h>
|
|
|
|
#include "glfw_keycodes.h"
|
|
#include "utils.h"
|
|
|
|
BOOL shouldDismissPopover = YES;
|
|
NSMutableArray *keyCodeMap, *keyValueMap;
|
|
|
|
@implementation ControlHandleView
|
|
// Nothing
|
|
@end
|
|
|
|
@interface CustomControlsViewController () <UIGestureRecognizerDelegate, UIPopoverPresentationControllerDelegate>{
|
|
}
|
|
|
|
@property(nonatomic) NSString* currentFileName;
|
|
@property(nonatomic) CGRect selectedPoint;
|
|
@property(nonatomic) UINavigationBar* navigationBar;
|
|
|
|
@end
|
|
|
|
@implementation CustomControlsViewController
|
|
|
|
- (void)viewDidLoad
|
|
{
|
|
[super viewDidLoad];
|
|
[self.undoManager removeAllActions];
|
|
self.view.backgroundColor = [UIColor colorWithWhite:0.2 alpha:0.5];
|
|
isControlModifiable = YES;
|
|
|
|
[self setNeedsUpdateOfScreenEdgesDeferringSystemGestures];
|
|
[self setNeedsUpdateOfHomeIndicatorAutoHidden];
|
|
|
|
CGRect screenBounds = [[UIScreen mainScreen] bounds];
|
|
UIEdgeInsets insets = UIApplication.sharedApplication.windows.firstObject.safeAreaInsets;
|
|
|
|
UILabel *guideLabel = [[UILabel alloc] initWithFrame:self.view.frame];
|
|
guideLabel.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
|
|
guideLabel.numberOfLines = 0;
|
|
guideLabel.textAlignment = NSTextAlignmentCenter;
|
|
guideLabel.textColor = UIColor.whiteColor;
|
|
guideLabel.text = localize(@"custom_controls.hint", nil);
|
|
[self.view addSubview:guideLabel];
|
|
|
|
self.ctrlView = [[ControlLayout alloc] initWithFrame:CGRectFromString(getPreference(@"control_safe_area"))];
|
|
if (@available(iOS 13.0, *)) {
|
|
self.ctrlView.layer.borderColor = UIColor.labelColor.CGColor;
|
|
} else {
|
|
self.ctrlView.layer.borderColor = UIColor.blackColor.CGColor;
|
|
}
|
|
[self.view addSubview:self.ctrlView];
|
|
|
|
// Prepare the navigation bar for safe area customization
|
|
UINavigationItem *navigationItem = [[UINavigationItem alloc] init];
|
|
UISegmentedControl *segmentedControl = [[UISegmentedControl alloc] initWithItems:@[@"None", @"Default", @"Custom"]];
|
|
[segmentedControl addTarget:self action:@selector(changeSafeAreaSelection:) forControlEvents:UIControlEventValueChanged];
|
|
[segmentedControl setEnabled:(insets.left+insets.right)>0 forSegmentAtIndex:1];
|
|
[self loadSafeAreaSelectionFor:segmentedControl];
|
|
navigationItem.titleView = segmentedControl;
|
|
navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:@selector(actionMenuSafeAreaCancel)];
|
|
navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(actionMenuSafeAreaDone)];
|
|
self.navigationBar = [[UINavigationBar alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 44.0)];
|
|
self.navigationBar.autoresizingMask = UIViewAutoresizingFlexibleWidth;
|
|
self.navigationBar.hidden = YES;
|
|
self.navigationBar.items = @[navigationItem];
|
|
self.navigationBar.translucent = YES;
|
|
[self.view addSubview:self.navigationBar];
|
|
|
|
CGFloat buttonScale = [getPreference(@"button_scale") floatValue] / 100.0;
|
|
|
|
self.resizeView = [[ControlHandleView alloc] initWithFrame:CGRectMake(0, 0, 30, 30)];
|
|
self.resizeView.backgroundColor = self.view.tintColor;
|
|
self.resizeView.layer.cornerRadius = self.resizeView.frame.size.width / 2;
|
|
self.resizeView.clipsToBounds = YES;
|
|
self.resizeView.hidden = YES;
|
|
[self.resizeView addGestureRecognizer:[[UIPanGestureRecognizer alloc]
|
|
initWithTarget:self action:@selector(onTouch:)]];
|
|
[self.view addSubview:self.resizeView];
|
|
|
|
UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panControlArea:)];
|
|
panGesture.delegate = self;
|
|
panGesture.maximumNumberOfTouches = 1;
|
|
[self.ctrlView addGestureRecognizer:panGesture];
|
|
|
|
UIPinchGestureRecognizer *pinchGesture = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(pinchControlArea:)];
|
|
pinchGesture.delegate = self;
|
|
[self.ctrlView addGestureRecognizer:pinchGesture];
|
|
|
|
UILongPressGestureRecognizer *longpressGesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(showControlPopover:)];
|
|
longpressGesture.minimumPressDuration = 0.5;
|
|
[self.ctrlView addGestureRecognizer:longpressGesture];
|
|
self.currentFileName = [getPreference(@"default_ctrl") stringByDeletingPathExtension];
|
|
[self initKeyCodeMap];
|
|
[self loadControlFile:[NSString stringWithFormat:@"%s/controlmap/%@", getenv("POJAV_HOME"), getPreference(@"default_ctrl")]];
|
|
}
|
|
|
|
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)sender shouldReceiveTouch:(UITouch *)touch {
|
|
return sender.view != self.view || !CGRectContainsPoint(self.resizeView.frame, [sender locationInView:self.view]);
|
|
}
|
|
/*
|
|
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)sender shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
|
|
return YES;
|
|
}
|
|
*/
|
|
- (void)panControlArea:(UIPanGestureRecognizer *)sender {
|
|
static CGPoint previous;
|
|
if (sender.state == UIGestureRecognizerStateBegan) {
|
|
[self setButtonMenuVisibleForView:nil];
|
|
self.resizeView.hidden = self.ctrlView.layer.borderWidth == 0;
|
|
self.resizeView.layer.maskedCorners = kCALayerMinXMinYCorner | kCALayerMaxXMinYCorner | kCALayerMinXMaxYCorner;
|
|
previous = [sender locationInView:self.view];
|
|
return;
|
|
} else if (self.navigationBar.hidden) {
|
|
return;
|
|
}
|
|
|
|
CGPoint current = [sender locationInView:self.view];
|
|
|
|
CGRect rect = self.ctrlView.frame;
|
|
rect.origin.x = clamp(rect.origin.x + current.x - previous.x, 0, self.view.frame.size.width - rect.size.width);
|
|
rect.origin.y = clamp(rect.origin.y + current.y - previous.y, 0, self.view.frame.size.height - rect.size.height);
|
|
self.ctrlView.frame = rect;
|
|
|
|
self.resizeView.frame = CGRectMake(CGRectGetMaxX(self.ctrlView.frame) - self.resizeView.frame.size.width, CGRectGetMaxY(self.ctrlView.frame) - self.resizeView.frame.size.height, self.resizeView.frame.size.width, self.resizeView.frame.size.height);
|
|
|
|
previous = current;
|
|
}
|
|
|
|
- (void)pinchControlArea:(UIPinchGestureRecognizer *)sender {
|
|
if (sender.numberOfTouches < 2 || self.navigationBar.hidden) {
|
|
return;
|
|
}
|
|
|
|
static CGPoint previous;
|
|
CGPoint current = [sender locationInView:self.view];
|
|
if (sender.state == UIGestureRecognizerStateBegan) {
|
|
previous = current;
|
|
return;
|
|
}
|
|
|
|
self.ctrlView.frame = CGRectMake(
|
|
clamp(self.ctrlView.frame.origin.x + current.x - previous.x, 0, self.view.frame.size.width - self.ctrlView.frame.size.width),
|
|
clamp(self.ctrlView.frame.origin.y + current.y - previous.y, 0, self.view.frame.size.height - self.ctrlView.frame.size.height),
|
|
clamp(self.ctrlView.frame.size.width * sender.scale, self.view.frame.size.width / 2, self.view.frame.size.width),
|
|
clamp(self.ctrlView.frame.size.height * sender.scale, self.view.frame.size.height / 2, self.view.frame.size.height)
|
|
);
|
|
self.resizeView.frame = CGRectMake(CGRectGetMaxX(self.ctrlView.frame), CGRectGetMaxY(self.ctrlView.frame), self.resizeView.frame.size.width, self.resizeView.frame.size.height);
|
|
|
|
previous = current;
|
|
|
|
sender.scale = 1.0;
|
|
}
|
|
|
|
- (void)loadControlFile:(NSString *)controlFilePath {
|
|
for (UIView *view in self.ctrlView.subviews) {
|
|
if ([view isKindOfClass:[ControlButton class]]) {
|
|
[view removeFromSuperview];
|
|
}
|
|
}
|
|
|
|
self.cc_dictionary = parseJSONFromFile(controlFilePath);
|
|
if (self.cc_dictionary == nil) return;
|
|
|
|
loadControlObject(self.ctrlView, self.cc_dictionary, ^void(ControlButton* button) {
|
|
[button addGestureRecognizer:[[UITapGestureRecognizer alloc]
|
|
initWithTarget:self action:@selector(showControlPopover:)]];
|
|
[button addGestureRecognizer:[[UIPanGestureRecognizer alloc]
|
|
initWithTarget:self action:@selector(onTouch:)]];
|
|
});
|
|
}
|
|
|
|
- (void)viewDidLayoutSubviews {
|
|
CGRect ctrlFrame = CGRectFromString(getPreference(@"control_safe_area"));
|
|
if ((ctrlFrame.size.width > ctrlFrame.size.height) != (self.view.frame.size.width > self.view.frame.size.height)) {
|
|
CGFloat tmpHeight = ctrlFrame.size.width;
|
|
ctrlFrame.size.width = ctrlFrame.size.height;
|
|
ctrlFrame.size.height = tmpHeight;
|
|
self.ctrlView.frame = ctrlFrame;
|
|
setPreference(@"control_safe_area", NSStringFromCGRect(ctrlFrame));
|
|
}
|
|
|
|
// Update dynamic position for each view
|
|
for (UIView *view in self.ctrlView.subviews) {
|
|
if ([view isKindOfClass:[ControlButton class]]) {
|
|
[(ControlButton *)view update];
|
|
}
|
|
}
|
|
}
|
|
|
|
- (void)changeSafeAreaSelection:(UISegmentedControl *)sender {
|
|
switch (sender.selectedSegmentIndex) {
|
|
case 0:
|
|
self.ctrlView.frame = self.view.frame;
|
|
break;
|
|
case 1:
|
|
self.ctrlView.frame = getDefaultSafeArea();
|
|
break;
|
|
case 2:
|
|
self.ctrlView.frame = CGRectFromString(getPreference(@"control_safe_area"));
|
|
break;
|
|
}
|
|
self.ctrlView.userInteractionEnabled = sender.selectedSegmentIndex == 2;
|
|
self.resizeView.hidden = sender.selectedSegmentIndex != 2;
|
|
}
|
|
|
|
- (void)loadSafeAreaSelectionFor:(UISegmentedControl *)control {
|
|
if (CGRectEqualToRect(self.ctrlView.frame, UIScreen.mainScreen.bounds)) {
|
|
control.selectedSegmentIndex = 0;
|
|
} else {
|
|
control.selectedSegmentIndex = !CGRectEqualToRect(self.ctrlView.frame, getDefaultSafeArea()) + 1;
|
|
}
|
|
}
|
|
|
|
- (void)showControlPopover:(UIGestureRecognizer *)sender {
|
|
self.currentGesture = sender;
|
|
|
|
switch (sender.state) {
|
|
case UIGestureRecognizerStateBegan:
|
|
if (![sender isKindOfClass:[UILongPressGestureRecognizer class]]) {
|
|
return;
|
|
}
|
|
break;
|
|
case UIGestureRecognizerStateEnded:
|
|
if ([sender isKindOfClass:[UILongPressGestureRecognizer class]]) {
|
|
return;
|
|
}
|
|
break;
|
|
default:
|
|
return;
|
|
}
|
|
|
|
UIMenuController *menuController = [UIMenuController sharedMenuController];
|
|
|
|
if (![sender.view isKindOfClass:[ControlButton class]]) {
|
|
UIMenuItem *actionExit = [[UIMenuItem alloc] initWithTitle:localize(@"custom_controls.control_menu.exit", nil) action:@selector(actionMenuExit)];
|
|
UIMenuItem *actionSave = [[UIMenuItem alloc] initWithTitle:localize(@"custom_controls.control_menu.save", nil) action:@selector(actionMenuSave)];
|
|
UIMenuItem *actionLoad = [[UIMenuItem alloc] initWithTitle:localize(@"custom_controls.control_menu.load", nil) action:@selector(actionMenuLoad)];
|
|
UIMenuItem *actionSetDef = [[UIMenuItem alloc] initWithTitle:localize(@"custom_controls.control_menu.make_default", nil) action:@selector(actionMenuSetDef)];
|
|
UIMenuItem *actionSafeArea = [[UIMenuItem alloc] initWithTitle:localize(@"custom_controls.control_menu.safe_area", nil) action:@selector(actionMenuSafeArea)];
|
|
UIMenuItem *actionAddButton = [[UIMenuItem alloc] initWithTitle:localize(@"custom_controls.control_menu.add_button", nil) action:@selector(actionMenuAddButton)];
|
|
UIMenuItem *actionAddDrawer = [[UIMenuItem alloc] initWithTitle:localize(@"custom_controls.control_menu.add_drawer", nil) action:@selector(actionMenuAddDrawer)];
|
|
[menuController setMenuItems:@[actionExit, actionSave, actionLoad, actionSetDef, actionSafeArea, actionAddButton, actionAddDrawer]];
|
|
|
|
CGPoint point = [sender locationInView:sender.view];
|
|
self.selectedPoint = CGRectMake(point.x, point.y, 1.0, 1.0);
|
|
} else {
|
|
UIMenuItem *actionEdit = [[UIMenuItem alloc] initWithTitle:localize(@"Edit", nil) action:@selector(actionMenuBtnEdit)];
|
|
UIMenuItem *actionCopy = [[UIMenuItem alloc] initWithTitle:localize(@"Copy", nil) action:@selector(actionMenuBtnCopy)];
|
|
UIMenuItem *actionDelete = [[UIMenuItem alloc] initWithTitle:localize(@"Remove", nil) action:@selector(actionMenuBtnDelete)];
|
|
if ([sender.view isKindOfClass:[ControlDrawer class]]) {
|
|
UIMenuItem *actionAddSubButton = [[UIMenuItem alloc] initWithTitle:localize(@"custom_controls.button_menu.add_subbutton", nil) action:@selector(actionMenuAddSubButton)];
|
|
[menuController setMenuItems:@[actionEdit, /* actionCopy, */ actionDelete, actionAddSubButton]];
|
|
} else {
|
|
[menuController setMenuItems:@[actionEdit, /* actionCopy, */ actionDelete]];
|
|
}
|
|
self.selectedPoint = sender.view.bounds;
|
|
}
|
|
|
|
if (sender.view != self.ctrlView) {
|
|
[self.ctrlView becomeFirstResponder];
|
|
}
|
|
[sender.view becomeFirstResponder];
|
|
|
|
self.resizeView.hidden = sender.view == self.ctrlView;
|
|
[self setButtonMenuVisibleForView:sender.view];
|
|
}
|
|
|
|
- (void)actionMenuExit {
|
|
if (self.undoManager.canUndo) {
|
|
[self actionMenuSaveWithExit:YES];
|
|
return;
|
|
}
|
|
[self dismissViewControllerAnimated:YES completion:nil];
|
|
}
|
|
|
|
- (void)actionMenuSaveWithExit:(BOOL)exit {
|
|
UIAlertController *controller = [UIAlertController alertControllerWithTitle: localize(@"custom_controls.control_menu.save", nil)
|
|
message:exit?localize(@"custom_controls.control_menu.exit.warn", nil):@""
|
|
preferredStyle:UIAlertControllerStyleAlert];
|
|
[controller addTextFieldWithConfigurationHandler:^(UITextField *textField) {
|
|
textField.placeholder = @"Name";
|
|
textField.text = self.currentFileName;
|
|
textField.clearButtonMode = UITextFieldViewModeWhileEditing;
|
|
textField.borderStyle = UITextBorderStyleRoundedRect;
|
|
}];
|
|
[controller addAction:[UIAlertAction actionWithTitle:localize(@"OK", nil) style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
|
|
NSArray *textFields = controller.textFields;
|
|
UITextField *field = textFields[0];
|
|
if ([field.text isEqualToString:@"default"]) {
|
|
controller.message = localize(@"custom_controls.control_menu.save.error.default", nil);
|
|
[self presentViewController:controller animated:YES completion:nil];
|
|
} else {
|
|
NSError *error;
|
|
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:self.cc_dictionary options:NSJSONWritingPrettyPrinted error:&error];
|
|
if (jsonData == nil) {
|
|
showDialog(self, localize(@"custom_controls.control_menu.save.error.json", nil), error.localizedDescription);
|
|
return;
|
|
}
|
|
BOOL success = [jsonData writeToFile:[NSString stringWithFormat:@"%s/controlmap/%@.json", getenv("POJAV_HOME"), field.text] options:NSDataWritingAtomic error:&error];
|
|
if (!success) {
|
|
showDialog(self, localize(@"custom_controls.control_menu.save.error.write", nil), error.localizedDescription);
|
|
return;
|
|
}
|
|
|
|
if (exit) {
|
|
[self dismissViewControllerAnimated:YES completion:nil];
|
|
}
|
|
|
|
self.currentFileName = field.text;
|
|
[self.undoManager removeAllActions];
|
|
}
|
|
}]];
|
|
if (exit) {
|
|
[controller addAction:[UIAlertAction actionWithTitle:localize(@"custom_controls.control_menu.discard_changes", nil) style:UIAlertActionStyleDestructive handler:^(UIAlertAction *action) {
|
|
[self dismissViewControllerAnimated:YES completion:nil];
|
|
}]];
|
|
}
|
|
[controller addAction:[UIAlertAction actionWithTitle:localize(@"Cancel", nil) style:UIAlertActionStyleCancel handler:nil]];
|
|
[self presentViewController:controller animated:YES completion:nil];
|
|
}
|
|
|
|
- (void)actionMenuSave {
|
|
[self actionMenuSaveWithExit:NO];
|
|
}
|
|
|
|
- (void)actionOpenFilePicker:(void (^)(NSString *name))handler {
|
|
FileListViewController *vc = [[FileListViewController alloc] init];
|
|
vc.listPath = [NSString stringWithFormat:@"%s/controlmap", getenv("POJAV_HOME")];
|
|
vc.whenItemSelected = handler;
|
|
vc.modalPresentationStyle = UIModalPresentationPopover;
|
|
vc.preferredContentSize = CGSizeMake(350, 250);
|
|
|
|
UIPopoverPresentationController *popoverController = [vc popoverPresentationController];
|
|
popoverController.sourceView = self.view;
|
|
popoverController.sourceRect = self.selectedPoint;
|
|
popoverController.permittedArrowDirections = UIPopoverArrowDirectionAny;
|
|
popoverController.delegate = self;
|
|
[self presentViewController:vc animated:YES completion:nil];
|
|
}
|
|
|
|
- (void)actionMenuLoad {
|
|
[self actionOpenFilePicker:^void(NSString* name) {
|
|
self.currentFileName = name;
|
|
[self loadControlFile:[NSString stringWithFormat:@"%s/controlmap/%@.json", getenv("POJAV_HOME"), name]];
|
|
}];
|
|
}
|
|
|
|
- (void)actionMenuSetDef {
|
|
[self actionOpenFilePicker:^void(NSString* name) {
|
|
self.currentFileName = name;
|
|
[self loadControlFile:[NSString stringWithFormat:@"%s/controlmap/%@.json", getenv("POJAV_HOME"), name]];
|
|
setPreference(@"default_ctrl", [NSString stringWithFormat:@"%@.json", name]);
|
|
}];
|
|
}
|
|
|
|
- (void)actionMenuSafeArea {
|
|
// Set _UIBarBackground alpha to 0.8
|
|
self.navigationBar.subviews[0].alpha = 0.8;
|
|
|
|
BOOL isCustom = ((UISegmentedControl *)self.navigationBar.items[0].titleView).selectedSegmentIndex == 2;
|
|
|
|
self.navigationBar.hidden = !self.navigationBar.hidden;
|
|
self.ctrlView.layer.borderWidth = self.navigationBar.hidden ? 0 : 2;
|
|
self.ctrlView.userInteractionEnabled = self.navigationBar.hidden || isCustom;
|
|
self.resizeView.frame = CGRectMake(CGRectGetMaxX(self.ctrlView.frame), CGRectGetMaxY(self.ctrlView.frame), self.resizeView.frame.size.width, self.resizeView.frame.size.height);
|
|
self.resizeView.hidden = self.navigationBar.hidden || !isCustom;
|
|
self.resizeView.layer.maskedCorners = kCALayerMinXMinYCorner | kCALayerMaxXMinYCorner | kCALayerMinXMaxYCorner;
|
|
self.resizeView.target = nil;
|
|
}
|
|
|
|
- (void)actionMenuSafeAreaCancel {
|
|
self.ctrlView.frame = CGRectFromString(getPreference(@"control_safe_area"));
|
|
[self actionMenuSafeArea];
|
|
}
|
|
|
|
- (void)actionMenuSafeAreaDone {
|
|
setPreference(@"control_safe_area", NSStringFromCGRect(self.ctrlView.frame));
|
|
[self actionMenuSafeArea];
|
|
}
|
|
|
|
- (void)actionMenuAddButtonWithDrawer:(ControlDrawer *)drawer {
|
|
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
|
|
dict[@"name"] = @"New";
|
|
dict[@"keycodes"] = [[NSMutableArray alloc] initWithCapacity:4];
|
|
for (int i = 0; i < 4; i++) {
|
|
dict[@"keycodes"][i] = @(0);
|
|
}
|
|
dict[@"dynamicX"] = @"0";
|
|
dict[@"dynamicY"] = @"0";
|
|
dict[@"width"] = @(50.0);
|
|
dict[@"height"] = @(50.0);
|
|
dict[@"opacity"] = @(1);
|
|
dict[@"cornerRadius"] = @(0);
|
|
dict[@"bgColor"] = @(0x4d000000);
|
|
ControlButton *button;
|
|
if (drawer == nil) {
|
|
button = [ControlButton buttonWithProperties:dict];
|
|
[self doAddButton:button atIndex:@([self.cc_dictionary[@"mControlDataList"] count])];
|
|
[button snapAndAlignX:self.selectedPoint.origin.x-25.0 Y:self.selectedPoint.origin.y-25.0];
|
|
[button update];
|
|
} else {
|
|
button = [ControlSubButton buttonWithProperties:dict];
|
|
((ControlSubButton *)button).parentDrawer = drawer;
|
|
[self doAddButton:button atIndex:@(drawer.buttons.count)];
|
|
[button snapAndAlignX:self.selectedPoint.origin.x-25.0 Y:self.selectedPoint.origin.y-25.0];
|
|
[drawer syncButtons];
|
|
}
|
|
|
|
[button addGestureRecognizer:[[UITapGestureRecognizer alloc]
|
|
initWithTarget:self action:@selector(showControlPopover:)]];
|
|
[button addGestureRecognizer:[[UIPanGestureRecognizer alloc]
|
|
initWithTarget:self action:@selector(onTouch:)]];
|
|
}
|
|
|
|
- (void)actionMenuAddButton {
|
|
[self actionMenuAddButtonWithDrawer:nil];
|
|
}
|
|
|
|
- (void)actionMenuAddDrawer {
|
|
NSMutableDictionary *properties = [[NSMutableDictionary alloc] init];
|
|
properties[@"name"] = @"New";
|
|
properties[@"dynamicX"] = @"0";
|
|
properties[@"dynamicY"] = @"0";
|
|
properties[@"width"] = @(50.0);
|
|
properties[@"height"] = @(50.0);
|
|
properties[@"opacity"] = @(1);
|
|
properties[@"cornerRadius"] = @(0);
|
|
properties[@"bgColor"] = @(0x4d000000);
|
|
NSMutableDictionary *data = [[NSMutableDictionary alloc] init];
|
|
data[@"orientation"] = @"FREE";
|
|
data[@"properties"] = properties;
|
|
data[@"buttonProperties"] = [[NSMutableArray alloc] init];
|
|
ControlDrawer *button = [ControlDrawer buttonWithData:data];
|
|
[self doAddButton:button atIndex:@([self.cc_dictionary[@"mDrawerDataList"] count])];
|
|
[button snapAndAlignX:self.selectedPoint.origin.x-25.0 Y:self.selectedPoint.origin.y-25.0];
|
|
[button update];
|
|
|
|
[button addGestureRecognizer:[[UITapGestureRecognizer alloc]
|
|
initWithTarget:self action:@selector(showControlPopover:)]];
|
|
[button addGestureRecognizer:[[UIPanGestureRecognizer alloc]
|
|
initWithTarget:self action:@selector(onTouch:)]];
|
|
}
|
|
|
|
- (void)actionMenuAddSubButton {
|
|
self.selectedPoint = CGRectMake(self.currentGesture.view.frame.origin.x + 25.0, self.currentGesture.view.frame.origin.y + 25.0, 1.0, 1.0);
|
|
[self actionMenuAddButtonWithDrawer:(ControlDrawer *)self.currentGesture.view];
|
|
}
|
|
|
|
- (void)actionMenuBtnCopy {
|
|
// copy
|
|
}
|
|
|
|
- (void)actionMenuBtnDelete {
|
|
self.resizeView.hidden = YES;
|
|
ControlButton *button = (ControlButton *)self.currentGesture.view;
|
|
[self doRemoveButton:button];
|
|
}
|
|
|
|
- (void)actionMenuBtnEdit {
|
|
shouldDismissPopover = NO;
|
|
CCMenuViewController *vc = [[CCMenuViewController alloc] init];
|
|
vc.modalPresentationStyle = UIModalPresentationOverFullScreen;
|
|
vc.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
|
|
vc.preferredContentSize = self.view.frame.size;
|
|
if (![self.currentGesture isKindOfClass:[UILongPressGestureRecognizer class]]) {
|
|
vc.targetButton = (ControlButton *)self.currentGesture.view;
|
|
}
|
|
[self presentViewController:vc animated:YES completion:nil];
|
|
}
|
|
|
|
- (void)setButtonMenuVisibleForView:(UIView *)view {
|
|
self.resizeView.layer.maskedCorners = kCALayerMaxXMaxYCorner | kCALayerMaxXMinYCorner | kCALayerMinXMaxYCorner;
|
|
self.resizeView.target = (ControlButton *)view;
|
|
UIMenuController *menuController = [UIMenuController sharedMenuController];
|
|
if(@available(iOS 13.0, *)) {
|
|
if (view) {
|
|
[menuController showMenuFromView:view rect:self.selectedPoint];
|
|
} else {
|
|
[menuController hideMenu];
|
|
}
|
|
} else {
|
|
if (view) {
|
|
[menuController setTargetRect:self.selectedPoint inView:view];
|
|
}
|
|
[menuController setMenuVisible:(view!=nil) animated:YES];
|
|
}
|
|
if (view) {
|
|
CGPoint origin = [self.ctrlView convertPoint:view.frame.origin toView:self.view];
|
|
self.resizeView.frame = CGRectMake(origin.x + view.frame.size.width, origin.y + view.frame.size.height, self.resizeView.frame.size.width, self.resizeView.frame.size.height);
|
|
}
|
|
}
|
|
|
|
- (UIRectEdge)preferredScreenEdgesDeferringSystemGestures {
|
|
return UIRectEdgeAll;
|
|
}
|
|
|
|
- (BOOL)prefersHomeIndicatorAutoHidden {
|
|
return YES;
|
|
}
|
|
|
|
- (BOOL)prefersStatusBarHidden {
|
|
return YES;
|
|
}
|
|
|
|
- (void)onTouchAreaHandleView:(UIPanGestureRecognizer *)sender {
|
|
if (sender.state != UIGestureRecognizerStateChanged) return;
|
|
CGPoint translation = [sender translationInView:sender.view];
|
|
|
|
// Perform safe area resize
|
|
CGRect targetFrame = self.ctrlView.frame;
|
|
targetFrame.size.width += translation.x;
|
|
targetFrame.size.height += translation.y;
|
|
self.ctrlView.frame = targetFrame;
|
|
|
|
// Keep track of handle view location
|
|
targetFrame = self.resizeView.frame;
|
|
targetFrame.origin.x = CGRectGetMaxX(self.ctrlView.frame) - targetFrame.size.width;
|
|
targetFrame.origin.y = CGRectGetMaxY(self.ctrlView.frame) - targetFrame.size.height;
|
|
self.resizeView.frame = targetFrame;
|
|
|
|
[sender setTranslation:CGPointZero inView:sender.view];
|
|
}
|
|
|
|
- (void)onTouchButtonHandleView:(UIPanGestureRecognizer *)sender {
|
|
static CGRect origButtonRect;
|
|
|
|
CGPoint translation = [sender translationInView:sender.view];
|
|
CGFloat width, height;
|
|
|
|
switch (sender.state) {
|
|
case UIGestureRecognizerStateBegan: {
|
|
// Save old button frame
|
|
origButtonRect = self.resizeView.target.frame;
|
|
} break;
|
|
case UIGestureRecognizerStateChanged: {
|
|
// Perform button resize
|
|
width = MAX(10, [self.resizeView.target.properties[@"width"] floatValue] + translation.x);
|
|
height = MAX(10, [self.resizeView.target.properties[@"height"] floatValue] + translation.y);
|
|
self.resizeView.target.properties[@"width"] = @(width);
|
|
self.resizeView.target.properties[@"height"] = @(height);
|
|
[self.resizeView.target update];
|
|
[sender setTranslation:CGPointZero inView:sender.view];
|
|
|
|
// Keep track of handle view location
|
|
self.resizeView.frame = CGRectMake(CGRectGetMaxX(self.resizeView.target.frame), CGRectGetMaxY(self.resizeView.target.frame),
|
|
self.resizeView.frame.size.width, self.resizeView.frame.size.height);
|
|
} break;
|
|
case UIGestureRecognizerStateCancelled:
|
|
case UIGestureRecognizerStateEnded: {
|
|
[self doMoveOrResizeButton:self.resizeView.target from:origButtonRect to:self.resizeView.target.frame];
|
|
} break;
|
|
default: break;
|
|
}
|
|
}
|
|
|
|
- (void)onTouch:(UIPanGestureRecognizer *)sender {
|
|
static CGRect origButtonRect;
|
|
|
|
if ([sender.view isKindOfClass:ControlHandleView.class]) {
|
|
if (self.resizeView.target == nil) {
|
|
[self onTouchAreaHandleView:sender];
|
|
} else {
|
|
[self onTouchButtonHandleView:sender];
|
|
}
|
|
return;
|
|
}
|
|
|
|
CGPoint translation = [sender translationInView:sender.view];
|
|
|
|
ControlButton *button = (ControlButton *)sender.view;
|
|
if ([button isKindOfClass:ControlSubButton.class] &&
|
|
![((ControlSubButton *)button).parentDrawer.drawerData[@"orientation"] isEqualToString:@"FREE"]) return;
|
|
|
|
switch (sender.state) {
|
|
case UIGestureRecognizerStateBegan: {
|
|
origButtonRect = button.frame;
|
|
[self setButtonMenuVisibleForView:nil];
|
|
self.resizeView.hidden = NO;
|
|
self.resizeView.target = button;
|
|
} break;
|
|
case UIGestureRecognizerStateChanged: {
|
|
//button.center = CGPointMake(button.center.x + translation.x, button.center.y + translation.y);
|
|
[button snapAndAlignX:clamp(button.frame.origin.x+translation.x, 0, self.ctrlView.frame.size.width - button.frame.size.width) Y:clamp(button.frame.origin.y+translation.y, 0, self.ctrlView.frame.size.height - button.frame.size.height)];
|
|
[sender setTranslation:CGPointZero inView:button];
|
|
self.resizeView.frame = CGRectMake(CGRectGetMaxX(button.frame), CGRectGetMaxY(button.frame), self.resizeView.frame.size.width, self.resizeView.frame.size.height);
|
|
} break;
|
|
case UIGestureRecognizerStateCancelled:
|
|
case UIGestureRecognizerStateEnded: {
|
|
[self doMoveOrResizeButton:button from:origButtonRect to:button.frame];
|
|
} break;
|
|
default: break;
|
|
}
|
|
}
|
|
|
|
#pragma mark - UIPopoverPresentationControllerDelegate
|
|
- (UIModalPresentationStyle)adaptivePresentationStyleForPresentationController:(UIPresentationController *)controller traitCollection:(UITraitCollection *)traitCollection {
|
|
return UIModalPresentationNone;
|
|
}
|
|
|
|
- (BOOL)popoverPresentationControllerShouldDismissPopover:(UIPopoverPresentationController *)popoverPresentationController
|
|
{
|
|
return shouldDismissPopover;
|
|
}
|
|
|
|
- (BOOL)presentationControllerShouldDismiss:(UIPresentationController *)presentationController API_AVAILABLE(ios(13.0))
|
|
{
|
|
return shouldDismissPopover;
|
|
}
|
|
|
|
#pragma mark - Keycode table init
|
|
- (void)initKeyCodeMap {
|
|
#define addkey(key) \
|
|
[keyCodeMap addObject:@(#key)]; \
|
|
[keyValueMap addObject:@(GLFW_KEY_##key)];
|
|
#define addspec(key) \
|
|
[keyCodeMap addObject:@(#key)]; \
|
|
[keyValueMap addObject:@(key)];
|
|
|
|
keyCodeMap = [[NSMutableArray alloc] init];
|
|
keyValueMap = [[NSMutableArray alloc] init];
|
|
addspec(SPECIALBTN_SCROLLDOWN)
|
|
addspec(SPECIALBTN_SCROLLUP)
|
|
addspec(SPECIALBTN_VIRTUALMOUSE)
|
|
addspec(SPECIALBTN_MOUSEMID)
|
|
addspec(SPECIALBTN_MOUSESEC)
|
|
addspec(SPECIALBTN_MOUSEPRI)
|
|
addspec(SPECIALBTN_TOGGLECTRL)
|
|
addspec(SPECIALBTN_KEYBOARD)
|
|
|
|
addkey(UNKNOWN)
|
|
addkey(HOME)
|
|
addkey(ESCAPE)
|
|
|
|
// 0-9 keys
|
|
addkey(0) addkey(1) addkey(2) addkey(3) addkey(4)
|
|
addkey(5) addkey(6) addkey(7) addkey(8) addkey(9)
|
|
//addkey(POUND)
|
|
|
|
// Arrow keys
|
|
addkey(DPAD_UP) addkey(DPAD_DOWN) addkey(DPAD_LEFT) addkey(DPAD_RIGHT)
|
|
|
|
// A-Z keys
|
|
addkey(A) addkey(B) addkey(C) addkey(D) addkey(E)
|
|
addkey(F) addkey(G) addkey(H) addkey(I) addkey(J)
|
|
addkey(K) addkey(L) addkey(M) addkey(N) addkey(O)
|
|
addkey(P) addkey(Q) addkey(R) addkey(S) addkey(T)
|
|
addkey(U) addkey(V) addkey(W) addkey(X) addkey(Y)
|
|
addkey(Z)
|
|
|
|
addkey(COMMA)
|
|
addkey(PERIOD)
|
|
|
|
// Alt keys
|
|
addkey(LEFT_ALT)
|
|
addkey(RIGHT_ALT)
|
|
|
|
// Shift keys
|
|
addkey(LEFT_SHIFT)
|
|
addkey(RIGHT_SHIFT)
|
|
|
|
addkey(TAB)
|
|
addkey(SPACE)
|
|
addkey(ENTER)
|
|
addkey(BACKSPACE)
|
|
addkey(DELETE)
|
|
addkey(GRAVE_ACCENT)
|
|
addkey(MINUS)
|
|
addkey(EQUAL)
|
|
addkey(LEFT_BRACKET) addkey(RIGHT_BRACKET)
|
|
addkey(BACKSLASH)
|
|
addkey(SEMICOLON)
|
|
addkey(SLASH)
|
|
//addkey(AT) //@
|
|
|
|
// Page keys
|
|
addkey(PAGE_UP) addkey(PAGE_DOWN)
|
|
|
|
// Control keys
|
|
addkey(LEFT_CONTROL)
|
|
addkey(RIGHT_CONTROL)
|
|
|
|
addkey(CAPS_LOCK)
|
|
addkey(PAUSE)
|
|
addkey(INSERT)
|
|
|
|
// Fn keys
|
|
addkey(F1) addkey(F2) addkey(F3) addkey(F4)
|
|
addkey(F5) addkey(F6) addkey(F7) addkey(F8)
|
|
addkey(F9) addkey(F10) addkey(F11) addkey(F12)
|
|
|
|
// Num keys
|
|
addkey(NUM_LOCK)
|
|
addkey(NUMPAD_0)
|
|
addkey(NUMPAD_1) addkey(NUMPAD_2) addkey(NUMPAD_3)
|
|
addkey(NUMPAD_4) addkey(NUMPAD_5) addkey(NUMPAD_6)
|
|
addkey(NUMPAD_7) addkey(NUMPAD_8) addkey(NUMPAD_9)
|
|
addkey(NUMPAD_DECIMAL)
|
|
addkey(NUMPAD_DIVIDE)
|
|
addkey(NUMPAD_MULTIPLY)
|
|
addkey(NUMPAD_SUBTRACT)
|
|
addkey(NUMPAD_ADD)
|
|
addkey(NUMPAD_ENTER)
|
|
addkey(NUMPAD_EQUAL)
|
|
|
|
//addkey(APOSTROPHE)
|
|
//addkey(WORLD_1) addkey(WORLD_2)
|
|
//addkey(END)
|
|
//addkey(SCROLL_LOCK)
|
|
//addkey(PRINT_SCREEN)
|
|
//addkey(LEFT_SUPER) addkey(RIGHT_ENTER)
|
|
//addkey(MENU)
|
|
#undef addkey
|
|
}
|
|
|
|
@end
|
|
|
|
#define TAG_SLIDER_STROKEWIDTH 10
|
|
#define TAG_SLIDER_CORNERRADIUS 11
|
|
#define TAG_SLIDER_OPACITY 12
|
|
#define TAG_SWITCH_DYNAMICPOS 13
|
|
|
|
#pragma mark - CCMenuViewController
|
|
|
|
CGFloat currentY;
|
|
|
|
@interface CCMenuViewController () <UIPickerViewDataSource, UIPickerViewDelegate, HBColorPickerDelegate> {
|
|
}
|
|
|
|
@property(nonatomic) NSArray* arrOrientation;
|
|
@property(nonatomic) NSMutableDictionary* oldProperties;
|
|
|
|
@property UITextField *activeField;
|
|
@property(nonatomic) UIScrollView* scrollView;
|
|
@property(nonatomic) UITextField *editName, *editSizeWidth, *editSizeHeight;
|
|
@property(nonatomic) UITextView* editMapping;
|
|
@property(nonatomic) UIPickerView* pickerMapping;
|
|
@property(nonatomic) UISegmentedControl* ctrlOrientation;
|
|
@property(nonatomic) UISwitch *switchToggleable, *switchMousePass, *switchSwipeable;
|
|
@property(nonatomic) UIColorWell API_AVAILABLE(ios(14.0)) *colorWellINTBackground, *colorWellINTStroke;
|
|
@property(nonatomic) HBColorWell *colorWellEXTBackground, *colorWellEXTStroke;
|
|
@property(nonatomic) DBNumberedSlider *sliderStrokeWidth, *sliderCornerRadius, *sliderOpacity;
|
|
|
|
@end
|
|
|
|
@implementation CCMenuViewController
|
|
|
|
- (UILabel*)addLabel:(NSString *)name {
|
|
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0.0, currentY, 0.0, 0.0)];
|
|
label.text = name;
|
|
label.numberOfLines = 0;
|
|
[label sizeToFit];
|
|
[self.scrollView addSubview:label];
|
|
return label;
|
|
}
|
|
|
|
- (void)viewDidLoad {
|
|
[super viewDidLoad];
|
|
self.oldProperties = self.targetButton.properties.mutableCopy;
|
|
currentY = 6.0;
|
|
|
|
CGFloat shortest = MIN(self.view.frame.size.width, self.view.frame.size.height);
|
|
CGFloat tempW = MIN(self.view.frame.size.width * 0.75, shortest);
|
|
CGFloat tempH = MIN(self.view.frame.size.height * 0.6, shortest);
|
|
|
|
UIBlurEffectStyle blurStyle;
|
|
UIVisualEffectView *blurView;
|
|
if (@available(iOS 13.0, *)) {
|
|
blurStyle = UIBlurEffectStyleSystemMaterial;
|
|
} else {
|
|
blurStyle = UIBlurEffectStyleExtraLight;
|
|
}
|
|
blurView = [[UIVisualEffectView alloc] initWithEffect:[UIBlurEffect effectWithStyle:blurStyle]];
|
|
blurView.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleBottomMargin;
|
|
blurView.frame = CGRectMake(
|
|
(self.view.frame.size.width - MAX(tempW, tempH))/2,
|
|
(self.view.frame.size.height - MIN(tempW, tempH))/2,
|
|
MAX(tempW, tempH), MIN(tempW, tempH));
|
|
blurView.layer.cornerRadius = 10.0;
|
|
blurView.clipsToBounds = YES;
|
|
[self.view addSubview:blurView];
|
|
|
|
UIBarButtonItem *btnFlexibleSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:self action:nil];
|
|
|
|
UIToolbar *popoverToolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0.0, 0.0, blurView.frame.size.width, 44.0)];
|
|
UIPanGestureRecognizer *dragVCGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(dragViewController:)];
|
|
dragVCGesture.minimumNumberOfTouches = 1;
|
|
dragVCGesture.maximumNumberOfTouches = 1;
|
|
[popoverToolbar addGestureRecognizer:dragVCGesture];
|
|
|
|
UIBarButtonItem *popoverCancelButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:@selector(actionEditCancel)];
|
|
UIBarButtonItem *popoverDoneButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(actionEditFinish)];
|
|
popoverToolbar.items = @[popoverCancelButton, btnFlexibleSpace, popoverDoneButton];
|
|
[blurView.contentView addSubview:popoverToolbar];
|
|
|
|
self.scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(5.0, popoverToolbar.frame.size.height, blurView.frame.size.width - 10.0, blurView.frame.size.height - popoverToolbar.frame.size.height)];
|
|
self.scrollView.keyboardDismissMode = UIScrollViewKeyboardDismissModeInteractive;
|
|
[blurView.contentView addSubview:self.scrollView];
|
|
|
|
UIToolbar *editPickToolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0.0, 0.0, blurView.frame.size.width, 44.0)];
|
|
|
|
UIBarButtonItem *editDoneButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(closeTextField)];
|
|
editPickToolbar.items = @[btnFlexibleSpace, editDoneButton];
|
|
|
|
CGFloat width = blurView.frame.size.width - 10.0;
|
|
CGFloat height = blurView.frame.size.height - 10.0;
|
|
|
|
|
|
// Property: Name
|
|
UILabel *labelName = [self addLabel:localize(@"custom_controls.button_edit.name", nil)];
|
|
self.editName = [[UITextField alloc] initWithFrame:CGRectMake(labelName.frame.size.width + 5.0, currentY, width - labelName.frame.size.width - 5.0, labelName.frame.size.height)];
|
|
[self.editName addTarget:self action:@selector(textFieldEditingChanged) forControlEvents:UIControlEventEditingChanged];
|
|
[self.editName addTarget:self.editName action:@selector(resignFirstResponder) forControlEvents:UIControlEventEditingDidEndOnExit];
|
|
self.editName.placeholder = localize(@"custom_controls.button_edit.name", nil);
|
|
self.editName.returnKeyType = UIReturnKeyDone;
|
|
self.editName.text = self.targetButton.properties[@"name"];
|
|
[self.scrollView addSubview:self.editName];
|
|
|
|
if (![self.targetButton isKindOfClass:[ControlSubButton class]]) {
|
|
// Property: Size
|
|
currentY += labelName.frame.size.height + 12.0;
|
|
UILabel *labelSize = [self addLabel:localize(@"custom_controls.button_edit.size", nil)];
|
|
// width / 2.0 + (labelSize.frame.size.width + 4.0) / 2.0
|
|
CGFloat editSizeWidthValue = (width - labelSize.frame.size.width) / 2 - labelSize.frame.size.height / 2;
|
|
UILabel *labelSizeX = [[UILabel alloc] initWithFrame:CGRectMake(labelSize.frame.size.width + editSizeWidthValue, labelSize.frame.origin.y, labelSize.frame.size.height, labelSize.frame.size.height)];
|
|
labelSizeX.text = @"x";
|
|
[self.scrollView addSubview:labelSizeX];
|
|
self.editSizeWidth = [[UITextField alloc] initWithFrame:CGRectMake(labelSize.frame.size.width, labelSize.frame.origin.y, editSizeWidthValue, labelSize.frame.size.height)];
|
|
[self.editSizeWidth addTarget:self action:@selector(textFieldEditingChanged) forControlEvents:UIControlEventEditingChanged];
|
|
[self.editSizeWidth addTarget:self.editSizeWidth action:@selector(resignFirstResponder) forControlEvents:UIControlEventEditingDidEndOnExit];
|
|
self.editSizeWidth.keyboardType = UIKeyboardTypeDecimalPad;
|
|
self.editSizeWidth.placeholder = @"width";
|
|
self.editSizeWidth.returnKeyType = UIReturnKeyDone;
|
|
self.editSizeWidth.text = [self.targetButton.properties[@"width"] stringValue];
|
|
self.editSizeWidth.textAlignment = NSTextAlignmentCenter;
|
|
[self.scrollView addSubview:self.editSizeWidth];
|
|
self.editSizeHeight = [[UITextField alloc] initWithFrame:CGRectMake(labelSizeX.frame.origin.x + labelSizeX.frame.size.width, labelSize.frame.origin.y, editSizeWidthValue, labelSize.frame.size.height)];
|
|
[self.editSizeHeight addTarget:self action:@selector(textFieldEditingChanged) forControlEvents:UIControlEventEditingChanged];
|
|
[self.editSizeHeight addTarget:self.editSizeHeight action:@selector(resignFirstResponder) forControlEvents:UIControlEventEditingDidEndOnExit];
|
|
self.editSizeHeight.keyboardType = UIKeyboardTypeDecimalPad;
|
|
self.editSizeHeight.placeholder = @"height";
|
|
self.editSizeHeight.returnKeyType = UIReturnKeyDone;
|
|
self.editSizeHeight.text = [self.targetButton.properties[@"height"] stringValue];
|
|
self.editSizeHeight.textAlignment = NSTextAlignmentCenter;
|
|
[self.scrollView addSubview:self.editSizeHeight];
|
|
}
|
|
|
|
|
|
currentY += labelName.frame.size.height + 12.0;
|
|
if (![self.targetButton isKindOfClass:[ControlDrawer class]]) {
|
|
// Property: Mapping
|
|
UILabel *labelMapping = [self addLabel:localize(@"custom_controls.button_edit.mapping", nil)];
|
|
|
|
self.editMapping = [[UITextView alloc] initWithFrame:CGRectMake(0,0,1,1)];
|
|
self.editMapping.text = @"\n\n\n";
|
|
[self.editMapping sizeToFit];
|
|
self.editMapping.scrollEnabled = NO;
|
|
self.editMapping.frame = CGRectMake(labelMapping.frame.size.width + 5.0, labelMapping.frame.origin.y, width - labelMapping.frame.size.width - 5.0, self.editMapping.frame.size.height);
|
|
|
|
self.pickerMapping = [[UIPickerView alloc] init];
|
|
self.pickerMapping.delegate = self;
|
|
self.pickerMapping.dataSource = self;
|
|
[self.pickerMapping reloadAllComponents];
|
|
for (int i = 0; i < 4; i++) {
|
|
[self.pickerMapping selectRow:[keyValueMap indexOfObject:self.targetButton.properties[@"keycodes"][i]] inComponent:i animated:NO];
|
|
}
|
|
[self pickerView:self.pickerMapping didSelectRow:0 inComponent:0];
|
|
|
|
self.editMapping.inputAccessoryView = editPickToolbar;
|
|
self.editMapping.inputView = self.pickerMapping;
|
|
[self.scrollView addSubview:self.editMapping];
|
|
currentY += self.editMapping.frame.size.height + 12.0;
|
|
} else {
|
|
// Property: Orientation
|
|
self.arrOrientation = @[@"DOWN", @"LEFT", @"UP", @"RIGHT", @"FREE"];
|
|
UILabel *labelOrientation = [self addLabel:localize(@"custom_controls.button_edit.orientation", nil)];
|
|
self.ctrlOrientation = [[UISegmentedControl alloc] initWithItems:self.arrOrientation];
|
|
[self.ctrlOrientation addTarget:self action:@selector(orientationValueChanged) forControlEvents:UIControlEventValueChanged];
|
|
self.ctrlOrientation.frame = CGRectMake(labelOrientation.frame.size.width + 5.0, currentY - 5.0, width - labelOrientation.frame.size.width - 5.0, 30.0);
|
|
self.ctrlOrientation.selectedSegmentIndex = [self.arrOrientation indexOfObject:
|
|
((ControlDrawer *)self.targetButton).drawerData[@"orientation"]];
|
|
[self.scrollView addSubview:self.ctrlOrientation];
|
|
currentY += labelName.frame.size.height + 12.0;
|
|
}
|
|
|
|
|
|
// Property: Toggleable
|
|
UILabel *labelToggleable = [self addLabel:localize(@"custom_controls.button_edit.toggleable", nil)];
|
|
self.switchToggleable = [[UISwitch alloc] initWithFrame:CGRectMake(width - 62.0, currentY - 5.0, 50.0, 30)];
|
|
[self.switchToggleable setOn:[self.targetButton.properties[@"isToggle"] boolValue] animated:NO];
|
|
[self.scrollView addSubview:self.switchToggleable];
|
|
|
|
|
|
// Property: Mouse pass
|
|
currentY += labelName.frame.size.height + 12.0;
|
|
UILabel *labelMousePass = [self addLabel:localize(@"custom_controls.button_edit.mouse_pass", nil)];
|
|
self.switchMousePass = [[UISwitch alloc] initWithFrame:CGRectMake(width - 62.0, currentY - 5.0, 50.0, 30)];
|
|
[self.switchMousePass setOn:[self.targetButton.properties[@"passThruEnabled"] boolValue]];
|
|
[self.scrollView addSubview:self.switchMousePass];
|
|
|
|
|
|
// Property: Swipeable
|
|
currentY += labelName.frame.size.height + 12.0;
|
|
UILabel *labelSwipeable = [self addLabel:localize(@"custom_controls.button_edit.swipeable", nil)];
|
|
self.switchSwipeable = [[UISwitch alloc] initWithFrame:CGRectMake(width - 62.0, currentY - 5.0, 50.0, 30)];
|
|
[self.switchSwipeable setOn:[self.targetButton.properties[@"isSwipeable"] boolValue]];
|
|
[self.scrollView addSubview:self.switchSwipeable];
|
|
|
|
|
|
// Property: Background color
|
|
currentY += labelName.frame.size.height + 12.0;
|
|
UILabel *labelBGColor = [self addLabel:localize(@"custom_controls.button_edit.bg_color", nil)];
|
|
if(@available(iOS 14.0, *)) {
|
|
self.colorWellINTBackground = [[UIColorWell alloc] initWithFrame:CGRectMake(width - 42.0, currentY - 5.0, 30.0, 30.0)];
|
|
[self.colorWellINTBackground addTarget:self action:@selector(colorWellChanged) forControlEvents:UIControlEventValueChanged];
|
|
self.colorWellINTBackground.selectedColor = self.targetButton.backgroundColor;
|
|
[self.scrollView addSubview:self.colorWellINTBackground];
|
|
} else {
|
|
if (!dlopen("Alderis.framework/Alderis", RTLD_NOW)) {
|
|
NSLog(@"Cannot load Alderis framework: %s", dlerror());
|
|
}
|
|
|
|
self.colorWellEXTBackground = [[NSClassFromString(@"HBColorWell") alloc] initWithFrame:CGRectMake(width - 42.0, currentY - 5.0, 30.0, 30.0)];
|
|
self.colorWellEXTBackground.color = self.targetButton.backgroundColor;
|
|
self.colorWellEXTBackground.isDragInteractionEnabled = YES;
|
|
self.colorWellEXTBackground.isDropInteractionEnabled = YES;
|
|
[self.colorWellEXTBackground addTarget:self action:@selector(presentColorPicker:) forControlEvents:UIControlEventTouchUpInside];
|
|
[self.scrollView addSubview:self.colorWellEXTBackground];
|
|
}
|
|
|
|
|
|
// Property: Stroke width
|
|
currentY += labelName.frame.size.height + 12.0;
|
|
UILabel *labelStrokeWidth = [self addLabel:localize(@"custom_controls.button_edit.stroke_width", nil)];
|
|
self.sliderStrokeWidth = [[DBNumberedSlider alloc] initWithFrame:CGRectMake(labelStrokeWidth.frame.size.width + 5.0, currentY - 5.0, width - labelStrokeWidth.frame.size.width - 5.0, 30.0)];
|
|
self.sliderStrokeWidth.continuous = YES;
|
|
self.sliderStrokeWidth.maximumValue = 100;
|
|
self.sliderStrokeWidth.tag = TAG_SLIDER_STROKEWIDTH;
|
|
self.sliderStrokeWidth.value = [self.targetButton.properties[@"strokeWidth"] intValue];
|
|
[self.sliderStrokeWidth addTarget:self action:@selector(sliderValueChanged:) forControlEvents:UIControlEventValueChanged];
|
|
[self.scrollView addSubview:self.sliderStrokeWidth];
|
|
|
|
|
|
// Property: Stroke color
|
|
currentY += labelName.frame.size.height + 12.0;
|
|
UILabel *labelStrokeColor = [self addLabel:localize(@"custom_controls.button_edit.stroke_color", nil)];
|
|
if(@available(iOS 14.0, *)) {
|
|
self.colorWellINTStroke = [[UIColorWell alloc] initWithFrame:CGRectMake(width - 42.0, currentY - 5.0, 30.0, 30.0)];
|
|
[self.colorWellINTStroke addTarget:self action:@selector(colorWellChanged) forControlEvents:UIControlEventValueChanged];
|
|
self.colorWellINTStroke.selectedColor = [[UIColor alloc] initWithCGColor:self.targetButton.layer.borderColor];
|
|
[self.scrollView addSubview:self.colorWellINTStroke];
|
|
} else {
|
|
self.colorWellEXTStroke = [[NSClassFromString(@"HBColorWell") alloc] initWithFrame:CGRectMake(width - 42.0, currentY - 5.0, 30.0, 30.0)];
|
|
self.colorWellEXTStroke.color = [[UIColor alloc] initWithCGColor:self.targetButton.layer.borderColor];
|
|
[self.colorWellEXTStroke addTarget:self action:@selector(presentColorPicker:) forControlEvents:UIControlEventTouchUpInside];
|
|
[self.scrollView addSubview:self.colorWellEXTStroke];
|
|
}
|
|
[self sliderValueChanged:self.sliderStrokeWidth];
|
|
|
|
|
|
// Property: Corner radius
|
|
currentY += labelName.frame.size.height + 12.0;
|
|
UILabel *labelCornerRadius = [self addLabel:localize(@"custom_controls.button_edit.corner_radius", nil)];
|
|
self.sliderCornerRadius = [[DBNumberedSlider alloc] initWithFrame:CGRectMake(labelCornerRadius.frame.size.width + 5.0, currentY - 5.0, width - labelCornerRadius.frame.size.width - 5.0, 30.0)];
|
|
self.sliderCornerRadius.continuous = YES;
|
|
self.sliderCornerRadius.maximumValue = 100;
|
|
self.sliderCornerRadius.tag = TAG_SLIDER_CORNERRADIUS;
|
|
self.sliderCornerRadius.value = [self.targetButton.properties[@"cornerRadius"] intValue];
|
|
[self.sliderCornerRadius addTarget:self action:@selector(sliderValueChanged:) forControlEvents:UIControlEventValueChanged];
|
|
[self.scrollView addSubview:self.sliderCornerRadius];
|
|
|
|
|
|
// Property: Button Opacity
|
|
currentY += labelName.frame.size.height + 12.0;
|
|
UILabel *labelOpacity = [self addLabel:localize(@"custom_controls.button_edit.opacity", nil)];
|
|
self.sliderOpacity = [[DBNumberedSlider alloc] initWithFrame:CGRectMake(labelOpacity.frame.size.width + 5.0, currentY - 5.0, width - labelOpacity.frame.size.width - 5.0, 30.0)];
|
|
self.sliderOpacity.continuous = YES;
|
|
self.sliderOpacity.minimumValue = 1;
|
|
self.sliderOpacity.maximumValue = 100;
|
|
self.sliderOpacity.tag = TAG_SLIDER_OPACITY;
|
|
self.sliderOpacity.value = [self.targetButton.properties[@"opacity"] floatValue] * 100.0;
|
|
[self.sliderOpacity addTarget:self action:@selector(sliderValueChanged:) forControlEvents:UIControlEventValueChanged];
|
|
[self.scrollView addSubview:self.sliderOpacity];
|
|
|
|
|
|
currentY += labelName.frame.size.height + 12.0;
|
|
self.scrollView.contentSize = CGSizeMake(self.scrollView.contentSize.width, currentY);
|
|
}
|
|
|
|
#pragma mark - Gesture callback
|
|
- (void)dragViewController:(UIPanGestureRecognizer *)sender {
|
|
static CGPoint lastPoint;
|
|
CGPoint point = [sender translationInView:self.view];
|
|
if (sender.state != UIGestureRecognizerStateBegan) {
|
|
CGRect rect = self.view.subviews[0].frame;
|
|
rect.origin.x = clamp(rect.origin.x - lastPoint.x + point.x, -self.view.frame.size.width/2, self.view.frame.size.width - sender.view.frame.size.width/2);
|
|
rect.origin.y = clamp(rect.origin.y - lastPoint.y + point.y, 0, self.view.frame.size.height - sender.view.frame.size.height);
|
|
self.view.subviews[0].frame = rect;
|
|
}
|
|
lastPoint = point;
|
|
}
|
|
|
|
#pragma mark - Alderis functions
|
|
// HBColorWell
|
|
- (void)presentColorPicker:(HBColorWell *)sender {
|
|
HBColorPickerViewController *vc = [[NSClassFromString(@"HBColorPickerViewController") alloc] init];
|
|
vc.delegate = self;
|
|
vc.popoverPresentationController.sourceView = sender;
|
|
vc.configuration = [[NSClassFromString(@"HBColorPickerConfiguration") alloc] initWithColor:sender.color];
|
|
if (sender == self.colorWellEXTBackground) {
|
|
vc.configuration.title = @"Background color";
|
|
vc.configuration.supportsAlpha = YES;
|
|
} else if (sender == self.colorWellEXTStroke) {
|
|
vc.configuration.title = @"Stroke color";
|
|
vc.configuration.supportsAlpha = YES;
|
|
} else {
|
|
NSLog(@"Unknown color well: %@", sender);
|
|
abort();
|
|
}
|
|
[self presentViewController:vc animated:YES completion:nil];
|
|
}
|
|
|
|
// iOS 14 color well
|
|
- (void)colorWellChanged {
|
|
if(@available(iOS 14.0, *)) {
|
|
self.targetButton.properties[@"bgColor"] = @(convertUIColor2ARGB(self.colorWellINTBackground.selectedColor));
|
|
self.targetButton.properties[@"strokeColor"] = @(convertUIColor2ARGB(self.colorWellINTStroke.selectedColor));
|
|
}
|
|
[self.targetButton update];
|
|
}
|
|
|
|
// HBColorPickerDelegate (iOS 12-13 color well)
|
|
- (void)colorPicker:(HBColorPickerViewController *)picker didSelectColor:(UIColor *)color {
|
|
if ([picker.configuration.title isEqualToString:@"Background color"]) {
|
|
self.colorWellEXTBackground.color = color;
|
|
self.targetButton.properties[@"bgColor"] = @(convertUIColor2ARGB(self.colorWellEXTBackground.color));
|
|
} else if ([picker.configuration.title isEqualToString:@"Stroke color"]) {
|
|
self.colorWellEXTStroke.color = color;
|
|
self.targetButton.properties[@"strokeColor"] = @(convertUIColor2ARGB(self.colorWellEXTStroke.color));
|
|
} else {
|
|
NSLog(@"Unknown color well: %@", picker.configuration.title);
|
|
abort();
|
|
}
|
|
[self.targetButton update];
|
|
}
|
|
|
|
- (void)textFieldEditingChanged {
|
|
self.targetButton.properties[@"name"] = self.editName.text;
|
|
self.targetButton.properties[@"width"] = @([self.editSizeWidth.text floatValue]);
|
|
self.targetButton.properties[@"height"] = @([self.editSizeHeight.text floatValue]);
|
|
[self.targetButton update];
|
|
}
|
|
|
|
#pragma mark - Control editor
|
|
- (void)actionEditCancel {
|
|
self.targetButton.properties = self.oldProperties;
|
|
[self.targetButton update];
|
|
shouldDismissPopover = YES;
|
|
[self dismissViewControllerAnimated:YES completion:nil];
|
|
}
|
|
|
|
- (void)actionEditFinish {
|
|
self.targetButton.properties[@"isToggle"] = @(self.switchToggleable.isOn);
|
|
self.targetButton.properties[@"passThruEnabled"] = @(self.switchMousePass.isOn);
|
|
self.targetButton.properties[@"isSwipeable"] = @(self.switchSwipeable.isOn);
|
|
|
|
NSMutableDictionary *newProperties = self.targetButton.properties.mutableCopy;
|
|
|
|
for (NSString *key in self.oldProperties) {
|
|
if ([self.oldProperties[key] isEqual:newProperties[key]]) {
|
|
[newProperties removeObjectForKey:key];
|
|
}
|
|
}
|
|
|
|
[(CustomControlsViewController *)self.presentingViewController
|
|
doUpdateButton:self.targetButton from:self.oldProperties to:newProperties];
|
|
self.oldProperties = nil;
|
|
shouldDismissPopover = YES;
|
|
[self dismissViewControllerAnimated:YES completion:nil];
|
|
}
|
|
|
|
- (void)orientationValueChanged {
|
|
((ControlDrawer *)self.targetButton).drawerData[@"orientation"] =
|
|
self.arrOrientation[self.ctrlOrientation.selectedSegmentIndex];
|
|
[(ControlDrawer *)self.targetButton syncButtons];
|
|
}
|
|
|
|
- (void)sliderValueChanged:(DBNumberedSlider *)sender {
|
|
[sender setValue:(NSInteger)sender.value animated:NO];
|
|
if (sender.tag == TAG_SLIDER_STROKEWIDTH) {
|
|
if(@available(iOS 14.0, *)) {
|
|
self.colorWellINTStroke.enabled = sender.value != 0;
|
|
} else {
|
|
self.colorWellEXTStroke.enabled = sender.value != 0;
|
|
}
|
|
self.targetButton.properties[@"strokeWidth"] = @((NSInteger) self.sliderStrokeWidth.value);
|
|
} else {
|
|
self.targetButton.properties[@"cornerRadius"] = @((NSInteger) self.sliderCornerRadius.value);
|
|
self.targetButton.properties[@"opacity"] = @(self.sliderOpacity.value / 100.0);
|
|
}
|
|
[self.targetButton update];
|
|
}
|
|
|
|
#pragma mark - UIPickerView stuff
|
|
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
|
|
self.editMapping.text = [NSString stringWithFormat:@"1: %@\n2: %@\n3: %@\n4: %@",
|
|
keyCodeMap[[pickerView selectedRowInComponent:0]],
|
|
keyCodeMap[[pickerView selectedRowInComponent:1]],
|
|
keyCodeMap[[pickerView selectedRowInComponent:2]],
|
|
keyCodeMap[[pickerView selectedRowInComponent:3]]
|
|
];
|
|
|
|
for (int i = 0; i < 4; i++) {
|
|
self.targetButton.properties[@"keycodes"][i] = keyValueMap[[self.pickerMapping selectedRowInComponent:i]];
|
|
}
|
|
}
|
|
|
|
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)thePickerView {
|
|
return 4;
|
|
}
|
|
|
|
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
|
|
return keyCodeMap.count;
|
|
}
|
|
|
|
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component {
|
|
return [keyCodeMap objectAtIndex:row];
|
|
}
|
|
|
|
- (void)closeTextField {
|
|
[self.editSizeWidth endEditing:YES];
|
|
[self.editSizeHeight endEditing:YES];
|
|
[self.editMapping endEditing:YES];
|
|
}
|
|
|
|
@end
|