index 87cd238a7fc45d20112102bcdf80ebc9522f5650..b4272a3a47227afdff671ac880d22641c0d759fb 100644 (file)
* Lauris Kaplinski <lauris@kaplinski.com>
* Frank Felfe <innerspace@iname.com>
* bulia byak <buliabyak@users.sf.net>
+ * Jon A. Cruz <jon@joncruz.org>
+ * Abhishek Sharma
*
* Copyright (C) 1999-2005 authors
* Copyright (C) 2001-2002 Ximian, Inc.
+ * Copyright (C) 2010 Jon A. Cruz
*
* Released under GNU GPL, read the file 'COPYING' for more information
*/
#endif
#include <glibmm/i18n.h>
+#include <gtkmm/box.h>
+#include <gtk/gtkvbox.h>
+#include "desktop.h"
+#include "selection.h"
#include "desktop-handles.h"
#include "desktop-style.h"
#include "display/sp-canvas.h"
#include "sp-radial-gradient.h"
#include "style.h"
#include "widgets/paint-selector.h"
-#include "widgets/sp-widget.h"
#include "xml/repr.h"
-#include "widgets/fill-style.h"
+#include "fill-style.h"
+#include "fill-n-stroke-factory.h"
// These can be deleted once we sort out the libart dependence.
#define ART_WIND_RULE_NONZERO 0
-static void sp_fill_style_widget_construct ( SPWidget *spw,
- SPPaintSelector *psel );
-
-static void sp_fill_style_widget_modify_selection ( SPWidget *spw,
- Inkscape::Selection *selection,
- guint flags,
- SPPaintSelector *psel );
-
-static void sp_fill_style_widget_change_subselection ( Inkscape::Application *inkscape, SPDesktop *desktop, SPWidget *spw );
-
-static void sp_fill_style_widget_change_selection ( SPWidget *spw,
- Inkscape::Selection *selection,
- SPPaintSelector *psel );
+/* Fill */
-static void sp_fill_style_widget_update (SPWidget *spw);
-static void sp_fill_style_widget_paint_mode_changed ( SPPaintSelector *psel,
- SPPaintSelectorMode mode,
- SPWidget *spw );
-static void sp_fill_style_widget_fillrule_changed ( SPPaintSelector *psel,
- SPPaintSelectorFillRule mode,
- SPWidget *spw );
-
-static void sp_fill_style_widget_paint_dragged (SPPaintSelector *psel, SPWidget *spw );
-static void sp_fill_style_widget_paint_changed (SPPaintSelector *psel, SPWidget *spw );
-
-GtkWidget *
-sp_fill_style_widget_new (void)
+Gtk::Widget *sp_fill_style_widget_new(void)
{
- GtkWidget *spw = sp_widget_new_global (INKSCAPE);
+ return Inkscape::Widgets::createStyleWidget( FILL );
+}
- GtkWidget *vb = gtk_vbox_new (FALSE, 0);
- gtk_widget_show (vb);
- gtk_container_add (GTK_CONTAINER (spw), vb);
- GtkWidget *psel = sp_paint_selector_new (true); // with fillrule selector
- gtk_widget_show (psel);
- gtk_box_pack_start (GTK_BOX (vb), psel, TRUE, TRUE, 0);
- g_object_set_data (G_OBJECT (spw), "paint-selector", psel);
+namespace Inkscape {
- g_signal_connect ( G_OBJECT (psel), "mode_changed",
- G_CALLBACK (sp_fill_style_widget_paint_mode_changed),
- spw );
+class FillNStroke : public Gtk::VBox
+{
+public:
+ FillNStroke( FillOrStroke kind );
+ ~FillNStroke();
- g_signal_connect ( G_OBJECT (psel), "dragged",
- G_CALLBACK (sp_fill_style_widget_paint_dragged),
- spw );
+ void setFillrule( SPPaintSelector::FillRule mode );
- g_signal_connect ( G_OBJECT (psel), "changed",
- G_CALLBACK (sp_fill_style_widget_paint_changed),
- spw );
+ void setDesktop(SPDesktop *desktop);
- g_signal_connect ( G_OBJECT (psel), "fillrule_changed",
- G_CALLBACK (sp_fill_style_widget_fillrule_changed),
- spw );
+private:
+ static void paintModeChangeCB(SPPaintSelector *psel, SPPaintSelector::Mode mode, FillNStroke *self);
+ static void paintChangedCB(SPPaintSelector *psel, FillNStroke *self);
+ static void paintDraggedCB(SPPaintSelector *psel, FillNStroke *self);
+ static gboolean dragDelayCB(gpointer data);
+ static void fillruleChangedCB( SPPaintSelector *psel, SPPaintSelector::FillRule mode, FillNStroke *self );
- g_signal_connect ( G_OBJECT (spw), "construct",
- G_CALLBACK (sp_fill_style_widget_construct), psel);
+ void selectionModifiedCB(guint flags);
-//FIXME: switch these from spw signals to global inkscape object signals; spw just retranslates
-//those anyway; then eliminate spw
- g_signal_connect ( G_OBJECT (spw), "modify_selection",
- G_CALLBACK (sp_fill_style_widget_modify_selection), psel);
+ void dragFromPaint();
+ void updateFromPaint();
- g_signal_connect ( G_OBJECT (spw), "change_selection",
- G_CALLBACK (sp_fill_style_widget_change_selection), psel);
+ void performUpdate();
- g_signal_connect (INKSCAPE, "change_subselection", G_CALLBACK (sp_fill_style_widget_change_subselection), spw);
+ FillOrStroke kind;
+ SPDesktop *desktop;
+ SPPaintSelector *psel;
+ guint32 lastDrag;
+ guint dragId;
+ bool update;
+ sigc::connection selectChangedConn;
+ sigc::connection subselChangedConn;
+ sigc::connection selectModifiedConn;
+};
- sp_fill_style_widget_update (SP_WIDGET (spw));
+} // namespace Inkscape
- return spw;
+void sp_fill_style_widget_set_desktop(Gtk::Widget *widget, SPDesktop *desktop)
+{
+ Inkscape::FillNStroke *fs = dynamic_cast<Inkscape::FillNStroke*>(widget);
+ if (fs) {
+ fs->setDesktop(desktop);
+ }
+}
-} // end of sp_fill_style_widget_new()
+namespace Inkscape {
+/**
+ * Create the fill or stroke style widget, and hook up all the signals.
+ */
+Gtk::Widget *Inkscape::Widgets::createStyleWidget( FillOrStroke kind )
+{
+ FillNStroke *filler = new FillNStroke(kind);
+ return filler;
+}
-static void
-sp_fill_style_widget_construct( SPWidget *spw, SPPaintSelector */*psel*/ )
+FillNStroke::FillNStroke( FillOrStroke kind ) :
+ Gtk::VBox(),
+ kind(kind),
+ desktop(0),
+ psel(0),
+ lastDrag(0),
+ dragId(0),
+ update(false),
+ selectChangedConn(),
+ subselChangedConn(),
+ selectModifiedConn()
{
-#ifdef SP_FS_VERBOSE
- g_print ( "Fill style widget constructed: inkscape %p repr %p\n",
- spw->inkscape, spw->repr );
-#endif
- if (spw->inkscape) {
- sp_fill_style_widget_update (spw);
+ // Add and connect up the paint selector widget:
+ psel = sp_paint_selector_new(kind);
+ gtk_widget_show(GTK_WIDGET(psel));
+ gtk_container_add(GTK_CONTAINER(gobj()), GTK_WIDGET(psel));
+ g_signal_connect( G_OBJECT(psel), "mode_changed",
+ G_CALLBACK(paintModeChangeCB),
+ this );
+
+ g_signal_connect( G_OBJECT(psel), "dragged",
+ G_CALLBACK(paintDraggedCB),
+ this );
+
+ g_signal_connect( G_OBJECT(psel), "changed",
+ G_CALLBACK(paintChangedCB),
+ this );
+ if (kind == FILL) {
+ g_signal_connect( G_OBJECT(psel), "fillrule_changed",
+ G_CALLBACK(fillruleChangedCB),
+ this );
}
-} // end of sp_fill_style_widget_construct()
+ performUpdate();
+}
-static void
-sp_fill_style_widget_modify_selection( SPWidget *spw,
- Inkscape::Selection */*selection*/,
- guint flags,
- SPPaintSelector */*psel*/ )
+FillNStroke::~FillNStroke()
{
- if (flags & ( SP_OBJECT_MODIFIED_FLAG |
- SP_OBJECT_PARENT_MODIFIED_FLAG |
- SP_OBJECT_STYLE_MODIFIED_FLAG) )
- {
- sp_fill_style_widget_update (spw);
+ if (dragId) {
+ g_source_remove(dragId);
+ dragId = 0;
}
+ psel = 0;
+ selectModifiedConn.disconnect();
+ subselChangedConn.disconnect();
+ selectChangedConn.disconnect();
}
-static void
-sp_fill_style_widget_change_subselection( Inkscape::Application */*inkscape*/,
- SPDesktop */*desktop*/,
- SPWidget *spw )
+/**
+ * On signal modified, invokes an update of the fill or stroke style paint object.
+ */
+void FillNStroke::selectionModifiedCB( guint flags )
{
- sp_fill_style_widget_update (spw);
+ if (flags & ( SP_OBJECT_MODIFIED_FLAG |
+ SP_OBJECT_PARENT_MODIFIED_FLAG |
+ SP_OBJECT_STYLE_MODIFIED_FLAG) ) {
+#ifdef SP_FS_VERBOSE
+ g_message("selectionModifiedCB(%d) on %p", flags, this);
+#endif
+ performUpdate();
+ }
}
-static void
-sp_fill_style_widget_change_selection( SPWidget *spw,
- Inkscape::Selection */*selection*/,
- SPPaintSelector */*psel*/ )
+void FillNStroke::setDesktop(SPDesktop *desktop)
{
- sp_fill_style_widget_update (spw);
+ if (this->desktop != desktop) {
+ if (dragId) {
+ g_source_remove(dragId);
+ dragId = 0;
+ }
+ if (this->desktop) {
+ selectModifiedConn.disconnect();
+ subselChangedConn.disconnect();
+ selectChangedConn.disconnect();
+ }
+ this->desktop = desktop;
+ if (desktop && desktop->selection) {
+ selectChangedConn = desktop->selection->connectChanged(sigc::hide(sigc::mem_fun(*this, &FillNStroke::performUpdate)));
+ subselChangedConn = desktop->connectToolSubselectionChanged(sigc::hide(sigc::mem_fun(*this, &FillNStroke::performUpdate)));
+
+ // Must check flags, so can't call performUpdate() directly.
+ selectModifiedConn = desktop->selection->connectModified(sigc::hide<0>(sigc::mem_fun(*this, &FillNStroke::selectionModifiedCB)));
+ }
+ performUpdate();
+ }
}
/**
-* \param sel Selection to use, or NULL.
-*/
-static void
-sp_fill_style_widget_update (SPWidget *spw)
+ * Gets the active fill or stroke style property, then sets the appropriate
+ * color, alpha, gradient, pattern, etc. for the paint-selector.
+ *
+ * @param sel Selection to use, or NULL.
+ */
+void FillNStroke::performUpdate()
{
- if (g_object_get_data (G_OBJECT (spw), "update"))
+ if ( update || !desktop ) {
return;
+ }
- if (g_object_get_data (G_OBJECT (spw), "local")) {
- g_object_set_data (G_OBJECT (spw), "local", GINT_TO_POINTER (FALSE)); // local change; do nothing, but reset the flag
+ if ( dragId ) {
+ // local change; do nothing, but reset the flag
+ g_source_remove(dragId);
+ dragId = 0;
return;
}
- g_object_set_data (G_OBJECT (spw), "update", GINT_TO_POINTER (TRUE));
-
- SPPaintSelector *psel = SP_PAINT_SELECTOR (g_object_get_data (G_OBJECT (spw), "paint-selector"));
+ update = true;
// create temporary style
- SPStyle *query = sp_style_new (SP_ACTIVE_DOCUMENT);
+ SPStyle *query = sp_style_new(desktop->doc());
+
// query style from desktop into it. This returns a result flag and fills query with the style of subselection, if any, or selection
- int result = sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FILL);
+ int result = sp_desktop_query_style(desktop, query, (kind == FILL) ? QUERY_STYLE_PROPERTY_FILL : QUERY_STYLE_PROPERTY_STROKE);
+
+ SPIPaint &targPaint = (kind == FILL) ? query->fill : query->stroke;
+ SPIScale24 &targOpacity = (kind == FILL) ? query->fill_opacity : query->stroke_opacity;
switch (result) {
case QUERY_STYLE_NOTHING:
{
/* No paint at all */
- sp_paint_selector_set_mode (psel, SP_PAINT_SELECTOR_MODE_EMPTY);
+ psel->setMode(SPPaintSelector::MODE_EMPTY);
break;
}
case QUERY_STYLE_MULTIPLE_AVERAGED: // TODO: treat this slightly differently, e.g. display "averaged" somewhere in paint selector
case QUERY_STYLE_MULTIPLE_SAME:
{
- SPPaintSelectorMode pselmode = sp_style_determine_paint_selector_mode (query, true);
- sp_paint_selector_set_mode (psel, pselmode);
+ SPPaintSelector::Mode pselmode = SPPaintSelector::getModeForStyle(*query, kind);
+ psel->setMode(pselmode);
- sp_paint_selector_set_fillrule (psel, query->fill_rule.computed == ART_WIND_RULE_NONZERO?
- SP_PAINT_SELECTOR_FILLRULE_NONZERO : SP_PAINT_SELECTOR_FILLRULE_EVENODD);
+ if (kind == FILL) {
+ psel->setFillrule(query->fill_rule.computed == ART_WIND_RULE_NONZERO?
+ SPPaintSelector::FILLRULE_NONZERO : SPPaintSelector::FILLRULE_EVENODD);
+ }
- if (query->fill.set && query->fill.isColor()) {
- sp_paint_selector_set_color_alpha (psel, &query->fill.value.color, SP_SCALE24_TO_FLOAT (query->fill_opacity.value));
- } else if (query->fill.set && query->fill.isPaintserver()) {
+ if (targPaint.set && targPaint.isColor()) {
+ psel->setColorAlpha(targPaint.value.color, SP_SCALE24_TO_FLOAT(targOpacity.value));
+ } else if (targPaint.set && targPaint.isPaintserver()) {
- SPPaintServer *server = SP_STYLE_FILL_SERVER (query);
+ SPPaintServer *server = (kind == FILL) ? query->getFillPaintServer() : query->getStrokePaintServer();
if (server && SP_IS_GRADIENT(server) && SP_GRADIENT(server)->getVector()->isSwatch()) {
SPGradient *vector = SP_GRADIENT(server)->getVector();
- sp_paint_selector_set_swatch( psel, vector );
- } else if (SP_IS_LINEARGRADIENT (server)) {
+ psel->setSwatch( vector );
+ } else if (SP_IS_LINEARGRADIENT(server)) {
SPGradient *vector = SP_GRADIENT(server)->getVector();
- sp_paint_selector_set_gradient_linear (psel, vector);
+ psel->setGradientLinear( vector );
- SPLinearGradient *lg = SP_LINEARGRADIENT (server);
- sp_paint_selector_set_gradient_properties (psel,
- SP_GRADIENT_UNITS (lg),
- SP_GRADIENT_SPREAD (lg));
- } else if (SP_IS_RADIALGRADIENT (server)) {
+ SPLinearGradient *lg = SP_LINEARGRADIENT(server);
+ psel->setGradientProperties( lg->getUnits(),
+ lg->getSpread() );
+ } else if (SP_IS_RADIALGRADIENT(server)) {
SPGradient *vector = SP_GRADIENT(server)->getVector();
- sp_paint_selector_set_gradient_radial (psel, vector);
-
- SPRadialGradient *rg = SP_RADIALGRADIENT (server);
- sp_paint_selector_set_gradient_properties (psel,
- SP_GRADIENT_UNITS (rg),
- SP_GRADIENT_SPREAD (rg));
- } else if (SP_IS_PATTERN (server)) {
- SPPattern *pat = pattern_getroot (SP_PATTERN (server));
- sp_update_pattern_list (psel, pat);
+ psel->setGradientRadial( vector );
+
+ SPRadialGradient *rg = SP_RADIALGRADIENT(server);
+ psel->setGradientProperties( rg->getUnits(),
+ rg->getSpread() );
+ } else if (SP_IS_PATTERN(server)) {
+ SPPattern *pat = pattern_getroot(SP_PATTERN(server));
+ psel->updatePatternList( pat );
}
}
break;
case QUERY_STYLE_MULTIPLE_DIFFERENT:
{
- sp_paint_selector_set_mode (psel, SP_PAINT_SELECTOR_MODE_MULTIPLE);
+ psel->setMode(SPPaintSelector::MODE_MULTIPLE);
break;
}
}
sp_style_unref(query);
- g_object_set_data (G_OBJECT (spw), "update", GINT_TO_POINTER (FALSE));
-
+ update = false;
}
-
-static void
-sp_fill_style_widget_paint_mode_changed ( SPPaintSelector *psel,
- SPPaintSelectorMode /*mode*/,
- SPWidget *spw )
+/**
+ * When the mode is changed, invoke a regular changed handler.
+ */
+void FillNStroke::paintModeChangeCB( SPPaintSelector * /*psel*/,
+ SPPaintSelector::Mode /*mode*/,
+ FillNStroke *self )
{
- if (g_object_get_data (G_OBJECT (spw), "update"))
- return;
+#ifdef SP_FS_VERBOSE
+ g_message("paintModeChangeCB(psel, mode, self:%p)", self);
+#endif
+ if (self && !self->update) {
+ self->updateFromPaint();
+ }
+}
- /* TODO: Does this work? */
- /* TODO: Not really, here we have to get old color back from object */
- /* Instead of relying on paint widget having meaningful colors set */
- sp_fill_style_widget_paint_changed (psel, spw);
+void FillNStroke::fillruleChangedCB( SPPaintSelector * /*psel*/,
+ SPPaintSelector::FillRule mode,
+ FillNStroke *self )
+{
+ if (self) {
+ self->setFillrule(mode);
+ }
}
-static void
-sp_fill_style_widget_fillrule_changed ( SPPaintSelector */*psel*/,
- SPPaintSelectorFillRule mode,
- SPWidget *spw )
+void FillNStroke::setFillrule( SPPaintSelector::FillRule mode )
{
- if (g_object_get_data (G_OBJECT (spw), "update"))
- return;
+ if (!update && desktop) {
+ SPCSSAttr *css = sp_repr_css_attr_new();
+ sp_repr_css_set_property(css, "fill-rule", (mode == SPPaintSelector::FILLRULE_EVENODD) ? "evenodd":"nonzero");
- SPDesktop *desktop = SP_ACTIVE_DESKTOP;
+ sp_desktop_set_style(desktop, css);
- SPCSSAttr *css = sp_repr_css_attr_new ();
- sp_repr_css_set_property (css, "fill-rule", mode == SP_PAINT_SELECTOR_FILLRULE_EVENODD? "evenodd":"nonzero");
+ sp_repr_css_attr_unref(css);
+ css = 0;
- sp_desktop_set_style (desktop, css);
+ DocumentUndo::done(desktop->doc(), SP_VERB_DIALOG_FILL_STROKE,
+ _("Change fill rule"));
+ }
+}
+
+static gchar const *undo_F_label_1 = "fill:flatcolor:1";
+static gchar const *undo_F_label_2 = "fill:flatcolor:2";
+
+static gchar const *undo_S_label_1 = "stroke:flatcolor:1";
+static gchar const *undo_S_label_2 = "stroke:flatcolor:2";
+
+static gchar const *undo_F_label = undo_F_label_1;
+static gchar const *undo_S_label = undo_S_label_1;
- sp_repr_css_attr_unref (css);
- sp_document_done (SP_ACTIVE_DOCUMENT, SP_VERB_DIALOG_FILL_STROKE,
- _("Change fill rule"));
+void FillNStroke::paintDraggedCB(SPPaintSelector * /*psel*/, FillNStroke *self)
+{
+#ifdef SP_FS_VERBOSE
+ g_message("paintDraggedCB(psel, spw:%p)", self);
+#endif
+ if (self && !self->update) {
+ self->dragFromPaint();
+ }
}
-static gchar const *undo_label_1 = "fill:flatcolor:1";
-static gchar const *undo_label_2 = "fill:flatcolor:2";
-static gchar const *undo_label = undo_label_1;
+
+gboolean FillNStroke::dragDelayCB(gpointer data)
+{
+ gboolean keepGoing = TRUE;
+ if (data) {
+ FillNStroke *self = reinterpret_cast<FillNStroke*>(data);
+ if (!self->update) {
+ if (self->dragId) {
+ g_source_remove(self->dragId);
+ self->dragId = 0;
+
+ self->dragFromPaint();
+ self->performUpdate();
+ }
+ keepGoing = FALSE;
+ }
+ } else {
+ keepGoing = FALSE;
+ }
+ return keepGoing;
+}
/**
-This is called repeatedly while you are dragging a color slider, only for flat color
-modes. Previously it set the color in style but did not update the repr for efficiency, however
-this was flakey and didn't buy us almost anything. So now it does the same as _changed, except
-lumps all its changes for undo.
+ * This is called repeatedly while you are dragging a color slider, only for flat color
+ * modes. Previously it set the color in style but did not update the repr for efficiency, however
+ * this was flakey and didn't buy us almost anything. So now it does the same as _changed, except
+ * lumps all its changes for undo.
*/
-static void
-sp_fill_style_widget_paint_dragged (SPPaintSelector *psel, SPWidget *spw)
+void FillNStroke::dragFromPaint()
{
- if (!spw->inkscape) {
+ if (!desktop || update) {
return;
}
- if (g_object_get_data (G_OBJECT (spw), "update")) {
- return;
+ guint32 when = gtk_get_current_event_time();
+
+ // Don't attempt too many updates per second.
+ // Assume a base 15.625ms resolution on the timer.
+ if (!dragId && lastDrag && when && ((when - lastDrag) < 32)) {
+ // local change, do not update from selection
+ dragId = g_timeout_add_full(G_PRIORITY_DEFAULT, 33, dragDelayCB, this, 0);
}
- if (g_object_get_data (G_OBJECT (spw), "local")) {
+ if (dragId) {
// previous local flag not cleared yet;
// this means dragged events come too fast, so we better skip this one to speed up display
// (it's safe to do this in any case)
return;
}
+ lastDrag = when;
- g_object_set_data (G_OBJECT (spw), "update", GINT_TO_POINTER (TRUE));
+ update = true;
switch (psel->mode) {
-
- case SP_PAINT_SELECTOR_MODE_COLOR_RGB:
- case SP_PAINT_SELECTOR_MODE_COLOR_CMYK:
+ case SPPaintSelector::MODE_COLOR_RGB:
+ case SPPaintSelector::MODE_COLOR_CMYK:
{
- sp_paint_selector_set_flat_color (psel, SP_ACTIVE_DESKTOP, "fill", "fill-opacity");
- sp_document_maybe_done (sp_desktop_document(SP_ACTIVE_DESKTOP), undo_label, SP_VERB_DIALOG_FILL_STROKE,
- _("Set fill color"));
- g_object_set_data (G_OBJECT (spw), "local", GINT_TO_POINTER (TRUE)); // local change, do not update from selection
+ // local change, do not update from selection
+ dragId = g_timeout_add_full(G_PRIORITY_DEFAULT, 100, dragDelayCB, this, 0);
+ psel->setFlatColor( desktop, (kind == FILL) ? "fill" : "stroke", (kind == FILL) ? "fill-opacity" : "stroke-opacity" );
+ DocumentUndo::maybeDone(desktop->doc(), (kind == FILL) ? undo_F_label : undo_S_label, SP_VERB_DIALOG_FILL_STROKE,
+ (kind == FILL) ? _("Set fill color") : _("Set stroke color"));
break;
}
default:
- g_warning ( "file %s: line %d: Paint %d should not emit 'dragged'",
- __FILE__, __LINE__, psel->mode );
+ g_warning( "file %s: line %d: Paint %d should not emit 'dragged'",
+ __FILE__, __LINE__, psel->mode );
break;
-
}
- g_object_set_data (G_OBJECT (spw), "update", GINT_TO_POINTER (FALSE));
+ update = false;
}
-
/**
This is called (at least) when:
1 paint selector mode is switched (e.g. flat color -> gradient)
3 you changed a gradient selector parameter (e.g. spread)
Must update repr.
*/
-static void
-sp_fill_style_widget_paint_changed ( SPPaintSelector *psel,
- SPWidget *spw )
+void FillNStroke::paintChangedCB( SPPaintSelector * /*psel*/, FillNStroke *self )
{
- if (g_object_get_data (G_OBJECT (spw), "update")) {
- return;
+#ifdef SP_FS_VERBOSE
+ g_message("paintChangedCB(psel, spw:%p)", self);
+#endif
+ if (self && !self->update) {
+ self->updateFromPaint();
}
- g_object_set_data (G_OBJECT (spw), "update", GINT_TO_POINTER (TRUE));
+}
- SPDesktop *desktop = SP_ACTIVE_DESKTOP;
+void FillNStroke::updateFromPaint()
+{
if (!desktop) {
return;
}
- SPDocument *document = sp_desktop_document (desktop);
- Inkscape::Selection *selection = sp_desktop_selection (desktop);
+ update = true;
+
+ SPDocument *document = sp_desktop_document(desktop);
+ Inkscape::Selection *selection = sp_desktop_selection(desktop);
GSList const *items = selection->itemList();
switch (psel->mode) {
-
- case SP_PAINT_SELECTOR_MODE_EMPTY:
+ case SPPaintSelector::MODE_EMPTY:
// This should not happen.
- g_warning ( "file %s: line %d: Paint %d should not emit 'changed'",
- __FILE__, __LINE__, psel->mode);
+ g_warning( "file %s: line %d: Paint %d should not emit 'changed'",
+ __FILE__, __LINE__, psel->mode);
break;
- case SP_PAINT_SELECTOR_MODE_MULTIPLE:
+ case SPPaintSelector::MODE_MULTIPLE:
// This happens when you switch multiple objects with different gradients to flat color;
// nothing to do here.
break;
- case SP_PAINT_SELECTOR_MODE_NONE:
+ case SPPaintSelector::MODE_NONE:
{
- SPCSSAttr *css = sp_repr_css_attr_new ();
- sp_repr_css_set_property (css, "fill", "none");
+ SPCSSAttr *css = sp_repr_css_attr_new();
+ sp_repr_css_set_property(css, (kind == FILL) ? "fill" : "stroke", "none");
- sp_desktop_set_style (desktop, css);
+ sp_desktop_set_style(desktop, css);
- sp_repr_css_attr_unref (css);
+ sp_repr_css_attr_unref(css);
+ css = 0;
- sp_document_done (document, SP_VERB_DIALOG_FILL_STROKE,
- _("Remove fill"));
+ DocumentUndo::done(document, SP_VERB_DIALOG_FILL_STROKE,
+ (kind == FILL) ? _("Remove fill") : _("Remove stroke"));
break;
}
- case SP_PAINT_SELECTOR_MODE_COLOR_RGB:
- case SP_PAINT_SELECTOR_MODE_COLOR_CMYK:
+ case SPPaintSelector::MODE_COLOR_RGB:
+ case SPPaintSelector::MODE_COLOR_CMYK:
{
- // FIXME: fix for GTK breakage, see comment in SelectedStyle::on_opacity_changed; here it results in losing release events
- sp_canvas_force_full_redraw_after_interruptions(sp_desktop_canvas(desktop), 0);
+ if (kind == FILL) {
+ // FIXME: fix for GTK breakage, see comment in SelectedStyle::on_opacity_changed; here it results in losing release events
+ sp_canvas_force_full_redraw_after_interruptions(sp_desktop_canvas(desktop), 0);
+ }
- sp_paint_selector_set_flat_color (psel, desktop, "fill", "fill-opacity");
- sp_document_maybe_done (sp_desktop_document(desktop), undo_label, SP_VERB_DIALOG_FILL_STROKE,
- _("Set fill color"));
- // resume interruptibility
- sp_canvas_end_forced_full_redraws(sp_desktop_canvas(desktop));
+ psel->setFlatColor( desktop,
+ (kind == FILL) ? "fill" : "stroke",
+ (kind == FILL) ? "fill-opacity" : "stroke-opacity" );
+ DocumentUndo::maybeDone(sp_desktop_document(desktop), (kind == FILL) ? undo_F_label : undo_S_label, SP_VERB_DIALOG_FILL_STROKE,
+ (kind == FILL) ? _("Set fill color") : _("Set stroke color"));
+
+ if (kind == FILL) {
+ // resume interruptibility
+ sp_canvas_end_forced_full_redraws(sp_desktop_canvas(desktop));
+ }
// on release, toggle undo_label so that the next drag will not be lumped with this one
- if (undo_label == undo_label_1)
- undo_label = undo_label_2;
- else
- undo_label = undo_label_1;
+ if (undo_F_label == undo_F_label_1) {
+ undo_F_label = undo_F_label_2;
+ undo_S_label = undo_S_label_2;
+ } else {
+ undo_F_label = undo_F_label_1;
+ undo_S_label = undo_S_label_1;
+ }
break;
}
- case SP_PAINT_SELECTOR_MODE_GRADIENT_LINEAR:
- case SP_PAINT_SELECTOR_MODE_GRADIENT_RADIAL:
- case SP_PAINT_SELECTOR_MODE_SWATCH:
+ case SPPaintSelector::MODE_GRADIENT_LINEAR:
+ case SPPaintSelector::MODE_GRADIENT_RADIAL:
+ case SPPaintSelector::MODE_SWATCH:
if (items) {
- SPGradientType const gradient_type = ( psel->mode != SP_PAINT_SELECTOR_MODE_GRADIENT_RADIAL
+ SPGradientType const gradient_type = ( psel->mode != SPPaintSelector::MODE_GRADIENT_RADIAL
? SP_GRADIENT_TYPE_LINEAR
: SP_GRADIENT_TYPE_RADIAL );
+ bool createSwatch = (psel->mode == SPPaintSelector::MODE_SWATCH);
- // HACK: reset fill-opacity - that 0.75 is annoying; BUT remove this when we have an opacity slider for all tabs
- SPCSSAttr *css = sp_repr_css_attr_new();
- sp_repr_css_set_property(css, "fill-opacity", "1.0");
+ SPCSSAttr *css = 0;
+ if (kind == FILL) {
+ // HACK: reset fill-opacity - that 0.75 is annoying; BUT remove this when we have an opacity slider for all tabs
+ css = sp_repr_css_attr_new();
+ sp_repr_css_set_property(css, "fill-opacity", "1.0");
+ }
- SPGradient *vector = sp_paint_selector_get_gradient_vector(psel);
+ SPGradient *vector = psel->getGradientVector();
if (!vector) {
/* No vector in paint selector should mean that we just changed mode */
- SPStyle *query = sp_style_new (SP_ACTIVE_DOCUMENT);
- int result = objects_query_fillstroke ((GSList *) items, query, true);
- guint32 common_rgb = 0;
+ SPStyle *query = sp_style_new(desktop->doc());
+ int result = objects_query_fillstroke(const_cast<GSList *>(items), query, kind == FILL);
if (result == QUERY_STYLE_MULTIPLE_SAME) {
- if (!query->fill.isColor()) {
- common_rgb = sp_desktop_get_color(desktop, true);
+ SPIPaint &targPaint = (kind == FILL) ? query->fill : query->stroke;
+ SPColor common;
+ if (!targPaint.isColor()) {
+ common = sp_desktop_get_color(desktop, kind == FILL);
} else {
- common_rgb = query->fill.value.color.toRGBA32( 0xff );
+ common = targPaint.value.color;
+ }
+ vector = sp_document_default_gradient_vector( document, common, createSwatch );
+ if ( vector && createSwatch ) {
+ vector->setSwatch();
}
- vector = sp_document_default_gradient_vector(document, common_rgb);
}
sp_style_unref(query);
for (GSList const *i = items; i != NULL; i = i->next) {
//FIXME: see above
- sp_repr_css_change_recursive(SP_OBJECT_REPR(i->data), css, "style");
+ if (kind == FILL) {
+ sp_repr_css_change_recursive(reinterpret_cast<SPObject*>(i->data)->getRepr(), css, "style");
+ }
if (!vector) {
+ SPGradient *gr = sp_gradient_vector_for_object( document, desktop, reinterpret_cast<SPObject*>(i->data), kind == FILL, createSwatch );
+ if ( gr && createSwatch ) {
+ gr->setSwatch();
+ }
sp_item_set_gradient(SP_ITEM(i->data),
- sp_gradient_vector_for_object(document, desktop, SP_OBJECT(i->data), true),
- gradient_type, true);
+ gr,
+ gradient_type, kind == FILL);
} else {
- sp_item_set_gradient(SP_ITEM(i->data), vector, gradient_type, true);
+ sp_item_set_gradient(SP_ITEM(i->data), vector, gradient_type, kind == FILL);
}
}
} else {
- /* We have changed from another gradient type, or modified spread/units within
- * this gradient type. */
- vector = sp_gradient_ensure_vector_normalized (vector);
+ // We have changed from another gradient type, or modified spread/units within
+ // this gradient type.
+ vector = sp_gradient_ensure_vector_normalized(vector);
for (GSList const *i = items; i != NULL; i = i->next) {
//FIXME: see above
- sp_repr_css_change_recursive (SP_OBJECT_REPR (i->data), css, "style");
+ if (kind == FILL) {
+ sp_repr_css_change_recursive(reinterpret_cast<SPObject*>(i->data)->getRepr(), css, "style");
+ }
- SPGradient *gr = sp_item_set_gradient(SP_ITEM(i->data), vector, gradient_type, true);
- sp_gradient_selector_attrs_to_gradient (gr, psel);
+ SPGradient *gr = sp_item_set_gradient(SP_ITEM(i->data), vector, gradient_type, kind == FILL);
+ psel->pushAttrsToGradient( gr );
}
}
- sp_repr_css_attr_unref (css);
+ if (css) {
+ sp_repr_css_attr_unref(css);
+ css = 0;
+ }
- sp_document_done (document, SP_VERB_DIALOG_FILL_STROKE,
- _("Set gradient on fill"));
+ DocumentUndo::done(document, SP_VERB_DIALOG_FILL_STROKE,
+ (kind == FILL) ? _("Set gradient on fill") : _("Set gradient on stroke"));
}
break;
- case SP_PAINT_SELECTOR_MODE_PATTERN:
+ case SPPaintSelector::MODE_PATTERN:
if (items) {
- SPPattern *pattern = sp_paint_selector_get_pattern (psel);
+ SPPattern *pattern = psel->getPattern();
if (!pattern) {
/* No Pattern in paint selector should mean that we just
*/
} else {
- Inkscape::XML::Node *patrepr = SP_OBJECT_REPR(pattern);
- SPCSSAttr *css = sp_repr_css_attr_new ();
- gchar *urltext = g_strdup_printf ("url(#%s)", patrepr->attribute("id"));
- sp_repr_css_set_property (css, "fill", urltext);
+ Inkscape::XML::Node *patrepr = pattern->getRepr();
+ SPCSSAttr *css = sp_repr_css_attr_new();
+ gchar *urltext = g_strdup_printf("url(#%s)", patrepr->attribute("id"));
+ sp_repr_css_set_property(css, (kind == FILL) ? "fill" : "stroke", urltext);
// HACK: reset fill-opacity - that 0.75 is annoying; BUT remove this when we have an opacity slider for all tabs
- sp_repr_css_set_property(css, "fill-opacity", "1.0");
+ if (kind == FILL) {
+ sp_repr_css_set_property(css, "fill-opacity", "1.0");
+ }
// cannot just call sp_desktop_set_style, because we don't want to touch those
// objects who already have the same root pattern but through a different href
// chain. FIXME: move this to a sp_item_set_pattern
for (GSList const *i = items; i != NULL; i = i->next) {
- SPObject *selobj = SP_OBJECT (i->data);
-
- SPStyle *style = SP_OBJECT_STYLE (selobj);
- if (style && style->fill.isPaintserver()) {
- SPObject *server = SP_OBJECT_STYLE_FILL_SERVER (selobj);
- if (SP_IS_PATTERN (server) && pattern_getroot (SP_PATTERN(server)) == pattern)
+ Inkscape::XML::Node *selrepr = reinterpret_cast<SPObject*>(i->data)->getRepr();
+ if ( (kind == STROKE) && !selrepr) {
+ continue;
+ }
+ SPObject *selobj = reinterpret_cast<SPObject*>(i->data);
+
+ SPStyle *style = selobj->style;
+ if (style && ((kind == FILL) ? style->fill : style->stroke).isPaintserver()) {
+ SPPaintServer *server = (kind == FILL) ?
+ selobj->style->getFillPaintServer() :
+ selobj->style->getStrokePaintServer();
+ if (SP_IS_PATTERN(server) && pattern_getroot(SP_PATTERN(server)) == pattern)
// only if this object's pattern is not rooted in our selected pattern, apply
- continue;
- }
+ continue;
+ }
- sp_desktop_apply_css_recursive (selobj, css, true);
- }
+ if (kind == FILL) {
+ sp_desktop_apply_css_recursive(selobj, css, true);
+ } else {
+ sp_repr_css_change_recursive(selrepr, css, "style");
+ }
+ }
- sp_repr_css_attr_unref (css);
- g_free (urltext);
+ sp_repr_css_attr_unref(css);
+ css = 0;
+ g_free(urltext);
} // end if
- sp_document_done (document, SP_VERB_DIALOG_FILL_STROKE,
- _("Set pattern on fill"));
-
+ DocumentUndo::done(document, SP_VERB_DIALOG_FILL_STROKE,
+ (kind == FILL) ? _("Set pattern on fill") :
+ _("Set pattern on stroke"));
} // end if
break;
- case SP_PAINT_SELECTOR_MODE_UNSET:
+ case SPPaintSelector::MODE_UNSET:
if (items) {
- SPCSSAttr *css = sp_repr_css_attr_new ();
- sp_repr_css_unset_property (css, "fill");
+ SPCSSAttr *css = sp_repr_css_attr_new();
+ if (kind == FILL) {
+ sp_repr_css_unset_property(css, "fill");
+ } else {
+ sp_repr_css_unset_property(css, "stroke");
+ sp_repr_css_unset_property(css, "stroke-opacity");
+ sp_repr_css_unset_property(css, "stroke-width");
+ sp_repr_css_unset_property(css, "stroke-miterlimit");
+ sp_repr_css_unset_property(css, "stroke-linejoin");
+ sp_repr_css_unset_property(css, "stroke-linecap");
+ sp_repr_css_unset_property(css, "stroke-dashoffset");
+ sp_repr_css_unset_property(css, "stroke-dasharray");
+ }
- sp_desktop_set_style (desktop, css);
- sp_repr_css_attr_unref (css);
+ sp_desktop_set_style(desktop, css);
+ sp_repr_css_attr_unref(css);
+ css = 0;
- sp_document_done (document, SP_VERB_DIALOG_FILL_STROKE,
- _("Unset fill"));
+ DocumentUndo::done(document, SP_VERB_DIALOG_FILL_STROKE,
+ (kind == FILL) ? _("Unset fill") : _("Unset stroke"));
}
break;
default:
- g_warning ( "file %s: line %d: Paint selector should not be in "
- "mode %d",
- __FILE__, __LINE__, psel->mode );
+ g_warning( "file %s: line %d: Paint selector should not be in "
+ "mode %d",
+ __FILE__, __LINE__,
+ psel->mode );
break;
}
- g_object_set_data (G_OBJECT (spw), "update", GINT_TO_POINTER (FALSE));
+ update = false;
}
+} // namespace Inkscape
/*
Local Variables:
fill-column:99
End:
*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :