Code

Store cached icons to disk between runs, and invalidate/purge as needed.
[inkscape.git] / src / widgets / fill-style.cpp
index 63def4c875449cc3cad416c2cf6e7eab872d3288..b4272a3a47227afdff671ac880d22641c0d759fb 100644 (file)
@@ -6,6 +6,7 @@
  *   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.
@@ -73,6 +74,7 @@ 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 );
 
@@ -86,8 +88,9 @@ private:
     FillOrStroke kind;
     SPDesktop *desktop;
     SPPaintSelector *psel;
+    guint32 lastDrag;
+    guint dragId;
     bool update;
-    bool local;
     sigc::connection selectChangedConn;
     sigc::connection subselChangedConn;
     sigc::connection selectModifiedConn;
@@ -120,8 +123,9 @@ FillNStroke::FillNStroke( FillOrStroke kind ) :
     kind(kind),
     desktop(0),
     psel(0),
+    lastDrag(0),
+    dragId(0),
     update(false),
-    local(false),
     selectChangedConn(),
     subselChangedConn(),
     selectModifiedConn()
@@ -152,6 +156,10 @@ FillNStroke::FillNStroke( FillOrStroke kind ) :
 
 FillNStroke::~FillNStroke()
 {
+    if (dragId) {
+        g_source_remove(dragId);
+        dragId = 0;
+    }
     psel = 0;
     selectModifiedConn.disconnect();
     subselChangedConn.disconnect();
@@ -176,6 +184,10 @@ void FillNStroke::selectionModifiedCB( guint flags )
 void FillNStroke::setDesktop(SPDesktop *desktop)
 {
     if (this->desktop != desktop) {
+        if (dragId) {
+            g_source_remove(dragId);
+            dragId = 0;
+        }
         if (this->desktop) {
             selectModifiedConn.disconnect();
             subselChangedConn.disconnect();
@@ -188,7 +200,6 @@ void FillNStroke::setDesktop(SPDesktop *desktop)
 
             // Must check flags, so can't call performUpdate() directly.
             selectModifiedConn = desktop->selection->connectModified(sigc::hide<0>(sigc::mem_fun(*this, &FillNStroke::selectionModifiedCB)));
-
         }
         performUpdate();
     }
@@ -206,12 +217,11 @@ void FillNStroke::performUpdate()
         return;
     }
 
-    if (kind == FILL) {
-        // TODO check. This probably should happen for stroke as well as fill.
-        if ( local ) {
-            local = false; // local change; do nothing, but reset the flag
-            return;
-        }
+    if ( dragId ) {
+        // local change; do nothing, but reset the flag
+        g_source_remove(dragId);
+        dragId = 0;
+        return;
     }
 
     update = true;
@@ -259,15 +269,15 @@ void FillNStroke::performUpdate()
                     psel->setGradientLinear( vector );
 
                     SPLinearGradient *lg = SP_LINEARGRADIENT(server);
-                    psel->setGradientProperties( SP_GRADIENT_UNITS(lg),
-                                                 SP_GRADIENT_SPREAD(lg) );
+                    psel->setGradientProperties( lg->getUnits(),
+                                                 lg->getSpread() );
                 } else if (SP_IS_RADIALGRADIENT(server)) {
                     SPGradient *vector = SP_GRADIENT(server)->getVector();
                     psel->setGradientRadial( vector );
 
                     SPRadialGradient *rg = SP_RADIALGRADIENT(server);
-                    psel->setGradientProperties( SP_GRADIENT_UNITS(rg),
-                                                 SP_GRADIENT_SPREAD(rg) );
+                    psel->setGradientProperties( rg->getUnits(),
+                                                 rg->getSpread() );
                 } else if (SP_IS_PATTERN(server)) {
                     SPPattern *pat = pattern_getroot(SP_PATTERN(server));
                     psel->updatePatternList( pat );
@@ -323,8 +333,8 @@ void FillNStroke::setFillrule( SPPaintSelector::FillRule mode )
         sp_repr_css_attr_unref(css);
         css = 0;
 
-        sp_document_done(desktop->doc(), SP_VERB_DIALOG_FILL_STROKE,
-                         _("Change fill rule"));
+        DocumentUndo::done(desktop->doc(), SP_VERB_DIALOG_FILL_STROKE,
+                           _("Change fill rule"));
     }
 }
 
@@ -348,6 +358,28 @@ void FillNStroke::paintDraggedCB(SPPaintSelector * /*psel*/, FillNStroke *self)
     }
 }
 
+
+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
@@ -360,27 +392,34 @@ void FillNStroke::dragFromPaint()
         return;
     }
 
