1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #import <Cocoa/Cocoa.h>
7 #include "base/logging.h"
8 #import "base/mac/scoped_nsobject.h"
9 #include "chrome/browser/ui/browser_dialogs.h"
10 #include "content/public/browser/color_chooser.h"
11 #include "content/public/browser/web_contents.h"
12 #include "skia/ext/skia_utils_mac.h"
14 class ColorChooserMac;
16 // A Listener class to act as a event target for NSColorPanel and send
17 // the results to the C++ class, ColorChooserMac.
18 @interface ColorPanelCocoa : NSObject<NSWindowDelegate> {
20 // We don't call DidChooseColor if the change wasn't caused by the user
21 // interacting with the panel.
23 ColorChooserMac* chooser_; // weak, owns this
26 - (id)initWithChooser:(ColorChooserMac*)chooser;
28 // Called from NSColorPanel.
29 - (void)didChooseColor:(NSColorPanel*)panel;
31 // Sets color to the NSColorPanel as a non user change.
32 - (void)setColor:(NSColor*)color;
36 class ColorChooserMac : public content::ColorChooser {
38 static ColorChooserMac* Open(content::WebContents* web_contents,
39 SkColor initial_color);
41 ColorChooserMac(content::WebContents* tab, SkColor initial_color);
42 virtual ~ColorChooserMac();
44 // Called from ColorPanelCocoa.
45 void DidChooseColorInColorPanel(SkColor color);
46 void DidCloseColorPabel();
48 virtual void End() OVERRIDE;
49 virtual void SetSelectedColor(SkColor color) OVERRIDE;
52 static ColorChooserMac* current_color_chooser_;
54 // The web contents invoking the color chooser. No ownership because it will
55 // outlive this class.
56 content::WebContents* web_contents_;
57 base::scoped_nsobject<ColorPanelCocoa> panel_;
60 ColorChooserMac* ColorChooserMac::current_color_chooser_ = NULL;
63 ColorChooserMac* ColorChooserMac::Open(content::WebContents* web_contents,
64 SkColor initial_color) {
65 if (current_color_chooser_)
66 current_color_chooser_->End();
67 DCHECK(!current_color_chooser_);
68 current_color_chooser_ =
69 new ColorChooserMac(web_contents, initial_color);
70 return current_color_chooser_;
73 ColorChooserMac::ColorChooserMac(content::WebContents* web_contents,
74 SkColor initial_color)
75 : web_contents_(web_contents) {
76 panel_.reset([[ColorPanelCocoa alloc] initWithChooser:this]);
77 [panel_ setColor:gfx::SkColorToDeviceNSColor(initial_color)];
78 [[NSColorPanel sharedColorPanel] makeKeyAndOrderFront:nil];
81 ColorChooserMac::~ColorChooserMac() {
82 // Always call End() before destroying.
86 void ColorChooserMac::DidChooseColorInColorPanel(SkColor color) {
88 web_contents_->DidChooseColorInColorChooser(color);
91 void ColorChooserMac::DidCloseColorPabel() {
95 void ColorChooserMac::End() {
97 DCHECK(current_color_chooser_ == this);
98 current_color_chooser_ = NULL;
100 web_contents_->DidEndColorChooser();
103 void ColorChooserMac::SetSelectedColor(SkColor color) {
104 [panel_ setColor:gfx::SkColorToDeviceNSColor(color)];
107 @implementation ColorPanelCocoa
109 - (id)initWithChooser:(ColorChooserMac*)chooser {
110 if ((self = [super init])) {
112 NSColorPanel* panel = [NSColorPanel sharedColorPanel];
113 [panel setShowsAlpha:NO];
114 [panel setDelegate:self];
115 [panel setTarget:self];
116 [panel setAction:@selector(didChooseColor:)];
122 NSColorPanel* panel = [NSColorPanel sharedColorPanel];
123 if ([panel delegate] == self) {
124 [panel setDelegate:nil];
125 [panel setTarget:nil];
126 [panel setAction:nil];
132 - (void)windowWillClose:(NSNotification*)notification {
133 chooser_->DidCloseColorPabel();
137 - (void)didChooseColor:(NSColorPanel*)panel {
138 if (nonUserChange_) {
142 chooser_->DidChooseColorInColorPanel(gfx::NSDeviceColorToSkColor(
143 [[panel color] colorUsingColorSpaceName:NSDeviceRGBColorSpace]));
147 - (void)setColor:(NSColor*)color {
148 nonUserChange_ = YES;
149 [[NSColorPanel sharedColorPanel] setColor:color];
154 content::ColorChooser* ShowColorChooser(content::WebContents* web_contents,
155 SkColor initial_color) {
156 return ColorChooserMac::Open(web_contents, initial_color);