diff --git a/atom/browser/native_window_mac.mm b/atom/browser/native_window_mac.mm index 4f720ef2a928..9ef09f625dfd 100644 --- a/atom/browser/native_window_mac.mm +++ b/atom/browser/native_window_mac.mm @@ -7,7 +7,7 @@ #include #include -#include "atom/browser/ui/cocoa/touch_bar_forward_declarations.h" +#include "atom/browser/ui/cocoa/atom_touch_bar.h" #include "atom/browser/window_list.h" #include "atom/common/color_util.h" #include "atom/common/draggable_region.h" @@ -356,18 +356,17 @@ bool ScopedDisableResize::disable_resize_ = false; - (void)reloadTouchBar; - (void)refreshTouchBarItem:(mate::Arguments*)args; - (void)resetTouchBar; -- (NSTouchBar*)touchBarFromMutatableArray:(NSMutableArray*)items; @end @interface AtomNSWindow () @end @implementation AtomNSWindow - std::map item_id_map; - std::map item_map; + base::scoped_nsobject touch_bar_; - (void)setShell:(atom::NativeWindowMac*)shell { shell_ = shell; + touch_bar_.reset([[AtomTouchBar alloc] initWithDelegate:self window:shell]); } - (void)setEnableLargerThanScreen:(bool)enable { @@ -378,357 +377,26 @@ bool ScopedDisableResize::disable_resize_ = false; self.touchBar = nil; } -- (NSMutableArray*)identifierArrayFromDicts:(std::vector)dicts { - NSMutableArray* idents = [[NSMutableArray alloc] init]; - - for (mate::PersistentDictionary &item : dicts) { - std::string type; - std::string item_id; - if (item.Get("type", &type) && item.Get("id", &item_id)) { - item_id_map.insert(make_pair(item_id, item)); - if (type == "button") { - [idents addObject:[NSString stringWithFormat:@"%@%@", ButtonIdentifier, [NSString stringWithUTF8String:item_id.c_str()]]]; - } else if (type == "label") { - [idents addObject:[NSString stringWithFormat:@"%@%@", LabelIdentifier, [NSString stringWithUTF8String:item_id.c_str()]]]; - } else if (type == "colorpicker") { - [idents addObject:[NSString stringWithFormat:@"%@%@", ColorPickerIdentifier, [NSString stringWithUTF8String:item_id.c_str()]]]; - } else if (type == "slider") { - [idents addObject:[NSString stringWithFormat:@"%@%@", SliderIdentifier, [NSString stringWithUTF8String:item_id.c_str()]]]; - } else if (type == "popover") { - [idents addObject:[NSString stringWithFormat:@"%@%@", PopOverIdentifier, [NSString stringWithUTF8String:item_id.c_str()]]]; - } else if (type == "group") { - [idents addObject:[NSString stringWithFormat:@"%@%@", GroupIdentifier, [NSString stringWithUTF8String:item_id.c_str()]]]; - } - } - } - [idents addObject:NSTouchBarItemIdentifierOtherItemsProxy]; - - return idents; -} - -- (void)refreshTouchBarItem:(mate::Arguments*)args { - std::string item_id; - std::string type; - mate::PersistentDictionary dict; - if (args->GetNext(&dict) && dict.Get("type", &type) && dict.Get("id", &item_id)) { - if (item_map.find(item_id) != item_map.end()) { - if (type == "button") { - [self updateButton:(NSCustomTouchBarItem *)item_map[item_id] withOpts:dict withID:[NSString stringWithUTF8String:item_id.c_str()] andCreate:false]; - } else if (type == "label") { - [self updateLabel:(NSCustomTouchBarItem *)item_map[item_id] withOpts:dict]; - } else if (type == "colorpicker") { - [self updateColorPicker:(NSColorPickerTouchBarItem *)item_map[item_id] withOpts:dict]; - } else if (type == "slider") { - [self updateSlider:(NSSliderTouchBarItem *)item_map[item_id] withOpts:dict]; - } else if (type == "popover") { - [self updatePopOver:(NSPopoverTouchBarItem *)item_map[item_id] withOpts:dict]; - } else if (type == "group") { - args->ThrowError("You can not update the config of a group. Update the individual items or replace the group"); - } - } - } -} - - (void)reloadTouchBar { - item_id_map.clear(); + [touch_bar_ clear]; self.touchBar = nil; } +- (void)refreshTouchBarItem:(mate::Arguments*)args { + [touch_bar_ refreshTouchBarItem:args]; +} + - (NSTouchBar*)makeTouchBar { - NSMutableArray* item_identifiers = - [self identifierArrayFromDicts:shell_->GetTouchBarItems()]; - return [self touchBarFromMutatableArray:item_identifiers]; + return [touch_bar_ makeTouchBarFromItemOptions:shell_->GetTouchBarItems()]; } -- (NSTouchBar*)touchBarFromMutatableArray:(NSMutableArray*)items { - NSTouchBar* bar = [[NSClassFromString(@"NSTouchBar") alloc] init]; - bar.delegate = self; - bar.defaultItemIdentifiers = items; - return bar; +- (nullable NSTouchBarItem*)touchBar:(NSTouchBar*)touchBar makeItemForIdentifier:(NSTouchBarItemIdentifier)identifier { + return [touch_bar_ makeItemForIdentifier:identifier]; } -- (void)buttonAction:(id)sender { - NSString* item_id = [NSString stringWithFormat:@"%@.%d", ButtonIdentifier, (int)((NSButton *)sender).tag]; - shell_->NotifyTouchBarItemInteraction("button", { std::string([item_id UTF8String]) }); -} - -- (void)colorPickerAction:(id)sender { - NSString* item_id = ((NSColorPickerTouchBarItem *)sender).identifier; - NSColor* color = ((NSColorPickerTouchBarItem *)sender).color; - std::string hex_color = atom::ToRGBHex(skia::NSDeviceColorToSkColor(color)); - shell_->NotifyTouchBarItemInteraction("color_picker", { std::string([item_id UTF8String]), hex_color }); -} - -- (void)sliderAction:(id)sender { - NSString* item_id = ((NSSliderTouchBarItem *)sender).identifier; - shell_->NotifyTouchBarItemInteraction("slider", { std::string([item_id UTF8String]), std::to_string([((NSSliderTouchBarItem *)sender).slider intValue]) }); -} - -- (NSString*)idFromIdentifier:(NSString*)identifier withPrefix:(NSString*)prefix { - return [identifier substringFromIndex:[prefix length]]; -} - -- (bool)hasTBDict:(std::string)id { - return item_id_map.find(id) != item_id_map.end(); -} - -- (NSColor*)colorFromHexColorString:(NSString*)inColorString { - SkColor color = atom::ParseHexColor([inColorString UTF8String]); - return skia::SkColorToCalibratedNSColor(color); -} - -- (NSButton*)makeButtonForDict:(mate::PersistentDictionary)dict withLabel:(std::string)label { - NSButton *theButton = [NSButton buttonWithTitle:[NSString stringWithUTF8String:label.c_str()] target:self action:@selector(buttonAction:)]; - - return [self updateNSButton:theButton forDict:dict withLabel:label]; -} - -- (NSButton*)updateNSButton:(NSButton*)theButton forDict:(mate::PersistentDictionary)dict withLabel:(std::string)label { - std::string backgroundColor; - if (dict.Get("backgroundColor", &backgroundColor)) { - theButton.bezelColor = [self colorFromHexColorString:[NSString stringWithUTF8String:backgroundColor.c_str()]]; - } - - std::string labelColor; - if (dict.Get("labelColor", &labelColor)) { - NSMutableAttributedString *attrTitle = [[[NSMutableAttributedString alloc] initWithString:[NSString stringWithUTF8String:label.c_str()]] autorelease]; - NSUInteger len = [attrTitle length]; - NSRange range = NSMakeRange(0, len); - [attrTitle addAttribute:NSForegroundColorAttributeName value:[self colorFromHexColorString:[NSString stringWithUTF8String:labelColor.c_str()]] range:range]; - [attrTitle fixAttributesInRange:range]; - [theButton setAttributedTitle:attrTitle]; - } - - gfx::Image image; - if (dict.Get("image", &image)) { - theButton.image = image.AsNSImage(); - } - return theButton; -} - -- (nullable NSTouchBarItem *)makeButtonForID:(NSString*)id withIdentifier:(NSString*)identifier { - std::string s_id = std::string([id UTF8String]); - if (![self hasTBDict:s_id]) return nil; - mate::PersistentDictionary item = item_id_map[s_id]; - NSCustomTouchBarItem *customItem = [[NSClassFromString(@"NSCustomTouchBarItem") alloc] initWithIdentifier:identifier]; - return [self updateButton:customItem withOpts:item withID:id andCreate:true]; -} - -- (nullable NSTouchBarItem *)updateButton:(NSCustomTouchBarItem*)customItem withOpts:(mate::PersistentDictionary)item withID:(NSString*)id andCreate:(bool)create { - std::string label; - if (item.Get("label", &label)) { - NSButton* theButton = nil; - if (!create) { - theButton = (NSButton*)customItem.view; - [self updateNSButton:theButton forDict:item withLabel:label]; - } else { - theButton = [self makeButtonForDict:item withLabel:label]; - } - theButton.tag = [id floatValue]; - - customItem.view = theButton; - - std::string customizationLabel; - if (item.Get("customizationLabel", &customizationLabel)) { - customItem.customizationLabel = [NSString stringWithUTF8String:customizationLabel.c_str()]; - } - - return customItem; - } - return nil; -} - -- (nullable NSTouchBarItem*) makeLabelForID:(NSString*)id withIdentifier:(NSString*)identifier { - std::string s_id = std::string([id UTF8String]); - if (![self hasTBDict:s_id]) return nil; - mate::PersistentDictionary item = item_id_map[s_id]; - NSCustomTouchBarItem *customItem = [[NSClassFromString(@"NSCustomTouchBarItem") alloc] initWithIdentifier:identifier]; - return [self updateLabel:customItem withOpts:item]; -} - -- (nullable NSTouchBarItem*) updateLabel:(NSCustomTouchBarItem*)customItem withOpts:(mate::PersistentDictionary)item { - std::string label; - if (item.Get("label", &label)) { - NSTextField *theLabel = [NSTextField labelWithString:[NSString stringWithUTF8String:label.c_str()]]; - - customItem.view = theLabel; - - std::string customizationLabel; - if (item.Get("customizationLabel", &customizationLabel)) { - customItem.customizationLabel = [NSString stringWithUTF8String:customizationLabel.c_str()]; - } - - return customItem; - } - return nil; -} - -- (nullable NSTouchBarItem*) makeColorPickerForID:(NSString*)id withIdentifier:(NSString*)identifier { - std::string s_id = std::string([id UTF8String]); - if (![self hasTBDict:s_id]) return nil; - mate::PersistentDictionary item = item_id_map[s_id]; - NSColorPickerTouchBarItem *colorPickerItem = [[NSClassFromString(@"NSColorPickerTouchBarItem") alloc] initWithIdentifier:identifier]; - return [self updateColorPicker:colorPickerItem withOpts:item]; -} - -- (nullable NSTouchBarItem*) updateColorPicker:(NSColorPickerTouchBarItem*)colorPickerItem withOpts:(mate::PersistentDictionary)item { - colorPickerItem.target = self; - colorPickerItem.action = @selector(colorPickerAction:); - - std::string customizationLabel; - if (item.Get("customizationLabel", &customizationLabel)) { - colorPickerItem.customizationLabel = [NSString stringWithUTF8String:customizationLabel.c_str()]; - } - - return colorPickerItem; -} - -- (nullable NSTouchBarItem*) makeSliderForID:(NSString*)id withIdentifier:(NSString*)identifier { - std::string s_id = std::string([id UTF8String]); - if (![self hasTBDict:s_id]) return nil; - mate::PersistentDictionary item = item_id_map[s_id]; - NSSliderTouchBarItem *sliderItem = [[NSClassFromString(@"NSSliderTouchBarItem") alloc] initWithIdentifier:identifier]; - return [self updateSlider:sliderItem withOpts:item]; -} - -- (nullable NSTouchBarItem*) updateSlider:(NSSliderTouchBarItem*)sliderItem withOpts:(mate::PersistentDictionary)item { - sliderItem.target = self; - sliderItem.action = @selector(sliderAction:); - - std::string customizationLabel; - if (item.Get("customizationLabel", &customizationLabel)) { - sliderItem.customizationLabel = [NSString stringWithUTF8String:customizationLabel.c_str()]; - } - - std::string label; - if (item.Get("label", &label)) { - sliderItem.label = [NSString stringWithUTF8String:label.c_str()]; - } - - int maxValue = 100; - int minValue = 0; - int initialValue = 50; - item.Get("minValue", &minValue); - item.Get("maxValue", &maxValue); - item.Get("initialValue", &initialValue); - - sliderItem.slider.minValue = minValue; - sliderItem.slider.maxValue = maxValue; - sliderItem.slider.doubleValue = initialValue; - - return sliderItem; -} - -- (nullable NSTouchBarItem*) makePopOverForID:(NSString*)id withIdentifier:(NSString*)identifier { - std::string s_id = std::string([id UTF8String]); - if (![self hasTBDict:s_id]) return nil; - mate::PersistentDictionary item = item_id_map[s_id]; - NSPopoverTouchBarItem *popOverItem = [[NSClassFromString(@"NSPopoverTouchBarItem") alloc] initWithIdentifier:identifier]; - return [self updatePopOver:popOverItem withOpts:item]; -} - -- (nullable NSTouchBarItem*) updatePopOver:(NSPopoverTouchBarItem*)popOverItem withOpts:(mate::PersistentDictionary)item { - std::string customizationLabel; - if (item.Get("customizationLabel", &customizationLabel)) { - popOverItem.customizationLabel = [NSString stringWithUTF8String:customizationLabel.c_str()]; - } - - std::string label; - gfx::Image image; - if (item.Get("label", &label)) { - popOverItem.collapsedRepresentationLabel = [NSString stringWithUTF8String:label.c_str()]; - } else if (item.Get("image", &image)) { - popOverItem.collapsedRepresentationImage = image.AsNSImage(); - } - - bool showCloseButton; - if (item.Get("showCloseButton", &showCloseButton)) { - popOverItem.showsCloseButton = showCloseButton; - } - - std::vector touchBar; - if (item.Get("touchBar", &touchBar)) { - popOverItem.popoverTouchBar = [self touchBarFromMutatableArray:[self identifierArrayFromDicts:touchBar]]; - } else { - return nil; - } - - return popOverItem; -} - -- (nullable NSTouchBarItem*) makeGroupForID:(NSString*)id withIdentifier:(NSString*)identifier { - std::string s_id = std::string([id UTF8String]); - if (![self hasTBDict:s_id]) return nil; - mate::PersistentDictionary item = item_id_map[s_id]; - - std::vector items; - if (!item.Get("items", &items)) { - return nil; - } - - NSMutableArray* generatedItems = [[NSMutableArray alloc] init]; - NSMutableArray* identList = [self identifierArrayFromDicts:items]; - for (NSUInteger i = 0; i < [identList count]; i++) { - if ([identList objectAtIndex:i] != NSTouchBarItemIdentifierOtherItemsProxy) { - NSTouchBarItem* generatedItem = [self makeItemForIdentifier:[identList objectAtIndex:i]]; - if (generatedItem) { - [generatedItems addObject:generatedItem]; - } - } - } - NSGroupTouchBarItem *groupItem = [NSClassFromString(@"NSGroupTouchBarItem") groupItemWithIdentifier:identifier items:generatedItems]; - - std::string customizationLabel; - if (item.Get("customizationLabel", &customizationLabel)) { - groupItem.customizationLabel = [NSString stringWithUTF8String:customizationLabel.c_str()]; - } - - return groupItem; -} - -static NSTouchBarItemIdentifier ButtonIdentifier = @"com.electron.tb.button."; -static NSTouchBarItemIdentifier ColorPickerIdentifier = @"com.electron.tb.colorpicker."; -static NSTouchBarItemIdentifier GroupIdentifier = @"com.electron.tb.group."; -static NSTouchBarItemIdentifier LabelIdentifier = @"com.electron.tb.label."; -static NSTouchBarItemIdentifier PopOverIdentifier = @"com.electron.tb.popover."; -static NSTouchBarItemIdentifier SliderIdentifier = @"com.electron.tb.slider."; - -- (nullable NSTouchBarItem *)makeItemForIdentifier:(NSTouchBarItemIdentifier)identifier { - NSTouchBarItem * item = nil; - NSString * id = nil; - if ([identifier hasPrefix:ButtonIdentifier]) { - id = [self idFromIdentifier:identifier withPrefix:ButtonIdentifier]; - item = [self makeButtonForID:id withIdentifier:identifier]; - } else if ([identifier hasPrefix:LabelIdentifier]) { - id = [self idFromIdentifier:identifier withPrefix:LabelIdentifier]; - item = [self makeLabelForID:id withIdentifier:identifier]; - } else if ([identifier hasPrefix:ColorPickerIdentifier]) { - id = [self idFromIdentifier:identifier withPrefix:ColorPickerIdentifier]; - item = [self makeColorPickerForID:id withIdentifier:identifier]; - } else if ([identifier hasPrefix:SliderIdentifier]) { - id = [self idFromIdentifier:identifier withPrefix:SliderIdentifier]; - item = [self makeSliderForID:id withIdentifier:identifier]; - } else if ([identifier hasPrefix:PopOverIdentifier]) { - id = [self idFromIdentifier:identifier withPrefix:PopOverIdentifier]; - item = [self makePopOverForID:id withIdentifier:identifier]; - } else if ([identifier hasPrefix:GroupIdentifier]) { - id = [self idFromIdentifier:identifier withPrefix:GroupIdentifier]; - item = [self makeGroupForID:id withIdentifier:identifier]; - } - - item_map.insert(make_pair(std::string([id UTF8String]), item)); - - return item; -} - -- (nullable NSTouchBarItem *)touchBar:(NSTouchBar *)touchBar makeItemForIdentifier:(NSTouchBarItemIdentifier)identifier { - return [self makeItemForIdentifier:identifier]; -} - - // NSWindow overrides. -- (void)swipeWithEvent:(NSEvent *)event { +- (void)swipeWithEvent:(NSEvent*)event { if (event.deltaY == 1.0) { shell_->NotifyWindowSwipe("up"); } else if (event.deltaX == -1.0) { diff --git a/atom/browser/ui/cocoa/atom_touch_bar.h b/atom/browser/ui/cocoa/atom_touch_bar.h new file mode 100644 index 000000000000..2bd5a736ec12 --- /dev/null +++ b/atom/browser/ui/cocoa/atom_touch_bar.h @@ -0,0 +1,63 @@ +// 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_TOUCH_BAR_H_ +#define ATOM_BROWSER_UI_COCOA_ATOM_TOUCH_BAR_H_ + +#import + +#include +#include +#include + +#include "atom/browser/native_window.h" +#include "atom/browser/ui/cocoa/touch_bar_forward_declarations.h" +#include "native_mate/constructor.h" +#include "native_mate/persistent_dictionary.h" + +@interface AtomTouchBar : NSObject { + @protected + std::map item_id_map; + std::map item_map; + id delegate_; + atom::NativeWindow* window_; +} + +- (id)initWithDelegate:(id)delegate + window:(atom::NativeWindow*)window; + +- (NSTouchBar*)makeTouchBarFromItemOptions:(const std::vector&)item_options; +- (NSTouchBar*)touchBarFromMutatableArray:(NSMutableArray*)items; +- (NSMutableArray*)identifierArrayFromDicts:(const std::vector&)dicts; +- (void)refreshTouchBarItem:(mate::Arguments*)args; +- (void)clear; + +- (NSString*)idFromIdentifier:(NSString*)identifier withPrefix:(NSString*)prefix; +- (bool)hasTBDict:(const std::string&)id; +- (NSColor*)colorFromHexColorString:(const std::string&)colorString; + +// Selector actions +- (void)buttonAction:(id)sender; +- (void)colorPickerAction:(id)sender; +- (void)sliderAction:(id)sender; + +// Helpers to create touch bar items +- (NSTouchBarItem*)makeItemForIdentifier:(NSTouchBarItemIdentifier)identifier; +- (NSTouchBarItem*)makeButtonForID:(NSString*)id withIdentifier:(NSString*)identifier; +- (NSTouchBarItem*)makeLabelForID:(NSString*)id withIdentifier:(NSString*)identifier; +- (NSTouchBarItem*)makeColorPickerForID:(NSString*)id withIdentifier:(NSString*)identifier; +- (NSTouchBarItem*)makeSliderForID:(NSString*)id withIdentifier:(NSString*)identifier; +- (NSTouchBarItem*)makePopoverForID:(NSString*)id withIdentifier:(NSString*)identifier; +- (NSTouchBarItem*)makeGroupForID:(NSString*)id withIdentifier:(NSString*)identifier; + +// Helpers to update touch bar items +- (void)updateButton:(NSCustomTouchBarItem*)item withOptions:(const mate::PersistentDictionary&)options; +- (void)updateLabel:(NSCustomTouchBarItem*)item withOptions:(const mate::PersistentDictionary&)options; +- (void)updateColorPicker:(NSColorPickerTouchBarItem*)item withOptions:(const mate::PersistentDictionary)options; +- (void)updateSlider:(NSSliderTouchBarItem*)item withOptions:(const mate::PersistentDictionary&)options; +- (void)updatePopover:(NSPopoverTouchBarItem*)item withOptions:(const mate::PersistentDictionary&)options; + +@end + +#endif // ATOM_BROWSER_UI_COCOA_ATOM_TOUCH_BAR_H_ diff --git a/atom/browser/ui/cocoa/atom_touch_bar.mm b/atom/browser/ui/cocoa/atom_touch_bar.mm new file mode 100644 index 000000000000..ac5a907d7a23 --- /dev/null +++ b/atom/browser/ui/cocoa/atom_touch_bar.mm @@ -0,0 +1,362 @@ +// 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_touch_bar.h" + +#include "atom/common/color_util.h" +#include "atom/common/native_mate_converters/image_converter.h" +#include "skia/ext/skia_utils_mac.h" +#include "ui/gfx/image/image.h" + +@implementation AtomTouchBar + +static NSTouchBarItemIdentifier ButtonIdentifier = @"com.electron.touchbar.button."; +static NSTouchBarItemIdentifier ColorPickerIdentifier = @"com.electron.touchbar.colorpicker."; +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."; + +- (id)initWithDelegate:(id)delegate + window:(atom::NativeWindow*)window { + if ((self = [super init])) { + delegate_ = delegate; + window_ = window; + } + return self; +} + +- (void)clear { + item_id_map.clear(); +} + +- (NSTouchBar*)makeTouchBarFromItemOptions:(const std::vector&)item_options { + NSMutableArray* identifiers = [self identifierArrayFromDicts:item_options]; + return [self touchBarFromMutatableArray:identifiers]; +} + +- (NSTouchBar*)touchBarFromMutatableArray:(NSMutableArray*)items { + NSTouchBar* bar = [[NSClassFromString(@"NSTouchBar") alloc] init]; + bar.delegate = delegate_; + bar.defaultItemIdentifiers = items; + return bar; +} + +- (NSMutableArray*)identifierArrayFromDicts:(const std::vector&)dicts { + NSMutableArray* idents = [[NSMutableArray alloc] init]; + + for (const auto& item : dicts) { + std::string type; + std::string item_id; + if (item.Get("type", &type) && item.Get("id", &item_id)) { + item_id_map.insert(make_pair(item_id, item)); + if (type == "button") { + [idents addObject:[NSString stringWithFormat:@"%@%@", ButtonIdentifier, [NSString stringWithUTF8String:item_id.c_str()]]]; + } else if (type == "label") { + [idents addObject:[NSString stringWithFormat:@"%@%@", LabelIdentifier, [NSString stringWithUTF8String:item_id.c_str()]]]; + } else if (type == "colorpicker") { + [idents addObject:[NSString stringWithFormat:@"%@%@", ColorPickerIdentifier, [NSString stringWithUTF8String:item_id.c_str()]]]; + } else if (type == "slider") { + [idents addObject:[NSString stringWithFormat:@"%@%@", SliderIdentifier, [NSString stringWithUTF8String:item_id.c_str()]]]; + } else if (type == "popover") { + [idents addObject:[NSString stringWithFormat:@"%@%@", PopOverIdentifier, [NSString stringWithUTF8String:item_id.c_str()]]]; + } else if (type == "group") { + [idents addObject:[NSString stringWithFormat:@"%@%@", GroupIdentifier, [NSString stringWithUTF8String:item_id.c_str()]]]; + } + } + } + [idents addObject:NSTouchBarItemIdentifierOtherItemsProxy]; + + return idents; +} + +- (NSTouchBarItem*)makeItemForIdentifier:(NSTouchBarItemIdentifier)identifier { + NSTouchBarItem* item = nil; + NSString* id = nil; + if ([identifier hasPrefix:ButtonIdentifier]) { + id = [self idFromIdentifier:identifier withPrefix:ButtonIdentifier]; + item = [self makeButtonForID:id withIdentifier:identifier]; + } else if ([identifier hasPrefix:LabelIdentifier]) { + id = [self idFromIdentifier:identifier withPrefix:LabelIdentifier]; + item = [self makeLabelForID:id withIdentifier:identifier]; + } else if ([identifier hasPrefix:ColorPickerIdentifier]) { + id = [self idFromIdentifier:identifier withPrefix:ColorPickerIdentifier]; + item = [self makeColorPickerForID:id withIdentifier:identifier]; + } else if ([identifier hasPrefix:SliderIdentifier]) { + id = [self idFromIdentifier:identifier withPrefix:SliderIdentifier]; + item = [self makeSliderForID:id withIdentifier:identifier]; + } else if ([identifier hasPrefix:PopOverIdentifier]) { + id = [self idFromIdentifier:identifier withPrefix:PopOverIdentifier]; + item = [self makePopoverForID:id withIdentifier:identifier]; + } else if ([identifier hasPrefix:GroupIdentifier]) { + id = [self idFromIdentifier:identifier withPrefix:GroupIdentifier]; + item = [self makeGroupForID:id withIdentifier:identifier]; + } + + item_map.insert(make_pair(std::string([id UTF8String]), item)); + + return item; +} + + +- (void)refreshTouchBarItem:(mate::Arguments*)args { + std::string item_id; + std::string type; + mate::PersistentDictionary options; + if (!args->GetNext(&options)) return; + if (!options.Get("type", &type)) return; + if (!options.Get("id", &item_id)) return; + if (item_map.find(item_id) == item_map.end()) return; + + if (type == "button") { + [self updateButton:(NSCustomTouchBarItem*)item_map[item_id] + withOptions:options]; + } else if (type == "label") { + [self updateLabel:(NSCustomTouchBarItem*)item_map[item_id] + withOptions:options]; + } else if (type == "colorpicker") { + [self updateColorPicker:(NSColorPickerTouchBarItem*)item_map[item_id] + withOptions:options]; + } else if (type == "slider") { + [self updateSlider:(NSSliderTouchBarItem*)item_map[item_id] + withOptions:options]; + } else if (type == "popover") { + [self updatePopover:(NSPopoverTouchBarItem*)item_map[item_id] + withOptions:options]; + } else if (type == "group") { + args->ThrowError("You can not update the config of a group. Update the individual items or replace the group"); + } +} + +- (void)buttonAction:(id)sender { + NSString* item_id = [NSString stringWithFormat:@"%@.%d", ButtonIdentifier, (int)((NSButton*)sender).tag]; + window_->NotifyTouchBarItemInteraction("button", { std::string([item_id UTF8String]) }); +} + +- (void)colorPickerAction:(id)sender { + NSString* item_id = ((NSColorPickerTouchBarItem*)sender).identifier; + NSColor* color = ((NSColorPickerTouchBarItem*)sender).color; + std::string hex_color = atom::ToRGBHex(skia::NSDeviceColorToSkColor(color)); + window_->NotifyTouchBarItemInteraction("color_picker", { std::string([item_id UTF8String]), hex_color }); +} + +- (void)sliderAction:(id)sender { + NSString* item_id = ((NSSliderTouchBarItem*)sender).identifier; + window_->NotifyTouchBarItemInteraction("slider", { std::string([item_id UTF8String]), std::to_string([((NSSliderTouchBarItem*)sender).slider intValue]) }); +} + +- (NSString*)idFromIdentifier:(NSString*)identifier withPrefix:(NSString*)prefix { + return [identifier substringFromIndex:[prefix length]]; +} + +- (bool)hasTBDict:(const std::string&)id { + return item_id_map.find(id) != item_id_map.end(); +} + +- (NSColor*)colorFromHexColorString:(const std::string&)colorString { + SkColor color = atom::ParseHexColor(colorString); + return skia::SkColorToCalibratedNSColor(color); +} + +- (NSTouchBarItem*)makeButtonForID:(NSString*)id + withIdentifier:(NSString*)identifier { + std::string s_id([id UTF8String]); + if (![self hasTBDict:s_id]) return nil; + + mate::PersistentDictionary options = item_id_map[s_id]; + NSCustomTouchBarItem* item = [[NSClassFromString(@"NSCustomTouchBarItem") alloc] initWithIdentifier:identifier]; + NSButton* button = [NSButton buttonWithTitle:@"" + target:self + action:@selector(buttonAction:)]; + button.tag = [id floatValue]; + item.view = button; + [self updateButton:item withOptions:options]; + return item; +} + +- (void)updateButton:(NSCustomTouchBarItem*)item + withOptions:(const mate::PersistentDictionary&)options { + NSButton* button = (NSButton*)item.view; + + std::string customizationLabel; + if (options.Get("customizationLabel", &customizationLabel)) { + item.customizationLabel = [NSString stringWithUTF8String:customizationLabel.data()]; + } + + std::string backgroundColor; + if (options.Get("backgroundColor", &backgroundColor)) { + button.bezelColor = [self colorFromHexColorString:backgroundColor]; + } + + std::string label; + if (options.Get("label", &label)) { + button.title = [NSString stringWithUTF8String:label.data()]; + } + + std::string labelColor; + if (!label.empty() && options.Get("labelColor", &labelColor)) { + NSMutableAttributedString* attrTitle = [[[NSMutableAttributedString alloc] initWithString:[NSString stringWithUTF8String:label.data()]] autorelease]; + NSRange range = NSMakeRange(0, [attrTitle length]); + [attrTitle addAttribute:NSForegroundColorAttributeName + value:[self colorFromHexColorString:labelColor] + range:range]; + [attrTitle fixAttributesInRange:range]; + button.attributedTitle = attrTitle; + } + + gfx::Image image; + if (options.Get("image", &image)) { + button.image = image.AsNSImage(); + } +} + +- (NSTouchBarItem*)makeLabelForID:(NSString*)id + withIdentifier:(NSString*)identifier { + std::string s_id([id UTF8String]); + if (![self hasTBDict:s_id]) return nil; + + mate::PersistentDictionary item = item_id_map[s_id]; + NSCustomTouchBarItem* customItem = [[NSClassFromString(@"NSCustomTouchBarItem") alloc] initWithIdentifier:identifier]; + customItem.view = [NSTextField labelWithString:@""]; + [self updateLabel:customItem withOptions:item]; + + return customItem; +} + +- (void)updateLabel:(NSCustomTouchBarItem*)item + withOptions:(const mate::PersistentDictionary&)options { + std::string label; + options.Get("label", &label); + NSTextField* text_field = (NSTextField*)item.view; + text_field.stringValue = [NSString stringWithUTF8String:label.data()]; + + std::string customizationLabel; + if (options.Get("customizationLabel", &customizationLabel)) { + item.customizationLabel = [NSString stringWithUTF8String:customizationLabel.data()]; + } +} + +- (NSTouchBarItem*)makeColorPickerForID:(NSString*)id + withIdentifier:(NSString*)identifier { + std::string s_id([id UTF8String]); + if (![self hasTBDict:s_id]) return nil; + + mate::PersistentDictionary options = item_id_map[s_id]; + NSColorPickerTouchBarItem* item = [[NSClassFromString(@"NSColorPickerTouchBarItem") alloc] initWithIdentifier:identifier]; + item.target = self; + item.action = @selector(colorPickerAction:); + [self updateColorPicker:item withOptions:options]; + return item; +} + +- (void)updateColorPicker:(NSColorPickerTouchBarItem*)item + withOptions:(const mate::PersistentDictionary)options { + std::string customizationLabel; + if (options.Get("customizationLabel", &customizationLabel)) { + item.customizationLabel = [NSString stringWithUTF8String:customizationLabel.data()]; + } +} + +- (NSTouchBarItem*)makeSliderForID:(NSString*)id + withIdentifier:(NSString*)identifier { + std::string s_id([id UTF8String]); + if (![self hasTBDict:s_id]) return nil; + + mate::PersistentDictionary options = item_id_map[s_id]; + NSSliderTouchBarItem* item = [[NSClassFromString(@"NSSliderTouchBarItem") alloc] initWithIdentifier:identifier]; + item.target = self; + item.action = @selector(sliderAction:); + [self updateSlider:item withOptions:options]; + return item; +} + +- (void)updateSlider:(NSSliderTouchBarItem*)item + withOptions:(const mate::PersistentDictionary&)options { + std::string customizationLabel; + if (options.Get("customizationLabel", &customizationLabel)) { + item.customizationLabel = [NSString stringWithUTF8String:customizationLabel.data()]; + } + + std::string label; + options.Get("label", &label); + item.label = [NSString stringWithUTF8String:label.data()]; + + int maxValue = 100; + int minValue = 0; + int initialValue = 50; + options.Get("minValue", &minValue); + options.Get("maxValue", &maxValue); + options.Get("initialValue", &initialValue); + + item.slider.minValue = minValue; + item.slider.maxValue = maxValue; + item.slider.doubleValue = initialValue; +} + +- (NSTouchBarItem*)makePopoverForID:(NSString*)id + withIdentifier:(NSString*)identifier { + std::string s_id = std::string([id UTF8String]); + if (![self hasTBDict:s_id]) return nil; + + mate::PersistentDictionary options = item_id_map[s_id]; + NSPopoverTouchBarItem* item = [[NSClassFromString(@"NSPopoverTouchBarItem") alloc] initWithIdentifier:identifier]; + [self updatePopover:item withOptions:options]; + return item; +} + +- (void)updatePopover:(NSPopoverTouchBarItem*)item + withOptions:(const mate::PersistentDictionary&)options { + std::string customizationLabel; + if (options.Get("customizationLabel", &customizationLabel)) { + item.customizationLabel = [NSString stringWithUTF8String:customizationLabel.data()]; + } + + std::string label; + gfx::Image image; + if (options.Get("label", &label)) { + item.collapsedRepresentationLabel = [NSString stringWithUTF8String:label.data()]; + } else if (options.Get("image", &image)) { + item.collapsedRepresentationImage = image.AsNSImage(); + } + + bool showCloseButton; + if (options.Get("showCloseButton", &showCloseButton)) { + item.showsCloseButton = showCloseButton; + } + + std::vector touchBar; + if (options.Get("touchBar", &touchBar)) { + item.popoverTouchBar = [self touchBarFromMutatableArray:[self identifierArrayFromDicts:touchBar]]; + } +} + +- (NSTouchBarItem*)makeGroupForID:(NSString*)id + withIdentifier:(NSString*)identifier { + std::string s_id([id UTF8String]); + if (![self hasTBDict:s_id]) return nil; + mate::PersistentDictionary options = item_id_map[s_id]; + + std::vector items; + if (!options.Get("items", &items)) return nil; + + NSMutableArray* generatedItems = [[NSMutableArray alloc] init]; + NSMutableArray* identList = [self identifierArrayFromDicts:items]; + for (NSUInteger i = 0; i < [identList count]; i++) { + if ([identList objectAtIndex:i] != NSTouchBarItemIdentifierOtherItemsProxy) { + NSTouchBarItem* generatedItem = [self makeItemForIdentifier:[identList objectAtIndex:i]]; + if (generatedItem) { + [generatedItems addObject:generatedItem]; + } + } + } + + NSGroupTouchBarItem* item = [NSClassFromString(@"NSGroupTouchBarItem") groupItemWithIdentifier:identifier items:generatedItems]; + std::string customizationLabel; + if (options.Get("customizationLabel", &customizationLabel)) { + item.customizationLabel = [NSString stringWithUTF8String:customizationLabel.data()]; + } + return item; +} + +@end diff --git a/filenames.gypi b/filenames.gypi index a1758e2acff0..6ac732c24a30 100644 --- a/filenames.gypi +++ b/filenames.gypi @@ -281,6 +281,8 @@ 'atom/browser/ui/atom_menu_model.h', 'atom/browser/ui/cocoa/atom_menu_controller.h', 'atom/browser/ui/cocoa/atom_menu_controller.mm', + '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/drag_util_mac.mm', 'atom/browser/ui/drag_util_views.cc',