summaryrefslogtreecommitdiffstats
path: root/src/widgets/dash-selector.cpp
diff options
context:
space:
mode:
authorJohn Smith <john.smith7545@yahoo.com>2012-03-12 09:55:25 +0000
committerJohn Smith <removethis.john.q.public@bigmail.com>2012-03-12 09:55:25 +0000
commitda6b3a2529230d8983fe72e82c919c6fa611695c (patch)
treeb4f33f45a0172a1146bc00733d88304cf1e97ccc /src/widgets/dash-selector.cpp
parentReplace deprecated GtkSignal API (diff)
downloadinkscape-da6b3a2529230d8983fe72e82c919c6fa611695c.tar.gz
inkscape-da6b3a2529230d8983fe72e82c919c6fa611695c.zip
Fix for 903671 : GtkOptionMenu needs replacing with GtkComboBox. Fill and Stroke Dashes
(bzr r11072)
Diffstat (limited to 'src/widgets/dash-selector.cpp')
-rw-r--r--src/widgets/dash-selector.cpp239
1 files changed, 68 insertions, 171 deletions
diff --git a/src/widgets/dash-selector.cpp b/src/widgets/dash-selector.cpp
index d30c0c328..7f36b91f5 100644
--- a/src/widgets/dash-selector.cpp
+++ b/src/widgets/dash-selector.cpp
@@ -1,6 +1,6 @@
/**
* @file
- * Option menu for selecting dash patterns - implementation.
+ * Combobox for selecting dash patterns - implementation.
*/
/* Author:
* Lauris Kaplinski <lauris@kaplinski.com>
@@ -12,9 +12,6 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-#define DASH_PREVIEW_WIDTH 2
-#define DASH_PREVIEW_LENGTH 80
-
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
@@ -24,16 +21,14 @@
#include <cstring>
#include <string>
#include <glibmm/i18n.h>
+#include <gtkmm/adjustment.h>
#include <2geom/coord.h>
#include "style.h"
#include "dialogs/dialog-events.h"
#include "preferences.h"
-
-#include <gtkmm/optionmenu.h>
-#include <gtkmm/adjustment.h>
#include "ui/widget/spinbutton.h"
-
+#include "display/cairo-utils.h"
gchar const *const SPDashSelector::_prefs_path = "/palette/dashes";
@@ -48,34 +43,40 @@ static double *builtin_dashes[] = {dash_0, dash_1_1, dash_2_1, dash_4_1, dash_1_
static double **dashes = NULL;
-static void sp_dash_selector_menu_item_image_realize(Gtk::Image *px, double *pattern);
-
-SPDashSelector::SPDashSelector() {
+SPDashSelector::SPDashSelector()
+ : preview_width(80),
+ preview_height(16),
+ preview_lineheight(2)
+{
// TODO: find something more sensible here!!
init_dashes();
- dash = new Gtk::OptionMenu();
- dash->set_tooltip_text(_("Dash pattern"));
- dash->show();
- this->pack_start(*dash, false, false, 0);
+ dash_store = Gtk::ListStore::create(dash_columns);
+ dash_combo.set_model(dash_store);
+ dash_combo.pack_start(image_renderer);
+ dash_combo.set_cell_data_func(image_renderer, sigc::mem_fun(*this, &SPDashSelector::prepareImageRenderer));
+ dash_combo.set_tooltip_text(_("Dash pattern"));
+ dash_combo.show();
+ dash_combo.signal_changed().connect( sigc::mem_fun(*this, &SPDashSelector::on_selection) );
- Gtk::Menu *m = new Gtk::Menu();
- m->show();
- for (int i = 0; dashes[i]; i++) {
- Gtk::MenuItem *mi = menu_item_new(dashes[i]);
- mi->show();
- m->append(*mi);
- }
- dash->set_menu(*m);
+ this->pack_start(dash_combo, false, false, 0);
offset = new Gtk::Adjustment(0.0, 0.0, 10.0, 0.1, 1.0, 0.0);
+ offset->signal_value_changed().connect(sigc::mem_fun(*this, &SPDashSelector::offset_value_changed));
Inkscape::UI::Widget::SpinButton *sb = new Inkscape::UI::Widget::SpinButton(*offset, 0.1, 2);
sb->set_tooltip_text(_("Pattern offset"));
-
sp_dialog_defocus_on_enter_cpp(sb);
sb->show();
+
this->pack_start(*sb, false, false, 0);
- offset->signal_value_changed().connect(sigc::mem_fun(*this, &SPDashSelector::offset_value_changed));
+
+
+ for (int i = 0; dashes[i]; i++) {
+ // Add the dashes to the combobox
+ Gtk::TreeModel::Row row = *(dash_store->append());
+ row[dash_columns.dash] = dashes[i];
+ row[dash_columns.pixbuf] = Glib::wrap(sp_dash_to_pixbuf(dashes[i]));
+ }
this->set_data("pattern", dashes[0]);
}
@@ -83,14 +84,18 @@ SPDashSelector::SPDashSelector() {
SPDashSelector::~SPDashSelector() {
// FIXME: for some reason this doesn't get called; does the call to manage() in
// sp_stroke_style_line_widget_new() not processed correctly?
- delete dash;
delete offset;
}
-void
-SPDashSelector::init_dashes() {
+void SPDashSelector::prepareImageRenderer( Gtk::TreeModel::const_iterator const &row ) {
+
+ Glib::RefPtr<Gdk::Pixbuf> pixbuf = (*row)[dash_columns.pixbuf];
+ image_renderer.property_pixbuf() = pixbuf;
+}
+
+void SPDashSelector::init_dashes() {
+
if (!dashes) {
-
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
std::vector<Glib::ustring> dash_prefs = prefs->getAllDirs(_prefs_path);
@@ -122,8 +127,7 @@ SPDashSelector::init_dashes() {
}
}
-void
-SPDashSelector::set_dash (int ndash, double *dash, double o)
+void SPDashSelector::set_dash (int ndash, double *dash, double o)
{
int pos = 0;
if (ndash > 0) {
@@ -152,12 +156,11 @@ SPDashSelector::set_dash (int ndash, double *dash, double o)
}
this->set_data("pattern", dashes[pos]);
- this->dash->set_history(pos);
+ this->dash_combo.set_active(pos);
this->offset->set_value(o);
}
-void
-SPDashSelector::get_dash(int *ndash, double **dash, double *off)
+void SPDashSelector::get_dash(int *ndash, double **dash, double *off)
{
double *pattern = (double*) this->get_data("pattern");
@@ -184,152 +187,46 @@ SPDashSelector::get_dash(int *ndash, double **dash, double *off)
}
}
-Gtk::MenuItem *
-SPDashSelector::menu_item_new(double *pattern)
-{
- Gtk::MenuItem *mi = new Gtk::MenuItem();
- Gtk::Image *px = new Gtk::Image();
-
- px->show();
- mi->add(*px);
-
- mi->set_data("pattern", pattern);
- mi->set_data("px", px);
- mi->signal_activate().connect(sigc::bind(sigc::mem_fun(*this, &SPDashSelector::dash_activate), mi));
-
- px->signal_realize().connect(sigc::bind(sigc::ptr_fun(&sp_dash_selector_menu_item_image_realize), px, pattern));
-
- return mi;
-}
-
-static bool
-all_even_are_zero (double *pattern, int n)
-{
- for (int i = 0; i < n; i += 2) {
- if (pattern[i] != 0)
- return false;
- }
- return true;
-}
-
-static bool
-all_odd_are_zero (double *pattern, int n)
-{
- for (int i = 1; i < n; i += 2) {
- if (pattern[i] != 0)
- return false;
- }
- return true;
+/**
+ * Fill a pixbuf with the dash pattern using standard cairo drawing
+ */
+GdkPixbuf* SPDashSelector::sp_dash_to_pixbuf(double *pattern) {
+
+ int n_dashes;
+ for (n_dashes = 0; pattern[n_dashes] >= 0.0; n_dashes ++) ;
+
+ cairo_surface_t *s = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, preview_width, preview_height);
+ cairo_t *ct = cairo_create(s);
+
+ cairo_set_line_width (ct, preview_lineheight);
+ cairo_scale (ct, preview_lineheight, 1);
+ //cairo_set_source_rgb (ct, 0, 0, 0);
+ cairo_move_to (ct, 0, preview_height/2);
+ cairo_line_to (ct, preview_width, preview_height/2);
+ cairo_set_dash(ct, pattern, n_dashes, 0);
+ cairo_stroke (ct);
+
+ cairo_destroy(ct);
+ cairo_surface_flush(s);
+
+ GdkPixbuf* pixbuf = gdk_pixbuf_new_from_data( cairo_image_surface_get_data(s),
+ GDK_COLORSPACE_RGB, TRUE, 8,
+ preview_width, preview_height, cairo_image_surface_get_stride(s),
+ ink_cairo_pixbuf_cleanup, s);
+ convert_pixbuf_argb32_to_normal(pixbuf);
+ return pixbuf;
}
-static void sp_dash_selector_menu_item_image_realize(Gtk::Image *px, double *pattern) {
- Glib::RefPtr<Gdk::Pixmap> pixmap = Gdk::Pixmap::create(px->get_window(), DASH_PREVIEW_LENGTH + 4, 16, -1);
- Glib::RefPtr<Gdk::GC> gc = Gdk::GC::create(pixmap);
-
- gc->set_rgb_fg_color(Gdk::Color("#ffffff"));
- pixmap->draw_rectangle(gc, true, 0, 0, DASH_PREVIEW_LENGTH + 4, 16);
-
- // FIXME: all of the below twibblering is due to the limitations of gdk_gc_set_dashes (only integers, no zeroes).
- // Perhaps would make sense to rework this with manually drawn dashes.
-
- // Fill in the integer array of pixel-lengths, for display
- gint8 pixels_i[64];
- gdouble pixels_d[64];
- int n_source_dashes = 0;
- int n_pixel_dashes = 0;
-
- signed int i_s, i_p;
- for (i_s = 0, i_p = 0; pattern[i_s] >= 0.0; i_s ++, i_p ++) {
- pixels_d[i_p] = 0.0;
- }
-
- n_source_dashes = i_s;
-
- for (i_s = 0, i_p = 0; i_s < n_source_dashes; i_s ++, i_p ++) {
- // calculate the pixel length corresponding to the current dash
- gdouble pixels = DASH_PREVIEW_WIDTH * pattern[i_s];
-
- if (pixels > 0.0)
- pixels_d [i_p] += pixels;
- else {
- if (i_p >= 1) {
- // dash is zero, skip this element in the array, and set pointer backwards
- // so the next dash is added to the previous
- i_p -= 2;
- } else {
- // the first dash is zero; bad luck, gdk cannot start pattern with non-stroke, so we
- // put a 1-pixel stub here (it may turn out not shown, though, see special cases below)
- pixels_d [i_p] = 1.0;
- }
- }
- }
-
- n_pixel_dashes = i_p;
- gdouble longest_dash = 0.0;
-
- // after summation, convert double dash lengths to ints
- for (i_p = 0; i_p < n_pixel_dashes; i_p ++) {
- pixels_i [i_p] = (gint8) (pixels_d [i_p] + 0.5);
- // zero-length dashes are already eliminated, so the <1 dash is short but not zero;
- // we approximate it with a one-pixel mark
- if (pixels_i [i_p] < 1)
- pixels_i [i_p] = 1;
- if (i_p % 2 == 0) { // it's a dash
- if (pixels_d [i_p] > longest_dash)
- longest_dash = pixels_d [i_p];
- }
- }
-
- Gdk::Color color;
- if (longest_dash > 1e-18 && longest_dash < 0.5) {
- // fake "shortening" of one-pixel marks by painting them lighter-than-black
- gint rgb = 0xffff - (gint) (0xffff * longest_dash / 0.5);
- color.set_rgb(rgb, rgb, rgb);
- gc->set_rgb_fg_color(color);
- } else {
- color.set_rgb(0, 0, 0);
- gc->set_rgb_fg_color(color);
- }
-
- if (n_source_dashes > 0) {
- // special cases:
- if (all_even_are_zero (pattern, n_source_dashes)) {
- ; // do not draw anything, only gaps are non-zero
- } else if (all_odd_are_zero (pattern, n_source_dashes)) {
- // draw solid line, only dashes are non-zero
- gc->set_line_attributes(DASH_PREVIEW_WIDTH,
- Gdk::LINE_SOLID, Gdk::CAP_BUTT,
- Gdk::JOIN_MITER);
- pixmap->draw_line(gc, 4, 8, DASH_PREVIEW_LENGTH, 8);
- } else {
- // regular pattern with both gaps and dashes non-zero
- gc->set_line_attributes(DASH_PREVIEW_WIDTH, Gdk::LINE_ON_OFF_DASH, Gdk::CAP_BUTT, Gdk::JOIN_MITER);
- gc->set_dashes(0, pixels_i, n_pixel_dashes);
- pixmap->draw_line(gc, 4, 8, DASH_PREVIEW_LENGTH, 8);
- }
- } else {
- // no pattern, draw solid line
- gc->set_line_attributes(DASH_PREVIEW_WIDTH, Gdk::LINE_SOLID, Gdk::CAP_BUTT, Gdk::JOIN_MITER);
- pixmap->draw_line(gc, 4, 8, DASH_PREVIEW_LENGTH, 8);
- }
-
- Glib::RefPtr<Gdk::Bitmap> null_ptr;
- px->set(pixmap, null_ptr);
-}
-
-void
-SPDashSelector::dash_activate (Gtk::MenuItem *mi)
+void SPDashSelector::on_selection ()
{
- double *pattern = (double*) mi->get_data("pattern");
+ double *pattern = dash_combo.get_active()->get_value(dash_columns.dash);
this->set_data ("pattern", pattern);
changed_signal.emit();
}
-
-void
-SPDashSelector::offset_value_changed()
+void SPDashSelector::offset_value_changed()
{
changed_signal.emit();
}