* Fix Duy's deploy and install stuffs * Fix Makefile error and move external_include to external/zink * Bug fix: version ordering when types are disabled This commit fixes #293 * Update README.md * Add option to disable symlink to /var/mobile/Documents/.pojavlauncher (off by default) * Reset preferences option, switch to POJAV_HOME * Update bug_report.yml Update pojavlauncher directory location * Mitigation for the Apache Log4j RCE in 1.8.x-1.18 * Experimental things * Multitouch handling, allows one of these actions below to work with moving camera at the same time. - Switching hotbar slot; might not work properly - Destroying block (left mouse button) with another finger long-pressed (without pressing the PRI button) - Right mouse trigger with another finger tapped onto the screen (without pressing the SEC button); not working properly yet * Sub-pixel cursor support; not yet checked * Completely fix Log4J RCE (1.7-1.16.5) (not yet tested) TODO: checker with SHA1 * Log4J RCE patch config: disable XML format output This applies for Minecraft 1.12+ Disable XML formatting for now until we have a log viewer. * Create newsfeed.html * Update newsfeed.html * Delete newsfeed.html * WIP Demo mode stuff Sign in with a Microsoft account that doesn't own the game, demo_user will be made. This is very much WIP as my iPhone 7 doesn't feel like launching PojavLauncher. * New toggle option: Restart before launching game This option allows the launcher to restart itself before launching the game, therefore all changes are applied such as JVM Arguments and Java version. The restart mechanism doesn't always work, so a toggle is here for now. * A few UI changes Disable the Play button until version list finished loading Disable ability to go back while a version is downloading Display loading alert while logging in * Possible fix for broken Mojang login * Fix a NullPointerException when launching ≤ 1.6.4 * Bug fix: NPE when setting inherited fields Unable to insert id=null java.lang.NoSuchFieldException: id at java.lang.Class.getDeclaredField(Class.java:2070) at net.kdt.pojavlaunch.Tools.insertSafety(Tools.java:544) at net.kdt.pojavlaunch.Tools.getVersionInfo(Tools.java:466) at net.kdt.pojavlaunch.PLaunchApp.launchMinecraft(PLaunchApp.java:61) at net.kdt.pojavlaunch.uikit.UIKit.callback_SurfaceViewController_launchMi necraft(UIKit.java:104) at net.kdt.pojavlaunch.uikit.UIKit.launchUI(Native Method) at net.kdt.pojavlaunch.PLaunchApp.main(PLaunchApp.java:40) * Keyboard + Mouse input handling; some cleanups * Keyboard input: KeyboardInput.m - Requires iOS 13.4. Used pressesBegan and pressesEnded. - Not all keys are handled, these will be handled later. * Mouse input - Requires iOS 13.0 for hovering. Used UIHoverGestureRecognizer. - Requires iOS 14.0 for L/R mouse buttons and scroll handling. Used GCMouse for now. We will use iOS 13.4(?)'s API later. - Pointer lock is not yet handled. These above apply to iPadOS aswell, not sure about tvOS. iPhone users need to disable "Perform Touch Gestures" in the AssistiveTouch Accessibility settings in order to get the pointer hovering to work. * Cleanups - Use asprintf instead of sprintf when possible - CallbackBridge functions: removed unnecessary JNI fields. - Condition cleanup (managing virtual mouse position). * Use the old jvm arguments parser back for now There’s no handling for backslash yet, or ignoring spaces inside delimiters. * Remove duplicated code * Support for input cursor movement from keyboard New class: TrackedTextField. This class keeps track of the pointer in the text field. The hidden text field now has 40 placeholder spaces and the pointer is placed at the middle. When typing, placeholder spaces won't get removed as before. Autocorrect seem to be broken a bit for now. Additional changes: - Added missing GLFW functions (array version of other functions) - Hotbar handling: doubled barWidth and barHeight Bug fix: - Touching onto the hotbar breaks the handling of on-screen tap/long-press gestures * Bug fix: inputStringLength is not set back to 40 This caused a bug that clears the text when pressing backspace after the keyboard is displayed again. * Consolidate some code * Fix undeclared identifier * Consolidate some more code, fix my dumb mistake * Added VGPU renderer Commit: https://github.com/PojavLauncherTeam/VGPU/commit/9f4ded5934b24c62368d70 1647855c9c9077d903 * Update LauncherPreferencesViewController.m This line was mistakenly removed * Various bug fixes - Input cursor movement seems too fast, attempt to reduce it by setting larger font size in the hidden text field. - latestlog.txt doesn't log in 1.12+ since Log4j patch. Fixed by adding some config lines. - Makefile: building is broken when run make from a path with space(s). Fixed by handling spaces with backslashes. - text2speech is not overridden properly. Fixed by excluding it from download list and adding launcher.jar itself to the classpath. - XML log output in < 1.12 since Log4j patch. Fixed by using our own configuration file. Some more changes: - Commented out a debug line in LWJGLX - Fix a typo. - JavaLauncher: use (ObjC)BOOL instead of (std)bool. * Better click handling * Finish make ipa Still requires proper codesigning afterwards, and until I figure out the depends folder you'll need to download a copy of the Azul JDK artifact on our android-openjdk-build-multiarch repository and extract it to depends/jre. Tested and working on my MacBook Pro, although I need to find out why libjsig.dylib is defined twice (this issue doesn't hinder the build though, install_name_tool just doesn't apply changes). * Added readable MSA errors * Merge unjailbroken changes with main (#313) * fix that lol * IPABuilder moment * typo moment * Hooking changes Now hook only dladdr and realpath, JRE works now. However, need to obtain libffi. * Sole more changes Add RPATH to libraries Hook dlopen since loading libawt_headless somehow point to Frameworks directory. * Update development.yml * Update development.yml Co-authored-by: Duy Tran Khanh <[email protected]> Co-authored-by: Duy Tran Khanh <[email protected]> * Fix issue with text alignment * Makefile: multi-jobs building native code * Bump to Xcode 13.2.1 * Bump to Xcode 13.2.1 pt 2 * use gnproc and nproc (for procursus on macos) on the road development is bumpy * oops * [Custom controls] Added color picker for iOS < 14 Might aswell add an option to optionally use this instead of the system color picker on iOS 14+. Used library: Alderis Other changes - [Custom controls] The editor is now fullscreen due to the presentation of the color picker. - Fixes scroll wheel input is always int * I’m too tired of getting dpkg exits, so it’s here * Fix broken share log * Bug fix: Fabric 1.17+ crash at startup(fixes #304) Microsoft account now set accountType to msa. Minor change in custom control view controller. * Add Arc capes * Minor bug fix for Arc capes switch * Change how the login progress is displayed Login progress now displays on the title bar instead of a dialog. This will prevent infinite loading in case a connection error occurs. Closes #315 * Bug fix: Arc DNS injector breaks on Java 16+ This is caused by a missing function in our class loader. Error: System class loader does not define the appendToClassPathForInstrumentation method Unable to add /Applications/PojavLauncher.app/libs/arc_dns_injector.jar to system class path - the system class loader does not define the appendToClassPathForInstrumentation method or the method failed FATAL ERROR in native method: processing of -javaagent failed, appending to system class path failed * Why did I add set -e * Add changelog for 2.1 release * FAQ changes * Workflow changes and typo fix * Workflow changes part 2 * Fixes swipeable button state handling * Update informational.yml * Add A7 warning * Remove codesign from Alderis + thin lib * Only load Alderis.framework when needed * CC editor: view controller now follow bounds(#326) * Update README.md (#324) * Update LauncherPreferencesViewController.m Co-authored-by: Duy Tran Khanh <[email protected]> Co-authored-by: Duy Tran Khanh <[email protected]> Co-authored-by: Silly Sock <[email protected]>
947 lines
43 KiB
Objective-C
947 lines
43 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/CustomControlsUtils.h"
|
|
|
|
#include <dlfcn.h>
|
|
|
|
#include "glfw_keycodes.h"
|
|
#include "utils.h"
|
|
|
|
BOOL shouldDismissPopover = YES;
|
|
int width;
|
|
NSMutableArray *keyCodeMap, *keyValueMap;
|
|
|
|
@interface ControlLayout ()
|
|
@end
|
|
@implementation ControlLayout
|
|
- (BOOL)canPerformAction:(SEL)action withSender:(id)sender
|
|
{
|
|
if (action == @selector(actionMenuExit:) ||
|
|
action == @selector(actionMenuSave:) ||
|
|
action == @selector(actionMenuLoad:) ||
|
|
action == @selector(actionMenuSetDef:) ||
|
|
action == @selector(actionMenuAddButton:) ||
|
|
action == @selector(actionMenuAddDrawer:) ||
|
|
action == @selector(actionMenuAddSubButton:) ||
|
|
action == @selector(actionMenuBtnCopy:) ||
|
|
action == @selector(actionMenuBtnDelete:) ||
|
|
action == @selector(actionMenuBtnEdit:)) {
|
|
return YES;
|
|
}
|
|
return NO;
|
|
}
|
|
|
|
- (BOOL)canBecomeFirstResponder {
|
|
return YES;
|
|
}
|
|
@end
|
|
|
|
@interface CustomControlsViewController () <UIPopoverPresentationControllerDelegate>{
|
|
}
|
|
|
|
@property(nonatomic, strong) NSMutableDictionary* cc_dictionary;
|
|
@property(nonatomic) UIView* offsetView;
|
|
@property(nonatomic) NSString* currentFileName;
|
|
@property(nonatomic) CGRect selectedPoint;
|
|
|
|
// - (void)method
|
|
|
|
@end
|
|
|
|
@implementation CustomControlsViewController
|
|
|
|
- (void)viewDidLoad
|
|
{
|
|
[super viewDidLoad];
|
|
viewController = self;
|
|
isControlModifiable = YES;
|
|
|
|
[self.navigationController setNavigationBarHidden:YES animated:YES];
|
|
[self setNeedsUpdateOfScreenEdgesDeferringSystemGestures];
|
|
[self setNeedsUpdateOfHomeIndicatorAutoHidden];
|
|
|
|
// Update color mode once
|
|
if(@available(iOS 13.0, *)) {
|
|
[self traitCollectionDidChange:nil];
|
|
} else {
|
|
self.view.backgroundColor = [UIColor whiteColor];
|
|
}
|
|
|
|
CGRect screenBounds = [[UIScreen mainScreen] bounds];
|
|
UIEdgeInsets insets = UIApplication.sharedApplication.windows.firstObject.safeAreaInsets;
|
|
|
|
self.offsetView = [[ControlLayout alloc] initWithFrame:CGRectMake(
|
|
insets.left, 0,
|
|
self.view.frame.size.width - insets.left - insets.right,
|
|
self.view.frame.size.height
|
|
)];
|
|
[self.view addSubview:self.offsetView];
|
|
|
|
int height = (int) roundf(screenBounds.size.height);
|
|
width = width - insets.left - insets.right;
|
|
CGFloat buttonScale = [getPreference(@"button_scale") floatValue] / 100.0;
|
|
|
|
UILongPressGestureRecognizer *longpressGesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(showControlPopover:)];
|
|
longpressGesture.minimumPressDuration = 0.5;
|
|
[self.offsetView addGestureRecognizer:longpressGesture];
|
|
self.currentFileName = [getPreference(@"default_ctrl") stringByDeletingPathExtension];
|
|
[self initKeyCodeMap];
|
|
[self loadControlFile:[NSString stringWithFormat:@"%s/%@", getenv("POJAV_PATH_CONTROL"), getPreference(@"default_ctrl")]];
|
|
}
|
|
|
|
- (void)loadControlFile:(NSString *)controlFilePath {
|
|
for (UIView *view in self.offsetView.subviews) {
|
|
if ([view isKindOfClass:[ControlButton class]]) {
|
|
[view removeFromSuperview];
|
|
}
|
|
}
|
|
|
|
NSError *cc_error;
|
|
NSString *cc_data = [NSString stringWithContentsOfFile:controlFilePath encoding:NSUTF8StringEncoding error:&cc_error];
|
|
|
|
if (cc_error) {
|
|
NSLog(@"Error: could not read %@: %@", controlFilePath, cc_error.localizedDescription);
|
|
showDialog(self, @"Error", [NSString stringWithFormat:@"Could not read %@: %@", controlFilePath, cc_error.localizedDescription]);
|
|
return;
|
|
}
|
|
|
|
NSData* cc_objc_data = [cc_data dataUsingEncoding:NSUTF8StringEncoding];
|
|
self.cc_dictionary = [NSJSONSerialization JSONObjectWithData:cc_objc_data options:NSJSONReadingMutableContainers error:&cc_error];
|
|
if (cc_error) {
|
|
showDialog(self, @"Error parsing JSON", cc_error.localizedDescription);
|
|
return;
|
|
}
|
|
|
|
loadControlObject(self.offsetView, 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)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:@"Exit" action:@selector(actionMenuExit)];
|
|
UIMenuItem *actionSave = [[UIMenuItem alloc] initWithTitle:@"Save" action:@selector(actionMenuSave)];
|
|
UIMenuItem *actionLoad = [[UIMenuItem alloc] initWithTitle:@"Load" action:@selector(actionMenuLoad)];
|
|
UIMenuItem *actionSetDef = [[UIMenuItem alloc] initWithTitle:@"Select as default" action:@selector(actionMenuSetDef)];
|
|
UIMenuItem *actionAddButton = [[UIMenuItem alloc] initWithTitle:@"Add button" action:@selector(actionMenuAddButton)];
|
|
UIMenuItem *actionAddDrawer = [[UIMenuItem alloc] initWithTitle:@"Add drawer" action:@selector(actionMenuAddDrawer)];
|
|
[menuController setMenuItems:@[actionExit, actionSave, actionLoad, actionSetDef, 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:@"Edit" action:@selector(actionMenuBtnEdit)];
|
|
UIMenuItem *actionCopy = [[UIMenuItem alloc] initWithTitle:@"Copy" action:@selector(actionMenuBtnCopy)];
|
|
UIMenuItem *actionDelete = [[UIMenuItem alloc] initWithTitle:@"Remove" action:@selector(actionMenuBtnDelete)];
|
|
if ([sender.view isKindOfClass:[ControlDrawer class]]) {
|
|
UIMenuItem *actionAddSubButton = [[UIMenuItem alloc] initWithTitle:@"Add sub-button" action:@selector(actionMenuAddSubButton)];
|
|
[menuController setMenuItems:@[actionEdit, /* actionCopy, */ actionDelete, actionAddSubButton]];
|
|
} else {
|
|
[menuController setMenuItems:@[actionEdit, /* actionCopy, */ actionDelete]];
|
|
}
|
|
self.selectedPoint = sender.view.bounds;
|
|
}
|
|
|
|
if (sender.view != self.offsetView) {
|
|
[self.offsetView becomeFirstResponder];
|
|
}
|
|
[sender.view becomeFirstResponder];
|
|
|
|
if(@available(iOS 13.0, *)) {
|
|
[menuController showMenuFromView:sender.view rect:self.selectedPoint];
|
|
} else {
|
|
[menuController setTargetRect:self.selectedPoint inView:sender.view];
|
|
[menuController setMenuVisible:YES animated:YES];
|
|
}
|
|
}
|
|
|
|
- (void)actionMenuExit {
|
|
[self.navigationController setNavigationBarHidden:NO animated:YES];
|
|
[self.navigationController popViewControllerAnimated:YES];
|
|
}
|
|
|
|
- (void)actionMenuSave {
|
|
UIAlertController *controller = [UIAlertController alertControllerWithTitle: @"Save"
|
|
message:[NSString stringWithFormat:@"File will be saved to %s directory.", getenv("POJAV_PATH_CONTROL")]
|
|
preferredStyle:UIAlertControllerStyleAlert];
|
|
[controller addTextFieldWithConfigurationHandler:^(UITextField *textField) {
|
|
textField.placeholder = @"Name";
|
|
textField.text = self.currentFileName;
|
|
textField.clearButtonMode = UITextFieldViewModeWhileEditing;
|
|
textField.borderStyle = UITextBorderStyleRoundedRect;
|
|
}];
|
|
[controller addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
|
|
NSArray *textFields = controller.textFields;
|
|
UITextField *field = textFields[0];
|
|
if ([field.text isEqualToString:@"default"]) {
|
|
controller.message = @"Control name should not be \"default\" as it will be overriden.";
|
|
[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, @"Error while converting to JSON", error.localizedDescription);
|
|
return;
|
|
}
|
|
NSString *jsonStr = [NSString stringWithUTF8String:jsonData.bytes];
|
|
BOOL success = [jsonStr writeToFile:[NSString stringWithFormat:@"%s/%@.json", getenv("POJAV_PATH_CONTROL"), field.text] atomically:YES encoding:NSUTF8StringEncoding error:&error];
|
|
if (!success) {
|
|
showDialog(self, @"Error while saving file", error.localizedDescription);
|
|
return;
|
|
}
|
|
|
|
self.currentFileName = field.text;
|
|
}
|
|
}]];
|
|
[controller addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:nil]];
|
|
[self presentViewController:controller animated:YES completion:nil];
|
|
}
|
|
|
|
- (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/%@.json", getenv("POJAV_PATH_CONTROL"), name]];
|
|
}];
|
|
}
|
|
|
|
- (void)actionMenuSetDef {
|
|
[self actionOpenFilePicker:^void(NSString* name) {
|
|
self.currentFileName = name;
|
|
[self loadControlFile:[NSString stringWithFormat:@"%s/%@.json", getenv("POJAV_PATH_CONTROL"), name]];
|
|
setPreference(@"default_ctrl", [NSString stringWithFormat:@"%@.json", name]);
|
|
}];
|
|
}
|
|
|
|
- (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];
|
|
[button snapAndAlignX:self.selectedPoint.origin.x-25.0 Y:self.selectedPoint.origin.y-25.0];
|
|
[self.cc_dictionary[@"mControlDataList"] addObject:button.properties];
|
|
} else {
|
|
button = [drawer addButtonProp:dict];
|
|
[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:)]];
|
|
[self.offsetView addSubview:button];
|
|
}
|
|
|
|
- (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];
|
|
[button snapAndAlignX:self.selectedPoint.origin.x-25.0 Y:self.selectedPoint.origin.y-25.0];
|
|
[button addGestureRecognizer:[[UITapGestureRecognizer alloc]
|
|
initWithTarget:self action:@selector(showControlPopover:)]];
|
|
[button addGestureRecognizer:[[UIPanGestureRecognizer alloc]
|
|
initWithTarget:self action:@selector(onTouch:)]];
|
|
[self.offsetView addSubview:button];
|
|
[self.cc_dictionary[@"mDrawerDataList"] addObject:button.drawerData];
|
|
}
|
|
|
|
- (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 {
|
|
UIAlertController *alert = [UIAlertController alertControllerWithTitle:((ControlButton *)self.currentGesture.view).currentTitle message:@"Are you sure to remove this button?"preferredStyle:UIAlertControllerStyleAlert];
|
|
UIAlertAction *cancel = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:nil];
|
|
UIAlertAction *ok = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
|
|
ControlButton *button = (ControlButton *)self.currentGesture.view;
|
|
if ([button isKindOfClass:[ControlSubButton class]]) {
|
|
[((ControlSubButton *)button).parentDrawer.buttons removeObject:button];
|
|
[((ControlSubButton *)button).parentDrawer.drawerData[@"buttonProperties"] removeObject:button.properties];
|
|
[((ControlSubButton *)button).parentDrawer syncButtons];
|
|
} else if ([button isKindOfClass:[ControlDrawer class]]) {
|
|
for (ControlSubButton *subButton in ((ControlDrawer *)button).buttons) {
|
|
[subButton removeFromSuperview];
|
|
}
|
|
[self.cc_dictionary[@"mDrawerDataList"] removeObject:((ControlDrawer *)button).drawerData];
|
|
} else {
|
|
[self.cc_dictionary[@"mControlDataList"] removeObject:button.properties];
|
|
}
|
|
[button removeFromSuperview];
|
|
|
|
}];
|
|
[alert addAction:cancel];
|
|
[alert addAction:ok];
|
|
[self presentViewController:alert animated:YES completion:nil];
|
|
}
|
|
|
|
- (void)actionMenuBtnEdit {
|
|
shouldDismissPopover = NO;
|
|
CCMenuViewController *vc = [[CCMenuViewController alloc] init];
|
|
vc.modalPresentationStyle = UIModalPresentationFormSheet;
|
|
if (![self.currentGesture isKindOfClass:[UILongPressGestureRecognizer class]]) {
|
|
vc.targetButton = (ControlButton *)self.currentGesture.view;
|
|
}
|
|
[self presentViewController:vc animated:YES completion:nil];
|
|
}
|
|
|
|
- (UIRectEdge)preferredScreenEdgesDeferringSystemGestures {
|
|
return UIRectEdgeBottom;
|
|
}
|
|
|
|
- (BOOL)prefersHomeIndicatorAutoHidden {
|
|
return NO;
|
|
}
|
|
|
|
- (void)onTouch:(UIPanGestureRecognizer *)sender {
|
|
ControlButton *button = (ControlButton *)sender.view;
|
|
if (![button.properties[@"isDynamicBtn"] boolValue]) {
|
|
if ([button isKindOfClass:[ControlSubButton class]] &&
|
|
![((ControlSubButton *)button).parentDrawer.drawerData[@"orientation"] isEqualToString:@"FREE"]) return;
|
|
|
|
if (sender.state == UIGestureRecognizerStateBegan) {
|
|
UIMenuController *menuController = [UIMenuController sharedMenuController];
|
|
if(@available(iOS 13.0, *)) {
|
|
[menuController hideMenu];
|
|
} else {
|
|
[menuController setMenuVisible:NO animated:YES];
|
|
}
|
|
} else if (sender.state == UIGestureRecognizerStateChanged) {
|
|
CGPoint translation = [sender translationInView:button];
|
|
//button.center = CGPointMake(button.center.x + translation.x, button.center.y + translation.y);
|
|
[button snapAndAlignX:clamp(button.frame.origin.x+translation.x, 0, self.offsetView.frame.size.width - button.frame.size.width) Y:clamp(button.frame.origin.y+translation.y, 0, self.offsetView.frame.size.height - button.frame.size.height)];
|
|
[sender setTranslation:CGPointZero inView:button];
|
|
}
|
|
}
|
|
}
|
|
|
|
-(void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection {
|
|
if(@available(iOS 13.0, *)) {
|
|
if (UITraitCollection.currentTraitCollection.userInterfaceStyle == UIUserInterfaceStyleDark) {
|
|
self.view.backgroundColor = [UIColor blackColor];
|
|
} else {
|
|
self.view.backgroundColor = [UIColor whiteColor];
|
|
}
|
|
}
|
|
}
|
|
|
|
#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 UITextField *activeField;
|
|
@property(nonatomic) UIScrollView* scrollView;
|
|
@property(nonatomic) UITextField *editName, *editSizeWidth, *editSizeHeight, *editDynamicX, *editDynamicY;
|
|
@property(nonatomic) UITextView* editMapping;
|
|
@property(nonatomic) UIPickerView* pickerMapping;
|
|
@property(nonatomic) UISegmentedControl* ctrlOrientation;
|
|
@property(nonatomic) UISwitch *switchToggleable, *switchMousePass, *switchSwipeable, *switchDynamicPos;
|
|
@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 registerForKeyboardNotifications];
|
|
currentY = 6.0;
|
|
|
|
if (self.view.bounds.origin.x == 0) {
|
|
CGFloat x = self.view.bounds.size.width/10.0;
|
|
CGFloat y = self.view.bounds.size.height/10.0;
|
|
self.view.bounds = CGRectMake(-x, -y, self.view.bounds.size.width - x * 2.0, self.view.bounds.size.height - y * 2.0);
|
|
//self.view.layer.cornerRadius = self.view.bounds.size.height/2;
|
|
//self.view.layer.masksToBounds = YES;
|
|
}
|
|
UIVisualEffectView *blurView = [[UIVisualEffectView alloc] initWithEffect:[UIBlurEffect effectWithStyle:UIBlurEffectStyleRegular]];
|
|
blurView.frame = CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.height);
|
|
[self.view addSubview:blurView];
|
|
|
|
UIBarButtonItem *btnFlexibleSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:self action:nil];
|
|
|
|
UIToolbar *popoverToolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0.0, 0.0, self.view.bounds.size.width, 44.0)];
|
|
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];
|
|
[self.view addSubview:popoverToolbar];
|
|
|
|
self.scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(5.0, popoverToolbar.frame.size.height, self.view.bounds.size.width - 10.0, self.view.bounds.size.height - popoverToolbar.frame.size.height)];
|
|
[self.view addSubview:self.scrollView];
|
|
|
|
UIToolbar *editPickToolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0.0, 0.0, self.view.bounds.size.width, 44.0)];
|
|
UIBarButtonItem *editDoneButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(closeTextField)];
|
|
editPickToolbar.items = @[btnFlexibleSpace, editDoneButton];
|
|
|
|
CGFloat width = self.view.bounds.size.width - 10.0;
|
|
CGFloat height = self.view.bounds.size.height - 10.0;
|
|
|
|
|
|
// Property: Name
|
|
UILabel *labelName = [self addLabel:@"Name"];
|
|
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.editName action:@selector(resignFirstResponder) forControlEvents:UIControlEventEditingDidEndOnExit];
|
|
self.editName.placeholder = @"Name";
|
|
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:@"Size"];
|
|
// 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.keyboardType = UIKeyboardTypeDecimalPad;
|
|
self.editSizeWidth.placeholder = @"width";
|
|
self.editSizeWidth.text = [self.targetButton.properties[@"width"] stringValue];
|
|
self.editSizeWidth.textAlignment = NSTextAlignmentCenter;
|
|
self.editSizeWidth.inputAccessoryView = editPickToolbar;
|
|
[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.keyboardType = UIKeyboardTypeDecimalPad;
|
|
self.editSizeHeight.placeholder = @"height";
|
|
self.editSizeHeight.text = [self.targetButton.properties[@"height"] stringValue];
|
|
self.editSizeHeight.textAlignment = NSTextAlignmentCenter;
|
|
self.editSizeHeight.inputAccessoryView = editPickToolbar;
|
|
[self.scrollView addSubview:self.editSizeHeight];
|
|
}
|
|
|
|
|
|
currentY += labelName.frame.size.height + 12.0;
|
|
if (![self.targetButton isKindOfClass:[ControlDrawer class]]) {
|
|
// Property: Mapping
|
|
UILabel *labelMapping = [self addLabel:@"Mapping"];
|
|
|
|
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 = [NSArray arrayWithObjects:@"DOWN", @"LEFT", @"UP", @"RIGHT", @"FREE", nil];
|
|
UILabel *labelOrientation = [self addLabel:@"Orientation"];
|
|
self.ctrlOrientation = [[UISegmentedControl alloc] initWithItems:self.arrOrientation];
|
|
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:@"Toggleable"];
|
|
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:@"Mouse pass"];
|
|
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:@"Swipeable"];
|
|
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:@"Background color"];
|
|
if(@available(iOS 14.0, *)) {
|
|
self.colorWellINTBackground = [[UIColorWell alloc] initWithFrame:CGRectMake(width - 42.0, currentY - 5.0, 30.0, 30.0)];
|
|
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:@"Stroke width (%)"];
|
|
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:@"Stroke color"];
|
|
if(@available(iOS 14.0, *)) {
|
|
self.colorWellINTStroke = [[UIColorWell alloc] initWithFrame:CGRectMake(width - 42.0, currentY - 5.0, 30.0, 30.0)];
|
|
self.colorWellINTStroke.selectedColor = [[UIColor alloc] initWithCGColor:self.targetButton.layer.borderColor];
|
|
self.colorWellINTStroke.supportsAlpha = NO;
|
|
} 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:@"Corner radius (%)"];
|
|
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 = NO;
|
|
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:@"Button opacity"];
|
|
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 = NO;
|
|
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];
|
|
|
|
|
|
if (![self.targetButton isKindOfClass:[ControlSubButton class]] ||
|
|
[((ControlSubButton *)self.targetButton).parentDrawer.drawerData[@"orientation"] isEqualToString:@"FREE"]) {
|
|
// Property: Dynamic position
|
|
currentY += labelName.frame.size.height + 12.0;
|
|
UILabel *labelDynamicPos = [self addLabel:@"Dynamic position"];
|
|
self.switchDynamicPos = [[UISwitch alloc] initWithFrame:CGRectMake(width - 62.0, currentY - 5.0, 50.0, 30)];
|
|
self.switchDynamicPos.tag = TAG_SWITCH_DYNAMICPOS;
|
|
[self.switchDynamicPos setOn:[self.targetButton.properties[@"isDynamicBtn"] boolValue] animated:NO];
|
|
[self.switchDynamicPos addTarget:self action:@selector(switchValueChanged:) forControlEvents:UIControlEventValueChanged];
|
|
[self.scrollView addSubview:self.switchDynamicPos];
|
|
|
|
|
|
// Property: Dynamic X-axis
|
|
currentY += labelName.frame.size.height + 12.0;
|
|
UILabel *labelDynamicX = [self addLabel:@"Dynamic X-axis"];
|
|
self.editDynamicX = [[UITextField alloc] initWithFrame:CGRectMake(labelDynamicX.frame.size.width + 5.0, currentY, width - labelDynamicX.frame.size.width - 5.0, labelDynamicX.frame.size.height)];
|
|
[self.editDynamicX addTarget:self.editDynamicX action:@selector(resignFirstResponder) forControlEvents:UIControlEventEditingDidEndOnExit];
|
|
self.editDynamicX.text = self.targetButton.properties[@"dynamicX"];
|
|
[self.scrollView addSubview:self.editDynamicX];
|
|
|
|
|
|
// Property: Dynamic Y-axis
|
|
currentY += labelName.frame.size.height + 12.0;
|
|
UILabel *labelDynamicY = [self addLabel:@"Dynamic Y-axis"];
|
|
self.editDynamicY = [[UITextField alloc] initWithFrame:CGRectMake(labelDynamicY.frame.size.width + 5.0, currentY, width - labelDynamicY.frame.size.width - 5.0, labelDynamicY.frame.size.height)];
|
|
[self.editDynamicY addTarget:self.editDynamicY action:@selector(resignFirstResponder) forControlEvents:UIControlEventEditingDidEndOnExit];
|
|
self.editDynamicY.text = self.targetButton.properties[@"dynamicY"];
|
|
[self.scrollView addSubview:self.editDynamicY];
|
|
self.editDynamicX.enabled = self.editDynamicY.enabled = self.switchDynamicPos.isOn;
|
|
}
|
|
|
|
|
|
currentY += labelName.frame.size.height + 12.0;
|
|
self.scrollView.contentSize = CGSizeMake(self.scrollView.contentSize.width, currentY);
|
|
}
|
|
|
|
#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 = NO;
|
|
} else {
|
|
NSLog(@"Unknown color well: %@", sender);
|
|
abort();
|
|
}
|
|
[self presentViewController:vc animated:YES completion:nil];
|
|
}
|
|
|
|
// HBColorPickerDelegate
|
|
- (void)colorPicker:(HBColorPickerViewController *)picker didSelectColor:(UIColor *)color {
|
|
if ([picker.configuration.title isEqualToString:@"Background color"]) {
|
|
self.colorWellEXTBackground.color = color;
|
|
} else if ([picker.configuration.title isEqualToString:@"Stroke color"]) {
|
|
self.colorWellEXTStroke.color = color;
|
|
} else {
|
|
NSLog(@"Unknown color well: %@", picker.configuration.title);
|
|
abort();
|
|
}
|
|
}
|
|
|
|
#pragma mark - Keyboard observer functions
|
|
- (void)registerForKeyboardNotifications
|
|
{
|
|
[[NSNotificationCenter defaultCenter] addObserver:self
|
|
selector:@selector(keyboardWasShown:)
|
|
name:UIKeyboardDidShowNotification object:nil];
|
|
|
|
[[NSNotificationCenter defaultCenter] addObserver:self
|
|
selector:@selector(keyboardWillBeHidden:)
|
|
name:UIKeyboardWillHideNotification object:nil];
|
|
|
|
}
|
|
|
|
- (void)keyboardWasShown:(NSNotification*)aNotification
|
|
{
|
|
NSDictionary* info = [aNotification userInfo];
|
|
CGSize kbSize = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size;
|
|
UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, kbSize.height, 0.0);
|
|
self.scrollView.contentInset = contentInsets;
|
|
self.scrollView.scrollIndicatorInsets = contentInsets;
|
|
CGRect aRect = self.view.bounds;
|
|
aRect.size.height = self.view.frame.size.height - kbSize.height;
|
|
if (!CGRectContainsPoint(aRect, self.activeField.frame.origin) ) {
|
|
[self.scrollView scrollRectToVisible:self.activeField.frame animated:YES];
|
|
}
|
|
}
|
|
|
|
- (void)keyboardWillBeHidden:(NSNotification*)aNotification
|
|
{
|
|
UIEdgeInsets contentInsets = UIEdgeInsetsZero;
|
|
self.scrollView.contentInset = contentInsets;
|
|
self.scrollView.scrollIndicatorInsets = contentInsets;
|
|
}
|
|
|
|
- (void)textFieldDidBeginEditing:(UITextField *)textField {
|
|
self.activeField = textField;
|
|
}
|
|
|
|
- (void)textFieldDidEndEditing:(UITextField *)textField {
|
|
self.activeField = nil;
|
|
}
|
|
|
|
#pragma mark - Control editor
|
|
- (void)actionEditCancel {
|
|
shouldDismissPopover = YES;
|
|
[self dismissViewControllerAnimated:YES completion:nil];
|
|
}
|
|
|
|
- (void)actionEditFinish {
|
|
shouldDismissPopover = YES;
|
|
[self dismissViewControllerAnimated:YES completion:nil];
|
|
|
|
self.targetButton.properties[@"name"] = self.editName.text;
|
|
self.targetButton.properties[@"width"] = @([self.editSizeWidth.text floatValue]);
|
|
self.targetButton.properties[@"height"] = @([self.editSizeHeight.text floatValue]);
|
|
if (![self.targetButton isKindOfClass:[ControlDrawer class]]) {
|
|
for (int i = 0; i < 4; i++) {
|
|
self.targetButton.properties[@"keycodes"][i] = keyValueMap[[self.pickerMapping selectedRowInComponent:i]];
|
|
}
|
|
} else {
|
|
((ControlDrawer *)self.targetButton).drawerData[@"orientation"] =
|
|
self.arrOrientation[self.ctrlOrientation.selectedSegmentIndex];
|
|
[(ControlDrawer *)self.targetButton syncButtons];
|
|
}
|
|
self.targetButton.properties[@"isToggle"] = @(self.switchToggleable.isOn);
|
|
self.targetButton.properties[@"passThruEnabled"] = @(self.switchMousePass.isOn);
|
|
self.targetButton.properties[@"isSwipeable"] = @(self.switchSwipeable.isOn);
|
|
if(@available(iOS 14.0, *)) {
|
|
self.targetButton.properties[@"bgColor"] = @(convertUIColor2ARGB(self.colorWellINTBackground.selectedColor));
|
|
self.targetButton.properties[@"strokeColor"] = @(convertUIColor2RGB(self.colorWellINTStroke.selectedColor));
|
|
} else {
|
|
self.targetButton.properties[@"bgColor"] = @(convertUIColor2ARGB(self.colorWellEXTBackground.color));
|
|
self.targetButton.properties[@"strokeColor"] = @(convertUIColor2RGB(self.colorWellEXTStroke.color));
|
|
}
|
|
self.targetButton.properties[@"strokeWidth"] = @((NSInteger) self.sliderStrokeWidth.value);
|
|
self.targetButton.properties[@"cornerRadius"] = @((NSInteger) self.sliderCornerRadius.value);
|
|
self.targetButton.properties[@"opacity"] = @(self.sliderOpacity.value / 100.0);
|
|
self.targetButton.properties[@"isDynamicBtn"] = @(self.switchDynamicPos.isOn);
|
|
self.targetButton.properties[@"dynamicX"] = self.editDynamicX.text;
|
|
self.targetButton.properties[@"dynamicY"] = self.editDynamicY.text;
|
|
|
|
[self.targetButton update];
|
|
}
|
|
|
|
- (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;
|
|
}
|
|
}
|
|
}
|
|
|
|
- (void)switchValueChanged:(UISwitch *)sender {
|
|
if (sender.tag == TAG_SWITCH_DYNAMICPOS) {
|
|
self.editDynamicX.enabled = self.editDynamicY.enabled = self.switchDynamicPos.isOn;
|
|
}
|
|
}
|
|
|
|
#pragma mark - UIPickerView stuff
|
|
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
|
|
//versionTextField.text = [self pickerView:pickerView titleForRow:row forComponent:component];
|
|
//setPreference(@"selected_version", versionTextField.text);
|
|
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]]
|
|
];
|
|
}
|
|
|
|
- (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
|