mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-01 08:42:13 +00:00
9ee89fe42f
This patch tells all callers to use the existing behavior, so it is intended not to change behavior. Callers that will be modified in later patches are marked with "FIXME" comments that will be removed in those later patches (patches 3 and 4). MozReview-Commit-ID: FaLryfxaeHv
252 lines
7.5 KiB
C++
252 lines
7.5 KiB
C++
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
#include <gtk/gtk.h>
|
|
|
|
#include "nsColor.h"
|
|
#include "nsColorPicker.h"
|
|
#include "nsGtkUtils.h"
|
|
#include "nsIWidget.h"
|
|
#include "WidgetUtils.h"
|
|
|
|
NS_IMPL_ISUPPORTS(nsColorPicker, nsIColorPicker)
|
|
|
|
#if defined(ACTIVATE_GTK3_COLOR_PICKER) && GTK_CHECK_VERSION(3,4,0)
|
|
int nsColorPicker::convertGdkRgbaComponent(gdouble color_component) {
|
|
// GdkRGBA value is in range [0.0..1.0]. We need something in range [0..255]
|
|
return color_component * 255 + 0.5;
|
|
}
|
|
|
|
gdouble nsColorPicker::convertToGdkRgbaComponent(int color_component) {
|
|
return color_component / 255.0;
|
|
}
|
|
|
|
GdkRGBA nsColorPicker::convertToRgbaColor(nscolor color) {
|
|
GdkRGBA result = { convertToGdkRgbaComponent(NS_GET_R(color)),
|
|
convertToGdkRgbaComponent(NS_GET_G(color)),
|
|
convertToGdkRgbaComponent(NS_GET_B(color)),
|
|
convertToGdkRgbaComponent(NS_GET_A(color)) };
|
|
|
|
return result;
|
|
}
|
|
#else
|
|
int nsColorPicker::convertGdkColorComponent(guint16 color_component) {
|
|
// GdkColor value is in range [0..65535]. We need something in range [0..255]
|
|
return (color_component * 255 + 127) / 65535;
|
|
}
|
|
|
|
guint16 nsColorPicker::convertToGdkColorComponent(int color_component) {
|
|
return color_component * 65535 / 255;
|
|
}
|
|
|
|
GdkColor nsColorPicker::convertToGdkColor(nscolor color) {
|
|
GdkColor result = { 0 /* obsolete, unused 'pixel' value */,
|
|
convertToGdkColorComponent(NS_GET_R(color)),
|
|
convertToGdkColorComponent(NS_GET_G(color)),
|
|
convertToGdkColorComponent(NS_GET_B(color)) };
|
|
|
|
return result;
|
|
}
|
|
|
|
GtkColorSelection* nsColorPicker::WidgetGetColorSelection(GtkWidget* widget)
|
|
{
|
|
return GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(
|
|
GTK_COLOR_SELECTION_DIALOG(widget)));
|
|
}
|
|
#endif
|
|
|
|
NS_IMETHODIMP nsColorPicker::Init(mozIDOMWindowProxy *aParent,
|
|
const nsAString& title,
|
|
const nsAString& initialColor)
|
|
{
|
|
auto* parent = nsPIDOMWindowOuter::From(aParent);
|
|
mParentWidget = mozilla::widget::WidgetUtils::DOMWindowToWidget(parent);
|
|
mTitle = title;
|
|
mInitialColor = initialColor;
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP nsColorPicker::Open(nsIColorPickerShownCallback *aColorPickerShownCallback)
|
|
{
|
|
|
|
// Input color string should be 7 length (i.e. a string representing a valid
|
|
// simple color)
|
|
if (mInitialColor.Length() != 7) {
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
const nsAString& withoutHash = StringTail(mInitialColor, 6);
|
|
nscolor color;
|
|
if (!NS_HexToRGBA(withoutHash, nsHexColorType::NoAlpha, &color)) {
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
if (mCallback) {
|
|
// It means Open has already been called: this is not allowed
|
|
NS_WARNING("mCallback is already set. Open called twice?");
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
mCallback = aColorPickerShownCallback;
|
|
|
|
nsXPIDLCString title;
|
|
title.Adopt(ToNewUTF8String(mTitle));
|
|
GtkWindow *parent_window = GTK_WINDOW(mParentWidget->GetNativeData(NS_NATIVE_SHELLWIDGET));
|
|
|
|
#if defined(ACTIVATE_GTK3_COLOR_PICKER) && GTK_CHECK_VERSION(3,4,0)
|
|
GtkWidget* color_chooser = gtk_color_chooser_dialog_new(title, parent_window);
|
|
|
|
if (parent_window) {
|
|
gtk_window_set_destroy_with_parent(GTK_WINDOW(color_chooser), TRUE);
|
|
}
|
|
|
|
gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(color_chooser), FALSE);
|
|
GdkRGBA color_rgba = convertToRgbaColor(color);
|
|
gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(color_chooser),
|
|
&color_rgba);
|
|
|
|
g_signal_connect(GTK_COLOR_CHOOSER(color_chooser), "color-activated",
|
|
G_CALLBACK(OnColorChanged), this);
|
|
#else
|
|
GtkWidget *color_chooser = gtk_color_selection_dialog_new(title);
|
|
|
|
if (parent_window) {
|
|
GtkWindow *window = GTK_WINDOW(color_chooser);
|
|
gtk_window_set_transient_for(window, parent_window);
|
|
gtk_window_set_destroy_with_parent(window, TRUE);
|
|
}
|
|
|
|
GdkColor color_gdk = convertToGdkColor(color);
|
|
gtk_color_selection_set_current_color(WidgetGetColorSelection(color_chooser),
|
|
&color_gdk);
|
|
|
|
g_signal_connect(WidgetGetColorSelection(color_chooser), "color-changed",
|
|
G_CALLBACK(OnColorChanged), this);
|
|
#endif
|
|
|
|
NS_ADDREF_THIS();
|
|
|
|
g_signal_connect(color_chooser, "response", G_CALLBACK(OnResponse), this);
|
|
g_signal_connect(color_chooser, "destroy", G_CALLBACK(OnDestroy), this);
|
|
gtk_widget_show(color_chooser);
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
#if defined(ACTIVATE_GTK3_COLOR_PICKER) && GTK_CHECK_VERSION(3,4,0)
|
|
/* static */ void
|
|
nsColorPicker::OnColorChanged(GtkColorChooser* color_chooser, GdkRGBA* color,
|
|
gpointer user_data)
|
|
{
|
|
static_cast<nsColorPicker*>(user_data)->Update(color);
|
|
}
|
|
|
|
void
|
|
nsColorPicker::Update(GdkRGBA* color)
|
|
{
|
|
SetColor(color);
|
|
if (mCallback) {
|
|
mCallback->Update(mColor);
|
|
}
|
|
}
|
|
|
|
void nsColorPicker::SetColor(const GdkRGBA* color)
|
|
{
|
|
mColor.Assign('#');
|
|
mColor += ToHexString(convertGdkRgbaComponent(color->red));
|
|
mColor += ToHexString(convertGdkRgbaComponent(color->green));
|
|
mColor += ToHexString(convertGdkRgbaComponent(color->blue));
|
|
}
|
|
#else
|
|
/* static */ void
|
|
nsColorPicker::OnColorChanged(GtkColorSelection* colorselection,
|
|
gpointer user_data)
|
|
{
|
|
static_cast<nsColorPicker*>(user_data)->Update(colorselection);
|
|
}
|
|
|
|
void
|
|
nsColorPicker::Update(GtkColorSelection* colorselection)
|
|
{
|
|
ReadValueFromColorSelection(colorselection);
|
|
if (mCallback) {
|
|
mCallback->Update(mColor);
|
|
}
|
|
}
|
|
|
|
void nsColorPicker::ReadValueFromColorSelection(GtkColorSelection* colorselection)
|
|
{
|
|
GdkColor rgba;
|
|
gtk_color_selection_get_current_color(colorselection, &rgba);
|
|
|
|
mColor.Assign('#');
|
|
mColor += ToHexString(convertGdkColorComponent(rgba.red));
|
|
mColor += ToHexString(convertGdkColorComponent(rgba.green));
|
|
mColor += ToHexString(convertGdkColorComponent(rgba.blue));
|
|
}
|
|
#endif
|
|
|
|
/* static */ void
|
|
nsColorPicker::OnResponse(GtkWidget* color_chooser, gint response_id,
|
|
gpointer user_data)
|
|
{
|
|
static_cast<nsColorPicker*>(user_data)->
|
|
Done(color_chooser, response_id);
|
|
}
|
|
|
|
/* static */ void
|
|
nsColorPicker::OnDestroy(GtkWidget* color_chooser, gpointer user_data)
|
|
{
|
|
static_cast<nsColorPicker*>(user_data)->
|
|
Done(color_chooser, GTK_RESPONSE_CANCEL);
|
|
}
|
|
|
|
void
|
|
nsColorPicker::Done(GtkWidget* color_chooser, gint response)
|
|
{
|
|
switch (response) {
|
|
case GTK_RESPONSE_OK:
|
|
case GTK_RESPONSE_ACCEPT:
|
|
#if defined(ACTIVATE_GTK3_COLOR_PICKER) && GTK_CHECK_VERSION(3,4,0)
|
|
GdkRGBA color;
|
|
gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(color_chooser), &color);
|
|
SetColor(&color);
|
|
#else
|
|
ReadValueFromColorSelection(WidgetGetColorSelection(color_chooser));
|
|
#endif
|
|
break;
|
|
case GTK_RESPONSE_CANCEL:
|
|
case GTK_RESPONSE_CLOSE:
|
|
case GTK_RESPONSE_DELETE_EVENT:
|
|
mColor = mInitialColor;
|
|
break;
|
|
default:
|
|
NS_WARNING("Unexpected response");
|
|
break;
|
|
}
|
|
|
|
// A "response" signal won't be sent again but "destroy" will be.
|
|
g_signal_handlers_disconnect_by_func(color_chooser,
|
|
FuncToGpointer(OnDestroy), this);
|
|
|
|
gtk_widget_destroy(color_chooser);
|
|
if (mCallback) {
|
|
mCallback->Done(mColor);
|
|
mCallback = nullptr;
|
|
}
|
|
|
|
NS_RELEASE_THIS();
|
|
}
|
|
|
|
nsString nsColorPicker::ToHexString(int n)
|
|
{
|
|
nsString result;
|
|
if (n <= 0x0F) {
|
|
result.Append('0');
|
|
}
|
|
result.AppendInt(n, 16);
|
|
return result;
|
|
}
|