feat: "folder" onscreen button
This commit is contained in:
@@ -2888,8 +2888,8 @@
|
||||
<constraint firstAttribute="width" constant="180" id="TbL-OE-jvg"/>
|
||||
</constraints>
|
||||
<segments>
|
||||
<segment title="display"/>
|
||||
<segment title="hide"/>
|
||||
<segment title="unfold"/>
|
||||
<segment title="fold"/>
|
||||
</segments>
|
||||
<color key="tintColor" systemColor="systemGray3Color"/>
|
||||
<color key="selectedSegmentTintColor" red="0.23087820410000001" green="0.4576539993" blue="0.51765710119999997" alpha="1" colorSpace="custom" customColorSpace="displayP3"/>
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="24412" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" colorMatched="YES" initialViewController="DL0-L5-LOv">
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="24506" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" colorMatched="YES" initialViewController="DL0-L5-LOv">
|
||||
<device id="retina6_1" orientation="portrait" appearance="light"/>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="24405"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="24504"/>
|
||||
<capability name="Image references" minToolsVersion="12.0"/>
|
||||
<capability name="System colors in document resources" minToolsVersion="11.0"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
@@ -156,7 +156,7 @@
|
||||
<viewControllerLayoutGuide type="bottom" id="TWA-bF-hnk"/>
|
||||
</layoutGuides>
|
||||
<view key="view" opaque="NO" clearsContextBeforeDrawing="NO" contentMode="scaleToFill" id="Mwx-9q-yJJ">
|
||||
<rect key="frame" x="0.0" y="0.0" width="1300" height="896"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="1300" height="1800"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Jnu-63-bcf" customClass="ToolBarContainerView">
|
||||
@@ -315,7 +315,7 @@
|
||||
</constraints>
|
||||
</view>
|
||||
<stackView opaque="NO" contentMode="scaleToFill" ambiguous="YES" axis="vertical" spacing="7" translatesAutoresizingMaskIntoConstraints="NO" id="BVp-3O-vZ7" userLabel="widgetPanelStack" customClass="WidgetPanelStackView">
|
||||
<rect key="frame" x="375" y="132" width="550" height="786"/>
|
||||
<rect key="frame" x="375" y="132" width="550" height="813"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Profile:" textAlignment="center" lineBreakMode="tailTruncation" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="f46-Pt-0Pv">
|
||||
<rect key="frame" x="0.0" y="0.0" width="550" height="28"/>
|
||||
@@ -799,6 +799,55 @@
|
||||
<constraint firstAttribute="height" constant="20" id="Qap-bn-YnJ"/>
|
||||
</constraints>
|
||||
</stackView>
|
||||
<stackView opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="weV-Li-Itz">
|
||||
<rect key="frame" x="0.0" y="793" width="550" height="20"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Collected Widgets " textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumScaleFactor="0.10000000000000001" translatesAutoresizingMaskIntoConstraints="NO" id="kek-77-Kmg" userLabel="uilabel">
|
||||
<rect key="frame" x="0.0" y="0.0" width="120" height="20"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="120" id="TPJ-nn-WHY"/>
|
||||
</constraints>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<segmentedControl opaque="NO" alpha="0.69999998807907104" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="plain" selectedSegmentIndex="0" translatesAutoresizingMaskIntoConstraints="NO" id="Oo7-lI-LXT">
|
||||
<rect key="frame" x="120" y="0.0" width="161" height="21"/>
|
||||
<color key="backgroundColor" white="0.33333333329999998" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<segments>
|
||||
<segment title="unfold"/>
|
||||
<segment title="fold"/>
|
||||
</segments>
|
||||
<color key="tintColor" systemColor="systemGray2Color"/>
|
||||
<color key="selectedSegmentTintColor" red="0.23136288839999999" green="0.45776400810000001" blue="0.5149240678" alpha="1" colorSpace="custom" customColorSpace="displayP3"/>
|
||||
</segmentedControl>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text=" Reveal mode " textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumScaleFactor="0.10000000149011612" translatesAutoresizingMaskIntoConstraints="NO" id="YLN-X6-oj9" userLabel="uilabel">
|
||||
<rect key="frame" x="281" y="0.0" width="120" height="20"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="120" id="rIX-6N-uU4"/>
|
||||
</constraints>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<segmentedControl opaque="NO" alpha="0.69999998807907104" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="plain" selectedSegmentIndex="0" translatesAutoresizingMaskIntoConstraints="NO" id="myu-Th-CTZ">
|
||||
<rect key="frame" x="401" y="0.0" width="149" height="21"/>
|
||||
<color key="backgroundColor" white="0.33333333329999998" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="149" id="UjR-CH-nwX"/>
|
||||
</constraints>
|
||||
<segments>
|
||||
<segment title="coexist"/>
|
||||
<segment title="exclusive"/>
|
||||
</segments>
|
||||
<color key="tintColor" systemColor="systemGray2Color"/>
|
||||
<color key="selectedSegmentTintColor" red="0.23136288839999999" green="0.45776400810000001" blue="0.5149240678" alpha="1" colorSpace="custom" customColorSpace="displayP3"/>
|
||||
</segmentedControl>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="20" id="dxB-cV-EvQ"/>
|
||||
</constraints>
|
||||
</stackView>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.5" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<constraints>
|
||||
@@ -813,7 +862,7 @@
|
||||
<constraint firstItem="Jnu-63-bcf" firstAttribute="top" secondItem="Mwx-9q-yJJ" secondAttribute="top" id="wNr-7F-S0i" userLabel="Toolbar Top Constraint iPhone"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<size key="freeformSize" width="1300" height="896"/>
|
||||
<size key="freeformSize" width="1300" height="1800"/>
|
||||
<connections>
|
||||
<outlet property="autoTapField" destination="DOu-sG-eRq" id="Ubj-og-ThW"/>
|
||||
<outlet property="autoTapLabel" destination="IuG-44-1Je" id="YWb-0d-zbB"/>
|
||||
@@ -823,6 +872,8 @@
|
||||
<outlet property="buttonModeStack" destination="jE7-IB-GTS" id="hKb-gp-eem"/>
|
||||
<outlet property="chevronImageView" destination="76O-3K-aa8" id="yGv-fM-Ohf"/>
|
||||
<outlet property="chevronView" destination="Zll-IP-PFt" id="MGR-C0-h57"/>
|
||||
<outlet property="collectedWidgetsSelector" destination="Oo7-lI-LXT" id="ufg-er-4aZ"/>
|
||||
<outlet property="collectedWidgetsStack" destination="weV-Li-Itz" id="SII-3v-ylG"/>
|
||||
<outlet property="componentSizeLabel" destination="kcX-kR-3gl" id="FTP-ar-6Uh"/>
|
||||
<outlet property="componentSizeSlider" destination="hTI-E5-8cp" id="TSO-4T-sF3"/>
|
||||
<outlet property="componentSizeStack" destination="xNe-VP-2ix" id="zBD-X1-BNH"/>
|
||||
@@ -838,6 +889,7 @@
|
||||
<outlet property="pitchFactorLabel" destination="dEy-ER-Mb3" id="0or-ME-7P1"/>
|
||||
<outlet property="pitchFactorSlider" destination="ol0-mA-VxW" id="bmd-0a-O4H"/>
|
||||
<outlet property="pitchFactorStack" destination="gkc-td-lg4" id="gI0-q7-tO2"/>
|
||||
<outlet property="revealModeSelector" destination="myu-Th-CTZ" id="9lE-Vs-cxe"/>
|
||||
<outlet property="rollFactorLabel" destination="BNN-vq-Pve" id="4mm-f5-d93"/>
|
||||
<outlet property="rollFactorSlider" destination="Ple-mD-zK4" id="sHy-HC-68W"/>
|
||||
<outlet property="rollFactorStack" destination="7G4-Ms-mkR" id="EzV-6y-77h"/>
|
||||
@@ -883,7 +935,7 @@
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="ORo-HP-JDj" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="157.97101449275362" y="1245.5357142857142"/>
|
||||
<point key="canvasLocation" x="-96" y="1822"/>
|
||||
</scene>
|
||||
<!--Profiles Table View Controller-->
|
||||
<scene sceneID="C7c-yg-gQK">
|
||||
|
||||
@@ -30,6 +30,7 @@ typedef NS_ENUM(NSInteger, MapGyroTo) {
|
||||
|
||||
@property NSString *name;
|
||||
@property NSMutableArray <NSData *> *buttonStatesEncoded;
|
||||
@property (nonatomic, assign) int16_t unfoldedExclusiveFolderSequence;
|
||||
@property BOOL isSelected;
|
||||
@property (nonatomic, assign) MapGyroTo mapGyroTo;
|
||||
@property (nonatomic, assign) bool yawPitchToRightStick;
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
- (void) encodeWithCoder:(NSCoder*)encoder {
|
||||
[encoder encodeObject:self.name forKey:@"name"];
|
||||
[encoder encodeObject:self.buttonStatesEncoded forKey:@"buttonStates"];
|
||||
[encoder encodeInt32:self.unfoldedExclusiveFolderSequence forKey:@"unfoldedExclusiveFolderSequence"];
|
||||
[encoder encodeBool:self.isSelected forKey:@"isSelected"];
|
||||
[encoder encodeInt64:self.mapGyroTo forKey:@"mapGyroTo"];
|
||||
[encoder encodeBool:self.yawPitchToRightStick forKey:@"yawPitchToRightStick"];
|
||||
@@ -73,6 +74,7 @@
|
||||
[NSData class],
|
||||
nil]
|
||||
forKey:@"buttonStates"];
|
||||
self.unfoldedExclusiveFolderSequence = [decoder containsValueForKey:@"unfoldedExclusiveFolderSequence"] ? [decoder decodeInt32ForKey:@"unfoldedExclusiveFolderSequence"] : -1;
|
||||
self.isSelected = [decoder decodeBoolForKey:@"isSelected"];
|
||||
self.mapGyroTo = [decoder containsValueForKey:@"mapGyroTo"] ? [decoder decodeInt64ForKey:@"mapGyroTo"] : mapGyroToMouse;
|
||||
self.yawPitchToRightStick = [decoder containsValueForKey:@"yawPitchToRightStick"] ? [decoder decodeBoolForKey:@"yawPitchToRightStick"] : true;
|
||||
@@ -131,6 +133,7 @@
|
||||
OSCProfile *copy = [[[self class] allocWithZone:zone] init];
|
||||
copy.name = [self.name mutableCopy]; // NSString → NSMutableString
|
||||
copy.buttonStatesEncoded = [[NSMutableArray alloc] initWithArray:self.buttonStatesEncoded copyItems:YES];
|
||||
copy.unfoldedExclusiveFolderSequence = self.unfoldedExclusiveFolderSequence;
|
||||
copy.isSelected = self.isSelected;
|
||||
copy.mapGyroTo = self.mapGyroTo;
|
||||
copy.yawPitchToRightStick = self.yawPitchToRightStick;
|
||||
|
||||
@@ -291,6 +291,7 @@ static CGRect layoutViewBounds;
|
||||
*/
|
||||
OSCProfile *selectedProfile = [self getSelectedProfile];
|
||||
selectedProfile.buttonStatesEncoded = buttonStatesEncoded;
|
||||
selectedProfile.unfoldedExclusiveFolderSequence = OnScreenWidgetView.unfoldedExclusiveFolderSequence;
|
||||
[self replaceSelectedProfileWith:selectedProfile overwriteDefault:NO];
|
||||
return true;
|
||||
}
|
||||
@@ -389,10 +390,14 @@ static CGRect layoutViewBounds;
|
||||
// save on-screen widget views (keyboard & mouse command) as buttonstate:
|
||||
_widgetSizeTransition = keepWidgetSize;
|
||||
for(OnScreenWidgetView* widgetView in OnScreenWidgetViews){
|
||||
CGPoint normalizedPosition = [self normalizeWidgetPosition:widgetView.center];
|
||||
CGPoint normalizedPosition = [self normalizeWidgetPosition:widgetView.storedCenter];
|
||||
OnScreenButtonState *buttonState = [[OnScreenButtonState alloc] initWithButtonName:widgetView.cmdString buttonType:CustomOnScreenWidget andPosition:normalizedPosition];
|
||||
buttonState.alias = widgetView.widgetLabel;
|
||||
buttonState.sequence = widgetView.sequence;
|
||||
buttonState.sequenceSet = widgetView.sequenceSet;
|
||||
buttonState.parentSequence = widgetView.parentSequence;
|
||||
buttonState.folded = widgetView.folded;
|
||||
buttonState.revealMode = widgetView.revealMode;
|
||||
buttonState.widthFactor = [self normalizeSizeWidthFactorWith:widgetView];
|
||||
buttonState.heightFactor = [self normalizeSizeHeightFactorWith:widgetView];
|
||||
buttonState.componentSizeFactor = [self normalizeComponentSizeFactorWith:widgetView];
|
||||
@@ -421,7 +426,6 @@ static CGRect layoutViewBounds;
|
||||
|
||||
NSData *buttonStateEncoded = [NSKeyedArchiver archivedDataWithRootObject:buttonState requiringSecureCoding:YES error:nil];
|
||||
[buttonStatesEncoded addObject: buttonStateEncoded];
|
||||
|
||||
}
|
||||
return buttonStatesEncoded;
|
||||
}
|
||||
@@ -477,7 +481,7 @@ static CGRect layoutViewBounds;
|
||||
|
||||
- (OnScreenButtonState *)unarchiveButtonStateEncoded:(NSData *)data {
|
||||
OnScreenButtonState* buttonState;
|
||||
buttonState = [NSKeyedUnarchiver unarchivedObjectOfClasses:[NSSet setWithObjects:[NSString class], [OnScreenButtonState class], nil]
|
||||
buttonState = [NSKeyedUnarchiver unarchivedObjectOfClasses:[NSSet setWithObjects:[NSString class], [OnScreenButtonState class], [NSSet class], nil]
|
||||
fromData:data
|
||||
error:nil];
|
||||
return buttonState;
|
||||
|
||||
@@ -27,7 +27,8 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
@property (nonatomic, assign) BOOL folded;
|
||||
@property (nonatomic, assign) uint8_t revealMode;
|
||||
@property (nonatomic, assign) int16_t sequence;
|
||||
@property NSMutableSet *sequenceSet;
|
||||
@property (nonatomic, assign) int16_t parentSequence;
|
||||
@property NSSet *sequenceSet;
|
||||
@property CGPoint position;
|
||||
@property (nonatomic, assign) BOOL isHidden;
|
||||
@property (nonatomic, assign) uint8_t buttonMode;
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
[encoder encodeBool:self.folded forKey:@"folded"];
|
||||
[encoder encodeInt32:self.revealMode forKey:@"revealMode"];
|
||||
[encoder encodeInt32:self.sequence forKey:@"sequence"];
|
||||
[encoder encodeInt32:self.parentSequence forKey:@"parentSequence"];
|
||||
[encoder encodeObject:self.sequenceSet forKey:@"sequenceSet"];
|
||||
[encoder encodeObject:self.alias forKey:@"alias"];
|
||||
[encoder encodeInt:self.widgetType forKey:@"buttonType"]; // keep original key
|
||||
@@ -73,8 +74,9 @@
|
||||
if (self = [super init]) {
|
||||
self.name = [decoder decodeObjectForKey:@"name"];
|
||||
self.folded = [decoder containsValueForKey:@"folded"] ? [decoder decodeBoolForKey:@"folded"] : false;
|
||||
self.revealMode = [decoder containsValueForKey:@"revealMode"] ? [decoder decodeInt32ForKey:@"revealMode"] : exclusive;
|
||||
self.revealMode = [decoder containsValueForKey:@"revealMode"] ? [decoder decodeInt32ForKey:@"revealMode"] : coexist;
|
||||
self.sequence = [decoder containsValueForKey:@"sequence"] ? [decoder decodeInt32ForKey:@"sequence"] : -1;
|
||||
self.parentSequence = [decoder containsValueForKey:@"parentSequence"] ? [decoder decodeInt32ForKey:@"parentSequence"] : -1;
|
||||
self.sequenceSet = [decoder containsValueForKey:@"sequenceSet"] ? [decoder decodeObjectForKey:@"sequenceSet"] : [NSSet set];
|
||||
self.alias = [decoder decodeObjectForKey:@"alias"];
|
||||
self.widgetType = [decoder decodeIntForKey:@"buttonType"];
|
||||
|
||||
@@ -10,7 +10,18 @@ import UIKit
|
||||
import SVGKit
|
||||
|
||||
@objc class OnScreenWidgetView: UIView {
|
||||
|
||||
@objc public static var mapping: [Int16:OnScreenWidgetView] = [:]
|
||||
@objc public static func set(widget:OnScreenWidgetView, for key:Int16) {
|
||||
mapping[key] = widget
|
||||
}
|
||||
@objc public static func removeWidgetFromMappings(key:Int16) {
|
||||
mapping.removeValue(forKey: key)
|
||||
}
|
||||
@objc public static func clearMappings() {
|
||||
mapping.removeAll()
|
||||
}
|
||||
@objc public static var unfoldedExclusiveFolderSequence:Int16 = -1
|
||||
|
||||
@objc public weak var guidelineDelegate: OnScreenWidgetGuidelineUpdateDelegate?
|
||||
@objc protocol OnScreenWidgetGuidelineUpdateDelegate: AnyObject {
|
||||
func updateGuidelinesForOnScreenWidget(_ sender: Any)
|
||||
@@ -263,8 +274,9 @@ import SVGKit
|
||||
private var tickFlag: UInt8 = 0
|
||||
|
||||
@objc public var folded: Bool = false
|
||||
@objc public var revealMode: RevealMode = .exclusive
|
||||
@objc public var revealMode: RevealMode = .coexist
|
||||
@objc public var sequenceSet: Set<Int16> = Set()
|
||||
@objc public var parentSequence: Int16 = -1
|
||||
private weak var capturer: OnScreenWidgetView?
|
||||
|
||||
@objc init(cmdString: String, buttonLabel: String, shape:String, profile:OSCProfile) {
|
||||
@@ -1415,17 +1427,21 @@ import SVGKit
|
||||
}
|
||||
}
|
||||
|
||||
private func handleFingerUpOrSlideout() {
|
||||
|
||||
private func handleFingerUpOrSlideout(leaveFunctionalButtonAlone: Bool = false, event: UIEvent? = nil) {
|
||||
print("handleFingerUpOrSlideout triggered, \(self.widgetLabel) \(CACurrentMediaTime())")
|
||||
if autoTapInterval < OnScreenWidgetView.MinAutotapInterval {
|
||||
handleButtonUp()
|
||||
handleButtonUp(leaveFunctionalButtonAlone:leaveFunctionalButtonAlone, event:event)
|
||||
}
|
||||
else{
|
||||
self.autoTapTimer?.pause()
|
||||
self.handleButtonUp()
|
||||
self.handleButtonUp(leaveFunctionalButtonAlone: leaveFunctionalButtonAlone)
|
||||
}
|
||||
}
|
||||
|
||||
private func handleButtonDown() {
|
||||
if !self.isUserInteractionEnabled {return}
|
||||
|
||||
if !OnScreenWidgetView.editMode, !self.functionalButtonString.isEmpty {self.handleFunctionalButtonDown()}
|
||||
|
||||
if !OnScreenWidgetView.editMode {self.sendComboButtonsDownEvent(comboStrings: self.comboButtonStrings)}
|
||||
@@ -1460,7 +1476,8 @@ import SVGKit
|
||||
}
|
||||
}
|
||||
|
||||
private func handleButtonUp() {
|
||||
private func handleButtonUp(leaveFunctionalButtonAlone:Bool = false, event: UIEvent? = nil) {
|
||||
if !self.isUserInteractionEnabled {return}
|
||||
if !OnScreenWidgetView.editMode {self.sendComboButtonsUpEvent(comboStrings: self.comboButtonStrings)}
|
||||
|
||||
if !OnScreenWidgetView.editMode && !self.motionControlButtonString.isEmpty{
|
||||
@@ -1470,7 +1487,7 @@ import SVGKit
|
||||
self.buttonUpVisualEffect()
|
||||
|
||||
if !OnScreenWidgetView.editMode && !self.functionalButtonString.isEmpty{
|
||||
self.handleFunctionalButtonUp()
|
||||
if !leaveFunctionalButtonAlone {self.handleFunctionalButtonUp(event:event)}
|
||||
}
|
||||
|
||||
// legacy keyboard button combo connected by "+"
|
||||
@@ -1817,9 +1834,9 @@ import SVGKit
|
||||
if(self.tapToToggleFlag) {self.handleTapDownOrSlidein()}
|
||||
else {self.handleFingerUpOrSlideout()}
|
||||
self.tapToToggleFlag = !self.tapToToggleFlag
|
||||
case .slideToToggle:
|
||||
case .slideToToggle where !self.isFolder:
|
||||
self.handleButtonSliding(touches: touches)
|
||||
case .slideAndHold:
|
||||
case .slideAndHold where !self.isFolder:
|
||||
self.handleButtonSliding(touches: touches)
|
||||
default:
|
||||
self.handleTapDownOrSlidein()
|
||||
@@ -1843,11 +1860,11 @@ import SVGKit
|
||||
capturer = nil
|
||||
currentLocation = touch.location(in: superview)
|
||||
forEachWidget { (widget) in
|
||||
guard widget != self else {return}
|
||||
if widget.isFolder {
|
||||
if self.frame.intersects(widget.frame), !self.sequenceSet.contains(widget.sequence) {
|
||||
if isLocation(currentLocation, in: widget), !self.sequenceSet.contains(widget.sequence) {
|
||||
// self.layer.borderColor = UIColor.systemYellow.cgColor
|
||||
widget.highlightBorder(highlighted: true)
|
||||
if widget == self {return}
|
||||
capturer = widget
|
||||
return
|
||||
}
|
||||
@@ -1856,7 +1873,13 @@ import SVGKit
|
||||
}
|
||||
}
|
||||
else {
|
||||
if self.buttonMode == .movable {currentLocation = touch.location(in: superview)}
|
||||
if self.buttonMode == .movable {
|
||||
currentLocation = touch.location(in: superview)
|
||||
for sequence in self.sequenceSet {
|
||||
let widget = OnScreenWidgetView.mapping[sequence]
|
||||
if widget?.isHidden == true {widget?.center = currentLocation}
|
||||
}
|
||||
}
|
||||
else {return}
|
||||
}
|
||||
|
||||
@@ -1872,7 +1895,10 @@ import SVGKit
|
||||
let outOfBoundsX = center.x+offsetX >= (self.superview?.bounds.width)! || center.x+offsetX < 0
|
||||
let outOfBoundsY = center.y+offsetY >= (self.superview?.bounds.height)! || center.y+offsetY < 0
|
||||
|
||||
if firstTouchMoved {center = CGPoint(x: outOfBoundsX ? center.x : center.x+offsetX, y: outOfBoundsY ? center.y : center.y+offsetY)}
|
||||
if firstTouchMoved {
|
||||
center = CGPoint(x: outOfBoundsX ? center.x : center.x+offsetX, y: outOfBoundsY ? center.y : center.y+offsetY)
|
||||
storedCenter = center
|
||||
}
|
||||
|
||||
latestTouchLocation = currentLocation
|
||||
|
||||
@@ -1919,14 +1945,17 @@ import SVGKit
|
||||
}
|
||||
}
|
||||
|
||||
private func handleFingerUpAfterSliding(touches: Set<UITouch>) {
|
||||
private func handleFingerUpAfterSliding(touches: Set<UITouch>, event: UIEvent? = nil) {
|
||||
// a special touchUp handling for .slideToToggle
|
||||
for touch in touches {
|
||||
self.forEachWidget(){ widget in
|
||||
setLock.lock()
|
||||
let captured = widget.capturedTouches.contains(touch)
|
||||
setLock.unlock()
|
||||
if !captured || widget.buttonMode == .regular {return}
|
||||
widget.handleFingerUpOrSlideout()
|
||||
let needReleaseButton = (isLocation(touch.location(in: superview), in: widget)
|
||||
|| widget.buttonMode == .slideAndHold)
|
||||
if needReleaseButton {widget.handleFingerUpOrSlideout(event: event)}
|
||||
setLock.lock()
|
||||
widget.capturedTouches.remove(touch)
|
||||
setLock.unlock()
|
||||
@@ -1953,7 +1982,10 @@ import SVGKit
|
||||
let locationInSuperView = touch.location(in: self.superview)
|
||||
self.forEachWidget{ widget in
|
||||
if widget.widgetType != WidgetTypeEnum.button {return}
|
||||
let isSlidableButton = widget.buttonMode == .slideToToggle || widget.buttonMode == .slideAndHold
|
||||
let isSlidableButton = (widget.buttonMode == .slideToToggle
|
||||
|| widget.buttonMode == .slideAndHold
|
||||
|| (widget.buttonMode == .movable && widget != self)
|
||||
)
|
||||
if isLocation(locationInSuperView, in: widget){
|
||||
setLock.lock()
|
||||
let captured = widget.capturedTouches.contains(touch)
|
||||
@@ -1972,8 +2004,8 @@ import SVGKit
|
||||
setLock.unlock()
|
||||
if !captured || !isSlidableButton {return}
|
||||
// print("UIButton: \(widget.buttonLabel) out test, \(widget.touchPadString), \(CACurrentMediaTime())")
|
||||
if(widget.buttonMode == .slideToToggle){
|
||||
widget.handleFingerUpOrSlideout()
|
||||
if(widget.buttonMode == .slideToToggle || widget.buttonMode == .movable){
|
||||
widget.handleFingerUpOrSlideout(leaveFunctionalButtonAlone: widget.isFuncationalButton)
|
||||
setLock.lock()
|
||||
widget.capturedTouches.remove(touch)
|
||||
setLock.unlock()
|
||||
@@ -2271,6 +2303,10 @@ import SVGKit
|
||||
|
||||
private func handleFunctionalButtonDown(){
|
||||
switch self.functionalButtonString {
|
||||
case "FOLDER":
|
||||
if self.buttonMode != .slideAndHold {break}
|
||||
self.folded = false
|
||||
OnScreenWidgetView.set(folded: false, for: self)
|
||||
case "ABSTCHDRAG":
|
||||
let mouseButton = CommandManager.mouseButtonMappings[Set(self.comboButtonStrings).intersection(CommandManager.mouseButtonMappings.keys).first ?? "MLEFT"] ?? BUTTON_LEFT
|
||||
print("mouseButton \(mouseButton)");
|
||||
@@ -2292,10 +2328,16 @@ import SVGKit
|
||||
|
||||
private var singleTouchEnabled:Bool = true
|
||||
|
||||
private func handleFunctionalButtonUp(){
|
||||
private func handleFunctionalButtonUp(event: UIEvent? = nil){
|
||||
print("handleFunctionalButtonUp \(CACurrentMediaTime())")
|
||||
if buttonMode == .movable {
|
||||
if moveableButtonLongPressed() {return}
|
||||
if moveableButtonLongPressed() && !UITouchUtil.touches(in: self, from: event).isEmpty {return}
|
||||
print("handleFunctionalButtonUp movable, \(moveableButtonLongPressed()) \(CACurrentMediaTime())")
|
||||
|
||||
switch self.functionalButtonString {
|
||||
// case "FOLDER":
|
||||
// self.folded = !self.folded
|
||||
// OnScreenWidgetView.set(folded: self.folded, for: self)
|
||||
case "NOSINGLETOUCH":
|
||||
if !self.isPencilProEnabled() {break}
|
||||
singleTouchEnabled = !singleTouchEnabled
|
||||
@@ -2306,6 +2348,9 @@ import SVGKit
|
||||
}
|
||||
}
|
||||
switch self.functionalButtonString {
|
||||
case "FOLDER":
|
||||
self.folded = !self.folded
|
||||
OnScreenWidgetView.set(folded: self.folded, for: self)
|
||||
case "SETTINGS":
|
||||
self.functionalButtonDelegate?.expandSettingsView()
|
||||
case "TOOLBOX":
|
||||
@@ -2512,8 +2557,9 @@ import SVGKit
|
||||
}
|
||||
|
||||
if !OnScreenWidgetView.editMode && !self.cmdString.contains("+") && !self.comboButtonStrings.isEmpty { // if the command(keystring contains "+", it's a legacy multi-key command
|
||||
// print("self.comboButtonStrings \(self.comboButtonStrings),\(CACurrentMediaTime())")
|
||||
if self.buttonMode == .slideToToggle || self.buttonMode == .slideAndHold {
|
||||
self.handleFingerUpAfterSliding(touches: touches)
|
||||
self.handleFingerUpAfterSliding(touches: touches, event: event) // .slideAndHold has to be released at touchesEnded, don't deal with it here.
|
||||
setLock.lock()
|
||||
self.capturedTouches.minus(touches)
|
||||
setLock.unlock()
|
||||
@@ -2532,11 +2578,10 @@ import SVGKit
|
||||
if firstTouchMoved {undoRelocation()}
|
||||
if let capturer = capturer {
|
||||
capturer.highlightBorder(highlighted: false)
|
||||
guard !self.sequenceSet.contains(capturer.sequence) else { return }
|
||||
OnScreenWidgetView.put(widget: self, into: capturer)
|
||||
self.isHidden = capturer.folded
|
||||
OnScreenWidgetView.putWidget(self, into: capturer)
|
||||
}
|
||||
}
|
||||
capturer = nil
|
||||
|
||||
guard let superview = superview else { return }
|
||||
|
||||
@@ -2570,7 +2615,10 @@ import SVGKit
|
||||
}
|
||||
}
|
||||
|
||||
if self.buttonMode != .tapToToggle {self.handleFingerUpOrSlideout()}
|
||||
if (self.buttonMode != .tapToToggle
|
||||
&& self.buttonMode != .slideToToggle
|
||||
&& self.buttonMode != .slideAndHold
|
||||
&& self == touches.first?.view) {self.handleFingerUpOrSlideout(event:event)}
|
||||
}
|
||||
|
||||
@objc public func setAutoTapIntervalByText(str: String){
|
||||
@@ -2685,44 +2733,137 @@ import SVGKit
|
||||
return sequence+1
|
||||
}
|
||||
|
||||
@objc static func setCollection(hidden:Bool, for folder:OnScreenWidgetView) {
|
||||
private static func setCollection(hidden:Bool, for folder:OnScreenWidgetView, exception:OnScreenWidgetView? = nil, recursive:Bool = false) {
|
||||
guard folder.isFolder else {return}
|
||||
// guard folder.folded != hidden else { return }
|
||||
folder.folded = hidden
|
||||
folder.setupAtrributedText()
|
||||
if hidden {
|
||||
folder.forEachWidget{ widget in
|
||||
if widget == folder {return}
|
||||
if folder.sequenceSet.contains(widget.sequence){
|
||||
DispatchQueue.main.async {widget.isHidden = hidden}
|
||||
if widget.isFolder {
|
||||
// OnScreenWidgetView.setCollection(hidden: hidden, for: widget)
|
||||
guard widget != folder else {return}
|
||||
if folder.sequenceSet.contains(widget.sequence), widget != exception{
|
||||
DispatchQueue.main.async {
|
||||
widget.isUserInteractionEnabled = false
|
||||
UIView.animate(withDuration: folder.buttonMode == .slideAndHold ? 0.05 : 0.15, animations: {
|
||||
widget.center = folder.center
|
||||
},completion: { finished in
|
||||
widget.isUserInteractionEnabled = !folder.folded
|
||||
widget.center = folder.folded ? folder.storedCenter : widget.storedCenter
|
||||
widget.isHidden = folder.folded
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
folder.forEachWidget{ widget in
|
||||
if widget == folder {return}
|
||||
if folder.sequenceSet.contains(widget.sequence){
|
||||
DispatchQueue.main.async {widget.isHidden = hidden}
|
||||
guard widget != folder else {return}
|
||||
if folder.sequenceSet.contains(widget.sequence), widget != exception{
|
||||
DispatchQueue.main.async {
|
||||
widget.center = folder.storedCenter
|
||||
widget.isUserInteractionEnabled = false
|
||||
widget.isHidden = false
|
||||
UIView.animate(withDuration: folder.buttonMode == .slideAndHold ? 0.05 : 0.15, animations: {
|
||||
widget.center = widget.storedCenter
|
||||
},completion: { finished in
|
||||
widget.isUserInteractionEnabled = !folder.folded
|
||||
widget.center = folder.folded ? folder.storedCenter : widget.storedCenter
|
||||
widget.isHidden = folder.folded
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
if folder.revealMode == .exclusive {
|
||||
folder.forEachWidget{ widget in
|
||||
if widget == folder {return}
|
||||
if widget.isFolder, !widget.sequenceSet.contains(folder.sequence) {
|
||||
OnScreenWidgetView.setCollection(hidden: true, for: widget)
|
||||
}
|
||||
}
|
||||
if recursive {
|
||||
folder.forEachWidget{ widget in
|
||||
guard widget != folder else {return}
|
||||
guard widget.isFolder, widget != exception else {return}
|
||||
if folder.sequenceSet.contains(widget.sequence){
|
||||
OnScreenWidgetView.setCollection(hidden: hidden, for: widget, exception: exception, recursive: true)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static func put(widget:OnScreenWidgetView, into folder:OnScreenWidgetView){
|
||||
widget.forEachWidget{ otherWidget in
|
||||
otherWidget.sequenceSet.remove(widget.sequence)
|
||||
@objc static func set(folded:Bool, for folder:OnScreenWidgetView) { // folder综合逻辑
|
||||
guard folder.isFolder else {return}
|
||||
setCollection(hidden: folded, for: folder)
|
||||
if !folded, folder.revealMode == .exclusive {
|
||||
OnScreenWidgetView.unfoldedExclusiveFolderSequence = folder.sequence
|
||||
let currentRootFolder = OnScreenWidgetView.getRootFolder(of: folder) ?? folder
|
||||
var offshootRootFolders:Set<OnScreenWidgetView> = Set()
|
||||
folder.forEachWidget{ widget in
|
||||
guard folder != widget else {return}
|
||||
let rootFolder = getRootFolder(of: widget)
|
||||
guard let rootFolder = rootFolder else {return}
|
||||
offshootRootFolders.insert(rootFolder)
|
||||
}
|
||||
offshootRootFolders.remove(currentRootFolder)
|
||||
|
||||
guard !folder.sequenceSet.isEmpty else {return}
|
||||
for folder in offshootRootFolders {
|
||||
setCollection(hidden: true, for: folder, recursive: true)
|
||||
}
|
||||
|
||||
guard currentRootFolder != folder else {return}
|
||||
setCollection(hidden: true, for:currentRootFolder, exception: folder, recursive: true)
|
||||
}
|
||||
}
|
||||
|
||||
private static func getRootFolder(of widget:OnScreenWidgetView) -> OnScreenWidgetView?{
|
||||
var widgetRef:OnScreenWidgetView? = widget
|
||||
var parentFolder:OnScreenWidgetView? = OnScreenWidgetView.mapping[widgetRef?.parentSequence ?? -1]
|
||||
repeat {
|
||||
widgetRef = parentFolder
|
||||
parentFolder = OnScreenWidgetView.mapping[widgetRef?.parentSequence ?? -1]
|
||||
} while parentFolder != nil
|
||||
return widgetRef
|
||||
}
|
||||
|
||||
private static func getParentFolders(of widget: OnScreenWidgetView) -> Set<OnScreenWidgetView> {
|
||||
var parents = Set<OnScreenWidgetView>()
|
||||
var current = widget
|
||||
while let parent = OnScreenWidgetView.mapping[current.parentSequence] {
|
||||
parents.insert(parent)
|
||||
current = parent
|
||||
}
|
||||
return parents
|
||||
}
|
||||
|
||||
private static func putWidget(_ widget:OnScreenWidgetView, into folder:OnScreenWidgetView){
|
||||
guard !OnScreenWidgetView.getParentFolders(of: folder).contains(widget) else { return }
|
||||
let parentFolder = OnScreenWidgetView.mapping[widget.parentSequence]
|
||||
if parentFolder != nil {
|
||||
parentFolder?.sequenceSet.remove(widget.sequence)
|
||||
}
|
||||
widget.parentSequence = folder.sequence
|
||||
folder.sequenceSet.insert(widget.sequence)
|
||||
widget.isHidden = folder.folded
|
||||
if folder.buttonMode == .slideAndHold, widget.isFuncationalButton {
|
||||
widget.buttonMode = .slideToToggle
|
||||
}
|
||||
}
|
||||
|
||||
@objc static func setFree(widget:OnScreenWidgetView){
|
||||
let parentFolder = OnScreenWidgetView.mapping[widget.parentSequence]
|
||||
if parentFolder != nil {
|
||||
parentFolder?.sequenceSet.remove(widget.sequence)
|
||||
}
|
||||
widget.parentSequence = -1
|
||||
}
|
||||
|
||||
@objc static func restoreFoldedStates(){
|
||||
var unfoldedExclusiveFolder: OnScreenWidgetView?
|
||||
if unfoldedExclusiveFolderSequence != -1 {
|
||||
unfoldedExclusiveFolder = OnScreenWidgetView.mapping[unfoldedExclusiveFolderSequence]
|
||||
if(unfoldedExclusiveFolder != nil){
|
||||
OnScreenWidgetView.set(folded: false, for: unfoldedExclusiveFolder!)
|
||||
}
|
||||
}
|
||||
|
||||
for widget in OnScreenWidgetView.mapping.values {
|
||||
OnScreenWidgetView.setCollection(hidden: widget.folded, for: widget, exception: unfoldedExclusiveFolder)
|
||||
}
|
||||
}
|
||||
|
||||
override func didMoveToSuperview() {
|
||||
|
||||
@@ -467,6 +467,7 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
|
||||
|
||||
- (void) clearOnScreenWidgets{
|
||||
OnScreenWidgetView.isTweakingHighlight = false;
|
||||
[OnScreenWidgetView clearMappings];
|
||||
for (UIView *subview in self->_streamFrameTopLayerView.subviews) {
|
||||
// 检查子视图是否是特定类型的实例
|
||||
if ([subview isKindOfClass:[OnScreenWidgetView class]]) {
|
||||
@@ -503,7 +504,7 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
|
||||
}
|
||||
}
|
||||
|
||||
NSLog(@"relocatedWidgetDict.allKeys.count %d, %f", relocatedWidgetDict.allKeys.count, CACurrentMediaTime());
|
||||
// NSLog(@"relocatedWidgetDict.allKeys.count %d, %f", relocatedWidgetDict.allKeys.count, CACurrentMediaTime());
|
||||
|
||||
if(relocatedWidgetDict.allKeys.count == 0) return;
|
||||
|
||||
@@ -515,7 +516,7 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
|
||||
OnScreenButtonState *newButtonState = [oscProfileMan unarchiveButtonStateEncoded:buttonStateEncoded];
|
||||
if([relocatedWidgetDict.allKeys containsObject:@(newButtonState.sequence)]){
|
||||
OnScreenWidgetView* widget = [relocatedWidgetDict objectForKey:@(newButtonState.sequence)];
|
||||
newButtonState.position = [oscProfileMan normalizeWidgetPosition:widget.center];
|
||||
newButtonState.position = [oscProfileMan normalizeWidgetPosition:widget.storedCenter];
|
||||
NSData *newButtonStateEncoded = [NSKeyedArchiver archivedDataWithRootObject:newButtonState requiringSecureCoding:YES error:nil];
|
||||
newProfile.buttonStatesEncoded[i] = newButtonStateEncoded;
|
||||
}
|
||||
@@ -560,11 +561,11 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
|
||||
widgetView.sequence = buttonState.sequence == -1 ? i : buttonState.sequence;
|
||||
if(!sequenceGenerated) sequenceGenerated = buttonState.sequence == -1;
|
||||
if(!hasMovableWidget) hasMovableWidget = buttonState.buttonMode == movable;
|
||||
if(sequenceGenerated){
|
||||
NSLog(@"widgetView.sequence %d %f", widgetView.sequence, CACurrentMediaTime());
|
||||
buttonState.sequence = widgetView.sequence;
|
||||
oscProfile.buttonStatesEncoded[i] = [NSKeyedArchiver archivedDataWithRootObject:buttonState requiringSecureCoding:YES error:nil];
|
||||
}
|
||||
[OnScreenWidgetView setWithWidget:widgetView for:widgetView.sequence];
|
||||
widgetView.sequenceSet = buttonState.sequenceSet;
|
||||
widgetView.parentSequence = buttonState.parentSequence;
|
||||
widgetView.folded = buttonState.folded;
|
||||
widgetView.revealMode = buttonState.revealMode;
|
||||
|
||||
widgetView.translatesAutoresizingMaskIntoConstraints = NO; // weird but this is mandatory, or you will find no key views added to the right place
|
||||
widgetView.widthFactor = buttonState.widthFactor;
|
||||
@@ -602,6 +603,12 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
|
||||
[widgetView tweakHighlightAlphaWithAlpha:buttonState.highlightAlpha];
|
||||
[widgetView setupAutoTapTimer];
|
||||
[widgetView setupInertialScrollerWithFps:self->settings.framerate.intValue];
|
||||
|
||||
if(sequenceGenerated){
|
||||
// NSLog(@"widgetView.sequence %d %f", widgetView.sequence, CACurrentMediaTime());
|
||||
buttonState.sequence = widgetView.sequence;
|
||||
oscProfile.buttonStatesEncoded[i] = [NSKeyedArchiver archivedDataWithRootObject:buttonState requiringSecureCoding:YES error:nil];
|
||||
}
|
||||
}
|
||||
else if(buttonState.widgetType == LegacyOnScreenControls) hasLegacyWidget = true;
|
||||
}
|
||||
@@ -636,6 +643,8 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
|
||||
}
|
||||
}
|
||||
|
||||
[OnScreenWidgetView restoreFoldedStates];
|
||||
|
||||
NSLog(@"hasLegacyWidget %d %f", hasLegacyWidget, CACurrentMediaTime());
|
||||
// legacy widgets
|
||||
if(!OnScreenWidgetView.editMode && (hasLegacyWidget || !reload)){
|
||||
|
||||
+39
-7
@@ -128,6 +128,7 @@ typedef NS_ENUM(NSUInteger, DecelerationRateSliderMode) {
|
||||
}
|
||||
|
||||
- (void)clearOnScreenWidgets{
|
||||
[OnScreenWidgetView clearMappings];
|
||||
for (UIView *subview in self.view.subviews) {
|
||||
if ([subview isKindOfClass:[OnScreenWidgetView class]]) {
|
||||
[subview removeFromSuperview];
|
||||
@@ -156,7 +157,14 @@ typedef NS_ENUM(NSUInteger, DecelerationRateSliderMode) {
|
||||
NSLog(@"reloadOnScreenWidgets name %@", buttonState.name);
|
||||
if(buttonState.widgetType == CustomOnScreenWidget){
|
||||
OnScreenWidgetView* widgetView = [[OnScreenWidgetView alloc] initWithCmdString:buttonState.name buttonLabel:buttonState.alias shape:buttonState.widgetShape profile:oscProfile]; //reconstruct widgetView
|
||||
|
||||
widgetView.sequence = buttonState.sequence == -1 ? ++sequence : buttonState.sequence;
|
||||
[OnScreenWidgetView setWithWidget:widgetView for:widgetView.sequence];
|
||||
widgetView.sequenceSet = buttonState.sequenceSet;
|
||||
widgetView.parentSequence = buttonState.parentSequence;
|
||||
widgetView.folded = buttonState.folded;
|
||||
widgetView.revealMode = buttonState.revealMode;
|
||||
|
||||
widgetView.guidelineDelegate = (id<OnScreenWidgetGuidelineUpdateDelegate>)self;
|
||||
widgetView.translatesAutoresizingMaskIntoConstraints = NO; // weird but this is mandatory, or you will find no key views added to the right place
|
||||
widgetView.widthFactor = buttonState.widthFactor;
|
||||
@@ -194,6 +202,13 @@ typedef NS_ENUM(NSUInteger, DecelerationRateSliderMode) {
|
||||
}
|
||||
else if(buttonState.widgetType == LegacyOnScreenControls) hasLegacyWidget = true;
|
||||
}
|
||||
|
||||
for(OnScreenWidgetView* widget in self.onScreenWidgetViews){
|
||||
[widget accessWidgetAttributes];
|
||||
// if(widget.isFolder) [OnScreenWidgetView setWithFolded:widget.folded for:widget];
|
||||
}
|
||||
|
||||
[OnScreenWidgetView restoreFoldedStates];
|
||||
NSLog(@"reloadOnScreenWidgets hasLegacyWidget %d %f", hasLegacyWidget, CACurrentMediaTime());
|
||||
if(hasLegacyWidget) [self reloadLegacyOnScreenControls:oscProfile];
|
||||
else{
|
||||
@@ -789,6 +804,7 @@ typedef NS_ENUM(NSUInteger, DecelerationRateSliderMode) {
|
||||
OSCProfile* profile = [[OSCProfilesManager sharedManager:CGRectZero] getSelectedProfile];
|
||||
OnScreenWidgetView* newWidget = [[OnScreenWidgetView alloc] initWithCmdString:widgetInitParams[@"cmdString"] buttonLabel:widgetInitParams[@"buttonLabel"] shape:widgetInitParams[@"shape"] profile:profile]; //reconstruct widgetView
|
||||
newWidget.sequence = widget.sequence;
|
||||
newWidget.revealMode = widget.revealMode;
|
||||
newWidget.guidelineDelegate = (id<OnScreenWidgetGuidelineUpdateDelegate>)self;
|
||||
newWidget.translatesAutoresizingMaskIntoConstraints = NO; // weird but this is mandatory, or you will find no key views added to the right place
|
||||
newWidget.widthFactor = widget.widthFactor;
|
||||
@@ -824,7 +840,12 @@ typedef NS_ENUM(NSUInteger, DecelerationRateSliderMode) {
|
||||
[newWidget setLocationWithPosition:CGPointMake(90, 130)];
|
||||
newWidget.sequence = [newWidget getAvailableSequence];
|
||||
}
|
||||
else [newWidget setLocationWithPosition:widget.center];
|
||||
else{
|
||||
[newWidget setLocationWithPosition:widget.center];
|
||||
newWidget.sequenceSet = [widget.sequenceSet mutableCopy];
|
||||
newWidget.parentSequence = widget.parentSequence;
|
||||
}
|
||||
[OnScreenWidgetView setWithWidget:newWidget for:newWidget.sequence];
|
||||
newWidget.sizeReference = widget.sizeReference;
|
||||
[newWidget resizeWidgetView]; // resize must be called after relocation
|
||||
[newWidget adjustTransparencyWithAlpha:widget.backgroundAlpha tweakBorderAlpha:NO];
|
||||
@@ -849,6 +870,7 @@ typedef NS_ENUM(NSUInteger, DecelerationRateSliderMode) {
|
||||
[self.view insertSubview:widgetView belowSubview:self.widgetPanelStack];
|
||||
widgetView.hidden = true;
|
||||
widgetView.sequence = [widgetView getAvailableSequence];
|
||||
[OnScreenWidgetView setWithWidget:widgetView for:widgetView.sequence];
|
||||
widgetView.guidelineDelegate = (id<OnScreenWidgetGuidelineUpdateDelegate>)self;
|
||||
widgetView.translatesAutoresizingMaskIntoConstraints = NO; // weird but this is mandatory, or you will find no key views added to the right place
|
||||
[self.onScreenWidgetViews addObject:widgetView];
|
||||
@@ -1088,17 +1110,21 @@ typedef NS_ENUM(NSUInteger, DecelerationRateSliderMode) {
|
||||
self.mouseButtonDownSelector.selectedSegmentIndex = selectedWidgetView.mouseButtonAction;
|
||||
|
||||
self.buttonModeStack.hidden = selectedWidgetView.widgetType != WidgetTypeEnumButton;
|
||||
[self.buttonModeSelector setEnabled:!selectedWidgetView.isFuncationalButton forSegmentAtIndex:0];
|
||||
[self.buttonModeSelector setEnabled:!selectedWidgetView.isFuncationalButton forSegmentAtIndex:1];
|
||||
// bool slideToToggleEnabled = !selectedWidgetView.isFuncationalButton || selectedWidgetView.isFolder;
|
||||
// [self.buttonModeSelector setEnabled:!selectedWidgetView.isFuncationalButton forSegmentAtIndex:0];
|
||||
[self.buttonModeSelector setEnabled:true forSegmentAtIndex:slideToToggle];
|
||||
bool slideAndHoldEnabled = !selectedWidgetView.isFuncationalButton || selectedWidgetView.isFolder;
|
||||
[self.buttonModeSelector setEnabled:slideAndHoldEnabled forSegmentAtIndex:slideAndHold];
|
||||
[self.buttonModeSelector setEnabled:!selectedWidgetView.isFolder forSegmentAtIndex:regular];
|
||||
[self.buttonModeSelector setEnabled:!selectedWidgetView.isFuncationalButton
|
||||
|| [selectedWidgetView.functionalButtonString containsString:@"ABSTCHDRAG"]
|
||||
forSegmentAtIndex:3];
|
||||
forSegmentAtIndex:tapToToggle];
|
||||
[self.buttonModeSelector setSelectedSegmentIndex:selectedWidgetView.buttonMode];
|
||||
|
||||
self.collectedWidgetsStack.hidden = !selectedWidgetView.isFolder;
|
||||
[self.collectedWidgetsSelector setSelectedSegmentIndex:selectedWidgetView.folded ? 1 :0];
|
||||
[self.revealModeSelector setSelectedSegmentIndex:selectedWidgetView.revealMode];
|
||||
[OnScreenWidgetView setCollectionWithHidden:selectedWidgetView.folded for:selectedWidgetView];
|
||||
[OnScreenWidgetView setWithFolded:selectedWidgetView.folded for:selectedWidgetView];
|
||||
|
||||
[self autoFitStack:self.widgetPanelStack];
|
||||
|
||||
@@ -1264,14 +1290,14 @@ typedef NS_ENUM(NSUInteger, DecelerationRateSliderMode) {
|
||||
|
||||
- (void)collectionHiddenChanged:(UISegmentedControl* )sender{
|
||||
if(self->selectedWidgetView != nil && self->widgetViewSelected){
|
||||
[OnScreenWidgetView setCollectionWithHidden:sender.selectedSegmentIndex==1 for:selectedWidgetView];
|
||||
[OnScreenWidgetView setWithFolded:sender.selectedSegmentIndex==1 for:selectedWidgetView];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)revealModeChanged:(UISegmentedControl* )sender{
|
||||
if(self->selectedWidgetView != nil && self->widgetViewSelected){
|
||||
selectedWidgetView.revealMode = sender.selectedSegmentIndex;
|
||||
[OnScreenWidgetView setCollectionWithHidden:selectedWidgetView.folded for:selectedWidgetView];
|
||||
[OnScreenWidgetView setWithFolded:selectedWidgetView.folded for:selectedWidgetView];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1772,6 +1798,10 @@ typedef NS_ENUM(NSUInteger, DecelerationRateSliderMode) {
|
||||
[self.layoutOSC updateGuidelinesForOnScreenWidget:widget];
|
||||
[self.view bringSubviewToFront:widget];
|
||||
trashCanButton.tintColor = trashCanButton.titleLabel.textColor = [self layerIsOverlappingWithTrashcanButton:widget.layer] ? [UIColor redColor] : trashCanStoryBoardColor;
|
||||
|
||||
if(trashCanButton.tintColor == [UIColor redColor] && selectedWidgetView != nil){
|
||||
[OnScreenWidgetView setFreeWithWidget:selectedWidgetView];
|
||||
}
|
||||
|
||||
self.undoButton.alpha = 1.0;
|
||||
}
|
||||
@@ -1861,6 +1891,8 @@ typedef NS_ENUM(NSUInteger, DecelerationRateSliderMode) {
|
||||
|
||||
|
||||
if(!isToolbarHidden && self->selectedWidgetView != nil && [self layerIsOverlappingWithTrashcanButton:selectedWidgetView.layer]){
|
||||
[OnScreenWidgetView setFreeWithWidget:selectedWidgetView];
|
||||
[OnScreenWidgetView removeWidgetFromMappingsWithKey:selectedWidgetView.sequence];
|
||||
[self->selectedWidgetView removeFromSuperview];
|
||||
[self.onScreenWidgetViews removeObject:self->selectedWidgetView];
|
||||
}
|
||||
|
||||
@@ -4048,6 +4048,24 @@
|
||||
"state" : "new",
|
||||
"value" : " Reveal mode "
|
||||
}
|
||||
},
|
||||
"zh-Hans" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : " 展开模式"
|
||||
}
|
||||
},
|
||||
"zh-Hant" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : " 展開模式"
|
||||
}
|
||||
},
|
||||
"zh-HK" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : " 展開模式"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -4756,6 +4774,24 @@
|
||||
"state" : "new",
|
||||
"value" : "coexist"
|
||||
}
|
||||
},
|
||||
"zh-Hans" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "共存"
|
||||
}
|
||||
},
|
||||
"zh-Hant" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "共存"
|
||||
}
|
||||
},
|
||||
"zh-HK" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "共存"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -4768,6 +4804,24 @@
|
||||
"state" : "new",
|
||||
"value" : "exclusive"
|
||||
}
|
||||
},
|
||||
"zh-Hans" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "互斥"
|
||||
}
|
||||
},
|
||||
"zh-Hant" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "互斥"
|
||||
}
|
||||
},
|
||||
"zh-HK" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "互斥"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -5048,25 +5102,61 @@
|
||||
}
|
||||
},
|
||||
"sch-0e-nfa.segmentTitles[0]" : {
|
||||
"comment" : "Class = \"UISegmentedControl\"; sch-0e-nfa.segmentTitles[0] = \"display\"; ObjectID = \"sch-0e-nfa\";",
|
||||
"comment" : "Class = \"UISegmentedControl\"; sch-0e-nfa.segmentTitles[0] = \"unfold\"; ObjectID = \"sch-0e-nfa\";",
|
||||
"extractionState" : "extracted_with_value",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "new",
|
||||
"value" : "display"
|
||||
"value" : "unfold"
|
||||
}
|
||||
},
|
||||
"zh-Hans" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "展开"
|
||||
}
|
||||
},
|
||||
"zh-Hant" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "展開"
|
||||
}
|
||||
},
|
||||
"zh-HK" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "展開"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"sch-0e-nfa.segmentTitles[1]" : {
|
||||
"comment" : "Class = \"UISegmentedControl\"; sch-0e-nfa.segmentTitles[1] = \"hide\"; ObjectID = \"sch-0e-nfa\";",
|
||||
"comment" : "Class = \"UISegmentedControl\"; sch-0e-nfa.segmentTitles[1] = \"fold\"; ObjectID = \"sch-0e-nfa\";",
|
||||
"extractionState" : "extracted_with_value",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "new",
|
||||
"value" : "hide"
|
||||
"value" : "fold"
|
||||
}
|
||||
},
|
||||
"zh-Hans" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "收起"
|
||||
}
|
||||
},
|
||||
"zh-Hant" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "收起"
|
||||
}
|
||||
},
|
||||
"zh-HK" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "收起"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5518,6 +5608,24 @@
|
||||
"state" : "new",
|
||||
"value" : "Collected widgets "
|
||||
}
|
||||
},
|
||||
"zh-Hans" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "已收纳控件 "
|
||||
}
|
||||
},
|
||||
"zh-Hant" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "已收納小工具 "
|
||||
}
|
||||
},
|
||||
"zh-HK" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "已收納小工具 "
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -2815,6 +2815,36 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"kek-77-Kmg.text" : {
|
||||
"comment" : "Class = \"UILabel\"; text = \"Collected Widgets \"; ObjectID = \"kek-77-Kmg\";",
|
||||
"extractionState" : "extracted_with_value",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "new",
|
||||
"value" : "Collected Widgets "
|
||||
}
|
||||
},
|
||||
"zh-Hans" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "已收纳控件 "
|
||||
}
|
||||
},
|
||||
"zh-Hant" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "已收納小工具 "
|
||||
}
|
||||
},
|
||||
"zh-HK" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "已收納小工具 "
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"kva-gQ-CZh.text" : {
|
||||
"comment" : "Class = \"UILabel\"; text = \"Size\"; ObjectID = \"kva-gQ-CZh\";",
|
||||
"extractionState" : "extracted_with_value",
|
||||
@@ -3205,6 +3235,66 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"myu-Th-CTZ.segmentTitles[0]" : {
|
||||
"comment" : "Class = \"UISegmentedControl\"; myu-Th-CTZ.segmentTitles[0] = \"coexist\"; ObjectID = \"myu-Th-CTZ\";",
|
||||
"extractionState" : "extracted_with_value",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "new",
|
||||
"value" : "coexist"
|
||||
}
|
||||
},
|
||||
"zh-Hans" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "共存"
|
||||
}
|
||||
},
|
||||
"zh-Hant" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "共存"
|
||||
}
|
||||
},
|
||||
"zh-HK" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "共存"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"myu-Th-CTZ.segmentTitles[1]" : {
|
||||
"comment" : "Class = \"UISegmentedControl\"; myu-Th-CTZ.segmentTitles[1] = \"exclusive\"; ObjectID = \"myu-Th-CTZ\";",
|
||||
"extractionState" : "extracted_with_value",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "new",
|
||||
"value" : "exclusive"
|
||||
}
|
||||
},
|
||||
"zh-Hans" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "互斥"
|
||||
}
|
||||
},
|
||||
"zh-Hant" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "互斥"
|
||||
}
|
||||
},
|
||||
"zh-HK" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "互斥"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"n6Z-cT-3a1.text" : {
|
||||
"comment" : "Class = \"UILabel\"; text = \"Mic Volume\"; ObjectID = \"n6Z-cT-3a1\";",
|
||||
"extractionState" : "extracted_with_value",
|
||||
@@ -3775,6 +3865,66 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"Oo7-lI-LXT.segmentTitles[0]" : {
|
||||
"comment" : "Class = \"UISegmentedControl\"; Oo7-lI-LXT.segmentTitles[0] = \"unfold\"; ObjectID = \"Oo7-lI-LXT\";",
|
||||
"extractionState" : "extracted_with_value",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "new",
|
||||
"value" : "unfold"
|
||||
}
|
||||
},
|
||||
"zh-Hans" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "展开"
|
||||
}
|
||||
},
|
||||
"zh-Hant" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "展開"
|
||||
}
|
||||
},
|
||||
"zh-HK" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "展開"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"Oo7-lI-LXT.segmentTitles[1]" : {
|
||||
"comment" : "Class = \"UISegmentedControl\"; Oo7-lI-LXT.segmentTitles[1] = \"fold\"; ObjectID = \"Oo7-lI-LXT\";",
|
||||
"extractionState" : "extracted_with_value",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "new",
|
||||
"value" : "fold"
|
||||
}
|
||||
},
|
||||
"zh-Hans" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "收起"
|
||||
}
|
||||
},
|
||||
"zh-Hant" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "收起"
|
||||
}
|
||||
},
|
||||
"zh-HK" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "收起"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"ozU-7C-qKE.text" : {
|
||||
"comment" : "Class = \"UILabel\"; text = \"Button down\"; ObjectID = \"ozU-7C-qKE\";",
|
||||
"extractionState" : "extracted_with_value",
|
||||
@@ -5527,6 +5677,36 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"YLN-X6-oj9.text" : {
|
||||
"comment" : "Class = \"UILabel\"; text = \" Reveal mode \"; ObjectID = \"YLN-X6-oj9\";",
|
||||
"extractionState" : "extracted_with_value",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "new",
|
||||
"value" : " Reveal mode "
|
||||
}
|
||||
},
|
||||
"zh-Hans" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : " 展开模式"
|
||||
}
|
||||
},
|
||||
"zh-Hant" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : " 展開模式"
|
||||
}
|
||||
},
|
||||
"zh-HK" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : " 展開模式"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"Z9M-yq-an2.title" : {
|
||||
"comment" : "Class = \"UIBarButtonItem\"; title = \"Import\"; ObjectID = \"Z9M-yq-an2\";",
|
||||
"extractionState" : "extracted_with_value",
|
||||
|
||||
Reference in New Issue
Block a user