diff --git a/Limelight/Base.lproj/iPad.storyboard b/Limelight/Base.lproj/iPad.storyboard index 53d1ea43..17db8330 100644 --- a/Limelight/Base.lproj/iPad.storyboard +++ b/Limelight/Base.lproj/iPad.storyboard @@ -1164,7 +1164,7 @@ - + + + + + + + + + + + + + + + + + + @@ -1322,6 +1347,8 @@ + + @@ -1450,6 +1477,9 @@ + + + diff --git a/Limelight/Base.lproj/iPhone.storyboard b/Limelight/Base.lproj/iPhone.storyboard index aa46da82..494bb740 100644 --- a/Limelight/Base.lproj/iPhone.storyboard +++ b/Limelight/Base.lproj/iPhone.storyboard @@ -321,7 +321,7 @@ - + + + + + + + + + + + + + + + + + + + + + @@ -518,6 +546,8 @@ + + diff --git a/Limelight/Input/CustomOSC/OSCProfilesManager.m b/Limelight/Input/CustomOSC/OSCProfilesManager.m index 2dc6c514..54cc1ff5 100644 --- a/Limelight/Input/CustomOSC/OSCProfilesManager.m +++ b/Limelight/Input/CustomOSC/OSCProfilesManager.m @@ -366,6 +366,7 @@ static CGRect streamViewBounds; buttonState.backgroundAlpha = widgetView.backgroundAlpha; buttonState.borderWidth = widgetView.borderWidth; buttonState.vibrationStyle = widgetView.vibrationStyle; + buttonState.mouseButtonAction = widgetView.mouseButtonAction; buttonState.sensitivityFactor = widgetView.sensitivityFactor; buttonState.stickIndicatorOffset = widgetView.stickIndicatorOffset; buttonState.widgetShape = widgetView.shape; diff --git a/Limelight/Input/CustomOSC/OnScreenButtonState.h b/Limelight/Input/CustomOSC/OnScreenButtonState.h index ac308b1d..eb91fad7 100644 --- a/Limelight/Input/CustomOSC/OnScreenButtonState.h +++ b/Limelight/Input/CustomOSC/OnScreenButtonState.h @@ -38,6 +38,7 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, assign) CGFloat oscLayerSizeFactor; // for OnScreenController CALayer @property (nonatomic, assign) CGFloat backgroundAlpha; // for OnScreenController CALayer @property (nonatomic, assign) uint8_t vibrationStyle; // for OnScreenController CALayer +@property (nonatomic, assign) uint8_t mouseButtonAction; // for OnScreenController CALayer // @property (nonatomic, assign) BOOL hasValidPosition; @@ -46,6 +47,14 @@ typedef NS_ENUM(NSInteger, OnScreenButtonType) { CustomOnScreenWidget }; +typedef NS_ENUM(NSInteger, MouseButtonAction) { + hovering, + leftButtonDown, + middleButtonDown, + rightButtonDown, +}; + + - (id) initWithButtonName:(NSString*)name buttonType:(uint8_t)buttonType andPosition:(CGPoint)position; + (BOOL) supportsSecureCoding; diff --git a/Limelight/Input/CustomOSC/OnScreenButtonState.m b/Limelight/Input/CustomOSC/OnScreenButtonState.m index dd085904..b0b4b6af 100644 --- a/Limelight/Input/CustomOSC/OnScreenButtonState.m +++ b/Limelight/Input/CustomOSC/OnScreenButtonState.m @@ -34,6 +34,7 @@ [encoder encodeObject:self.alias forKey:@"alias"]; [encoder encodeInt:self.buttonType forKey:@"buttonType"]; [encoder encodeInt:self.vibrationStyle forKey:@"vibrationStyle"]; + [encoder encodeInt:self.mouseButtonAction forKey:@"mouseButtonAction"]; [encoder encodeCGPoint:self.position forKey:@"position"]; [encoder encodeBool:self.isHidden forKey:@"isHidden"]; [encoder encodeFloat:self.widthFactor forKey:@"widthFactor"]; @@ -53,6 +54,7 @@ self.alias = [decoder decodeObjectForKey:@"alias"]; self.buttonType = [decoder decodeIntForKey:@"buttonType"]; self.vibrationStyle = [decoder decodeIntForKey:@"vibrationStyle"]; + self.mouseButtonAction = [decoder decodeIntForKey:@"mouseButtonAction"]; self.position = [decoder decodeCGPointForKey:@"position"]; self.isHidden = [decoder decodeBoolForKey:@"isHidden"]; self.widthFactor = [decoder decodeFloatForKey:@"widthFactor"]; diff --git a/Limelight/Input/OnScreenWidgetView.swift b/Limelight/Input/OnScreenWidgetView.swift index 751ea1b2..3e11396d 100644 --- a/Limelight/Input/OnScreenWidgetView.swift +++ b/Limelight/Input/OnScreenWidgetView.swift @@ -19,19 +19,19 @@ import UIKit } } + @objc public weak var guidelineDelegate: OnScreenWidgetGuidelineUpdateDelegate? + @objc protocol OnScreenWidgetGuidelineUpdateDelegate: AnyObject { func updateGuidelinesForOnScreenWidget(_ sender: Any) } - @objc public weak var guidelineDelegate: OnScreenWidgetGuidelineUpdateDelegate? - - enum WidgetTypeEnum: UInt8 { - case uninitialized = 0 - case button = 1 - case touchPad = 2 + @objc enum WidgetTypeEnum: UInt8 { + case uninitialized + case button + case touchPad } - private var widgetType: WidgetTypeEnum = WidgetTypeEnum.uninitialized + @objc public var widgetType: WidgetTypeEnum = WidgetTypeEnum.uninitialized @objc static public var editMode: Bool = false @objc public var buttonLabel: String @@ -54,7 +54,7 @@ import UIKit @objc public var storedCenter: CGPoint = .zero // location from persisted data @objc public var initialCenter: CGPoint = .zero // location from persisted data @objc public var layoutChanges: [CGPoint] = [] - + @objc public var mouseButtonAction: MouseButtonAction = .hovering; private let appWindow: UIView @@ -1034,6 +1034,21 @@ import UIKit default: break } + + if self.widgetType == WidgetTypeEnum.touchPad && self.touchPadString == "MOUSEPAD" && allCapturedTouchesCount == 1 && !twoTouchesDetected { + switch mouseButtonAction{ + case .leftButtonDown: + LiSendMouseButtonEvent(CChar(BUTTON_ACTION_PRESS), BUTTON_LEFT) + case .middleButtonDown: + LiSendMouseButtonEvent(CChar(BUTTON_ACTION_PRESS), BUTTON_MIDDLE) + case .rightButtonDown: + LiSendMouseButtonEvent(CChar(BUTTON_ACTION_PRESS), BUTTON_RIGHT) + case .hovering: + break + default: + break + } + } } /* @@ -1178,14 +1193,28 @@ import UIKit // deal with pure MOUSPAD first if !OnScreenWidgetView.editMode && self.widgetType == WidgetTypeEnum.touchPad && self.touchPadString == "MOUSEPAD" && allCapturedTouchesCount == 1 && !twoTouchesDetected { - if !mousePointerMoved && !quickDoubleTapDetected {self.sendLongMouseLeftButtonClickEvent()} // deal with single tap(click) - if quickDoubleTapDetected { //deal with quick double tap - LiSendMouseButtonEvent(CChar(BUTTON_ACTION_RELEASE), BUTTON_LEFT) //must release the button anyway, because the button is likely being held down since the long click turned into a dragging event. - if !mousePointerMoved {self.sendShortMouseLeftButtonClickEvent()} - quickDoubleTapDetected = false - } - mousePointerMoved = false // reset this flag + + switch mouseButtonAction{ + case .leftButtonDown: + LiSendMouseButtonEvent(CChar(BUTTON_ACTION_RELEASE), BUTTON_LEFT) + case .middleButtonDown: + LiSendMouseButtonEvent(CChar(BUTTON_ACTION_RELEASE), BUTTON_MIDDLE) + case .rightButtonDown: + LiSendMouseButtonEvent(CChar(BUTTON_ACTION_RELEASE), BUTTON_RIGHT) + case .hovering: + if !mousePointerMoved && !quickDoubleTapDetected {self.sendLongMouseLeftButtonClickEvent()} // deal with single tap(click) + if quickDoubleTapDetected { //deal with quick double tap + LiSendMouseButtonEvent(CChar(BUTTON_ACTION_RELEASE), BUTTON_LEFT) //must release the button anyway, because the button is likely being held down since the long click turned into a dragging event. + if !mousePointerMoved {self.sendShortMouseLeftButtonClickEvent()} + quickDoubleTapDetected = false + } + mousePointerMoved = false // reset this flag + default: + break + } } + + if !OnScreenWidgetView.editMode && self.widgetType == WidgetTypeEnum.touchPad && self.touchPadString == "MOUSEPAD" && twoTouchesDetected && touches.count == allCapturedTouchesCount { // need to enable multi-touch first // touches.count == allCapturedTouchesCount means allfingers are lifting self.sendMouseRightButtonClickEvent() diff --git a/Limelight/Input/StreamView.m b/Limelight/Input/StreamView.m index 22859504..a7f5f2c6 100644 --- a/Limelight/Input/StreamView.m +++ b/Limelight/Input/StreamView.m @@ -403,6 +403,7 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5; widgetView.heightFactor = buttonState.heightFactor; widgetView.borderWidth = buttonState.borderWidth; [widgetView setVibrationWithStyle:buttonState.vibrationStyle]; + widgetView.mouseButtonAction = buttonState.mouseButtonAction; widgetView.sensitivityFactor = buttonState.sensitivityFactor; widgetView.stickIndicatorOffset = buttonState.stickIndicatorOffset; widgetView.minStickOffset = buttonState.minStickOffset; diff --git a/Limelight/Moonlight-Bridging-Header.h b/Limelight/Moonlight-Bridging-Header.h index f1856fc6..da39191d 100644 --- a/Limelight/Moonlight-Bridging-Header.h +++ b/Limelight/Moonlight-Bridging-Header.h @@ -4,4 +4,5 @@ #include #import "OnScreenControls.h" +#import "OnScreenButtonState.h" // #import "RelativeTouchHandler.h" diff --git a/Limelight/ViewControllers/CustomOSCViewControl/LayoutOnScreenControlsViewController.h b/Limelight/ViewControllers/CustomOSCViewControl/LayoutOnScreenControlsViewController.h index 54557f80..764f0a95 100644 --- a/Limelight/ViewControllers/CustomOSCViewControl/LayoutOnScreenControlsViewController.h +++ b/Limelight/ViewControllers/CustomOSCViewControl/LayoutOnScreenControlsViewController.h @@ -80,6 +80,8 @@ NS_ASSUME_NONNULL_BEGIN @property (strong, nonatomic) IBOutlet UILabel *loadConfigTipLabel; +@property (strong, nonatomic) IBOutlet UIStackView *mouseDownButtonStack; +@property (strong, nonatomic) IBOutlet UISegmentedControl *mouseButtonDownSelector; diff --git a/Limelight/ViewControllers/CustomOSCViewControl/LayoutOnScreenControlsViewController.m b/Limelight/ViewControllers/CustomOSCViewControl/LayoutOnScreenControlsViewController.m index 01a598c9..b130d492 100644 --- a/Limelight/ViewControllers/CustomOSCViewControl/LayoutOnScreenControlsViewController.m +++ b/Limelight/ViewControllers/CustomOSCViewControl/LayoutOnScreenControlsViewController.m @@ -108,6 +108,7 @@ widgetView.heightFactor = buttonState.heightFactor; widgetView.borderWidth = buttonState.borderWidth; [widgetView setVibrationWithStyle:buttonState.vibrationStyle]; + widgetView.mouseButtonAction = buttonState.mouseButtonAction; widgetView.sensitivityFactor = buttonState.sensitivityFactor; widgetView.stickIndicatorOffset = buttonState.stickIndicatorOffset; widgetView.minStickOffset = buttonState.minStickOffset; @@ -555,6 +556,7 @@ - (void) updateWidget:(OnScreenWidgetView* )widget byParams:(NSMutableDictionary* )widgetInitParams createNew:(bool)createNew{ if(![self isWidgetParamsValid:widgetInitParams]) return; OnScreenWidgetView* newWidget = [[OnScreenWidgetView alloc] initWithCmdString:widgetInitParams[@"cmdString"] buttonLabel:widgetInitParams[@"buttonLabel"] shape:widgetInitParams[@"shape"]]; //reconstruct widgetView + newWidget.guidelineDelegate = (id)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; newWidget.heightFactor = widget.heightFactor; @@ -563,7 +565,7 @@ newWidget.stickIndicatorOffset = widget.stickIndicatorOffset; newWidget.minStickOffset = [widgetInitParams[@"minStickOffsetString"] floatValue]; [newWidget setVibrationWithStyle:widget.vibrationStyle]; - // Add the widgetView to the view controller's view + newWidget.mouseButtonAction = widget.mouseButtonAction; [self.view insertSubview:newWidget belowSubview:self.widgetPanelStack]; if(createNew) [newWidget setLocationWithPosition:CGPointMake(90, 130)]; @@ -571,7 +573,6 @@ [newWidget resizeWidgetView]; // resize must be called after relocation [newWidget adjustTransparencyWithAlpha:widget.backgroundAlpha]; [newWidget adjustBorderWithWidth:widget.borderWidth]; - [newWidget setVibrationWithStyle:widget.vibrationStyle]; [self.OnScreenWidgetViews addObject:newWidget]; self->selectedWidgetView = newWidget; if(!createNew){ @@ -585,6 +586,7 @@ if(![self isWidgetParamsValid:widgetInitParams]) return; //saving & present the keyboard button: OnScreenWidgetView* widgetView = [[OnScreenWidgetView alloc] initWithCmdString:widgetInitParams[@"cmdString"] buttonLabel:widgetInitParams[@"buttonLabel"] shape:widgetInitParams[@"shape"]]; + widgetView.guidelineDelegate = (id)self; widgetView.translatesAutoresizingMaskIntoConstraints = NO; // weird but this is mandatory, or you will find no key views added to the right place widgetView.minStickOffset = [widgetInitParams[@"minStickOffsetString"] floatValue]; [self.OnScreenWidgetViews addObject:widgetView]; @@ -659,6 +661,7 @@ self.sensitivityStack.hidden = !showSensitivityFactorSlider; self.stickIndicatorOffsetStack.hidden = !showStickIndicatorOffsetSlider; + self.mouseDownButtonStack.hidden = !([selectedWidgetView.cmdString containsString:@"MOUSEPAD"] && selectedWidgetView.widgetType == WidgetTypeEnumTouchPad); [self autoFitView:self.widgetPanelStack]; if(showSensitivityFactorSlider){ @@ -679,7 +682,12 @@ [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]]; + + self.mouseButtonDownSelector.selectedSegmentIndex = selectedWidgetView.mouseButtonAction; + if([self isIPhone]){ + self.vibrationStyleStack.hidden = [widgetView.cmdString containsString:@"MOUSEPAD"]; + [self autoFitView:self.widgetPanelStack]; self.vibrationStyleSelector.selectedSegmentIndex = self->selectedWidgetView.vibrationStyle; } } @@ -710,6 +718,7 @@ [self.widgetHeightLabel setText:[LocalizationHelper localizedStringForKey:@"Height: %.2f", sizeFactor]]; [self.widgetAlphaLabel setText:[LocalizationHelper localizedStringForKey:@"Alpha: %.2f", alpha]]; if([self isIPhone]){ + self.vibrationStyleStack.hidden = NO; NSNumber *style = [OnScreenControls.layerVibrationStyleDic objectForKey:selectedControllerLayer.name]; self.vibrationStyleSelector.selectedSegmentIndex = [style unsignedCharValue]; } @@ -762,6 +771,12 @@ return; } +- (void)mouseDownButtonChanged:(UISegmentedControl* )sender{ + if(self->selectedWidgetView != nil && self->widgetViewSelected){ + selectedWidgetView.mouseButtonAction = _mouseButtonDownSelector.selectedSegmentIndex; + } +} + - (void)vibrationStyleChanged:(UISegmentedControl* )sender{ bool vibraiontOn; if (@available(iOS 13.0, *)) { @@ -878,14 +893,18 @@ self.stickIndicatorOffsetLabel.text = [LocalizationHelper localizedStringForKey:@"Indicator Offset"]; self.stickIndicatorOffsetStack.hidden = YES; + [self.mouseButtonDownSelector addTarget:self action:@selector(mouseDownButtonChanged:) forControlEvents:(UIControlEventValueChanged)]; + NSDictionary *whiteFontAttributes = @{ + NSForegroundColorAttributeName: [UIColor whiteColor] + }; + [self.mouseButtonDownSelector setTitleTextAttributes:whiteFontAttributes forState:UIControlStateNormal]; + self.mouseDownButtonStack.hidden = YES; + if([self isIPhone]){ [self.vibrationStyleSelector addTarget:self action:@selector(vibrationStyleChanged:) forControlEvents:(UIControlEventValueChanged)]; self.vibrationStyleStack.hidden = YES; - NSDictionary *normalAttributes = @{ - NSForegroundColorAttributeName: [UIColor whiteColor] - }; - [self.vibrationStyleSelector setTitleTextAttributes:normalAttributes forState:UIControlStateNormal]; + [self.vibrationStyleSelector setTitleTextAttributes:whiteFontAttributes forState:UIControlStateNormal]; } diff --git a/Limelight/mul.lproj/iPad.xcstrings b/Limelight/mul.lproj/iPad.xcstrings index 01bd678a..ef6dcd39 100644 --- a/Limelight/mul.lproj/iPad.xcstrings +++ b/Limelight/mul.lproj/iPad.xcstrings @@ -643,6 +643,36 @@ } } }, + "c1r-Hf-b7t.text" : { + "comment" : "Class = \"UILabel\"; text = \"Down Button\"; ObjectID = \"c1r-Hf-b7t\";", + "extractionState" : "extracted_with_value", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Down Button" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "鼠标按下" + } + }, + "zh-Hant" : { + "stringUnit" : { + "state" : "translated", + "value" : "鼠标按下" + } + }, + "zh-HK" : { + "stringUnit" : { + "state" : "translated", + "value" : "鼠标按下" + } + } + } + }, "ckc-Dm-8ex.segmentTitles[0]" : { "comment" : "Class = \"UISegmentedControl\"; ckc-Dm-8ex.segmentTitles[0] = \"360p\"; ObjectID = \"ckc-Dm-8ex\";", "extractionState" : "extracted_with_value", @@ -1093,6 +1123,126 @@ } } }, + "H8S-aI-EBo.segmentTitles[0]" : { + "comment" : "Class = \"UISegmentedControl\"; H8S-aI-EBo.segmentTitles[0] = \"hovering\"; ObjectID = \"H8S-aI-EBo\";", + "extractionState" : "extracted_with_value", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "hovering" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "悬浮" + } + }, + "zh-Hant" : { + "stringUnit" : { + "state" : "translated", + "value" : "悬浮" + } + }, + "zh-HK" : { + "stringUnit" : { + "state" : "translated", + "value" : "悬浮" + } + } + } + }, + "H8S-aI-EBo.segmentTitles[1]" : { + "comment" : "Class = \"UISegmentedControl\"; H8S-aI-EBo.segmentTitles[1] = \"left button\"; ObjectID = \"H8S-aI-EBo\";", + "extractionState" : "extracted_with_value", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "left button" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "左键" + } + }, + "zh-Hant" : { + "stringUnit" : { + "state" : "translated", + "value" : "左键" + } + }, + "zh-HK" : { + "stringUnit" : { + "state" : "translated", + "value" : "左键" + } + } + } + }, + "H8S-aI-EBo.segmentTitles[2]" : { + "comment" : "Class = \"UISegmentedControl\"; H8S-aI-EBo.segmentTitles[2] = \"middle button\"; ObjectID = \"H8S-aI-EBo\";", + "extractionState" : "extracted_with_value", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "middle button" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "中键" + } + }, + "zh-Hant" : { + "stringUnit" : { + "state" : "translated", + "value" : "中键" + } + }, + "zh-HK" : { + "stringUnit" : { + "state" : "translated", + "value" : "中键" + } + } + } + }, + "H8S-aI-EBo.segmentTitles[3]" : { + "comment" : "Class = \"UISegmentedControl\"; H8S-aI-EBo.segmentTitles[3] = \"right button\"; ObjectID = \"H8S-aI-EBo\";", + "extractionState" : "extracted_with_value", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "right button" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "右键" + } + }, + "zh-Hant" : { + "stringUnit" : { + "state" : "translated", + "value" : "右键" + } + }, + "zh-HK" : { + "stringUnit" : { + "state" : "translated", + "value" : "右键" + } + } + } + }, "hAo-1k-oYF.text" : { "comment" : "Class = \"UILabel\"; text = \"90° Display Rotation\"; ObjectID = \"hAo-1k-oYF\";", "extractionState" : "extracted_with_value", @@ -1105,19 +1255,19 @@ }, "zh-Hans" : { "stringUnit" : { - "state" : "needs_review", + "state" : "translated", "value" : "90°转屏" } }, "zh-Hant" : { "stringUnit" : { - "state" : "needs_review", + "state" : "translated", "value" : "90°转屏" } }, "zh-HK" : { "stringUnit" : { - "state" : "needs_review", + "state" : "translated", "value" : "90°转屏" } } diff --git a/Limelight/mul.lproj/iPhone.xcstrings b/Limelight/mul.lproj/iPhone.xcstrings index 52e16056..14703690 100644 --- a/Limelight/mul.lproj/iPhone.xcstrings +++ b/Limelight/mul.lproj/iPhone.xcstrings @@ -1807,6 +1807,36 @@ } } }, + "ozU-7C-qKE.text" : { + "comment" : "Class = \"UILabel\"; text = \"Button Down\"; ObjectID = \"ozU-7C-qKE\";", + "extractionState" : "extracted_with_value", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Button Down" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "鼠标按下" + } + }, + "zh-Hant" : { + "stringUnit" : { + "state" : "translated", + "value" : "鼠标按下" + } + }, + "zh-HK" : { + "stringUnit" : { + "state" : "translated", + "value" : "鼠标按下" + } + } + } + }, "Pdb-Bs-kMJ.text" : { "comment" : "Class = \"UILabel\"; text = \"Statistics Overlay\"; ObjectID = \"Pdb-Bs-kMJ\";", "extractionState" : "extracted_with_value", @@ -2149,6 +2179,126 @@ } } }, + "tE5-Bm-4OB.segmentTitles[0]" : { + "comment" : "Class = \"UISegmentedControl\"; tE5-Bm-4OB.segmentTitles[0] = \"hovering\"; ObjectID = \"tE5-Bm-4OB\";", + "extractionState" : "extracted_with_value", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "hovering" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "悬浮" + } + }, + "zh-Hant" : { + "stringUnit" : { + "state" : "translated", + "value" : "悬浮" + } + }, + "zh-HK" : { + "stringUnit" : { + "state" : "translated", + "value" : "悬浮" + } + } + } + }, + "tE5-Bm-4OB.segmentTitles[1]" : { + "comment" : "Class = \"UISegmentedControl\"; tE5-Bm-4OB.segmentTitles[1] = \"left button\"; ObjectID = \"tE5-Bm-4OB\";", + "extractionState" : "extracted_with_value", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "left button" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "左键" + } + }, + "zh-Hant" : { + "stringUnit" : { + "state" : "translated", + "value" : "左键" + } + }, + "zh-HK" : { + "stringUnit" : { + "state" : "translated", + "value" : "左键" + } + } + } + }, + "tE5-Bm-4OB.segmentTitles[2]" : { + "comment" : "Class = \"UISegmentedControl\"; tE5-Bm-4OB.segmentTitles[2] = \"middle button\"; ObjectID = \"tE5-Bm-4OB\";", + "extractionState" : "extracted_with_value", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "middle button" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "中键" + } + }, + "zh-Hant" : { + "stringUnit" : { + "state" : "translated", + "value" : "中键" + } + }, + "zh-HK" : { + "stringUnit" : { + "state" : "translated", + "value" : "中键" + } + } + } + }, + "tE5-Bm-4OB.segmentTitles[3]" : { + "comment" : "Class = \"UISegmentedControl\"; tE5-Bm-4OB.segmentTitles[3] = \"right button\"; ObjectID = \"tE5-Bm-4OB\";", + "extractionState" : "extracted_with_value", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "right button" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "右键" + } + }, + "zh-Hant" : { + "stringUnit" : { + "state" : "translated", + "value" : "右键" + } + }, + "zh-HK" : { + "stringUnit" : { + "state" : "translated", + "value" : "右键" + } + } + } + }, "TJx-6E-kgr.segmentTitles[0]" : { "comment" : "Class = \"UISegmentedControl\"; TJx-6E-kgr.segmentTitles[0] = \"No\"; ObjectID = \"TJx-6E-kgr\";", "extractionState" : "extracted_with_value",