summaryrefslogtreecommitdiffstats
path: root/src/ui
diff options
context:
space:
mode:
authorTomasz Boczkowski <penginsbacon@gmail.com>2014-05-23 09:09:05 +0000
committerTomasz Boczkowski <penginsbacon@gmail.com>2014-05-23 09:09:05 +0000
commita06f51f786230bfd26ddd34d27be438d4bebbd04 (patch)
treefe7754c7e976e5b76e9fd03ea80c81feaa9d7b39 /src/ui
parentSPColorSlider c++-sification: added ColorSlider class (diff)
downloadinkscape-a06f51f786230bfd26ddd34d27be438d4bebbd04.tar.gz
inkscape-a06f51f786230bfd26ddd34d27be438d4bebbd04.zip
moved widgets/sp-color-slider to ui/widget/color-slider
(bzr r13341.6.2)
Diffstat (limited to 'src/ui')
-rw-r--r--src/ui/CMakeLists.txt2
-rw-r--r--src/ui/widget/Makefile_insert2
-rw-r--r--src/ui/widget/color-slider.cpp961
-rw-r--r--src/ui/widget/color-slider.h146
4 files changed, 1111 insertions, 0 deletions
diff --git a/src/ui/CMakeLists.txt b/src/ui/CMakeLists.txt
index 7d80f1e36..883ba3427 100644
--- a/src/ui/CMakeLists.txt
+++ b/src/ui/CMakeLists.txt
@@ -109,6 +109,7 @@ set(ui_SRC
widget/button.cpp
widget/color-picker.cpp
widget/color-preview.cpp
+ widget/color-slider.cpp
widget/dock-item.cpp
widget/dock.cpp
widget/entity-entry.cpp
@@ -270,6 +271,7 @@ set(ui_SRC
widget/button.h
widget/color-picker.h
widget/color-preview.h
+ widget/color-slider.h
widget/combo-enums.h
widget/dock-item.h
widget/dock.h
diff --git a/src/ui/widget/Makefile_insert b/src/ui/widget/Makefile_insert
index 608dd5334..6deaf6671 100644
--- a/src/ui/widget/Makefile_insert
+++ b/src/ui/widget/Makefile_insert
@@ -10,6 +10,8 @@ ink_common_sources += \
ui/widget/color-picker.h \
ui/widget/color-preview.cpp \
ui/widget/color-preview.h \
+ ui/widget/color-slider.cpp \
+ ui/widget/color-slider.h \
ui/widget/combo-enums.h \
ui/widget/dock.h \
ui/widget/dock.cpp \
diff --git a/src/ui/widget/color-slider.cpp b/src/ui/widget/color-slider.cpp
new file mode 100644
index 000000000..430239f00
--- /dev/null
+++ b/src/ui/widget/color-slider.cpp
@@ -0,0 +1,961 @@
+/**
+ * @file
+ * A slider with colored background - implementation.
+ */
+/* Author:
+ * Lauris Kaplinski <lauris@kaplinski.com>
+ * bulia byak <buliabyak@users.sf.net>
+ *
+ * Copyright (C) 2001-2002 Lauris Kaplinski
+ *
+ * This code is in public domain
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "color-slider.h"
+
+#include <gtk/gtk.h>
+#include <gdkmm/screen.h>
+#include <gdkmm/general.h>
+#include <gtkmm/adjustment.h>
+
+#include "widgets/sp-color-scales.h"
+#include "preferences.h"
+
+static const gint SLIDER_WIDTH = 96;
+static const gint SLIDER_HEIGHT = 8;
+static const gint ARROW_SIZE = 7;
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+ColorSlider::ColorSlider(Gtk::Adjustment* adjustment)
+ : _dragging(false)
+ , _adjustment(NULL)
+ , _value(0.0)
+ , _oldvalue(0.0)
+ , _mapsize(0)
+ , _map(NULL)
+{
+ _c0[0] = 0x00;
+ _c0[1] = 0x00;
+ _c0[2] = 0x00;
+ _c0[3] = 0xff;
+
+ _cm[0] = 0xff;
+ _cm[1] = 0x00;
+ _cm[2] = 0x00;
+ _cm[3] = 0xff;
+
+ _c0[0] = 0xff;
+ _c0[1] = 0xff;
+ _c0[2] = 0xff;
+ _c0[3] = 0xff;
+
+ _b0 = 0x5f;
+ _b1 = 0xa0;
+ _bmask = 0x08;
+
+ set_adjustment(adjustment);
+}
+
+ColorSlider::~ColorSlider() {
+ if (_adjustment) {
+ //TODO: disconnect all connections
+ delete _adjustment;
+ _adjustment = NULL;
+ }
+}
+
+void ColorSlider::on_realize() {
+ set_realized();
+
+ if(!_refGdkWindow)
+ {
+ GdkWindowAttr attributes;
+ gint attributes_mask;
+ Gtk::Allocation allocation = get_allocation();
+
+ memset(&attributes, 0, sizeof(attributes));
+ attributes.x = allocation.get_x();
+ attributes.y = allocation.get_y();
+ attributes.width = allocation.get_width();
+ attributes.height = allocation.get_height();
+ attributes.window_type = GDK_WINDOW_CHILD;
+ attributes.wclass = GDK_INPUT_OUTPUT;
+ attributes.visual = gdk_screen_get_system_visual(gdk_screen_get_default());
+#if !GTK_CHECK_VERSION(3,0,0)
+ attributes.colormap = gdk_screen_get_system_colormap(gdk_screen_get_default());
+#endif
+ attributes.event_mask = get_events ();
+ attributes.event_mask |= (Gdk::EXPOSURE_MASK |
+ Gdk::BUTTON_PRESS_MASK |
+ Gdk::BUTTON_RELEASE_MASK |
+ Gdk::POINTER_MOTION_MASK |
+ Gdk::ENTER_NOTIFY_MASK |
+ Gdk::LEAVE_NOTIFY_MASK);
+
+#if GTK_CHECK_VERSION(3,0,0)
+ attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL;
+#else
+ attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
+#endif
+
+ _refGdkWindow = Gdk::Window::create(get_parent_window(), &attributes,
+ attributes_mask);
+ set_window(_refGdkWindow);
+ _refGdkWindow->set_user_data(gobj());
+
+ style_attach();
+ }
+}
+
+void ColorSlider::on_unrealize() {
+ _refGdkWindow.reset();
+
+ Gtk::Widget::on_unrealize();
+}
+
+void ColorSlider::on_size_request(Gtk::Requisition* requisition) {
+ GtkStyle *style = gtk_widget_get_style(gobj());
+ requisition->width = SLIDER_WIDTH + style->xthickness * 2;
+ requisition->height = SLIDER_HEIGHT + style->ythickness * 2;
+}
+
+//TODO: GTK3 prefferred width/height
+
+void ColorSlider::on_size_allocate(Gtk::Allocation& allocation) {
+ if (get_realized()) {
+ _refGdkWindow->move_resize(allocation.get_x(), allocation.get_y(),
+ allocation.get_width(), allocation.get_height());
+ }
+}
+
+//TODO: if not GTK3
+bool ColorSlider::on_expose_event(GdkEventExpose* event) {
+ bool result = false;
+
+ if (get_is_drawable()) {
+ Cairo::RefPtr<Cairo::Context> cr = _refGdkWindow->create_cairo_context();
+ result = on_draw(cr);
+ }
+ return result;
+}
+
+bool ColorSlider::on_button_press_event(GdkEventButton *event) {
+ //TODO: implementation
+ return false;
+}
+
+bool ColorSlider::on_button_release_event(GdkEventButton *event) {
+ //TODO: implementation
+ return false;
+}
+
+bool ColorSlider::on_motion_notify_event(GdkEventMotion *event) {
+ //TODO: implementation
+ return false;
+}
+
+void ColorSlider::set_adjustment(Gtk::Adjustment* /*adjustment*/) {
+ //TODO: implementation
+}
+
+void ColorSlider::set_colors(guint32 start, guint32 min, guint32 end) {
+
+}
+
+void ColorSlider::set_map(const guchar *map) {
+
+}
+
+void ColorSlider::set_background(guint dark, guint light, guint size) {
+
+}
+
+bool ColorSlider::on_draw(const Cairo::RefPtr<Cairo::Context>& cr) {
+ return false;
+}
+
+}//namespace Widget
+}//namespace UI
+}//namespace Inkscape
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+enum {
+ GRABBED,
+ DRAGGED,
+ RELEASED,
+ CHANGED,
+ LAST_SIGNAL
+};
+
+static void sp_color_slider_class_init (SPColorSliderClass *klass);
+static void sp_color_slider_init (SPColorSlider *slider);
+static void sp_color_slider_dispose(GObject *object);
+
+static void sp_color_slider_realize (GtkWidget *widget);
+static void sp_color_slider_size_request (GtkWidget *widget, GtkRequisition *requisition);
+
+#if GTK_CHECK_VERSION(3,0,0)
+static void sp_color_slider_get_preferred_width(GtkWidget *widget,
+ gint *minimal_width,
+ gint *natural_width);
+
+static void sp_color_slider_get_preferred_height(GtkWidget *widget,
+ gint *minimal_height,
+ gint *natural_height);
+#else
+static gboolean sp_color_slider_expose(GtkWidget *widget, GdkEventExpose *event);
+#endif
+
+static void sp_color_slider_size_allocate (GtkWidget *widget, GtkAllocation *allocation);
+
+static gboolean sp_color_slider_draw(GtkWidget *widget, cairo_t *cr);
+
+static gint sp_color_slider_button_press (GtkWidget *widget, GdkEventButton *event);
+static gint sp_color_slider_button_release (GtkWidget *widget, GdkEventButton *event);
+static gint sp_color_slider_motion_notify (GtkWidget *widget, GdkEventMotion *event);
+
+static void sp_color_slider_adjustment_changed (GtkAdjustment *adjustment, SPColorSlider *slider);
+static void sp_color_slider_adjustment_value_changed (GtkAdjustment *adjustment, SPColorSlider *slider);
+
+static const guchar *sp_color_slider_render_gradient (gint x0, gint y0, gint width, gint height,
+ gint c[], gint dc[], guint b0, guint b1, guint mask);
+static const guchar *sp_color_slider_render_map (gint x0, gint y0, gint width, gint height,
+ guchar *map, gint start, gint step, guint b0, guint b1, guint mask);
+
+static GtkWidgetClass *parent_class;
+static guint slider_signals[LAST_SIGNAL] = {0};
+
+GType
+sp_color_slider_get_type (void)
+{
+ static GType type = 0;
+ if (!type) {
+ GTypeInfo info = {
+ sizeof (SPColorSliderClass),
+ NULL, NULL,
+ (GClassInitFunc) sp_color_slider_class_init,
+ NULL, NULL,
+ sizeof (SPColorSlider),
+ 0,
+ (GInstanceInitFunc) sp_color_slider_init,
+ NULL
+ };
+ type = g_type_register_static (GTK_TYPE_WIDGET, "SPColorSlider", &info, (GTypeFlags)0);
+ }
+ return type;
+}
+
+static void sp_color_slider_class_init(SPColorSliderClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS(klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(klass);
+
+ parent_class = GTK_WIDGET_CLASS(g_type_class_peek_parent(klass));
+
+ slider_signals[GRABBED] = g_signal_new ("grabbed",
+ G_TYPE_FROM_CLASS(object_class),
+ (GSignalFlags)(G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE),
+ G_STRUCT_OFFSET (SPColorSliderClass, grabbed),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+ slider_signals[DRAGGED] = g_signal_new ("dragged",
+ G_TYPE_FROM_CLASS(object_class),
+ (GSignalFlags)(G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE),
+ G_STRUCT_OFFSET (SPColorSliderClass, dragged),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+ slider_signals[RELEASED] = g_signal_new ("released",
+ G_TYPE_FROM_CLASS(object_class),
+ (GSignalFlags)(G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE),
+ G_STRUCT_OFFSET (SPColorSliderClass, released),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+ slider_signals[CHANGED] = g_signal_new ("changed",
+ G_TYPE_FROM_CLASS(object_class),
+ (GSignalFlags)(G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE),
+ G_STRUCT_OFFSET (SPColorSliderClass, changed),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ object_class->dispose = sp_color_slider_dispose;
+
+ widget_class->realize = sp_color_slider_realize;
+#if GTK_CHECK_VERSION(3,0,0)
+ widget_class->get_preferred_width = sp_color_slider_get_preferred_width;
+ widget_class->get_preferred_height = sp_color_slider_get_preferred_height;
+ widget_class->draw = sp_color_slider_draw;
+#else
+ widget_class->size_request = sp_color_slider_size_request;
+ widget_class->expose_event = sp_color_slider_expose;
+#endif
+ widget_class->size_allocate = sp_color_slider_size_allocate;
+/* widget_class->draw_focus = sp_color_slider_draw_focus; */
+/* widget_class->draw_default = sp_color_slider_draw_default; */
+
+ widget_class->button_press_event = sp_color_slider_button_press;
+ widget_class->button_release_event = sp_color_slider_button_release;
+ widget_class->motion_notify_event = sp_color_slider_motion_notify;
+}
+
+static void
+sp_color_slider_init (SPColorSlider *slider)
+{
+ /* We are widget with window */
+ gtk_widget_set_has_window (GTK_WIDGET(slider), TRUE);
+
+ slider->dragging = FALSE;
+
+ slider->adjustment = NULL;
+ slider->value = 0.0;
+
+ slider->c0[0] = 0x00;
+ slider->c0[1] = 0x00;
+ slider->c0[2] = 0x00;
+ slider->c0[3] = 0xff;
+
+ slider->cm[0] = 0xff;
+ slider->cm[1] = 0x00;
+ slider->cm[2] = 0x00;
+ slider->cm[3] = 0xff;
+
+ slider->c1[0] = 0xff;
+ slider->c1[1] = 0xff;
+ slider->c1[2] = 0xff;
+ slider->c1[3] = 0xff;
+
+ slider->b0 = 0x5f;
+ slider->b1 = 0xa0;
+ slider->bmask = 0x08;
+
+ slider->map = NULL;
+}
+
+static void sp_color_slider_dispose(GObject *object)
+{
+ SPColorSlider *slider = SP_COLOR_SLIDER (object);
+
+ if (slider->adjustment) {
+ g_signal_handlers_disconnect_matched (G_OBJECT (slider->adjustment), G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, slider);
+ g_object_unref (slider->adjustment);
+ slider->adjustment = NULL;
+ }
+
+ if ((G_OBJECT_CLASS(parent_class))->dispose)
+ (* (G_OBJECT_CLASS(parent_class))->dispose) (object);
+}
+
+static void
+sp_color_slider_realize (GtkWidget *widget)
+{
+ GdkWindowAttr attributes;
+ gint attributes_mask;
+ GtkAllocation allocation;
+
+ gtk_widget_get_allocation(widget, &allocation);
+ gtk_widget_set_realized (widget, TRUE);
+
+ attributes.window_type = GDK_WINDOW_CHILD;
+ attributes.x = allocation.x;
+ attributes.y = allocation.y;
+ attributes.width = allocation.width;
+ attributes.height = allocation.height;
+ attributes.wclass = GDK_INPUT_OUTPUT;
+ attributes.visual = gdk_screen_get_system_visual(gdk_screen_get_default());
+
+#if !GTK_CHECK_VERSION(3,0,0)
+ attributes.colormap = gdk_screen_get_system_colormap(gdk_screen_get_default());
+#endif
+
+ attributes.event_mask = gtk_widget_get_events (widget);
+ attributes.event_mask |= (GDK_EXPOSURE_MASK |
+ GDK_BUTTON_PRESS_MASK |
+ GDK_BUTTON_RELEASE_MASK |
+ GDK_POINTER_MOTION_MASK |
+ GDK_ENTER_NOTIFY_MASK |
+ GDK_LEAVE_NOTIFY_MASK);
+#if GTK_CHECK_VERSION(3,0,0)
+ attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL;
+#else
+ attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
+#endif
+
+ gtk_widget_set_window(widget,
+ gdk_window_new(gtk_widget_get_parent_window(widget),
+ &attributes, attributes_mask));
+
+ gdk_window_set_user_data(gtk_widget_get_window(widget), widget);
+
+#if !GTK_CHECK_VERSION(3,0,0)
+ // This doesn't do anything in GTK+ 3
+ gtk_widget_set_style(widget,
+ gtk_style_attach(gtk_widget_get_style(widget),
+ gtk_widget_get_window(widget)));
+#endif
+}
+
+static void
+sp_color_slider_size_request (GtkWidget *widget, GtkRequisition *requisition)
+{
+ GtkStyle *style = gtk_widget_get_style(widget);
+ requisition->width = SLIDER_WIDTH + style->xthickness * 2;
+ requisition->height = SLIDER_HEIGHT + style->ythickness * 2;
+}
+
+#if GTK_CHECK_VERSION(3,0,0)
+static void sp_color_slider_get_preferred_width(GtkWidget *widget, gint *minimal_width, gint *natural_width)
+{
+ GtkRequisition requisition;
+ sp_color_slider_size_request(widget, &requisition);
+ *minimal_width = *natural_width = requisition.width;
+}
+
+static void sp_color_slider_get_preferred_height(GtkWidget *widget, gint *minimal_height, gint *natural_height)
+{
+ GtkRequisition requisition;
+ sp_color_slider_size_request(widget, &requisition);
+ *minimal_height = *natural_height = requisition.height;
+}
+#endif
+
+static void
+sp_color_slider_size_allocate (GtkWidget *widget, GtkAllocation *allocation)
+{
+ gtk_widget_set_allocation(widget, allocation);
+
+ if (gtk_widget_get_realized (widget)) {
+ /* Resize GdkWindow */
+ gdk_window_move_resize(gtk_widget_get_window(widget),
+ allocation->x, allocation->y,
+ allocation->width, allocation->height);
+ }
+}
+
+#if !GTK_CHECK_VERSION(3,0,0)
+static gboolean sp_color_slider_expose(GtkWidget *widget, GdkEventExpose * /*event*/)
+{
+ gboolean result = FALSE;
+
+ if (gtk_widget_is_drawable(widget)) {
+ GdkWindow *window = gtk_widget_get_window(widget);
+ cairo_t *cr = gdk_cairo_create(window);
+ result = sp_color_slider_draw(widget, cr);
+ cairo_destroy(cr);
+ }
+
+ return result;
+}
+#endif
+
+static gint
+sp_color_slider_button_press (GtkWidget *widget, GdkEventButton *event)
+{
+ SPColorSlider *slider;
+
+ slider = SP_COLOR_SLIDER (widget);
+
+ if (event->button == 1) {
+ GtkAllocation allocation;
+ gtk_widget_get_allocation(widget, &allocation);
+ gint cx, cw;
+ cx = gtk_widget_get_style(widget)->xthickness;
+ cw = allocation.width - 2 * cx;
+ g_signal_emit (G_OBJECT (slider), slider_signals[GRABBED], 0);
+ slider->dragging = TRUE;
+ slider->oldvalue = slider->value;
+ ColorScales::setScaled( slider->adjustment, CLAMP ((gfloat) (event->x - cx) / cw, 0.0, 1.0) );
+ g_signal_emit (G_OBJECT (slider), slider_signals[DRAGGED], 0);
+
+#if GTK_CHECK_VERSION(3,0,0)
+ gdk_device_grab(gdk_event_get_device(reinterpret_cast<GdkEvent *>(event)),
+ gtk_widget_get_window(widget),
+ GDK_OWNERSHIP_NONE,
+ FALSE,
+ static_cast<GdkEventMask>(GDK_POINTER_MOTION_MASK | GDK_BUTTON_RELEASE_MASK),
+ NULL,
+ event->time);
+#else
+ gdk_pointer_grab(gtk_widget_get_window(widget), FALSE,
+ static_cast<GdkEventMask>(GDK_POINTER_MOTION_MASK | GDK_BUTTON_RELEASE_MASK),
+ NULL, NULL, event->time);
+#endif
+ }
+
+ return FALSE;
+}
+
+static gint
+sp_color_slider_button_release (GtkWidget *widget, GdkEventButton *event)
+{
+ SPColorSlider *slider;
+
+ slider = SP_COLOR_SLIDER (widget);
+
+ if (event->button == 1) {
+
+#if GTK_CHECK_VERSION(3,0,0)
+ gdk_device_ungrab(gdk_event_get_device(reinterpret_cast<GdkEvent *>(event)),
+ gdk_event_get_time(reinterpret_cast<GdkEvent *>(event)));
+#else
+ gdk_pointer_ungrab (event->time);
+#endif
+
+ slider->dragging = FALSE;
+ g_signal_emit (G_OBJECT (slider), slider_signals[RELEASED], 0);
+ if (slider->value != slider->oldvalue) g_signal_emit (G_OBJECT (slider), slider_signals[CHANGED], 0);
+ }
+
+ return FALSE;
+}
+
+static gint
+sp_color_slider_motion_notify (GtkWidget *widget, GdkEventMotion *event)
+{
+ SPColorSlider *slider;
+
+ slider = SP_COLOR_SLIDER (widget);
+
+ if (slider->dragging) {
+ gint cx, cw;
+ GtkAllocation allocation;
+ gtk_widget_get_allocation(widget, &allocation);
+ cx = gtk_widget_get_style(widget)->xthickness;
+ cw = allocation.width - 2 * cx;
+ ColorScales::setScaled( slider->adjustment, CLAMP ((gfloat) (event->x - cx) / cw, 0.0, 1.0) );
+ g_signal_emit (G_OBJECT (slider), slider_signals[DRAGGED], 0);
+ }
+
+ return FALSE;
+}
+
+GtkWidget *sp_color_slider_new(GtkAdjustment *adjustment)
+{
+ SPColorSlider *slider = SP_COLOR_SLIDER(g_object_new(SP_TYPE_COLOR_SLIDER, NULL));
+
+ sp_color_slider_set_adjustment (slider, adjustment);
+
+ return GTK_WIDGET (slider);
+}
+
+void sp_color_slider_set_adjustment(SPColorSlider *slider, GtkAdjustment *adjustment)
+{
+ g_return_if_fail (slider != NULL);
+ g_return_if_fail (SP_IS_COLOR_SLIDER (slider));
+
+ if (!adjustment) {
+ adjustment = GTK_ADJUSTMENT(gtk_adjustment_new(0.0, 0.0, 1.0, 0.01, 0.0, 0.0));
+ } else {
+ gtk_adjustment_set_page_increment(adjustment, 0.0);
+ gtk_adjustment_set_page_size(adjustment, 0.0);
+ }
+
+ if (slider->adjustment != adjustment) {
+ if (slider->adjustment) {
+ g_signal_handlers_disconnect_matched (G_OBJECT (slider->adjustment), G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, slider);
+ g_object_unref (slider->adjustment);
+ }
+
+ slider->adjustment = adjustment;
+ g_object_ref (adjustment);
+ g_object_ref_sink (adjustment);
+
+ g_signal_connect (G_OBJECT (adjustment), "changed",
+ G_CALLBACK (sp_color_slider_adjustment_changed), slider);
+ g_signal_connect (G_OBJECT (adjustment), "value_changed",
+ G_CALLBACK (sp_color_slider_adjustment_value_changed), slider);
+
+ slider->value = ColorScales::getScaled( adjustment );
+
+ sp_color_slider_adjustment_changed (adjustment, slider);
+ }
+}
+
+void
+sp_color_slider_set_colors (SPColorSlider *slider, guint32 start, guint32 mid, guint32 end)
+{
+ g_return_if_fail (slider != NULL);
+ g_return_if_fail (SP_IS_COLOR_SLIDER (slider));
+
+ // Remove any map, if set
+ slider->map = 0;
+
+ slider->c0[0] = start >> 24;
+ slider->c0[1] = (start >> 16) & 0xff;
+ slider->c0[2] = (start >> 8) & 0xff;
+ slider->c0[3] = start & 0xff;
+
+ slider->cm[0] = mid >> 24;
+ slider->cm[1] = (mid >> 16) & 0xff;
+ slider->cm[2] = (mid >> 8) & 0xff;
+ slider->cm[3] = mid & 0xff;
+
+ slider->c1[0] = end >> 24;
+ slider->c1[1] = (end >> 16) & 0xff;
+ slider->c1[2] = (end >> 8) & 0xff;
+ slider->c1[3] = end & 0xff;
+
+ gtk_widget_queue_draw (GTK_WIDGET (slider));
+}
+
+void
+sp_color_slider_set_map (SPColorSlider *slider, const guchar *map)
+{
+ g_return_if_fail (slider != NULL);
+ g_return_if_fail (SP_IS_COLOR_SLIDER (slider));
+
+ slider->map = const_cast<guchar *>(map);
+
+ gtk_widget_queue_draw (GTK_WIDGET (slider));
+}
+
+void
+sp_color_slider_set_background (SPColorSlider *slider, guint dark, guint light, guint size)
+{
+ g_return_if_fail (slider != NULL);
+ g_return_if_fail (SP_IS_COLOR_SLIDER (slider));
+
+ slider->b0 = dark;
+ slider->b1 = light;
+ slider->bmask = size;
+
+ gtk_widget_queue_draw (GTK_WIDGET (slider));
+}
+
+static void
+sp_color_slider_adjustment_changed (GtkAdjustment */*adjustment*/, SPColorSlider *slider)
+{
+ gtk_widget_queue_draw (GTK_WIDGET (slider));
+}
+
+static void
+sp_color_slider_adjustment_value_changed (GtkAdjustment *adjustment, SPColorSlider *slider)
+{
+ GtkWidget *widget;
+
+ widget = GTK_WIDGET (slider);
+
+ if (slider->value != ColorScales::getScaled( adjustment )) {
+ gint cx, cy, cw, ch;
+ GtkStyle *style = gtk_widget_get_style(widget);
+ GtkAllocation allocation;
+ gtk_widget_get_allocation(widget, &allocation);
+ cx = style->xthickness;
+ cy = style->ythickness;
+ cw = allocation.width - 2 * cx;
+ ch = allocation.height - 2 * cy;
+ if ((gint) (ColorScales::getScaled( adjustment ) * cw) != (gint) (slider->value * cw)) {
+ gint ax, ay;
+ gfloat value;
+ value = slider->value;
+ slider->value = ColorScales::getScaled( adjustment );
+ ax = (int)(cx + value * cw - ARROW_SIZE / 2 - 2);
+ ay = cy;
+ gtk_widget_queue_draw_area (widget, ax, ay, ARROW_SIZE + 4, ch);
+ ax = (int)(cx + slider->value * cw - ARROW_SIZE / 2 - 2);
+ ay = cy;
+ gtk_widget_queue_draw_area (widget, ax, ay, ARROW_SIZE + 4, ch);
+ } else {
+ slider->value = ColorScales::getScaled( adjustment );
+ }
+ }
+}
+
+static gboolean sp_color_slider_draw(GtkWidget *widget, cairo_t *cr)
+{
+ SPColorSlider *slider = SP_COLOR_SLIDER(widget);
+
+ gboolean colorsOnTop = Inkscape::Preferences::get()->getBool("/options/workarounds/colorsontop", false);
+
+ GtkAllocation allocation;
+ gtk_widget_get_allocation(widget, &allocation);
+
+#if GTK_CHECK_VERSION(3,0,0)
+ GtkStyleContext *context = gtk_widget_get_style_context(widget);
+#else
+ GdkWindow *window = gtk_widget_get_window(widget);
+ GtkStyle *style = gtk_widget_get_style(widget);
+#endif
+
+ // Draw shadow
+ if (colorsOnTop) {
+#if GTK_CHECK_VERSION(3,0,0)
+ gtk_render_frame(context,
+ cr,
+ 0, 0,
+ allocation.width, allocation.height);
+#else
+ gtk_paint_shadow( style, window,
+ gtk_widget_get_state(widget), GTK_SHADOW_IN,
+ NULL, widget, "colorslider",
+ 0, 0,
+ allocation.width, allocation.height);
+#endif
+ }
+
+ /* Paintable part of color gradient area */
+ GdkRectangle carea;
+
+#if GTK_CHECK_VERSION(3,0,0)
+ GtkBorder padding;
+
+ gtk_style_context_get_padding(context,
+ gtk_widget_get_state_flags(widget),
+ &padding);
+
+ carea.x = padding.left;
+ carea.y = padding.top;
+#else
+ carea.x = style->xthickness;
+ carea.y = style->ythickness;
+#endif
+
+ carea.width = allocation.width - 2 * carea.x;
+ carea.height = allocation.height - 2 * carea.y;
+
+ if (slider->map) {
+ /* Render map pixelstore */
+ gint d = (1024 << 16) / carea.width;
+ gint s = 0;
+
+ const guchar *b = sp_color_slider_render_map(0, 0, carea.width, carea.height,
+ slider->map, s, d,
+ slider->b0, slider->b1, slider->bmask);
+
+ if (b != NULL && carea.width > 0) {
+ GdkPixbuf *pb = gdk_pixbuf_new_from_data (b, GDK_COLORSPACE_RGB,
+ 0, 8, carea.width, carea.height, carea.width * 3, NULL, NULL);
+
+ gdk_cairo_set_source_pixbuf(cr, pb, carea.x, carea.y);
+ cairo_paint(cr);
+ g_object_unref(pb);
+ }
+
+ } else {
+ gint c[4], dc[4];
+
+ /* Render gradient */
+
+ // part 1: from c0 to cm
+ if (carea.width > 0) {
+ for (gint i = 0; i < 4; i++) {
+ c[i] = slider->c0[i] << 16;
+ dc[i] = ((slider->cm[i] << 16) - c[i]) / (carea.width/2);
+ }
+ guint wi = carea.width/2;
+ const guchar *b = sp_color_slider_render_gradient(0, 0, wi, carea.height,
+ c, dc, slider->b0, slider->b1, slider->bmask);
+
+ /* Draw pixelstore 1 */
+ if (b != NULL && wi > 0) {
+ GdkPixbuf *pb = gdk_pixbuf_new_from_data (b, GDK_COLORSPACE_RGB,
+ 0, 8, wi, carea.height, wi * 3, NULL, NULL);
+
+ gdk_cairo_set_source_pixbuf(cr, pb, carea.x, carea.y);
+ cairo_paint(cr);
+ g_object_unref(pb);
+ }
+ }
+
+ // part 2: from cm to c1
+ if (carea.width > 0) {
+ for (gint i = 0; i < 4; i++) {
+ c[i] = slider->cm[i] << 16;
+ dc[i] = ((slider->c1[i] << 16) - c[i]) / (carea.width/2);
+ }
+ guint wi = carea.width/2;
+ const guchar *b = sp_color_slider_render_gradient(carea.width/2, 0, wi, carea.height,
+ c, dc,
+ slider->b0, slider->b1, slider->bmask);
+
+ /* Draw pixelstore 2 */
+ if (b != NULL && wi > 0) {
+ GdkPixbuf *pb = gdk_pixbuf_new_from_data (b, GDK_COLORSPACE_RGB,
+ 0, 8, wi, carea.height, wi * 3, NULL, NULL);
+
+ gdk_cairo_set_source_pixbuf(cr, pb, carea.width/2 + carea.x, carea.y);
+ cairo_paint(cr);
+
+ g_object_unref(pb);
+ }
+ }
+ }
+
+ /* Draw shadow */
+ if (!colorsOnTop) {
+#if GTK_CHECK_VERSION(3,0,0)
+ gtk_render_frame(context,
+ cr,
+ 0, 0,
+ allocation.width, allocation.height);
+#else
+ gtk_paint_shadow( style, window,
+ gtk_widget_get_state(widget), GTK_SHADOW_IN,
+ NULL, widget, "colorslider",
+ 0, 0,
+ allocation.width, allocation.height);
+#endif
+ }
+
+ /* Draw arrow */
+ gint x = (int)(slider->value * (carea.width - 1) - ARROW_SIZE / 2 + carea.x);
+ gint y1 = carea.y;
+ gint y2 = carea.y + carea.height - 1;
+ cairo_set_line_width(cr, 1.0);
+
+ // Define top arrow
+ cairo_move_to(cr, x - 0.5, y1 + 0.5);
+ cairo_line_to(cr, x + ARROW_SIZE - 0.5, y1 + 0.5);
+ cairo_line_to(cr, x + (ARROW_SIZE-1)/2.0, y1 + ARROW_SIZE/2.0 + 0.5);
+ cairo_line_to(cr, x - 0.5, y1 + 0.5);
+
+ // Define bottom arrow
+ cairo_move_to(cr, x - 0.5, y2 + 0.5);
+ cairo_line_to(cr, x + ARROW_SIZE - 0.5, y2 + 0.5);
+ cairo_line_to(cr, x + (ARROW_SIZE-1)/2.0, y2 - ARROW_SIZE/2.0 + 0.5);
+ cairo_line_to(cr, x - 0.5, y2 + 0.5);
+
+ // Render both arrows
+ cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
+ cairo_stroke_preserve(cr);
+ cairo_set_source_rgb(cr, 0.0, 0.0, 0.0);
+ cairo_fill(cr);
+
+ return FALSE;
+}
+
+/* Colors are << 16 */
+
+static const guchar *
+sp_color_slider_render_gradient (gint x0, gint y0, gint width, gint height,
+ gint c[], gint dc[], guint b0, guint b1, guint mask)
+{
+ static guchar *buf = NULL;
+ static gint bs = 0;
+ guchar *dp;
+ gint x, y;
+ guint r, g, b, a;
+
+ if (buf && (bs < width * height)) {
+ g_free (buf);
+ buf = NULL;
+ }
+ if (!buf) {
+ buf = g_new (guchar, width * height * 3);
+ bs = width * height;
+ }
+
+ dp = buf;
+ r = c[0];
+ g = c[1];
+ b = c[2];
+ a = c[3];
+ for (x = x0; x < x0 + width; x++) {
+ gint cr, cg, cb, ca;
+ guchar *d;
+ cr = r >> 16;
+ cg = g >> 16;
+ cb = b >> 16;
+ ca = a >> 16;
+ d = dp;
+ for (y = y0; y < y0 + height; y++) {
+ guint bg, fc;
+ /* Background value */
+ bg = ((x & mask) ^ (y & mask)) ? b0 : b1;
+ fc = (cr - bg) * ca;
+ d[0] = bg + ((fc + (fc >> 8) + 0x80) >> 8);
+ fc = (cg - bg) * ca;
+ d[1] = bg + ((fc + (fc >> 8) + 0x80) >> 8);
+ fc = (cb - bg) * ca;
+ d[2] = bg + ((fc + (fc >> 8) + 0x80) >> 8);
+ d += 3 * width;
+ }
+ r += dc[0];
+ g += dc[1];
+ b += dc[2];
+ a += dc[3];
+ dp += 3;
+ }
+
+ return buf;
+}
+
+/* Positions are << 16 */
+
+static const guchar *
+sp_color_slider_render_map (gint x0, gint y0, gint width, gint height,
+ guchar *map, gint start, gint step, guint b0, guint b1, guint mask)
+{
+ static guchar *buf = NULL;
+ static gint bs = 0;
+ guchar *dp;
+ gint x, y;
+
+ if (buf && (bs < width * height)) {
+ g_free (buf);
+ buf = NULL;
+ }
+ if (!buf) {
+ buf = g_new (guchar, width * height * 3);
+ bs = width * height;
+ }
+
+ dp = buf;
+ for (x = x0; x < x0 + width; x++) {
+ gint cr, cg, cb, ca;
+ guchar *d = dp;
+ guchar *sp = map + 4 * (start >> 16);
+ cr = *sp++;
+ cg = *sp++;
+ cb = *sp++;
+ ca = *sp++;
+ for (y = y0; y < y0 + height; y++) {
+ guint bg, fc;
+ /* Background value */
+ bg = ((x & mask) ^ (y & mask)) ? b0 : b1;
+ fc = (cr - bg) * ca;
+ d[0] = bg + ((fc + (fc >> 8) + 0x80) >> 8);
+ fc = (cg - bg) * ca;
+ d[1] = bg + ((fc + (fc >> 8) + 0x80) >> 8);
+ fc = (cb - bg) * ca;
+ d[2] = bg + ((fc + (fc >> 8) + 0x80) >> 8);
+ d += 3 * width;
+ }
+ dp += 3;
+ start += step;
+ }
+
+ return buf;
+}
+
diff --git a/src/ui/widget/color-slider.h b/src/ui/widget/color-slider.h
new file mode 100644
index 000000000..d8be7d111
--- /dev/null
+++ b/src/ui/widget/color-slider.h
@@ -0,0 +1,146 @@
+#ifndef __SP_COLOR_SLIDER_H__
+#define __SP_COLOR_SLIDER_H__
+
+/* Author:
+ * Lauris Kaplinski <lauris@kaplinski.com>
+ *
+ * Copyright (C) 2001-2002 Lauris Kaplinski
+ *
+ * This code is in public domain
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#if GLIBMM_DISABLE_DEPRECATED && HAVE_GLIBMM_THREADS_H
+#include <glibmm/threads.h>
+#endif
+
+#include <gtkmm/widget.h>
+#include <sigc++/signal.h>
+
+namespace Inkscape
+{
+namespace UI
+{
+namespace Widget
+{
+
+/*
+ * A slider with colored background
+ */
+class ColorSlider: public Gtk::Widget {
+public:
+ //if GTK2
+ ColorSlider(Gtk::Adjustment *adjustment);
+ ~ColorSlider();
+
+ void set_adjustment(Gtk::Adjustment *adjustment);
+
+ void set_colors(guint32 start, guint32 mid, guint32 end);
+
+ void set_map(const guchar* map);
+
+ void set_background(guint dark, guint light, guint size);
+
+ sigc::signal<void> signal_grabbed;
+ sigc::signal<void> signal_dragged;
+ sigc::signal<void> signal_released;
+ sigc::signal<void> signal_value_changed;
+
+protected:
+ void on_size_allocate(Gtk::Allocation& allocation);
+ void on_realize();
+ void on_unrealize();
+ bool on_button_press_event(GdkEventButton *event);
+ bool on_button_release_event(GdkEventButton *event);
+ bool on_motion_notify_event(GdkEventMotion *event);
+
+ //if GTK2
+ void on_size_request(Gtk::Requisition* requisition);
+ bool on_expose_event(GdkEventExpose* event);
+ //if GTK3
+ //request mode, get preffered width/height vfunc
+ //endif
+
+ bool on_draw(const Cairo::RefPtr<Cairo::Context>& cr);
+
+ //TODO: on_adjustment_changed method
+ //TODO: on_adjustment value changed method + connection
+
+private:
+ bool _dragging;
+
+ Gtk::Adjustment *_adjustment;
+
+ gfloat _value;
+ gfloat _oldvalue;
+ guchar _c0[4], _cm[4], _c1[4];
+ guchar _b0, _b1;
+ guchar _bmask;
+
+ gint _mapsize;
+ guchar *_map;
+
+ Glib::RefPtr<Gdk::Window> _refGdkWindow;
+};
+
+}//namespace Widget
+}//namespace UI
+}//namespace Inkscape
+
+
+#include <gtk/gtk.h>
+
+#include <glib.h>
+
+
+
+struct SPColorSlider;
+struct SPColorSliderClass;
+
+#define SP_TYPE_COLOR_SLIDER (sp_color_slider_get_type ())
+#define SP_COLOR_SLIDER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), SP_TYPE_COLOR_SLIDER, SPColorSlider))
+#define SP_COLOR_SLIDER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), SP_TYPE_COLOR_SLIDER, SPColorSliderClass))
+#define SP_IS_COLOR_SLIDER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), SP_TYPE_COLOR_SLIDER))
+#define SP_IS_COLOR_SLIDER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), SP_TYPE_COLOR_SLIDER))
+
+struct SPColorSlider {
+ GtkWidget widget;
+
+ guint dragging : 1;
+
+ GtkAdjustment *adjustment;
+
+ gfloat value;
+ gfloat oldvalue;
+ guchar c0[4], cm[4], c1[4];
+ guchar b0, b1;
+ guchar bmask;
+
+ gint mapsize;
+ guchar *map;
+};
+
+struct SPColorSliderClass {
+ GtkWidgetClass parent_class;
+
+ void (* grabbed) (SPColorSlider *slider);
+ void (* dragged) (SPColorSlider *slider);
+ void (* released) (SPColorSlider *slider);
+ void (* changed) (SPColorSlider *slider);
+};
+
+GType sp_color_slider_get_type (void);
+
+GtkWidget *sp_color_slider_new (GtkAdjustment *adjustment);
+
+void sp_color_slider_set_adjustment (SPColorSlider *slider, GtkAdjustment *adjustment);
+void sp_color_slider_set_colors (SPColorSlider *slider, guint32 start, guint32 mid, guint32 end);
+void sp_color_slider_set_map (SPColorSlider *slider, const guchar *map);
+void sp_color_slider_set_background (SPColorSlider *slider, guint dark, guint light, guint size);
+
+
+
+#endif