From 8e00552c61c5d21853c46843a63e2dbb03ba8396 Mon Sep 17 00:00:00 2001 From: TrueZhuanjia Date: Mon, 9 Jun 2025 20:28:41 +0800 Subject: [PATCH] - new on-screen widget tool UI with movable widget panel with iOS12 compatibility --- Limelight/Base.lproj/iPad.storyboard | 306 +++++++++---- Limelight/Base.lproj/iPhone.storyboard | 7 +- .../Input/CustomOSC/LayoutOnScreenControls.m | 5 +- .../Input/CustomOSC/OSCProfilesManager.m | 2 +- Limelight/Input/OnScreenControls.m | 1 - Limelight/Input/OnScreenWidgetView.swift | 7 +- Limelight/Localization/Localizable.xcstrings | 284 ++++++------ .../LayoutOnScreenControlsViewController.h | 45 +- .../LayoutOnScreenControlsViewController.m | 421 ++++++++---------- Limelight/mul.lproj/iPad.xcstrings | 92 +++- 10 files changed, 678 insertions(+), 492 deletions(-) diff --git a/Limelight/Base.lproj/iPad.storyboard b/Limelight/Base.lproj/iPad.storyboard index 9c761059..307facc7 100644 --- a/Limelight/Base.lproj/iPad.storyboard +++ b/Limelight/Base.lproj/iPad.storyboard @@ -3,6 +3,7 @@ + @@ -954,25 +955,28 @@ ICAgICAgICAgICAgICA - + - + - + - - - + @@ -1102,53 +1126,140 @@ ICAgICAgICAgICAgICA - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + @@ -1159,25 +1270,42 @@ ICAgICAgICAgICAgICA + + - - - + + + + + + + + + + + - - - - + + + + + + + + + + + - + @@ -1260,23 +1388,25 @@ ICAgICAgICAgICAgICA - - - - - + + + + + + + - - - + + + diff --git a/Limelight/Base.lproj/iPhone.storyboard b/Limelight/Base.lproj/iPhone.storyboard index 660ba759..e30c3aa9 100644 --- a/Limelight/Base.lproj/iPhone.storyboard +++ b/Limelight/Base.lproj/iPhone.storyboard @@ -2,7 +2,6 @@ - @@ -13,7 +12,7 @@ - + @@ -926,7 +925,7 @@ ICAgICAgICAgICAgIA - + @@ -1030,7 +1029,7 @@ ICAgICAgICAgICAgIA - + diff --git a/Limelight/Input/CustomOSC/LayoutOnScreenControls.m b/Limelight/Input/CustomOSC/LayoutOnScreenControls.m index c0580033..405c9625 100644 --- a/Limelight/Input/CustomOSC/LayoutOnScreenControls.m +++ b/Limelight/Input/CustomOSC/LayoutOnScreenControls.m @@ -34,7 +34,7 @@ - (id) initWithView:(UIView*)view controllerSup:(ControllerSupport*)controllerSupport streamConfig:(StreamConfiguration*)streamConfig oscLevel:(int)oscLevel { [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleMovingOnScreenWidgetNotification:) - name:@"OnScreenWidgetMovedByTouch" // This is a special notification for reloading the on screen keyboard buttons. which can't be executed by _oscProfilesTableViewController.needToUpdateOscLayoutTVC code block, and has to be triggered by a notification + name:@"OnScreenWidgetMovedByTouch" object:nil]; @@ -247,7 +247,6 @@ - (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { /* Reset variables related to on screen controller button drag and drop routine. These variables should be reset in 'touchesCancelled' or 'touchesEnded' but these may not be called in unaccounted-for edge cases such as when the user opens various OS-level control center related views by dragging down from the top of the screen, or dragging up from the bottom of the screen. Since Apple likes to add new control centers and new ways of opening them (i.e. Dynamic Island on iPhone 14 Pro) it's best to reset these variables here when the user is beginning a new on screen controller button drag routine */ - // [[NSNotificationCenter defaultCenter] postNotificationName:@"LegacyOscCALayerSelectedNotification" object:self]; layerBeingDragged = nil; horizontalGuideline.backgroundColor = [UIColor blueColor]; verticalGuideline.backgroundColor = [UIColor blueColor]; @@ -293,6 +292,8 @@ layerBeingDragged = layer; } + if(!layerBeingDragged) return; + [[NSNotificationCenter defaultCenter] postNotificationName:@"LegacyOscCALayerSelectedNotification" object:layerBeingDragged]; // inform that a CALayer of onScreen controller has being selected /* save the name, position, and visibility of button being touched in array in case user wants to undo the change later */ diff --git a/Limelight/Input/CustomOSC/OSCProfilesManager.m b/Limelight/Input/CustomOSC/OSCProfilesManager.m index 0379d988..b384f3db 100644 --- a/Limelight/Input/CustomOSC/OSCProfilesManager.m +++ b/Limelight/Input/CustomOSC/OSCProfilesManager.m @@ -337,7 +337,7 @@ static CGRect streamViewBounds; buttonState.isHidden = oscButtonLayer.isHidden; buttonState.oscLayerSizeFactor = [OnScreenControls getControllerLayerSizeFactor:oscButtonLayer]; buttonState.backgroundAlpha = oscButtonLayer.opacity; - NSLog(@"oscLayerName: %@, opacity: %f, ", oscButtonLayer.name, buttonState.backgroundAlpha); + // NSLog(@"oscLayerName: %@, opacity: %f, ", oscButtonLayer.name, buttonState.backgroundAlpha); // buttonState.oscLayerSizeFactor = oscButtonLayer.bounds; diff --git a/Limelight/Input/OnScreenControls.m b/Limelight/Input/OnScreenControls.m index 57b046b3..4b6978ca 100644 --- a/Limelight/Input/OnScreenControls.m +++ b/Limelight/Input/OnScreenControls.m @@ -1387,7 +1387,6 @@ static float L3_Y; [_deadTouches addObject:touch]; updated = true; touchEventCapturedByOsc = true; - // NSLog(@"blablablab updated true"); } // additionally, populate the touchesCapturedByOSButton set, for native/relative touch handler to deal with. if(touchEventCapturedByOsc) [touchAddrsCapturedByOnScreenControls addObject:@((uintptr_t)touch)]; diff --git a/Limelight/Input/OnScreenWidgetView.swift b/Limelight/Input/OnScreenWidgetView.swift index fbbe4be1..d52a1933 100644 --- a/Limelight/Input/OnScreenWidgetView.swift +++ b/Limelight/Input/OnScreenWidgetView.swift @@ -151,8 +151,11 @@ import UIKit // let stickAndMouseTouchpads = ["LSPAD", "RSPAD", "LSVPAD", "RSVPAD", "MOUSEPAD"] let nonVectorStickPads = ["LSPAD", "RSPAD"] - if CommandManager.touchPadCmds.contains(self.touchPadString) {self.hasSensitivityTweak = true} - if nonVectorStickPads.contains(self.touchPadString) && widgetType == WidgetTypeEnum.touchPad {self.hasStickIndicator = true} + // if CommandManager.touchPadCmds.contains(self.touchPadString) {self.hasSensitivityTweak = true} + self.hasSensitivityTweak = CommandManager.touchPadCmds.contains(self.touchPadString) + + // if nonVectorStickPads.contains(self.touchPadString) && widgetType == WidgetTypeEnum.touchPad {self.hasStickIndicator = true} + self.hasStickIndicator = nonVectorStickPads.contains(self.touchPadString) && widgetType == WidgetTypeEnum.touchPad switch self.cmdString { case "LSPAD", "LSVPAD": diff --git a/Limelight/Localization/Localizable.xcstrings b/Limelight/Localization/Localizable.xcstrings index 22cff6f3..c863bd03 100644 --- a/Limelight/Localization/Localizable.xcstrings +++ b/Limelight/Localization/Localizable.xcstrings @@ -260,6 +260,52 @@ } } }, + "Alpha" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "控件透明度" + } + }, + "zh-Hant" : { + "stringUnit" : { + "state" : "translated", + "value" : "控件透明度" + } + }, + "zh-HK" : { + "stringUnit" : { + "state" : "translated", + "value" : "控件透明度" + } + } + } + }, + "Alpha: %.2f" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "控件透明度: %.2f" + } + }, + "zh-Hant" : { + "stringUnit" : { + "state" : "translated", + "value" : "控件透明度: %.2f" + } + }, + "zh-HK" : { + "stringUnit" : { + "state" : "translated", + "value" : "控件透明度: %.2f" + } + } + } + }, "Back" : { "extractionState" : "manual", "localizations" : { @@ -1238,6 +1284,52 @@ } } }, + "Height" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "控件高度" + } + }, + "zh-Hant" : { + "stringUnit" : { + "state" : "translated", + "value" : "控件高度" + } + }, + "zh-HK" : { + "stringUnit" : { + "state" : "translated", + "value" : "控件高度" + } + } + } + }, + "Height: %.2f" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "控件高度: %.2f" + } + }, + "zh-Hant" : { + "stringUnit" : { + "state" : "translated", + "value" : "控件高度: %.2f" + } + }, + "zh-HK" : { + "stringUnit" : { + "state" : "translated", + "value" : "控件高度: %.2f" + } + } + } + }, "Help" : { "extractionState" : "manual", "localizations" : { @@ -1330,25 +1422,25 @@ } } }, - "Indicator Offset: %.2f" : { + "Indicator Offset: %.0f" : { "extractionState" : "manual", "localizations" : { "zh-Hans" : { "stringUnit" : { "state" : "translated", - "value" : "指示器偏离: %.2f" + "value" : "指示器偏离: %.0f" } }, "zh-Hant" : { "stringUnit" : { "state" : "translated", - "value" : "指示器偏离: %.2f" + "value" : "指示器偏离: %.0f" } }, "zh-HK" : { "stringUnit" : { "state" : "translated", - "value" : "指示器偏离: %.2f" + "value" : "指示器偏离: %.0f" } } } @@ -2746,6 +2838,52 @@ } } }, + "Size" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "控件大小" + } + }, + "zh-Hant" : { + "stringUnit" : { + "state" : "translated", + "value" : "控件大小" + } + }, + "zh-HK" : { + "stringUnit" : { + "state" : "translated", + "value" : "控件大小" + } + } + } + }, + "Size: %.2f" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "控件大小: %.2f" + } + }, + "zh-Hant" : { + "stringUnit" : { + "state" : "translated", + "value" : "控件大小: %.2f" + } + }, + "zh-HK" : { + "stringUnit" : { + "state" : "translated", + "value" : "控件大小: %.2f" + } + } + } + }, "Slide Distance for in-Stream Menu: %.2f * screen-width" : { "extractionState" : "manual", "localizations" : { @@ -3310,144 +3448,6 @@ } } }, - "Widget Alpha" : { - "extractionState" : "manual", - "localizations" : { - "zh-Hans" : { - "stringUnit" : { - "state" : "translated", - "value" : "控件透明度" - } - }, - "zh-Hant" : { - "stringUnit" : { - "state" : "translated", - "value" : "控件透明度" - } - }, - "zh-HK" : { - "stringUnit" : { - "state" : "translated", - "value" : "控件透明度" - } - } - } - }, - "Widget Alpha: %.2f" : { - "extractionState" : "manual", - "localizations" : { - "zh-Hans" : { - "stringUnit" : { - "state" : "translated", - "value" : "控件透明度: %.2f" - } - }, - "zh-Hant" : { - "stringUnit" : { - "state" : "translated", - "value" : "控件透明度: %.2f" - } - }, - "zh-HK" : { - "stringUnit" : { - "state" : "translated", - "value" : "控件透明度: %.2f" - } - } - } - }, - "Widget Height" : { - "extractionState" : "manual", - "localizations" : { - "zh-Hans" : { - "stringUnit" : { - "state" : "translated", - "value" : "控件高度" - } - }, - "zh-Hant" : { - "stringUnit" : { - "state" : "translated", - "value" : "控件高度" - } - }, - "zh-HK" : { - "stringUnit" : { - "state" : "translated", - "value" : "控件高度" - } - } - } - }, - "Widget Height: %.2f" : { - "extractionState" : "manual", - "localizations" : { - "zh-Hans" : { - "stringUnit" : { - "state" : "translated", - "value" : "控件高度: %.2f" - } - }, - "zh-Hant" : { - "stringUnit" : { - "state" : "translated", - "value" : "控件高度: %.2f" - } - }, - "zh-HK" : { - "stringUnit" : { - "state" : "translated", - "value" : "控件高度: %.2f" - } - } - } - }, - "Widget Size" : { - "extractionState" : "manual", - "localizations" : { - "zh-Hans" : { - "stringUnit" : { - "state" : "translated", - "value" : "控件大小" - } - }, - "zh-Hant" : { - "stringUnit" : { - "state" : "translated", - "value" : "控件大小" - } - }, - "zh-HK" : { - "stringUnit" : { - "state" : "translated", - "value" : "控件大小" - } - } - } - }, - "Widget Size: %.2f" : { - "extractionState" : "manual", - "localizations" : { - "zh-Hans" : { - "stringUnit" : { - "state" : "translated", - "value" : "控件大小: %.2f" - } - }, - "zh-Hant" : { - "stringUnit" : { - "state" : "translated", - "value" : "控件大小: %.2f" - } - }, - "zh-HK" : { - "stringUnit" : { - "state" : "translated", - "value" : "控件大小: %.2f" - } - } - } - }, "Your network connection isn't performing well. Reduce your video bitrate setting or try a faster connection." : { "extractionState" : "manual", "localizations" : { diff --git a/Limelight/ViewControllers/CustomOSCViewControl/LayoutOnScreenControlsViewController.h b/Limelight/ViewControllers/CustomOSCViewControl/LayoutOnScreenControlsViewController.h index ba777b2f..8900b2d0 100644 --- a/Limelight/ViewControllers/CustomOSCViewControl/LayoutOnScreenControlsViewController.h +++ b/Limelight/ViewControllers/CustomOSCViewControl/LayoutOnScreenControlsViewController.h @@ -40,14 +40,47 @@ NS_ASSUME_NONNULL_BEGIN @property (weak, nonatomic) IBOutlet UIImageView *chevronImageView; @property (weak, nonatomic) IBOutlet UIStackView *toolbarStackView; @property (strong, nonatomic) OSCProfilesTableViewController *oscProfilesTableViewController; + @property (nonatomic, assign) NSString *currentProfileName; @property (strong, nonatomic) IBOutlet UILabel *currentProfileLabel; -@property (strong, nonatomic) IBOutlet UISlider *widgetSizeSlider; -@property (strong, nonatomic) IBOutlet UISlider *widgetHeightSlider; -@property (strong, nonatomic) IBOutlet UISlider *widgetAlphaSlider; -@property (strong, nonatomic) IBOutlet UISlider *sensitivityFactorSlider; -@property (strong, nonatomic) IBOutlet UISlider *stickIndicatorOffsetSlider; -@property (strong, nonatomic) IBOutlet UISlider *widgetBorderWidthSlider; + +@property (weak, nonatomic) IBOutlet UILabel *widgetSizeLabel; +@property (weak, nonatomic) IBOutlet UISlider *widgetSizeSlider; +@property (weak, nonatomic) IBOutlet UIStackView *widgetSizeStack; + +@property (weak, nonatomic) IBOutlet UILabel *widgetHeightLabel; +@property (weak, nonatomic) IBOutlet UISlider *widgetHeightSlider; + +@property (weak, nonatomic) IBOutlet UIStackView *widgetHeightStack; + +@property (weak, nonatomic) IBOutlet UILabel *widgetBorderWidthLabel; +@property (weak, nonatomic) IBOutlet UISlider *widgetBorderWidthSlider; +@property (weak, nonatomic) IBOutlet UILabel *widgetAlphaLabel; +@property (weak, nonatomic) IBOutlet UISlider *widgetAlphaSlider; +@property (weak, nonatomic) IBOutlet UIStackView *borderWidthAlphaStack; +@property (weak, nonatomic) IBOutlet UIButton *saveButton; +@property (weak, nonatomic) IBOutlet UIButton *exitButton; +@property (weak, nonatomic) IBOutlet UIButton *loadButton; +@property (weak, nonatomic) IBOutlet UIButton *addButton; +@property (weak, nonatomic) IBOutlet UIButton *editButton; + + + + +@property (weak, nonatomic) IBOutlet UILabel *stickIndicatorOffsetLabel; +@property (weak, nonatomic) IBOutlet UISlider *stickIndicatorOffsetSlider; +@property (weak, nonatomic) IBOutlet UIStackView *stickIndicatorOffsetStack; + +@property (weak, nonatomic) IBOutlet UILabel *sensitivityLabel; +@property (weak, nonatomic) IBOutlet UISlider *sensitivitySlider; +@property (weak, nonatomic) IBOutlet UIStackView *sensitivityStack; + + + + + + +@property (weak, nonatomic) IBOutlet UIStackView *widgetPanelStack; @end diff --git a/Limelight/ViewControllers/CustomOSCViewControl/LayoutOnScreenControlsViewController.m b/Limelight/ViewControllers/CustomOSCViewControl/LayoutOnScreenControlsViewController.m index 225d9198..89a0c5d6 100644 --- a/Limelight/ViewControllers/CustomOSCViewControl/LayoutOnScreenControlsViewController.m +++ b/Limelight/ViewControllers/CustomOSCViewControl/LayoutOnScreenControlsViewController.m @@ -16,6 +16,7 @@ #import "OSCProfilesManager.h" #import "LocalizationHelper.h" #import "Moonlight-Swift.h" +#import "ThemeManager.h" @interface LayoutOnScreenControlsViewController () @@ -32,13 +33,10 @@ bool controllerLayerSelected; __weak IBOutlet NSLayoutConstraint *toolbarTopConstraintiPhone; __weak IBOutlet NSLayoutConstraint *toolbarTopConstraintiPad; - UILabel *widgetSizeSliderLabel; - UILabel *widgetHeightSliderLabel; - UILabel *widgetAlphaSliderLabel; - UILabel *widgetBorderWidthSliderLabel; - UILabel *sensitivitySliderLabel; - UILabel *stickIndicatorOffsetSliderLabel; - UILabel *stickIndicatorOffsetExplain; + UIColor* trashCanStoryBoardColor; + BOOL widgetPanelMovedByTouch; + CGPoint widgetPanelStoredCenter; + CGPoint latestTouchLocation; } @synthesize trashCanButton; @@ -80,13 +78,12 @@ } - (void) reloadOnScreenWidgetViews { + OnScreenWidgetView.editMode = true; [self->selectedWidgetView.stickBallLayer removeFromSuperlayer]; [self->selectedWidgetView.crossMarkLayer removeFromSuperlayer]; for (UIView *subview in self.view.subviews) { - // 检查子视图是否是特定类型的实例 if ([subview isKindOfClass:[OnScreenWidgetView class]]) { - // 如果是,就添加到将要被移除的数组中 [subview removeFromSuperview]; } } @@ -111,7 +108,7 @@ widgetView.stickIndicatorOffset = buttonState.stickIndicatorOffset; widgetView.minStickOffset = buttonState.minStickOffset; // Add the widgetView to the view controller's view - [self.view addSubview:widgetView]; + [self.view insertSubview:widgetView belowSubview:self.widgetSizeStack]; buttonState.position = [self denormalizeWidgetPosition:buttonState.position]; [widgetView setLocationWithPosition:buttonState.position]; [widgetView resizeWidgetView]; // resize must be called after relocation @@ -128,17 +125,9 @@ self.OnScreenWidgetViews = [[NSMutableSet alloc] init]; // will be revised to read persisted data , somewhere else [OSCProfilesManager setOnScreenWidgetViewsSet:self.OnScreenWidgetViews]; // pass the keyboard button dict to profiles manager - isToolbarHidden = NO; // keeps track if the toolbar is hidden up above the screen so that we know whether to hide or show it when the user taps the toolbar's hide/show button + //isToolbarHidden = NO; // keeps track if the toolbar is hidden up above the screen so that we know whether to hide or show it when the user taps the toolbar's hide/show button _quickSwitchEnabled = false; - widgetSizeSliderLabel = [[UILabel alloc] init]; - widgetHeightSliderLabel = [[UILabel alloc] init]; - widgetAlphaSliderLabel = [[UILabel alloc] init]; - widgetBorderWidthSliderLabel = [[UILabel alloc] init]; - sensitivitySliderLabel = [[UILabel alloc] init]; - stickIndicatorOffsetSliderLabel = [[UILabel alloc] init]; - stickIndicatorOffsetExplain = [[UILabel alloc] init]; - /* add curve to bottom of chevron tab view */ UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:self.chevronView.bounds byRoundingCorners:(UIRectCornerBottomLeft | UIRectCornerBottomRight) cornerRadii:CGSizeMake(10.0, 10.0)]; CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init]; @@ -197,7 +186,11 @@ selector:@selector(widgetViewTapped:) name:@"OnScreenWidgetViewSelected" object:nil]; - + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(handleMovingOnScreenWidgetNotification:) + name:@"OnScreenWidgetMovedByTouch" + object:nil]; @@ -226,6 +219,7 @@ }]; }]; }); + trashCanStoryBoardColor = trashCanButton.tintColor; } @@ -233,11 +227,13 @@ - (void) viewDidAppear:(BOOL)animated { OnScreenWidgetView.editMode = true; selectedWidgetView = nil; + widgetPanelStoredCenter = self.widgetPanelStack.center; [super viewDidAppear:animated]; } - (void) viewWillAppear:(BOOL)animated{ - self.navigationController.navigationBar.hidden = _quickSwitchEnabled; + OnScreenWidgetView.editMode = true; + [self handleMissingToolBarIcon:toolbarRootView]; [self profileRefresh]; } @@ -261,7 +257,6 @@ [UIView animateWithDuration:0.2 animations:^{ // animates toolbar up and off screen toolbarTopConstraint.constant -= self.toolbarRootView.frame.size.height; [self.view layoutIfNeeded]; - } completion:^(BOOL finished) { if (finished) { @@ -553,16 +548,19 @@ newWidget.stickIndicatorOffset = widget.stickIndicatorOffset; newWidget.minStickOffset = [widgetInitParams[@"minStickOffsetString"] floatValue]; // Add the widgetView to the view controller's view - [self.view addSubview:newWidget]; - if(createNew) [newWidget setLocationWithPosition:CGPointMake(50, 50)]; + [self.view insertSubview:newWidget belowSubview:self.widgetSizeStack]; + + if(createNew) [newWidget setLocationWithPosition:CGPointMake(90, 130)]; else [newWidget setLocationWithPosition:widget.center]; [newWidget resizeWidgetView]; // resize must be called after relocation [newWidget adjustTransparencyWithAlpha:widget.backgroundAlpha]; [newWidget adjustBorderWithWidth:widget.borderWidth]; - if(!createNew) [self.OnScreenWidgetViews removeObject:widget]; [self.OnScreenWidgetViews addObject:newWidget]; - if(!createNew) [widget removeFromSuperview]; self->selectedWidgetView = newWidget; + if(!createNew){ + [self.OnScreenWidgetViews removeObject:widget]; + [widget removeFromSuperview]; + } } @@ -574,8 +572,8 @@ widgetView.minStickOffset = [widgetInitParams[@"minStickOffsetString"] floatValue]; [self.OnScreenWidgetViews addObject:widgetView]; // Add the widgetView to the view controller's view - [self.view addSubview:widgetView]; - [widgetView setLocationWithPosition:CGPointMake(50, 50)]; + [self.view insertSubview:widgetView belowSubview:self.widgetSizeStack]; + [widgetView setLocationWithPosition:CGPointMake(90, 130)]; [widgetView resizeWidgetView]; } @@ -598,6 +596,13 @@ } } +- (void)autoFitView:(UIView* )view{ + CGSize fittingSize = [view systemLayoutSizeFittingSize:UILayoutFittingCompressedSize]; + CGRect newFrame = view.frame; + newFrame.size = fittingSize; + view.frame = newFrame; +} + - (void)widgetViewTapped: (NSNotification *)notification{ // receive the selected widgetView obj passed from the notification OnScreenWidgetView* widgetView = (OnScreenWidgetView* )notification.object; @@ -615,11 +620,14 @@ bool showSensitivityFactorSlider = selectedWidgetView.hasSensitivityTweak; bool showStickIndicatorOffsetSlider = selectedWidgetView.hasStickIndicator; - self.sensitivityFactorSlider.hidden = self->sensitivitySliderLabel.hidden = !showSensitivityFactorSlider; - self.stickIndicatorOffsetSlider.hidden = self->stickIndicatorOffsetExplain.hidden = self->stickIndicatorOffsetSliderLabel.hidden = !showStickIndicatorOffsetSlider; + + self.sensitivityStack.hidden = !showSensitivityFactorSlider; + self.stickIndicatorOffsetStack.hidden = !showStickIndicatorOffsetSlider; + [self autoFitView:self.widgetPanelStack]; + if(showSensitivityFactorSlider){ - [self.sensitivityFactorSlider setValue:self->selectedWidgetView.sensitivityFactor]; - [sensitivitySliderLabel setText:[LocalizationHelper localizedStringForKey:@"Sensitivity: %.2f", self->selectedWidgetView.sensitivityFactor]]; + [self.sensitivitySlider setValue:self->selectedWidgetView.sensitivityFactor]; + [self.sensitivityLabel setText:[LocalizationHelper localizedStringForKey:@"Sensitivity: %.2f", self->selectedWidgetView.sensitivityFactor]]; } if(showStickIndicatorOffsetSlider){ // illustrating the indicator offset, @@ -628,13 +636,13 @@ selectedWidgetView.touchBeganLocation = CGPointMake(CGRectGetWidth(selectedWidgetView.frame)/2, CGRectGetHeight(selectedWidgetView.frame)/4); [selectedWidgetView showStickIndicator];// this will create the indicator CAShapeLayers [self.stickIndicatorOffsetSlider setValue:self->selectedWidgetView.stickIndicatorOffset]; - [stickIndicatorOffsetSliderLabel setText:[LocalizationHelper localizedStringForKey:@"Indicator Offset: %.2f", self->selectedWidgetView.stickIndicatorOffset]]; + [self.stickIndicatorOffsetLabel setText:[LocalizationHelper localizedStringForKey:@"Indicator Offset: %.0f", self->selectedWidgetView.stickIndicatorOffset]]; [self->selectedWidgetView updateStickIndicator]; } - [widgetSizeSliderLabel setText:[LocalizationHelper localizedStringForKey:@"Widget Size: %.2f", self->selectedWidgetView.widthFactor]]; - [widgetHeightSliderLabel setText:[LocalizationHelper localizedStringForKey:@"Widget Height: %.2f", self->selectedWidgetView.heightFactor]]; - [widgetAlphaSliderLabel setText:[LocalizationHelper localizedStringForKey:@"Widget Alpha: %.2f", self->selectedWidgetView.backgroundAlpha]]; - [widgetBorderWidthSliderLabel setText:[LocalizationHelper localizedStringForKey:@"Border Width: %.2f", self->selectedWidgetView.borderWidth]]; + [self.widgetSizeLabel setText:[LocalizationHelper localizedStringForKey:@"Size: %.2f", self->selectedWidgetView.widthFactor]]; + [self.widgetHeightLabel setText:[LocalizationHelper localizedStringForKey:@"Height: %.2f", self->selectedWidgetView.heightFactor]]; + [self.widgetAlphaLabel setText:[LocalizationHelper localizedStringForKey:@"Alpha: %.2f", self->selectedWidgetView.backgroundAlpha]]; + [self.widgetBorderWidthLabel setText:[LocalizationHelper localizedStringForKey:@"Border Width: %.2f", self->selectedWidgetView.borderWidth]]; } - (void)setControllerCALayerSliderValues: (NSNotification *)notification{ @@ -644,11 +652,9 @@ [self->selectedWidgetView.crossMarkLayer removeFromSuperlayer]; self->widgetViewSelected = false; self->selectedWidgetView = nil; - self->stickIndicatorOffsetExplain.hidden = true; - self->stickIndicatorOffsetSliderLabel.hidden = true; - self.stickIndicatorOffsetSlider.hidden = true; - self->sensitivitySliderLabel.hidden = true; - self.sensitivityFactorSlider.hidden = true; + + self.stickIndicatorOffsetStack.hidden = true; + self.sensitivityStack.hidden = true; self->controllerLayerSelected = true; self->selectedControllerLayer = controllerLayer; @@ -661,14 +667,14 @@ CGFloat alpha = [self.layoutOSC getControllerLayerOpacity:controllerLayer]; [self.widgetAlphaSlider setValue:alpha]; - [widgetSizeSliderLabel setText:[LocalizationHelper localizedStringForKey:@"Widget Size: %.2f", sizeFactor]]; - [widgetHeightSliderLabel setText:[LocalizationHelper localizedStringForKey:@"Widget Height: %.2f", sizeFactor]]; - [widgetAlphaSliderLabel setText:[LocalizationHelper localizedStringForKey:@"Widget Alpha: %.2f", alpha]]; + [self.widgetSizeLabel setText:[LocalizationHelper localizedStringForKey:@"Size: %.2f", sizeFactor]]; + [self.widgetHeightLabel setText:[LocalizationHelper localizedStringForKey:@"Height: %.2f", sizeFactor]]; + [self.widgetAlphaLabel setText:[LocalizationHelper localizedStringForKey:@"Alpha: %.2f", alpha]]; } - (void)widgetSizeSliderMoved{ - [widgetSizeSliderLabel setText:[LocalizationHelper localizedStringForKey:@"Widget Size: %.2f", self.widgetSizeSlider.value]]; - [widgetHeightSliderLabel setText:[LocalizationHelper localizedStringForKey:@"Widget Height: %.2f", self.widgetSizeSlider.value]]; // resizing the whole button + [self.widgetSizeLabel setText:[LocalizationHelper localizedStringForKey:@"Size: %.2f", self.widgetSizeSlider.value]]; + [self.widgetHeightLabel setText:[LocalizationHelper localizedStringForKey:@"Height: %.2f", self.widgetSizeSlider.value]]; // resizing the whole button [self.widgetHeightSlider setValue: self.widgetSizeSlider.value]; if(self->selectedWidgetView != nil && self->widgetViewSelected){ @@ -683,7 +689,7 @@ } - (void)widgetHeightSliderMoved{ - [widgetHeightSliderLabel setText:[LocalizationHelper localizedStringForKey:@"Widget Height: %.2f", self.widgetHeightSlider.value]]; + [self.widgetHeightLabel setText:[LocalizationHelper localizedStringForKey:@"Height: %.2f", self.widgetHeightSlider.value]]; if(self->selectedWidgetView != nil && self->widgetViewSelected){ self->selectedWidgetView.translatesAutoresizingMaskIntoConstraints = true; // this is mandatory to prevent unexpected key view location change if([self->selectedWidgetView.shape isEqualToString:@"round"]) return; // don't change height for round buttons, except for dPad buttons which are in rectangle shape @@ -693,7 +699,7 @@ } - (void)widgetAlphaSliderMoved{ - [widgetAlphaSliderLabel setText:[LocalizationHelper localizedStringForKey:@"Widget Alpha: %.2f", self.widgetAlphaSlider.value]]; + [self.widgetAlphaLabel setText:[LocalizationHelper localizedStringForKey:@"Alpha: %.2f", self.widgetAlphaSlider.value]]; if(self->selectedWidgetView != nil && self->widgetViewSelected){ [self->selectedWidgetView adjustTransparencyWithAlpha:self.widgetAlphaSlider.value]; } @@ -705,7 +711,7 @@ } - (void)widgetBorderWidthSliderMoved{ - [widgetBorderWidthSliderLabel setText:[LocalizationHelper localizedStringForKey:@"Border Width: %.2f", self.widgetBorderWidthSlider.value]]; + [self.widgetBorderWidthLabel setText:[LocalizationHelper localizedStringForKey:@"Border Width: %.2f", self.widgetBorderWidthSlider.value]]; if(self->selectedWidgetView != nil && self->widgetViewSelected){ [self->selectedWidgetView adjustBorderWithWidth:self.widgetBorderWidthSlider.value]; } @@ -713,13 +719,13 @@ } - (void)sensitivitySliderMoved{ - [sensitivitySliderLabel setText:[LocalizationHelper localizedStringForKey:@"Sensitivity: %.2f", self.sensitivityFactorSlider.value]]; - if(self->selectedWidgetView != nil && self->widgetViewSelected) self->selectedWidgetView.sensitivityFactor = self.sensitivityFactorSlider.value; + [self.sensitivityLabel setText:[LocalizationHelper localizedStringForKey:@"Sensitivity: %.2f", self.sensitivitySlider.value]]; + if(self->selectedWidgetView != nil && self->widgetViewSelected) self->selectedWidgetView.sensitivityFactor = self.sensitivitySlider.value; return; } - (void)stickIndicatorOffsetSliderMoved{ - [stickIndicatorOffsetSliderLabel setText:[LocalizationHelper localizedStringForKey:@"Indicator Offset: %.2f", self.stickIndicatorOffsetSlider.value]]; + [self.stickIndicatorOffsetLabel setText:[LocalizationHelper localizedStringForKey:@"Indicator Offset: %.0f", self.stickIndicatorOffsetSlider.value]]; if(self->selectedWidgetView != nil && self->widgetViewSelected){ self->selectedWidgetView.stickIndicatorOffset = self.stickIndicatorOffsetSlider.value; [self->selectedWidgetView updateStickIndicator]; @@ -732,158 +738,93 @@ [selectedWidgetView showStickIndicator]; } -- (void)setupProfileLableAndSliders{ - //if(_quickSwitchEnabled) return; - // self.currentProfileLabel.frame = CGRectMake(0, 0, 180, 35); - // CGFloat profileLabelXPosition = self.view.bounds.size.width - self.currentProfileLabel.frame.size.width - 20; - CGFloat sliderXPosition = (self.view.bounds.size.width - self.widgetSizeSlider.frame.size.width)/2 ; - CGFloat profileLabelXPosition = self.view.bounds.size.width/2 + (self.widgetSizeSlider.frame.size.width)/2 + 8; - // Set the label's frame with the calculated x-position - self.currentProfileLabel.frame = CGRectMake(profileLabelXPosition, self.currentProfileLabel.frame.origin.y, self.currentProfileLabel.frame.size.width, self.currentProfileLabel.frame.size.height); - self.currentProfileLabel.hidden = _quickSwitchEnabled; // Show Current Profile display - if (@available(iOS 13.0, *)) { - self.currentProfileLabel.textAlignment = NSTextAlignmentNatural; - self.currentProfileLabel.numberOfLines = 2; - } else { - // Fallback on earlier versions +- (void)handleMissingToolBarIcon:(UIView *)view { + for (UIView *subview in view.subviews) { + if ([subview isKindOfClass:[UIButton class]]) { + UIButton *button = (UIButton *)subview; + if(!button.imageView.image){ + NSLog(@"missing image %d", button==_saveButton); + button.titleLabel.font = [UIFont systemFontOfSize:18 weight:UIFontWeightMedium]; + if(button==_exitButton) [button setTitle:[LocalizationHelper localizedStringForKey:@"Exit"] forState:UIControlStateNormal]; + if(button==trashCanButton) [button setTitle:[LocalizationHelper localizedStringForKey:@"Del"] forState:UIControlStateNormal]; + if(button==undoButton) [button setTitle:[LocalizationHelper localizedStringForKey:@"Undo"] forState:UIControlStateNormal]; + if(button==_saveButton) [button setTitle:[LocalizationHelper localizedStringForKey:@"Save"] forState:UIControlStateNormal]; + if(button==_loadButton) [button setTitle:[LocalizationHelper localizedStringForKey:@"Load"] forState:UIControlStateNormal]; + if(button==_addButton) [button setTitle:[LocalizationHelper localizedStringForKey:@"Add"] forState:UIControlStateNormal]; + if(button==_editButton) [button setTitle:[LocalizationHelper localizedStringForKey:@"Edit"] forState:UIControlStateNormal]; + } + } + [self handleMissingToolBarIcon:subview]; + } +} + + +- (void)setupWidgetPanel{ + //[self handleMissingToolBarIcon]; + self.widgetPanelStack.hidden = NO; + self.widgetPanelStack.layoutMargins = UIEdgeInsetsMake(10, 10, 10, 10); + self.widgetPanelStack.layoutMarginsRelativeArrangement = YES; + self.widgetPanelStack.layer.cornerRadius = 16; + self.widgetPanelStack.clipsToBounds = YES; + + /* + [NSLayoutConstraint activateConstraints:@[ + [self.widgetPanelStack.centerXAnchor constraintEqualToAnchor:self.view.centerXAnchor constant:0], + [self.widgetPanelStack.topAnchor constraintEqualToAnchor:self.view.topAnchor constant:120], + ]]; + */ + + self.widgetPanelStack.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.5]; + + [self.currentProfileLabel setText:[LocalizationHelper localizedStringForKey:@"Profile: %@",[profilesManager getSelectedProfile].name]]; + self.currentProfileLabel.layer.cornerRadius = 12; + self.currentProfileLabel.clipsToBounds = YES; + + self.widgetSizeStack.userInteractionEnabled = YES; + for(UIView* view in _widgetPanelStack.subviews){ + view.userInteractionEnabled = YES; + if([view isKindOfClass:[UILabel class]]){ + UILabel* label = (UILabel* )view; + label.font = [UIFont systemFontOfSize:18]; + label.textColor = [UIColor whiteColor]; + } } - [self.currentProfileLabel setText:[LocalizationHelper localizedStringForKey:@"Profile: %@",[profilesManager getSelectedProfile].name]]; // display current profile name when profile is being refreshed. - // button size sliders - self.widgetSizeSlider.hidden = _quickSwitchEnabled; - self.widgetSizeSlider.frame = CGRectMake(sliderXPosition, self.widgetSizeSlider.frame.origin.y, self.widgetSizeSlider.frame.size.width, self.widgetSizeSlider.frame.size.height); [self.widgetSizeSlider addTarget:self action:@selector(widgetSizeSliderMoved) forControlEvents:(UIControlEventValueChanged)]; - widgetSizeSliderLabel.text = [LocalizationHelper localizedStringForKey:@"Widget Size"]; - widgetSizeSliderLabel.font = [UIFont systemFontOfSize:18]; - widgetSizeSliderLabel.textColor = [UIColor whiteColor]; - widgetSizeSliderLabel.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.5]; - widgetSizeSliderLabel.translatesAutoresizingMaskIntoConstraints = NO; // Disable autoresizing mask for Auto Layout - // Add slider and label to the view - [self.view addSubview:widgetSizeSliderLabel]; - // Use Auto Layout to position the label relative to the slider - [NSLayoutConstraint activateConstraints:@[ - // Position the label to the left of the slider - [widgetSizeSliderLabel.trailingAnchor constraintEqualToAnchor:self.widgetSizeSlider.leadingAnchor constant:-10], - // Align vertically with the slider - [widgetSizeSliderLabel.centerYAnchor constraintEqualToAnchor:self.widgetSizeSlider.centerYAnchor] - ]]; - widgetSizeSliderLabel.hidden = _quickSwitchEnabled; + self.widgetSizeLabel.text = [LocalizationHelper localizedStringForKey:@"Size"]; + self.widgetSizeStack.hidden = _quickSwitchEnabled; - // button height sliders - self.widgetHeightSlider.hidden = _quickSwitchEnabled; - self.widgetHeightSlider.frame = CGRectMake(sliderXPosition, self.widgetHeightSlider.frame.origin.y, self.widgetHeightSlider.frame.size.width, self.widgetHeightSlider.frame.size.height); [self.widgetHeightSlider addTarget:self action:@selector(widgetHeightSliderMoved) forControlEvents:(UIControlEventValueChanged)]; - // button height label - widgetHeightSliderLabel.text = [LocalizationHelper localizedStringForKey:@"Widget Height"]; - widgetHeightSliderLabel.font = [UIFont systemFontOfSize:18]; - widgetHeightSliderLabel.textColor = [UIColor whiteColor]; - widgetHeightSliderLabel.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.5]; - widgetHeightSliderLabel.translatesAutoresizingMaskIntoConstraints = NO; // Disable autoresizing mask for Auto Layout - // Add slider and label to the view - [self.view addSubview:widgetHeightSliderLabel]; - // Use Auto Layout to position the label relative to the slider - [NSLayoutConstraint activateConstraints:@[ - // Position the label to the left of the slider - [widgetHeightSliderLabel.trailingAnchor constraintEqualToAnchor:self.widgetHeightSlider.leadingAnchor constant:-10], - // Align vertically with the slider - [widgetHeightSliderLabel.centerYAnchor constraintEqualToAnchor:self.widgetHeightSlider.centerYAnchor] - ]]; - widgetHeightSliderLabel.hidden = _quickSwitchEnabled; - // button alpha label - self.widgetAlphaSlider.hidden = _quickSwitchEnabled; - self.widgetAlphaSlider.frame = CGRectMake(sliderXPosition, self.widgetAlphaSlider.frame.origin.y, self.widgetAlphaSlider.frame.size.width, self.widgetAlphaSlider.frame.size.height); + self.widgetHeightLabel.text = [LocalizationHelper localizedStringForKey:@"Height"]; + self.widgetHeightStack.hidden = _quickSwitchEnabled; + [self.widgetAlphaSlider addTarget:self action:@selector(widgetAlphaSliderMoved) forControlEvents:(UIControlEventValueChanged)]; - widgetAlphaSliderLabel.text = [LocalizationHelper localizedStringForKey:@"Widget Alpha"]; - widgetAlphaSliderLabel.font = [UIFont systemFontOfSize:18]; - widgetAlphaSliderLabel.textColor = [UIColor whiteColor]; - widgetAlphaSliderLabel.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.5]; - widgetAlphaSliderLabel.translatesAutoresizingMaskIntoConstraints = NO; // Disable autoresizing mask for Auto Layout - // Add slider and label to the view - [self.view addSubview:widgetAlphaSliderLabel]; - // Use Auto Layout to position the label relative to the slider - [NSLayoutConstraint activateConstraints:@[ - // Position the label to the left of the slider - [widgetAlphaSliderLabel.trailingAnchor constraintEqualToAnchor:self.widgetAlphaSlider.leadingAnchor constant:-10], - // Align vertically with the slider - [widgetAlphaSliderLabel.centerYAnchor constraintEqualToAnchor:self.widgetAlphaSlider.centerYAnchor] - ]]; - widgetAlphaSliderLabel.hidden = _quickSwitchEnabled; - - - // border Width slider - self.widgetBorderWidthSlider.hidden = _quickSwitchEnabled; - self.widgetBorderWidthSlider.frame = CGRectMake(CGRectGetMaxX(self.currentProfileLabel.frame)-self.widgetBorderWidthSlider.frame.size.width, self.widgetBorderWidthSlider.frame.origin.y, self.widgetBorderWidthSlider.frame.size.width, self.widgetBorderWidthSlider.frame.size.height); - + self.widgetAlphaLabel.text = [LocalizationHelper localizedStringForKey:@"Alpha"]; + [self.widgetBorderWidthSlider addTarget:self action:@selector(widgetBorderWidthSliderMoved) forControlEvents:(UIControlEventValueChanged)]; - widgetBorderWidthSliderLabel.text = [LocalizationHelper localizedStringForKey:@"Border Width"]; - widgetBorderWidthSliderLabel.font = [UIFont systemFontOfSize:18]; - widgetBorderWidthSliderLabel.textColor = [UIColor whiteColor]; - widgetBorderWidthSliderLabel.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.5]; - widgetBorderWidthSliderLabel.translatesAutoresizingMaskIntoConstraints = NO; // Disable autoresizing mask for Auto Layout - [self.view addSubview:widgetBorderWidthSliderLabel]; - [NSLayoutConstraint activateConstraints:@[ - // Position the label to the left of the slider - [widgetBorderWidthSliderLabel.trailingAnchor constraintEqualToAnchor:self.widgetBorderWidthSlider.leadingAnchor constant:-10], - // Align vertically with the slider - [widgetBorderWidthSliderLabel.centerYAnchor constraintEqualToAnchor:self.widgetBorderWidthSlider.centerYAnchor] - ]]; - widgetBorderWidthSliderLabel.hidden = _quickSwitchEnabled; - - - - // sensitivity slider - self.sensitivityFactorSlider.hidden = YES; - self.sensitivityFactorSlider.frame = CGRectMake(sliderXPosition, self.sensitivityFactorSlider.frame.origin.y, self.sensitivityFactorSlider.frame.size.width, self.sensitivityFactorSlider.frame.size.height); - [self.sensitivityFactorSlider addTarget:self action:@selector(sensitivitySliderMoved) forControlEvents:(UIControlEventValueChanged)]; - sensitivitySliderLabel.text = [LocalizationHelper localizedStringForKey:@"Sensitivity"]; - sensitivitySliderLabel.font = [UIFont systemFontOfSize:18]; - sensitivitySliderLabel.textColor = [UIColor whiteColor]; - sensitivitySliderLabel.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.5]; - sensitivitySliderLabel.translatesAutoresizingMaskIntoConstraints = NO; // Disable autoresizing mask for Auto Layout - // Add slider and label to the view - [self.view addSubview:sensitivitySliderLabel]; - // Use Auto Layout to position the label relative to the slider - [NSLayoutConstraint activateConstraints:@[ - // Position the label to the left of the slider - [sensitivitySliderLabel.trailingAnchor constraintEqualToAnchor:self.sensitivityFactorSlider.leadingAnchor constant:-10], - // Align vertically with the slider - [sensitivitySliderLabel.centerYAnchor constraintEqualToAnchor:self.sensitivityFactorSlider.centerYAnchor] - ]]; - sensitivitySliderLabel.hidden = self.sensitivityFactorSlider.hidden; - + self.widgetBorderWidthLabel.text = [LocalizationHelper localizedStringForKey:@"Border Width"]; + self.borderWidthAlphaStack.hidden = _quickSwitchEnabled; + + [self.sensitivitySlider addTarget:self action:@selector(sensitivitySliderMoved) forControlEvents:(UIControlEventValueChanged)]; + self.sensitivityLabel.text = [LocalizationHelper localizedStringForKey:@"Sensitivity"]; + self.sensitivityStack.hidden = YES; // stick indicator offset slider - self.stickIndicatorOffsetSlider.hidden = YES; - self.stickIndicatorOffsetSlider.frame = CGRectMake(sliderXPosition, self.stickIndicatorOffsetSlider.frame.origin.y, self.stickIndicatorOffsetSlider.frame.size.width, self.stickIndicatorOffsetSlider.frame.size.height); // make this label bigger to show some tips + //self.stickIndicatorOffsetSlider.hidden = YES; [self.stickIndicatorOffsetSlider addTarget:self action:@selector(stickIndicatorOffsetSliderMoved) forControlEvents:(UIControlEventValueChanged)]; - stickIndicatorOffsetSliderLabel.text = [LocalizationHelper localizedStringForKey:@"Indicator Offset"]; - stickIndicatorOffsetSliderLabel.font = [UIFont systemFontOfSize:18]; - stickIndicatorOffsetSliderLabel.textColor = [UIColor whiteColor]; - stickIndicatorOffsetSliderLabel.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.5]; - stickIndicatorOffsetSliderLabel.translatesAutoresizingMaskIntoConstraints = NO; // Disable autoresizing mask for Auto Layout - // tips for stick indicator - stickIndicatorOffsetExplain.text = [LocalizationHelper localizedStringForKey:@"Ball: assumed touch point. Cross: indicator location"]; - //stickIndicatorOffsetExplain.frame = CGRectMake(sliderXPosition, self.stickIndicatorOffsetSlider.frame.origin.y + self.stickIndicatorOffsetSlider.frame.size.height, self.stickIndicatorOffsetSlider.frame.size.width, self.stickIndicatorOffsetSlider.frame.size.height); // label bigger show some tips - stickIndicatorOffsetExplain.font = [UIFont systemFontOfSize:18]; - stickIndicatorOffsetExplain.textColor = [UIColor whiteColor]; - stickIndicatorOffsetExplain.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.5]; - stickIndicatorOffsetExplain.translatesAutoresizingMaskIntoConstraints = NO; // Disable autoresizing mask for Auto Layout - // Add slider and label to the view - [self.view addSubview:stickIndicatorOffsetSliderLabel]; - [self.view addSubview:stickIndicatorOffsetExplain]; - // Use Auto Layout to position the label relative to the slider - [NSLayoutConstraint activateConstraints:@[ - // Position the label to the left of the slider - [stickIndicatorOffsetSliderLabel.trailingAnchor constraintEqualToAnchor:self.stickIndicatorOffsetSlider.leadingAnchor constant:-10], - // Align vertically with the slider - [stickIndicatorOffsetSliderLabel.centerYAnchor constraintEqualToAnchor:self.stickIndicatorOffsetSlider.centerYAnchor], - // Position the explain label - [stickIndicatorOffsetExplain.centerXAnchor constraintEqualToAnchor:self.stickIndicatorOffsetSlider.leadingAnchor constant:-10], - [stickIndicatorOffsetExplain.topAnchor constraintEqualToAnchor:self.stickIndicatorOffsetSlider.bottomAnchor] - ]]; - stickIndicatorOffsetSliderLabel.hidden = stickIndicatorOffsetExplain.hidden = self.stickIndicatorOffsetSlider.hidden; + self.stickIndicatorOffsetLabel.text = [LocalizationHelper localizedStringForKey:@"Indicator Offset"]; + self.stickIndicatorOffsetStack.hidden = YES; + + [self.view bringSubviewToFront:self.toolbarRootView]; + [self.view insertSubview:self.widgetSizeStack belowSubview:self.toolbarRootView]; + self.widgetSizeStack.translatesAutoresizingMaskIntoConstraints = YES; + CGRect frame = CGRectMake(0, 0, self.widgetSizeStack.frame.size.width, self.widgetSizeStack.frame.size.height); + //frame.origin = CGPointMake(self.view.bounds.size.width/2, 100); + frame.origin = CGPointMake(self.view.bounds.size.width/2-self.widgetSizeStack.frame.size.width/2, 100); + self.widgetSizeStack.frame = frame; + [self autoFitView:self.widgetPanelStack]; } - (void)handleProfileTablViewDismiss{ @@ -904,7 +845,7 @@ } // setup: current profile lable, button width slider, button height slider & button alpha slider - [self setupProfileLableAndSliders]; + [self setupWidgetPanel]; //initialiaze _oscProfilesTableViewController self->_oscProfilesTableViewController = [storyboard instantiateViewControllerWithIdentifier:@"OSCProfilesTableViewController"]; @@ -947,20 +888,8 @@ [self OSCLayoutChanged]; // fades the 'Undo Button' out }; - self.currentProfileLabel.hidden = YES; // Hide Current Profile display before entering the profile table view - self.widgetSizeSlider.hidden = YES; - self.widgetHeightSlider.hidden = YES; - self.widgetAlphaSlider.hidden = YES; - self.widgetBorderWidthSlider.hidden = YES; - self.sensitivityFactorSlider.hidden = YES; - self.stickIndicatorOffsetSlider.hidden = YES; - widgetSizeSliderLabel.hidden = YES; - widgetHeightSliderLabel.hidden = YES; - widgetAlphaSliderLabel.hidden = YES; - widgetBorderWidthSliderLabel.hidden = YES; - sensitivitySliderLabel.hidden = YES; - stickIndicatorOffsetSliderLabel.hidden = YES; - stickIndicatorOffsetExplain.hidden = YES; + + self.widgetPanelStack.hidden = YES; [self->selectedWidgetView.stickBallLayer removeFromSuperlayer]; [self->selectedWidgetView.crossMarkLayer removeFromSuperlayer]; @@ -977,7 +906,37 @@ #pragma mark - Touch +- (void) handleMovingOnScreenWidgetNotification: (NSNotification *)notification{ + OnScreenWidgetView* widget = notification.object; + [self.view bringSubviewToFront:widget]; + trashCanButton.tintColor = [self layerOverlapWithTrashcanButton:widget.layer] ? [UIColor redColor] : trashCanStoryBoardColor; +} + + +- (BOOL) widgetPanelTouched:(UITouch *)touch{ + CGPoint touchPoint = [touch locationInView:_widgetPanelStack]; + UIView *touchedView = [_widgetPanelStack hitTest:touchPoint withEvent:nil]; + return touchedView != nil; +} + +- (void) handleWidgetPanelMove:(UITouch *)touch{ + if(!widgetPanelMovedByTouch) return; + CGPoint currentLocation = [touch locationInView:self.view]; + CGFloat offsetX = currentLocation.x - latestTouchLocation.x; + CGFloat offsetY = currentLocation.y - latestTouchLocation.y; + _widgetPanelStack.center = CGPointMake(_widgetPanelStack.center.x+offsetX, _widgetPanelStack.center.y+offsetY); + latestTouchLocation = currentLocation; + widgetPanelStoredCenter = _widgetPanelStack.center; +} + - (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { + + UITouch* touch = touches.anyObject; + widgetPanelMovedByTouch = [self widgetPanelTouched:touch]; + if(widgetPanelMovedByTouch){ + latestTouchLocation = [touch locationInView:self.view]; + } + for (UITouch* touch in touches) { CGPoint touchLocation = [touch locationInView:self.view]; @@ -996,25 +955,16 @@ } - (void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { - // for OnScreenWidgets: - + [self handleWidgetPanelMove:touches.anyObject]; + // -------- for OSC buttons [self.layoutOSC touchesMoved:touches withEvent:event]; if ([self.layoutOSC isLayer:self.layoutOSC.layerBeingDragged hoveringOverButton:trashCanButton]) { // check if user is dragging around a button and hovering it over the trash can button trashCanButton.tintColor = [UIColor redColor]; } - else { - trashCanButton.tintColor = [UIColor colorWithRed:171.0/255.0 green:157.0/255.0 blue:255.0/255.0 alpha:1]; - } - - // -------- for keyboard Buttons - UITouch *touch = [touches anyObject]; // Get the first touch in the set - if([self touchWithinTashcanButton:touch]){ - trashCanButton.tintColor = [UIColor redColor]; - } - else trashCanButton.tintColor = [UIColor colorWithRed:171.0/255.0 green:157.0/255.0 blue:255.0/255.0 alpha:1]; + else trashCanButton.tintColor = trashCanStoryBoardColor; } - (bool)touchWithinTashcanButton:(UITouch* )touch { @@ -1028,24 +978,34 @@ return ret; } +- (bool)layerOverlapWithTrashcanButton:(CALayer* )layer{ + CALayer *commonLayer = self.view.layer; // 假设它们在同一个 superview 下 + + CGRect rect1 = [layer convertRect:layer.bounds toLayer:commonLayer]; + CGRect rect2 = [trashCanButton.layer convertRect:trashCanButton.layer.bounds toLayer:commonLayer]; + return CGRectIntersectsRect(rect1, rect2); +} + - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { // removing keyboard buttons objs UITouch *touch = [touches anyObject]; // Get the first touch in the set - if([self touchWithinTashcanButton:touch]){ - if(self->selectedWidgetView != nil){ - [self->selectedWidgetView removeFromSuperview]; - [self.OnScreenWidgetViews removeObject:self->selectedWidgetView]; - [selectedWidgetView.stickBallLayer removeFromSuperlayer]; - [selectedWidgetView.crossMarkLayer removeFromSuperlayer]; - [selectedWidgetView.buttonDownVisualEffectLayer removeFromSuperlayer]; - } + + if(selectedWidgetView) [self.view insertSubview:selectedWidgetView belowSubview:_widgetPanelStack]; + + + if(!isToolbarHidden && self->selectedWidgetView != nil && [self layerOverlapWithTrashcanButton:selectedWidgetView.layer]){ + [self->selectedWidgetView removeFromSuperview]; + [self.OnScreenWidgetViews removeObject:self->selectedWidgetView]; + [selectedWidgetView.stickBallLayer removeFromSuperlayer]; + [selectedWidgetView.crossMarkLayer removeFromSuperlayer]; + [selectedWidgetView.buttonDownVisualEffectLayer removeFromSuperlayer]; } //removing OSC buttons - if (self.layoutOSC.layerBeingDragged != nil && + if (!isToolbarHidden && self.layoutOSC.layerBeingDragged != nil && [self.layoutOSC isLayer:self.layoutOSC.layerBeingDragged hoveringOverButton:trashCanButton]) { // check if user wants to throw OSC button into the trash can // here we're going to delete something @@ -1078,7 +1038,8 @@ } - trashCanButton.tintColor = [UIColor colorWithRed:171.0/255.0 green:157.0/255.0 blue:255.0/255.0 alpha:1]; + trashCanButton.tintColor = trashCanStoryBoardColor; + widgetPanelMovedByTouch = false; } diff --git a/Limelight/mul.lproj/iPad.xcstrings b/Limelight/mul.lproj/iPad.xcstrings index a75604c1..0bbddad4 100644 --- a/Limelight/mul.lproj/iPad.xcstrings +++ b/Limelight/mul.lproj/iPad.xcstrings @@ -1131,7 +1131,7 @@ }, "cRV-Xw-CVi.text" : { "comment" : "Class = \"UILabel\"; text = \"Profile:\"; ObjectID = \"cRV-Xw-CVi\";", - "extractionState" : "extracted_with_value", + "extractionState" : "stale", "localizations" : { "en" : { "stringUnit" : { @@ -1537,18 +1537,6 @@ } } }, - "fKN-ja-TRi.normalTitle" : { - "comment" : "Class = \"UIButton\"; normalTitle = \"Add\"; ObjectID = \"fKN-ja-TRi\";", - "extractionState" : "extracted_with_value", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "new", - "value" : "Add" - } - } - } - }, "FwK-oG-vuz.text" : { "comment" : "Class = \"UILabel\"; text = \"Reverse Wheel Direction for Physical Mouse \"; ObjectID = \"FwK-oG-vuz\";", "extractionState" : "extracted_with_value", @@ -1969,6 +1957,18 @@ } } }, + "iel-xl-xd9.text" : { + "comment" : "Class = \"UILabel\"; text = \"Profile:\"; ObjectID = \"iel-xl-xd9\";", + "extractionState" : "extracted_with_value", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Profile:" + } + } + } + }, "IvI-tw-APj.text" : { "comment" : "Class = \"UILabel\"; text = \"Open Settings in Stream View by Sliding from: \"; ObjectID = \"IvI-tw-APj\";", "extractionState" : "extracted_with_value", @@ -3037,6 +3037,18 @@ } } }, + "Pwa-YK-6Q2.text" : { + "comment" : "Class = \"UILabel\"; text = \"test\"; ObjectID = \"Pwa-YK-6Q2\";", + "extractionState" : "extracted_with_value", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "test" + } + } + } + }, "pYZ-GR-EwO.text" : { "comment" : "Class = \"UILabel\"; text = \"Resolution \"; ObjectID = \"pYZ-GR-EwO\";", "extractionState" : "extracted_with_value", @@ -3277,14 +3289,14 @@ } } }, - "R45-lM-YPl.normalTitle" : { - "comment" : "Class = \"UIButton\"; normalTitle = \"Edit\"; ObjectID = \"R45-lM-YPl\";", + "r8L-dl-yLZ.text" : { + "comment" : "Class = \"UILabel\"; text = \"test\"; ObjectID = \"r8L-dl-yLZ\";", "extractionState" : "extracted_with_value", "localizations" : { "en" : { "stringUnit" : { "state" : "new", - "value" : "Edit" + "value" : "test" } } } @@ -3379,6 +3391,18 @@ } } }, + "sbd-0j-KWS.text" : { + "comment" : "Class = \"UILabel\"; text = \"test\"; ObjectID = \"sbd-0j-KWS\";", + "extractionState" : "extracted_with_value", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "test" + } + } + } + }, "sIU-PH-H7V.segmentTitles[0]" : { "comment" : "Class = \"UISegmentedControl\"; sIU-PH-H7V.segmentTitles[0] = \"No\"; ObjectID = \"sIU-PH-H7V\";", "extractionState" : "stale", @@ -3499,6 +3523,18 @@ } } }, + "tG7-oX-P9b.text" : { + "comment" : "Class = \"UILabel\"; text = \"test\"; ObjectID = \"tG7-oX-P9b\";", + "extractionState" : "extracted_with_value", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "test" + } + } + } + }, "uSS-ev-IFe.configuration.title" : { "comment" : "Class = \"UIButton\"; configuration.title = \"Back to Streaming\"; ObjectID = \"uSS-ev-IFe\";", "extractionState" : "stale", @@ -3559,6 +3595,18 @@ } } }, + "vJs-pg-hHe.text" : { + "comment" : "Class = \"UILabel\"; text = \"test\"; ObjectID = \"vJs-pg-hHe\";", + "extractionState" : "extracted_with_value", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "test" + } + } + } + }, "VWB-YB-Ptj.segmentTitles[0]" : { "comment" : "Class = \"UISegmentedControl\"; VWB-YB-Ptj.segmentTitles[0] = \"Stage Manager\"; ObjectID = \"VWB-YB-Ptj\";", "extractionState" : "extracted_with_value", @@ -3889,6 +3937,18 @@ } } }, + "ZuV-4A-0Zb.text" : { + "comment" : "Class = \"UILabel\"; text = \"test\"; ObjectID = \"ZuV-4A-0Zb\";", + "extractionState" : "extracted_with_value", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "test" + } + } + } + }, "ZWC-Gw-pSq.text" : { "comment" : "Class = \"UILabel\"; text = \"Frame Pacing Preference \"; ObjectID = \"ZWC-Gw-pSq\";", "extractionState" : "extracted_with_value",