1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/widget/gtk/nsColorPicker.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,182 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#include <gtk/gtk.h> 1.10 + 1.11 +#include "nsColor.h" 1.12 +#include "nsColorPicker.h" 1.13 +#include "nsGtkUtils.h" 1.14 +#include "nsIWidget.h" 1.15 +#include "WidgetUtils.h" 1.16 + 1.17 +NS_IMPL_ISUPPORTS(nsColorPicker, nsIColorPicker) 1.18 + 1.19 +int nsColorPicker::convertGdkColorComponent(guint16 color_component) { 1.20 + // GdkColor value is in range [0..65535]. We need something in range [0..255] 1.21 + return (color_component * 255 + 127) / 65535; 1.22 +} 1.23 + 1.24 +guint16 nsColorPicker::convertToGdkColorComponent(int color_component) { 1.25 + return color_component * 65535 / 255; 1.26 +} 1.27 + 1.28 +GdkColor nsColorPicker::convertToGdkColor(nscolor color) { 1.29 + GdkColor result = { 0 /* obsolete, unused 'pixel' value */, 1.30 + convertToGdkColorComponent(NS_GET_R(color)), 1.31 + convertToGdkColorComponent(NS_GET_G(color)), 1.32 + convertToGdkColorComponent(NS_GET_B(color)) }; 1.33 + 1.34 + return result; 1.35 +} 1.36 + 1.37 +GtkColorSelection* nsColorPicker::WidgetGetColorSelection(GtkWidget* widget) 1.38 +{ 1.39 + return GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection( 1.40 + GTK_COLOR_SELECTION_DIALOG(widget))); 1.41 +} 1.42 + 1.43 +/* void init (in nsIDOMWindow parent, in AString title, in short mode); */ 1.44 +NS_IMETHODIMP nsColorPicker::Init(nsIDOMWindow *parent, 1.45 + const nsAString& title, 1.46 + const nsAString& initialColor) 1.47 +{ 1.48 + mParentWidget = mozilla::widget::WidgetUtils::DOMWindowToWidget(parent); 1.49 + mTitle = title; 1.50 + mInitialColor = initialColor; 1.51 + 1.52 + return NS_OK; 1.53 +} 1.54 + 1.55 +/* void open (in nsIColorPickerShownCallback aColorPickerShownCallback); */ 1.56 +NS_IMETHODIMP nsColorPicker::Open(nsIColorPickerShownCallback *aColorPickerShownCallback) 1.57 +{ 1.58 + 1.59 + // Input color string should be 7 length (i.e. a string representing a valid 1.60 + // simple color) 1.61 + if (mInitialColor.Length() != 7) { 1.62 + return NS_ERROR_FAILURE; 1.63 + } 1.64 + 1.65 + const nsAString& withoutHash = StringTail(mInitialColor, 6); 1.66 + nscolor color; 1.67 + if (!NS_HexToRGB(withoutHash, &color)) { 1.68 + return NS_ERROR_FAILURE; 1.69 + } 1.70 + 1.71 + GdkColor color_gdk = convertToGdkColor(color); 1.72 + 1.73 + if (mCallback) { 1.74 + // It means Open has already been called: this is not allowed 1.75 + NS_WARNING("mCallback is already set. Open called twice?"); 1.76 + return NS_ERROR_FAILURE; 1.77 + } 1.78 + mCallback = aColorPickerShownCallback; 1.79 + 1.80 + nsXPIDLCString title; 1.81 + title.Adopt(ToNewUTF8String(mTitle)); 1.82 + GtkWidget *color_chooser = gtk_color_selection_dialog_new(title); 1.83 + 1.84 + GtkWindow *parent_window = GTK_WINDOW(mParentWidget->GetNativeData(NS_NATIVE_SHELLWIDGET)); 1.85 + if (parent_window) { 1.86 + GtkWindow *window = GTK_WINDOW(color_chooser); 1.87 + gtk_window_set_transient_for(window, parent_window); 1.88 + gtk_window_set_destroy_with_parent(window, TRUE); 1.89 + } 1.90 + 1.91 + gtk_color_selection_set_current_color(WidgetGetColorSelection(color_chooser), 1.92 + &color_gdk); 1.93 + 1.94 + NS_ADDREF_THIS(); 1.95 + g_signal_connect(WidgetGetColorSelection(color_chooser), "color-changed", 1.96 + G_CALLBACK(OnColorChanged), this); 1.97 + g_signal_connect(color_chooser, "response", G_CALLBACK(OnResponse), this); 1.98 + g_signal_connect(color_chooser, "destroy", G_CALLBACK(OnDestroy), this); 1.99 + gtk_widget_show(color_chooser); 1.100 + 1.101 + return NS_OK; 1.102 +} 1.103 + 1.104 +/* static */ void 1.105 +nsColorPicker::OnColorChanged(GtkColorSelection* colorselection, 1.106 + gpointer user_data) 1.107 +{ 1.108 + static_cast<nsColorPicker*>(user_data)->Update(colorselection); 1.109 +} 1.110 + 1.111 +/* static */ void 1.112 +nsColorPicker::OnResponse(GtkWidget* color_chooser, gint response_id, 1.113 + gpointer user_data) 1.114 +{ 1.115 + static_cast<nsColorPicker*>(user_data)-> 1.116 + Done(color_chooser, response_id); 1.117 +} 1.118 + 1.119 +/* static */ void 1.120 +nsColorPicker::OnDestroy(GtkWidget* color_chooser, gpointer user_data) 1.121 +{ 1.122 + static_cast<nsColorPicker*>(user_data)-> 1.123 + Done(color_chooser, GTK_RESPONSE_CANCEL); 1.124 +} 1.125 + 1.126 +void 1.127 +nsColorPicker::Update(GtkColorSelection* colorselection) 1.128 +{ 1.129 + ReadValueFromColorSelection(colorselection); 1.130 + if (mCallback) { 1.131 + mCallback->Update(mColor); 1.132 + } 1.133 +} 1.134 + 1.135 +void 1.136 +nsColorPicker::Done(GtkWidget* color_chooser, gint response) 1.137 +{ 1.138 + switch (response) { 1.139 + case GTK_RESPONSE_OK: 1.140 + case GTK_RESPONSE_ACCEPT: 1.141 + ReadValueFromColorSelection(WidgetGetColorSelection(color_chooser)); 1.142 + break; 1.143 + case GTK_RESPONSE_CANCEL: 1.144 + case GTK_RESPONSE_CLOSE: 1.145 + case GTK_RESPONSE_DELETE_EVENT: 1.146 + mColor = mInitialColor; 1.147 + break; 1.148 + default: 1.149 + NS_WARNING("Unexpected response"); 1.150 + break; 1.151 + } 1.152 + 1.153 + // A "response" signal won't be sent again but "destroy" will be. 1.154 + g_signal_handlers_disconnect_by_func(color_chooser, 1.155 + FuncToGpointer(OnDestroy), this); 1.156 + 1.157 + gtk_widget_destroy(color_chooser); 1.158 + if (mCallback) { 1.159 + mCallback->Done(mColor); 1.160 + mCallback = nullptr; 1.161 + } 1.162 + 1.163 + NS_RELEASE_THIS(); 1.164 +} 1.165 + 1.166 +nsString nsColorPicker::ToHexString(int n) 1.167 +{ 1.168 + nsString result; 1.169 + if (n <= 0x0F) { 1.170 + result.Append('0'); 1.171 + } 1.172 + result.AppendInt(n, 16); 1.173 + return result; 1.174 +} 1.175 + 1.176 +void nsColorPicker::ReadValueFromColorSelection(GtkColorSelection* colorselection) 1.177 +{ 1.178 + GdkColor rgba; 1.179 + gtk_color_selection_get_current_color(colorselection, &rgba); 1.180 + 1.181 + mColor.AssignLiteral("#"); 1.182 + mColor += ToHexString(convertGdkColorComponent(rgba.red)); 1.183 + mColor += ToHexString(convertGdkColorComponent(rgba.green)); 1.184 + mColor += ToHexString(convertGdkColorComponent(rgba.blue)); 1.185 +}