Merge pull request #8887 from electron/touchbar-segmneted-control
Touchbar segmented control
This commit is contained in:
commit
280337bf46
6 changed files with 166 additions and 3 deletions
|
@ -18,6 +18,7 @@ static NSTouchBarItemIdentifier GroupIdentifier = @"com.electron.touchbar.group.
|
|||
static NSTouchBarItemIdentifier LabelIdentifier = @"com.electron.touchbar.label.";
|
||||
static NSTouchBarItemIdentifier PopoverIdentifier = @"com.electron.touchbar.popover.";
|
||||
static NSTouchBarItemIdentifier SliderIdentifier = @"com.electron.touchbar.slider.";
|
||||
static NSTouchBarItemIdentifier SegmentedControlIdentifier = @"com.electron.touchbar.segmentedcontrol.";
|
||||
|
||||
- (id)initWithDelegate:(id<NSTouchBarDelegate>)delegate
|
||||
window:(atom::NativeWindow*)window
|
||||
|
@ -97,6 +98,9 @@ static NSTouchBarItemIdentifier SliderIdentifier = @"com.electron.touchbar.slide
|
|||
} else if ([identifier hasPrefix:GroupIdentifier]) {
|
||||
item_id = [self idFromIdentifier:identifier withPrefix:GroupIdentifier];
|
||||
return [self makeGroupForID:item_id withIdentifier:identifier];
|
||||
} else if ([identifier hasPrefix:SegmentedControlIdentifier]) {
|
||||
item_id = [self idFromIdentifier:identifier withPrefix:SegmentedControlIdentifier];
|
||||
return [self makeSegmentedControlForID:item_id withIdentifier:identifier];
|
||||
}
|
||||
|
||||
return nil;
|
||||
|
@ -129,7 +133,8 @@ static NSTouchBarItemIdentifier SliderIdentifier = @"com.electron.touchbar.slide
|
|||
[self updateSlider:(NSSliderTouchBarItem*)item withSettings:settings];
|
||||
} else if (item_type == "popover") {
|
||||
[self updatePopover:(NSPopoverTouchBarItem*)item withSettings:settings];
|
||||
}
|
||||
} else if (item_type == "segmented_control")
|
||||
[self updateSegmentedControl:(NSCustomTouchBarItem*)item withSettings:settings];
|
||||
}
|
||||
|
||||
- (void)buttonAction:(id)sender {
|
||||
|
@ -164,6 +169,14 @@ static NSTouchBarItemIdentifier SliderIdentifier = @"com.electron.touchbar.slide
|
|||
return [identifier substringFromIndex:[prefix length]];
|
||||
}
|
||||
|
||||
- (void)segmentedControlAction:(id)sender {
|
||||
NSString* item_id = [NSString stringWithFormat:@"%ld", ((NSSegmentedControl*)sender).tag];
|
||||
base::DictionaryValue details;
|
||||
details.SetInteger("selectedIndex", ((NSSegmentedControl*)sender).selectedSegment);
|
||||
window_->NotifyTouchBarItemInteraction([item_id UTF8String],
|
||||
details);
|
||||
}
|
||||
|
||||
- (NSTouchBarItemIdentifier)identifierFromID:(const std::string&)item_id
|
||||
type:(const std::string&)type {
|
||||
NSTouchBarItemIdentifier base_identifier = nil;
|
||||
|
@ -179,6 +192,8 @@ static NSTouchBarItemIdentifier SliderIdentifier = @"com.electron.touchbar.slide
|
|||
base_identifier = PopoverIdentifier;
|
||||
else if (type == "group")
|
||||
base_identifier = GroupIdentifier;
|
||||
else if (type == "segmented_control")
|
||||
base_identifier = SegmentedControlIdentifier;
|
||||
|
||||
if (base_identifier)
|
||||
return [NSString stringWithFormat:@"%@%s", base_identifier, item_id.data()];
|
||||
|
@ -384,4 +399,72 @@ static NSTouchBarItemIdentifier SliderIdentifier = @"com.electron.touchbar.slide
|
|||
items:generatedItems];
|
||||
}
|
||||
|
||||
- (NSTouchBarItem*)makeSegmentedControlForID:(NSString*)id
|
||||
withIdentifier:(NSString*)identifier {
|
||||
std::string s_id([id UTF8String]);
|
||||
if (![self hasItemWithID:s_id]) return nil;
|
||||
|
||||
mate::PersistentDictionary settings = settings_[s_id];
|
||||
base::scoped_nsobject<NSCustomTouchBarItem> item([[NSClassFromString(
|
||||
@"NSCustomTouchBarItem") alloc] initWithIdentifier:identifier]);
|
||||
|
||||
NSSegmentedControl* control = [NSSegmentedControl segmentedControlWithLabels:[NSMutableArray array]
|
||||
trackingMode:NSSegmentSwitchTrackingSelectOne
|
||||
target:self
|
||||
action:@selector(segmentedControlAction:)];
|
||||
control.tag = [id floatValue];
|
||||
[item setView:control];
|
||||
|
||||
[self updateSegmentedControl:item withSettings:settings];
|
||||
return item.autorelease();
|
||||
}
|
||||
|
||||
- (void)updateSegmentedControl:(NSCustomTouchBarItem*)item
|
||||
withSettings:(const mate::PersistentDictionary&)settings {
|
||||
|
||||
NSSegmentedControl* control = item.view;
|
||||
|
||||
std::string segmentStyle;
|
||||
settings.Get("segmentStyle", &segmentStyle);
|
||||
if (segmentStyle == "rounded")
|
||||
control.segmentStyle = NSSegmentStyleRounded;
|
||||
else if (segmentStyle == "textured-rounded")
|
||||
control.segmentStyle = NSSegmentStyleTexturedRounded;
|
||||
else if (segmentStyle == "round-rect")
|
||||
control.segmentStyle = NSSegmentStyleRoundRect;
|
||||
else if (segmentStyle == "textured-square")
|
||||
control.segmentStyle = NSSegmentStyleTexturedSquare;
|
||||
else if (segmentStyle == "capsule")
|
||||
control.segmentStyle = NSSegmentStyleCapsule;
|
||||
else if (segmentStyle == "small-square")
|
||||
control.segmentStyle = NSSegmentStyleSmallSquare;
|
||||
else if (segmentStyle == "separated")
|
||||
control.segmentStyle = NSSegmentStyleSeparated;
|
||||
else
|
||||
control.segmentStyle = NSSegmentStyleAutomatic;
|
||||
|
||||
std::vector<mate::Dictionary> segments;
|
||||
settings.Get("segments", &segments);
|
||||
|
||||
control.segmentCount = segments.size();
|
||||
for (int i = 0; i < (int)segments.size(); i++) {
|
||||
std::string label;
|
||||
gfx::Image image;
|
||||
bool enabled = true;
|
||||
segments[i].Get("enabled", &enabled);
|
||||
if (segments[i].Get("label", &label)) {
|
||||
[control setLabel:base::SysUTF8ToNSString(label) forSegment:i];
|
||||
} else if (segments[i].Get("icon", &image)) {
|
||||
[control setImage:image.AsNSImage() forSegment:i];
|
||||
[control setImageScaling:NSImageScaleProportionallyUpOrDown forSegment:i];
|
||||
}
|
||||
[control setEnabled:enabled forSegment:i];
|
||||
}
|
||||
|
||||
int selectedIndex = 0;
|
||||
settings.Get("selectedIndex", &selectedIndex);
|
||||
if (selectedIndex >= 0 && selectedIndex < control.segmentCount)
|
||||
control.selectedSegment = selectedIndex;
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -144,6 +144,15 @@ static const NSTouchBarItemIdentifier NSTouchBarItemIdentifierOtherItemsProxy =
|
|||
|
||||
@end
|
||||
|
||||
@interface NSSegmentedControl (TouchBarSDK)
|
||||
|
||||
+ (instancetype)segmentedControlWithLabels:(NSArray*)labels
|
||||
trackingMode:(NSSegmentSwitchTracking)trackingMode
|
||||
target:(id)target
|
||||
action:(SEL)action;
|
||||
|
||||
@end
|
||||
|
||||
@protocol NSTouchBarDelegate<NSObject>
|
||||
|
||||
@optional
|
||||
|
|
5
docs/api/structures/segmented-control-segment.md
Normal file
5
docs/api/structures/segmented-control-segment.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
# SegmentedControlSegment Object
|
||||
|
||||
* `label` String - (Optional) The text to appear in this segment
|
||||
* `icon` NativeImage - (Optional) The image to appear in this segment
|
||||
* `enabled` Boolean - (Optional) Whether this segment is selectable. Default: true
|
41
docs/api/touch-bar-segmented-control.md
Normal file
41
docs/api/touch-bar-segmented-control.md
Normal file
|
@ -0,0 +1,41 @@
|
|||
## Class: TouchBarSegmentedControl
|
||||
|
||||
> Create a segmented control (a button group) where one button has a selected state
|
||||
|
||||
Process: [Main](../tutorial/quick-start.md#main-process)
|
||||
|
||||
### `new TouchBarSegmentedControl(options)`
|
||||
|
||||
* `options` Object
|
||||
* `segmentStyle` String - (Optional) Style of the segments:
|
||||
* `automatic` - Default
|
||||
* `rounded`
|
||||
* `textured-rounded`
|
||||
* `round-rect`
|
||||
* `textured-square`
|
||||
* `capsule`
|
||||
* `small-square`
|
||||
* `separated`
|
||||
* `segments` [SegmentedControlSegment[]](structures/segmented-control-segment.md) - An array of segments to place in this control
|
||||
* `selectedIndex` Integer (Optional) - The index of the currently selected segment, will update automatically with user interaction
|
||||
* `change` Function - Called when the user selects a new segment
|
||||
* `selectedIndex` - The index of the segment the user selected
|
||||
|
||||
### Instance Properties
|
||||
|
||||
The following properties are available on instances of `TouchBarSegmentedControl`:
|
||||
|
||||
#### `touchBarSegmentedControl.segmentStyle`
|
||||
|
||||
A `String` representing the controls current segment style. Updating this value immediately updates the control
|
||||
in the touch bar.
|
||||
|
||||
#### `touchBarSegmentedControl.segments`
|
||||
|
||||
A `SegmentedControlSegment[]` array representing the segments in this control. Updating this value immediately
|
||||
updates the control in the touch bar. Updating deep properties inside this array **does not update the touch bar**.
|
||||
|
||||
#### `touchBarSegmentedControl.selectedIndex`
|
||||
|
||||
An `Integer` representing the currently selected segment. Changing this value immediately updates the control
|
||||
in the touch bar. User interaction with the touch bar will update this value automatically.
|
|
@ -212,4 +212,23 @@ TouchBar.TouchBarSpacer = class TouchBarSpacer extends TouchBarItem {
|
|||
}
|
||||
}
|
||||
|
||||
TouchBar.TouchBarSegmentedControl = class TouchBarSegmentedControl extends TouchBarItem {
|
||||
constructor (config) {
|
||||
super()
|
||||
if (config == null) config = {}
|
||||
const {segmentStyle, segments, selectedIndex, change} = config
|
||||
this.type = 'segmented_control'
|
||||
this._addLiveProperty('segmentStyle', segmentStyle)
|
||||
this._addLiveProperty('segments', segments || [])
|
||||
this._addLiveProperty('selectedIndex', selectedIndex)
|
||||
|
||||
if (typeof change === 'function') {
|
||||
this.onInteraction = (details) => {
|
||||
this._selectedIndex = details.selectedIndex
|
||||
change(details.selectedIndex)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = TouchBar
|
||||
|
|
|
@ -3,7 +3,7 @@ const {BrowserWindow, TouchBar} = require('electron').remote
|
|||
const {closeWindow} = require('./window-helpers')
|
||||
|
||||
const {TouchBarButton, TouchBarColorPicker, TouchBarGroup} = TouchBar
|
||||
const {TouchBarLabel, TouchBarPopover, TouchBarSlider, TouchBarSpacer} = TouchBar
|
||||
const {TouchBarLabel, TouchBarPopover, TouchBarSegmentedControl, TouchBarSlider, TouchBarSpacer} = TouchBar
|
||||
|
||||
describe('TouchBar module', function () {
|
||||
it('throws an error when created without an items array', function () {
|
||||
|
@ -41,7 +41,13 @@ describe('TouchBar module', function () {
|
|||
label,
|
||||
new TouchBarPopover({items: new TouchBar([new TouchBarButton({label: 'pop'})])}),
|
||||
new TouchBarSlider({label: 'slide', value: 5, minValue: 2, maxValue: 75, change: () => {}}),
|
||||
new TouchBarSpacer({size: 'large'})
|
||||
new TouchBarSpacer({size: 'large'}),
|
||||
new TouchBarSegmentedControl({
|
||||
segmentStyle: 'capsule',
|
||||
segments: [{label: 'baz', enabled: false}],
|
||||
selectedIndex: 5
|
||||
}),
|
||||
new TouchBarSegmentedControl({segments: []})
|
||||
])
|
||||
window.setTouchBar(touchBar)
|
||||
label.label = 'baz'
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue