widget/gtk/nsColorPicker.cpp

changeset 0
6474c204b198
     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 +}

mercurial