diff --git a/atom/browser/ui/cocoa/atom_scrubber_data_source.h b/atom/browser/ui/cocoa/atom_scrubber_data_source.h new file mode 100644 index 0000000000..c2d6299930 --- /dev/null +++ b/atom/browser/ui/cocoa/atom_scrubber_data_source.h @@ -0,0 +1,25 @@ +// Copyright (c) 2017 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#ifndef ATOM_BROWSER_UI_COCOA_ATOM_SCRUBBER_DATA_SOURCE_H_ +#define ATOM_BROWSER_UI_COCOA_ATOM_SCRUBBER_DATA_SOURCE_H_ + +#import + +#include +#include + +#include "native_mate/persistent_dictionary.h" + +@interface AtomScrubberDataSource : NSObject { + @protected + std::vector items_; +} + +- (id)initWithItems:(std::vector)items; +- (void)setItems:(std::vector)items; + +@end + +#endif // ATOM_BROWSER_UI_COCOA_ATOM_SCRUBBER_DATA_SOURCE_H_ diff --git a/atom/browser/ui/cocoa/atom_scrubber_data_source.mm b/atom/browser/ui/cocoa/atom_scrubber_data_source.mm new file mode 100644 index 0000000000..b320d7a2c3 --- /dev/null +++ b/atom/browser/ui/cocoa/atom_scrubber_data_source.mm @@ -0,0 +1,55 @@ +// Copyright (c) 2017 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#import "atom/browser/ui/cocoa/atom_scrubber_data_source.h" + +#include "atom/common/native_mate_converters/image_converter.h" +#include "base/strings/sys_string_conversions.h" +#include "ui/gfx/image/image.h" + +@implementation AtomScrubberDataSource + +static NSString* const TextItemIdentifier = @"scrubber.text.item"; +static NSString* const ImageItemIdentifier = @"scrubber.image.item"; + +- (id)initWithItems:(std::vector)items { + if ((self = [super init])) { + items_ = items; + } + return self; +} + +- (NSInteger)numberOfItemsForScrubber:(NSScrubber *)theScrubber { + return items_.size(); +} + +- (NSScrubberItemView *)scrubber:(NSScrubber *)scrubber viewForItemAtIndex:(NSInteger)index { + mate::PersistentDictionary item = items_[index]; + + NSScrubberItemView* itemView; + std::string title; + + if (item.Get("label", &title)) { + NSScrubberTextItemView* view = [scrubber makeItemWithIdentifier:TextItemIdentifier owner:self]; + view.title = base::SysUTF8ToNSString(title); + + itemView = view; + } else { + NSScrubberImageItemView* view = [scrubber makeItemWithIdentifier:ImageItemIdentifier owner:self]; + gfx::Image image; + if (item.Get("image", &image)) { + view.image = image.AsNSImage(); + } + + itemView = view; + } + + return itemView; +} + +- (void)setItems:(std::vector)items { + items_ = items; +} + +@end diff --git a/atom/browser/ui/cocoa/atom_touch_bar.h b/atom/browser/ui/cocoa/atom_touch_bar.h index d34a1f6d47..858799b939 100644 --- a/atom/browser/ui/cocoa/atom_touch_bar.h +++ b/atom/browser/ui/cocoa/atom_touch_bar.h @@ -17,7 +17,7 @@ #include "native_mate/constructor.h" #include "native_mate/persistent_dictionary.h" -@interface AtomTouchBar : NSObject { +@interface AtomTouchBar : NSObject { @protected std::vector ordered_settings_; std::map settings_; diff --git a/atom/browser/ui/cocoa/atom_touch_bar.mm b/atom/browser/ui/cocoa/atom_touch_bar.mm index 33a6d8c343..aaf1578918 100644 --- a/atom/browser/ui/cocoa/atom_touch_bar.mm +++ b/atom/browser/ui/cocoa/atom_touch_bar.mm @@ -4,6 +4,7 @@ #import "atom/browser/ui/cocoa/atom_touch_bar.h" +#include "atom/browser/ui/cocoa/atom_scrubber_data_source.h" #include "atom/common/color_util.h" #include "atom/common/native_mate_converters/image_converter.h" #include "base/strings/sys_string_conversions.h" @@ -19,6 +20,10 @@ 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."; +static NSTouchBarItemIdentifier ScrubberIdentifier = @"com.electron.touchbar.scrubber."; + +static NSString* const TextScrubberItemIdentifier = @"scrubber.text.item"; +static NSString* const ImageScrubberItemIdentifier = @"scrubber.image.item"; - (id)initWithDelegate:(id)delegate window:(atom::NativeWindow*)window @@ -101,6 +106,9 @@ static NSTouchBarItemIdentifier SegmentedControlIdentifier = @"com.electron.touc } else if ([identifier hasPrefix:SegmentedControlIdentifier]) { item_id = [self idFromIdentifier:identifier withPrefix:SegmentedControlIdentifier]; return [self makeSegmentedControlForID:item_id withIdentifier:identifier]; + } else if ([identifier hasPrefix:ScrubberIdentifier]) { + item_id = [self idFromIdentifier:identifier withPrefix:ScrubberIdentifier]; + return [self makeScrubberForID:item_id withIdentifier:identifier]; } return nil; @@ -133,8 +141,12 @@ static NSTouchBarItemIdentifier SegmentedControlIdentifier = @"com.electron.touc [self updateSlider:(NSSliderTouchBarItem*)item withSettings:settings]; } else if (item_type == "popover") { [self updatePopover:(NSPopoverTouchBarItem*)item withSettings:settings]; - } else if (item_type == "segmented_control") + } else if (item_type == "segmented_control") { [self updateSegmentedControl:(NSCustomTouchBarItem*)item withSettings:settings]; + } else if (item_type == "scrubber") { + [self updateScrubber:(NSCustomTouchBarItem*)item withSettings:settings]; + } + } - (void)buttonAction:(id)sender { @@ -177,6 +189,20 @@ static NSTouchBarItemIdentifier SegmentedControlIdentifier = @"com.electron.touc details); } +- (void)scrubber:(NSScrubber *)scrubber didSelectItemAtIndex:(NSInteger)selectedIndex { + base::DictionaryValue details; + details.SetInteger("selectedIndex", (long)selectedIndex); + details.SetString("type", "select"); + window_->NotifyTouchBarItemInteraction([scrubber.identifier UTF8String], details); +} + +- (void)scrubber:(NSScrubber *)scrubber didHighlightItemAtIndex:(NSInteger)highlightedIndex { + base::DictionaryValue details; + details.SetInteger("highlightedIndex", (long)highlightedIndex); + details.SetString("type", "highlight"); + window_->NotifyTouchBarItemInteraction([scrubber.identifier UTF8String], details); +} + - (NSTouchBarItemIdentifier)identifierFromID:(const std::string&)item_id type:(const std::string&)type { NSTouchBarItemIdentifier base_identifier = nil; @@ -194,6 +220,8 @@ static NSTouchBarItemIdentifier SegmentedControlIdentifier = @"com.electron.touc base_identifier = GroupIdentifier; else if (type == "segmented_control") base_identifier = SegmentedControlIdentifier; + else if (type == "scrubber") + base_identifier = ScrubberIdentifier; if (base_identifier) return [NSString stringWithFormat:@"%@%s", base_identifier, item_id.data()]; @@ -467,4 +495,50 @@ static NSTouchBarItemIdentifier SegmentedControlIdentifier = @"com.electron.touc control.selectedSegment = selectedIndex; } +- (NSTouchBarItem*)makeScrubberForID:(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 item([[NSClassFromString( + @"NSCustomTouchBarItem") alloc] initWithIdentifier:identifier]); + + + int width = 320; + int height = 30; + settings.Get("frameWidth", &width); + settings.Get("frameHeight", &height); + NSScrubber* scrubber = [[NSScrubber alloc] initWithFrame:NSMakeRect(0, 0, width, height)]; + + [scrubber registerClass:[NSScrubberTextItemView class] forItemIdentifier:TextScrubberItemIdentifier]; + [scrubber registerClass:[NSScrubberImageItemView class] forItemIdentifier:ImageScrubberItemIdentifier]; + + scrubber.delegate = self; + scrubber.identifier = id; + std::vector items; + settings.Get("items", &items); + scrubber.dataSource = [[AtomScrubberDataSource alloc] initWithItems:items]; + scrubber.mode = NSScrubberModeFree; + + [item setView:scrubber]; + + [self updateScrubber:item withSettings:settings]; + return item.autorelease(); +} + +- (void)updateScrubber:(NSCustomTouchBarItem*)item + withSettings:(const mate::PersistentDictionary&)settings { + + NSScrubber* scrubber = item.view; + + std::vector items; + settings.Get("items", &items); + + AtomScrubberDataSource* source = scrubber.dataSource; + [source setItems:items]; + + [scrubber reloadData]; +} + @end diff --git a/filenames.gypi b/filenames.gypi index 44a6fbfc43..d59a08da2f 100644 --- a/filenames.gypi +++ b/filenames.gypi @@ -287,6 +287,8 @@ 'atom/browser/ui/cocoa/atom_touch_bar.h', 'atom/browser/ui/cocoa/atom_touch_bar.mm', 'atom/browser/ui/cocoa/touch_bar_forward_declarations.h', + 'atom/browser/ui/cocoa/atom_scrubber_data_source.h', + 'atom/browser/ui/cocoa/atom_scrubber_data_source.mm', 'atom/browser/ui/drag_util_mac.mm', 'atom/browser/ui/drag_util_views.cc', 'atom/browser/ui/drag_util.h', diff --git a/lib/browser/api/touch-bar.js b/lib/browser/api/touch-bar.js index 0d428cb0f0..60a82f2903 100644 --- a/lib/browser/api/touch-bar.js +++ b/lib/browser/api/touch-bar.js @@ -231,4 +231,24 @@ TouchBar.TouchBarSegmentedControl = class TouchBarSegmentedControl extends Touch } } +TouchBar.TouchBarScrubber = class TouchBarScrubber extends TouchBarItem { + constructor(config) { + super() + if (config == null) config = {} + const {items, onSelect, onHighlight} = config + this.type = 'scrubber' + this._addLiveProperty('items', items) + + if (typeof onSelect === 'function' || typeof onHighlight === 'function') { + this.onInteraction = (details) => { + if (details.type === 'select') { + onSelect(details.selectedIndex); + } else if (details.type === 'highlight') { + onHighlight(details.highlightedIndex); + } + } + } + } +} + module.exports = TouchBar