-    if (kind == FILL) {
-        if (local) {
-            // 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;
-        }
+    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 (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;
+
     update = true;
 
     switch (psel->mode) {
         case SPPaintSelector::MODE_COLOR_RGB:
         case SPPaintSelector::MODE_COLOR_CMYK:
         {
+            // 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" );
-            sp_document_maybe_done(desktop->doc(), (kind == FILL) ? undo_F_label : undo_S_label, SP_VERB_DIALOG_FILL_STROKE,
-                                   (kind == FILL) ? _("Set fill color") : _("Set stroke color"));
-            if (kind == FILL) {
-                local = true; // local change, do not update from selection
-            }
+            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;
         }
 
@@ -442,8 +481,8 @@ void FillNStroke::updateFromPaint()
             sp_repr_css_attr_unref(css);
             css = 0;
 
-            sp_document_done(document, SP_VERB_DIALOG_FILL_STROKE,
-                             (kind == FILL) ? _("Remove fill") : _("Remove stroke"));
+            DocumentUndo::done(document, SP_VERB_DIALOG_FILL_STROKE,
+                               (kind == FILL) ? _("Remove fill") : _("Remove stroke"));
             break;
         }
 
@@ -458,8 +497,8 @@ void FillNStroke::updateFromPaint()
             psel->setFlatColor( desktop,
                                 (kind == FILL) ? "fill" : "stroke",
                                 (kind == FILL) ? "fill-opacity" : "stroke-opacity" );
-            sp_document_maybe_done(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"));
+            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
@@ -485,6 +524,7 @@ void FillNStroke::updateFromPaint()
                 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);
 
                 SPCSSAttr *css = 0;
                 if (kind == FILL) {
@@ -499,27 +539,34 @@ void FillNStroke::updateFromPaint()
 
                     SPStyle *query = sp_style_new(desktop->doc());
                     int result = objects_query_fillstroke(const_cast<GSList *>(items), query, kind == FILL);
-                    SPIPaint &targPaint = (kind == FILL) ? query->fill : query->stroke;
-                    guint32 common_rgb = 0;
                     if (result == QUERY_STYLE_MULTIPLE_SAME) {
+                        SPIPaint &targPaint = (kind == FILL) ? query->fill : query->stroke;
+                        SPColor common;
                         if (!targPaint.isColor()) {
-                            common_rgb = sp_desktop_get_color(desktop, kind == FILL);
+                            common = sp_desktop_get_color(desktop, kind == FILL);
                         } else {
-                            common_rgb = targPaint.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
                         if (kind == FILL) {
-                            sp_repr_css_change_recursive(SP_OBJECT_REPR(i->data), css, "style");
+                            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), kind == FILL),
+                                                 gr,
                                                  gradient_type, kind == FILL);
                         } else {
                             sp_item_set_gradient(SP_ITEM(i->data), vector, gradient_type, kind == FILL);
@@ -532,7 +579,7 @@ void FillNStroke::updateFromPaint()
                     for (GSList const *i = items; i != NULL; i = i->next) {
                         //FIXME: see above
                         if (kind == FILL) {
-                            sp_repr_css_change_recursive(SP_OBJECT_REPR(i->data), css, "style");
+                            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, kind == FILL);
@@ -545,8 +592,8 @@ void FillNStroke::updateFromPaint()
                     css = 0;
                 }
 
-                sp_document_done(document, SP_VERB_DIALOG_FILL_STROKE,
-                                 (kind == FILL) ? _("Set gradient on fill") : _("Set gradient on stroke"));
+                DocumentUndo::done(document, SP_VERB_DIALOG_FILL_STROKE,
+                                   (kind == FILL) ? _("Set gradient on fill") : _("Set gradient on stroke"));
             }
             break;
 
@@ -562,7 +609,7 @@ void FillNStroke::updateFromPaint()
                      */
 
                 } else {
-                    Inkscape::XML::Node *patrepr = SP_OBJECT_REPR(pattern);
+                    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);
@@ -576,17 +623,17 @@ void FillNStroke::updateFromPaint()
                     // 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) {
-                        Inkscape::XML::Node *selrepr = SP_OBJECT_REPR(i->data);
+                        Inkscape::XML::Node *selrepr = reinterpret_cast<SPObject*>(i->data)->getRepr();
                         if ( (kind == STROKE) && !selrepr) {
                             continue;
                         }
-                        SPObject *selobj = SP_OBJECT(i->data);
+                        SPObject *selobj = reinterpret_cast<SPObject*>(i->data);
 
-                        SPStyle *style = SP_OBJECT_STYLE(selobj);
+                        SPStyle *style = selobj->style;
                         if (style && ((kind == FILL) ? style->fill : style->stroke).isPaintserver()) {
-                            SPObject *server = (kind == FILL) ?
-                                SP_OBJECT_STYLE_FILL_SERVER(selobj) :
-                                SP_OBJECT_STYLE_STROKE_SERVER(selobj);
+                            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;
@@ -605,9 +652,9 @@ void FillNStroke::updateFromPaint()
 
                 } // end if
 
-                sp_document_done(document, SP_VERB_DIALOG_FILL_STROKE,
-                                 (kind == FILL) ? _("Set pattern on fill") :
-                                 _("Set pattern on stroke"));
+                DocumentUndo::done(document, SP_VERB_DIALOG_FILL_STROKE,
+                                   (kind == FILL) ? _("Set pattern on fill") :
+                                   _("Set pattern on stroke"));
             } // end if
 
             break;
@@ -632,8 +679,8 @@ void FillNStroke::updateFromPaint()
                 sp_repr_css_attr_unref(css);
                 css = 0;
 
-                sp_document_done(document, SP_VERB_DIALOG_FILL_STROKE,
-                                 (kind == FILL) ? _("Unset fill") : _("Unset stroke"));
+                DocumentUndo::done(document, SP_VERB_DIALOG_FILL_STROKE,
+                                   (kind == FILL) ? _("Unset fill") : _("Unset stroke"));
             }
             break;
 
@@ -659,4 +706,4 @@ void FillNStroke::updateFromPaint()
   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 :