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. 4 5#import <Cocoa/Cocoa.h> 6 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" 13 14class ColorChooserMac; 15 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> { 19 @private 20 // We don't call DidChooseColor if the change wasn't caused by the user 21 // interacting with the panel. 22 BOOL nonUserChange_; 23 ColorChooserMac* chooser_; // weak, owns this 24} 25 26- (id)initWithChooser:(ColorChooserMac*)chooser; 27 28// Called from NSColorPanel. 29- (void)didChooseColor:(NSColorPanel*)panel; 30 31// Sets color to the NSColorPanel as a non user change. 32- (void)setColor:(NSColor*)color; 33 34@end 35 36class ColorChooserMac : public content::ColorChooser { 37 public: 38 static ColorChooserMac* Open(content::WebContents* web_contents, 39 SkColor initial_color); 40 41 ColorChooserMac(content::WebContents* tab, SkColor initial_color); 42 virtual ~ColorChooserMac(); 43 44 // Called from ColorPanelCocoa. 45 void DidChooseColorInColorPanel(SkColor color); 46 void DidCloseColorPabel(); 47 48 virtual void End() OVERRIDE; 49 virtual void SetSelectedColor(SkColor color) OVERRIDE; 50 51 private: 52 static ColorChooserMac* current_color_chooser_; 53 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_; 58}; 59 60ColorChooserMac* ColorChooserMac::current_color_chooser_ = NULL; 61 62// static 63ColorChooserMac* 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_; 71} 72 73ColorChooserMac::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]; 79} 80 81ColorChooserMac::~ColorChooserMac() { 82 // Always call End() before destroying. 83 DCHECK(!panel_); 84} 85 86void ColorChooserMac::DidChooseColorInColorPanel(SkColor color) { 87 if (web_contents_) 88 web_contents_->DidChooseColorInColorChooser(color); 89} 90 91void ColorChooserMac::DidCloseColorPabel() { 92 End(); 93} 94 95void ColorChooserMac::End() { 96 panel_.reset(); 97 DCHECK(current_color_chooser_ == this); 98 current_color_chooser_ = NULL; 99 if (web_contents_) 100 web_contents_->DidEndColorChooser(); 101} 102 103void ColorChooserMac::SetSelectedColor(SkColor color) { 104 [panel_ setColor:gfx::SkColorToDeviceNSColor(color)]; 105} 106 107@implementation ColorPanelCocoa 108 109- (id)initWithChooser:(ColorChooserMac*)chooser { 110 if ((self = [super init])) { 111 chooser_ = chooser; 112 NSColorPanel* panel = [NSColorPanel sharedColorPanel]; 113 [panel setShowsAlpha:NO]; 114 [panel setDelegate:self]; 115 [panel setTarget:self]; 116 [panel setAction:@selector(didChooseColor:)]; 117 } 118 return self; 119} 120 121- (void)dealloc { 122 NSColorPanel* panel = [NSColorPanel sharedColorPanel]; 123 if ([panel delegate] == self) { 124 [panel setDelegate:nil]; 125 [panel setTarget:nil]; 126 [panel setAction:nil]; 127 } 128 129 [super dealloc]; 130} 131 132- (void)windowWillClose:(NSNotification*)notification { 133 chooser_->DidCloseColorPabel(); 134 nonUserChange_ = NO; 135} 136 137- (void)didChooseColor:(NSColorPanel*)panel { 138 if (nonUserChange_) { 139 nonUserChange_ = NO; 140 return; 141 } 142 chooser_->DidChooseColorInColorPanel(gfx::NSDeviceColorToSkColor( 143 [[panel color] colorUsingColorSpaceName:NSDeviceRGBColorSpace])); 144 nonUserChange_ = NO; 145} 146 147- (void)setColor:(NSColor*)color { 148 nonUserChange_ = YES; 149 [[NSColorPanel sharedColorPanel] setColor:color]; 150} 151 152namespace chrome { 153 154content::ColorChooser* ShowColorChooser(content::WebContents* web_contents, 155 SkColor initial_color) { 156 return ColorChooserMac::Open(web_contents, initial_color); 157} 158 159} // namepace chrome 160 161@end 162