diff options
| author | Tomasz Boczkowski <penginsbacon@gmail.com> | 2014-05-23 09:09:05 +0000 |
|---|---|---|
| committer | Tomasz Boczkowski <penginsbacon@gmail.com> | 2014-05-23 09:09:05 +0000 |
| commit | a06f51f786230bfd26ddd34d27be438d4bebbd04 (patch) | |
| tree | fe7754c7e976e5b76e9fd03ea80c81feaa9d7b39 /src/ui | |
| parent | SPColorSlider c++-sification: added ColorSlider class (diff) | |
| download | inkscape-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.txt | 2 | ||||
| -rw-r--r-- | src/ui/widget/Makefile_insert | 2 | ||||
| -rw-r--r-- | src/ui/widget/color-slider.cpp | 961 | ||||
| -rw-r--r-- | src/ui/widget/color-slider.h | 146 |
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 |
