Code

merging gsoc 2009 color management work by Felipe Sanches (a.k.a. JucaBlues)
[inkscape.git] / src / ui / dialog / swatches.cpp
index 8fb811e3d205448dc2693c8a5287e07e8d1843ce..1f708e3de3534c1c84f8387ecc391d7da91c0f2b 100644 (file)
@@ -26,6 +26,7 @@
 #include "desktop-handles.h"
 #include "desktop-style.h"
 #include "document.h"
+#include "document-private.h"
 #include "extension/db.h"
 #include "inkscape.h"
 #include "inkscape.h"
 #include "sp-gradient.h"
 #include "sp-gradient-vector.h"
 #include "swatches.h"
+#include "style.h"
+#include "widgets/gradient-vector.h"
 #include "widgets/eek-preview.h"
+#include "display/nr-plain-stuff.h"
+#include "sp-gradient-reference.h"
+
+//#define USE_DOCUMENT_PALETTE 1
 
 namespace Inkscape {
 namespace UI {
 namespace Dialogs {
 
+#define VBLOCK 16
+
+void _loadPaletteFile( gchar const *filename );
 
-ColorItem::ColorItem(eek::ColorDef::ColorType type) :
+/**
+ * The color swatch you see on screen as a clickable box.
+ */
+class ColorItem : public Inkscape::UI::Previewable
+{
+    friend void _loadPaletteFile( gchar const *filename );
+public:
+    ColorItem( ege::PaintDef::ColorType type );
+    ColorItem( unsigned int r, unsigned int g, unsigned int b,
+               Glib::ustring& name );
+    virtual ~ColorItem();
+    ColorItem(ColorItem const &other);
+    virtual ColorItem &operator=(ColorItem const &other);
+    virtual Gtk::Widget* getPreview(PreviewStyle style,
+                                    ViewType view,
+                                    ::PreviewSize size,
+                                    guint ratio);
+    void buttonClicked(bool secondary = false);
+
+    void setState( bool fill, bool stroke );
+    bool isFill() { return _isFill; }
+    bool isStroke() { return _isStroke; }
+
+    ege::PaintDef def;
+    void* ptr;
+
+private:
+    static void _dropDataIn( GtkWidget *widget,
+                             GdkDragContext *drag_context,
+                             gint x, gint y,
+                             GtkSelectionData *data,
+                             guint info,
+                             guint event_time,
+                             gpointer user_data);
+
+    static void _dragGetColorData( GtkWidget *widget,
+                                   GdkDragContext *drag_context,
+                                   GtkSelectionData *data,
+                                   guint info,
+                                   guint time,
+                                   gpointer user_data);
+
+    static void _wireMagicColors( void* p );
+    static void _colorDefChanged(void* data);
+
+    void _linkTint( ColorItem& other, int percent );
+    void _linkTone( ColorItem& other, int percent, int grayLevel );
+
+    Gtk::Tooltips tips;
+    std::vector<Gtk::Widget*> _previews;
+
+    bool _isFill;
+    bool _isStroke;
+    bool _isLive;
+    bool _linkIsTone;
+    int _linkPercent;
+    int _linkGray;
+    ColorItem* _linkSrc;
+    std::vector<ColorItem*> _listeners;
+};
+
+
+
+ColorItem::ColorItem(ege::PaintDef::ColorType type) :
     def(type),
+    ptr(0),
+    _isFill(false),
+    _isStroke(false),
     _isLive(false),
     _linkIsTone(false),
     _linkPercent(0),
@@ -59,6 +135,9 @@ ColorItem::ColorItem(eek::ColorDef::ColorType type) :
 
 ColorItem::ColorItem( unsigned int r, unsigned int g, unsigned int b, Glib::ustring& name ) :
     def( r, g, b, name ),
+    ptr(0),
+    _isFill(false),
+    _isStroke(false),
     _isLive(false),
     _linkIsTone(false),
     _linkPercent(0),
@@ -91,6 +170,31 @@ ColorItem &ColorItem::operator=(ColorItem const &other)
     return *this;
 }
 
+void ColorItem::setState( bool fill, bool stroke )
+{
+    if ( (_isFill != fill) || (_isStroke != stroke) ) {
+        _isFill = fill;
+        _isStroke = stroke;
+
+        for ( std::vector<Gtk::Widget*>::iterator it = _previews.begin(); it != _previews.end(); ++it ) {
+            Gtk::Widget* widget = *it;
+            if ( IS_EEK_PREVIEW(widget->gobj()) ) {
+                EekPreview * preview = EEK_PREVIEW(widget->gobj());
+
+                int val = eek_preview_get_linked( preview );
+                val &= ~(PREVIEW_FILL | PREVIEW_STROKE);
+                if ( _isFill ) {
+                    val |= PREVIEW_FILL;
+                }
+                if ( _isStroke ) {
+                    val |= PREVIEW_STROKE;
+                }
+                eek_preview_set_linked( preview, static_cast<LinkType>(val) );
+            }
+        }
+    }
+}
+
 
 class JustForNow
 {
@@ -108,6 +212,9 @@ static std::vector<JustForNow*> possible;
 static std::vector<std::string> mimeStrings;
 static std::map<std::string, guint> mimeToInt;
 
+static std::map<ColorItem*, guchar*> previewMap;
+static std::map<ColorItem*, SPGradient*> gradMap; // very temporary workaround.
+
 void ColorItem::_dragGetColorData( GtkWidget */*widget*/,
                                    GdkDragContext */*drag_context*/,
                                    GtkSelectionData *data,
@@ -144,8 +251,10 @@ static void dragBegin( GtkWidget */*widget*/, GdkDragContext* dc, gpointer data
         using Inkscape::IO::Resource::get_path;
         using Inkscape::IO::Resource::ICONS;
         using Inkscape::IO::Resource::SYSTEM;
+        int width = 32;
+        int height = 24;
 
-        if (item->def.getType() != eek::ColorDef::RGB){
+        if (item->def.getType() != ege::PaintDef::RGB){
             GError *error = NULL;
             gsize bytesRead = 0;
             gsize bytesWritten = 0;
@@ -154,18 +263,35 @@ static void dragBegin( GtkWidget */*widget*/, GdkDragContext* dc, gpointer data
                                                  &bytesRead,
                                                  &bytesWritten,
                                                  &error);
-            GdkPixbuf* pixbuf = gdk_pixbuf_new_from_file_at_scale(localFilename, 32, 24, FALSE, &error);
+            GdkPixbuf* pixbuf = gdk_pixbuf_new_from_file_at_scale(localFilename, width, height, FALSE, &error);
             g_free(localFilename);
             gtk_drag_set_icon_pixbuf( dc, pixbuf, 0, 0 );
-            return;
-        }
+        } else {
+            GdkPixbuf* pixbuf = 0;
+            if ( gradMap.find(item) == gradMap.end() ){
+                Glib::RefPtr<Gdk::Pixbuf> thumb = Gdk::Pixbuf::create( Gdk::COLORSPACE_RGB, false, 8, width, height );
+                guint32 fillWith = (0xff000000 & (item->def.getR() << 24))
+                    | (0x00ff0000 & (item->def.getG() << 16))
+                    | (0x0000ff00 & (item->def.getB() <<  8));
+                thumb->fill( fillWith );
+                pixbuf = thumb->gobj();
+            } else {
+                SPGradient* grad = gradMap[item];
+
+                guchar* px = g_new( guchar, 3 * height * width );
+                nr_render_checkerboard_rgb( px, width, height, 3 * width, 0, 0 );
 
-        Glib::RefPtr<Gdk::Pixbuf> thumb = Gdk::Pixbuf::create( Gdk::COLORSPACE_RGB, false, 8, 32, 24 );
-        guint32 fillWith = (0xff000000 & (item->def.getR() << 24))
-                         | (0x00ff0000 & (item->def.getG() << 16))
-                         | (0x0000ff00 & (item->def.getB() <<  8));
-        thumb->fill( fillWith );
-        gtk_drag_set_icon_pixbuf( dc, thumb->gobj(), 0, 0 );
+                sp_gradient_render_vector_block_rgb( grad,
+                                                     px, width, height, 3 * width,
+                                                     0, width, TRUE );
+
+                pixbuf = gdk_pixbuf_new_from_data( px, GDK_COLORSPACE_RGB, FALSE, 8,
+                                                   width, height, width * 3,
+                                                   0, // add delete function
+                                                   0 );
+            }
+            gtk_drag_set_icon_pixbuf( dc, pixbuf, 0, 0 );
+        }
     }
 
 }
@@ -223,6 +349,7 @@ static gboolean handleLeaveNotify( GtkWidget* /*widget*/, GdkEventCrossing* /*ev
 }
 
 static GtkWidget* popupMenu = 0;
+static std::vector<GtkWidget*> popupExtras;
 static ColorItem* bounceTarget = 0;
 
 static void redirClick( GtkMenuItem *menuitem, gpointer /*user_data*/ )
@@ -239,6 +366,69 @@ static void redirSecondaryClick( GtkMenuItem *menuitem, gpointer /*user_data*/ )
     }
 }
 
+#if USE_DOCUMENT_PALETTE
+static void editGradientImpl( SPGradient* gr )
+{
+    if ( gr ) {
+        GtkWidget *dialog = sp_gradient_vector_editor_new( gr );
+        gtk_widget_show( dialog );
+    }
+}
+
+static void editGradient( GtkMenuItem */*menuitem*/, gpointer /*user_data*/ )
+{
+    if ( bounceTarget ) {
+        SwatchesPanel* swp = bounceTarget->ptr ? reinterpret_cast<SwatchesPanel*>(bounceTarget->ptr) : 0;
+        SPDesktop* desktop = swp ? swp->getDesktop() : 0;
+        SPDocument *doc = desktop ? desktop->doc() : 0;
+        if (doc) {
+            std::string targetName(bounceTarget->def.descr);
+            const GSList *gradients = sp_document_get_resource_list(doc, "gradient");
+            for (const GSList *item = gradients; item; item = item->next) {
+                SPGradient* grad = SP_GRADIENT(item->data);
+                if ( targetName == grad->id ) {
+                    editGradientImpl( grad );
+                    break;
+                }
+            }
+        }
+    }
+}
+
+static void addNewGradient( GtkMenuItem */*menuitem*/, gpointer /*user_data*/ )
+{
+    if ( bounceTarget ) {
+        SwatchesPanel* swp = bounceTarget->ptr ? reinterpret_cast<SwatchesPanel*>(bounceTarget->ptr) : 0;
+        SPDesktop* desktop = swp ? swp->getDesktop() : 0;
+        SPDocument *doc = desktop ? desktop->doc() : 0;
+        if (doc) {
+            Inkscape::XML::Document *xml_doc = sp_document_repr_doc(doc);
+
+            Inkscape::XML::Node *repr = xml_doc->createElement("svg:linearGradient");
+            repr->setAttribute("osb:paint", "solid");
+            Inkscape::XML::Node *stop = xml_doc->createElement("svg:stop");
+            stop->setAttribute("offset", "0");
+            stop->setAttribute("style", "stop-color:#000;stop-opacity:1;");
+            repr->appendChild(stop);
+            Inkscape::GC::release(stop);
+
+            SP_OBJECT_REPR( SP_DOCUMENT_DEFS(doc) )->addChild(repr, NULL);
+
+            SPGradient * gr = static_cast<SPGradient *>(doc->getObjectByRepr(repr));
+
+            Inkscape::GC::release(repr);
+
+
+            editGradientImpl( gr );
+            // Work-around for timing of gradient addition change. Must follow edit.
+            if ( swp ) {
+                swp->handleGradientsChange();
+            }
+        }
+    }
+}
+#endif // USE_DOCUMENT_PALETTE
+
 static gboolean handleButtonPress( GtkWidget* /*widget*/, GdkEventButton* event, gpointer user_data)
 {
     gboolean handled = FALSE;
@@ -265,11 +455,53 @@ static gboolean handleButtonPress( GtkWidget* /*widget*/, GdkEventButton* event,
                               user_data);
             gtk_menu_shell_append(GTK_MENU_SHELL(popupMenu), child);
 
+#if USE_DOCUMENT_PALETTE
+            child = gtk_separator_menu_item_new();
+            gtk_menu_shell_append(GTK_MENU_SHELL(popupMenu), child);
+            popupExtras.push_back(child);
+
+            child = gtk_menu_item_new_with_label(_("Add"));
+            g_signal_connect( G_OBJECT(child),
+                              "activate",
+                              G_CALLBACK(addNewGradient),
+                              user_data );
+            gtk_menu_shell_append(GTK_MENU_SHELL(popupMenu), child);
+            popupExtras.push_back(child);
+
+            child = gtk_menu_item_new_with_label(_("Delete"));
+            gtk_menu_shell_append(GTK_MENU_SHELL(popupMenu), child);
+            //popupExtras.push_back(child);
+            gtk_widget_set_sensitive( child, FALSE );
+
+            child = gtk_menu_item_new_with_label(_("Edit..."));
+            g_signal_connect( G_OBJECT(child),
+                              "activate",
+                              G_CALLBACK(editGradient),
+                              user_data );
+            gtk_menu_shell_append(GTK_MENU_SHELL(popupMenu), child);
+            popupExtras.push_back(child);
+
+            child = gtk_separator_menu_item_new();
+            gtk_menu_shell_append(GTK_MENU_SHELL(popupMenu), child);
+            popupExtras.push_back(child);
+
+            child = gtk_menu_item_new_with_label(_("Convert"));
+            gtk_menu_shell_append(GTK_MENU_SHELL(popupMenu), child);
+            //popupExtras.push_back(child);
+            gtk_widget_set_sensitive( child, FALSE );
+#endif // USE_DOCUMENT_PALETTE
+
             gtk_widget_show_all(popupMenu);
         }
 
         ColorItem* item = reinterpret_cast<ColorItem*>(user_data);
         if ( item ) {
+            SwatchesPanel* swp = item->ptr ? reinterpret_cast<SwatchesPanel*>(item->ptr) : 0;
+            bool show = swp && (swp->getSelectedIndex() == 0);
+            for ( std::vector<GtkWidget*>::iterator it = popupExtras.begin(); it != popupExtras.end(); ++ it) {
+                gtk_widget_set_sensitive(*it, show);
+            }
+
             bounceTarget = item;
             if ( popupMenu ) {
                 gtk_menu_popup(GTK_MENU(popupMenu), NULL, NULL, NULL, NULL, event->button, event->time);
@@ -443,8 +675,21 @@ Gtk::Widget* ColorItem::getPreview(PreviewStyle style, ViewType view, ::PreviewS
         EekPreview * preview = EEK_PREVIEW(eekWidget);
         Gtk::Widget* newBlot = Glib::wrap(eekWidget);
 
-        eek_preview_set_color( preview, (def.getR() << 8) | def.getR(), (def.getG() << 8) | def.getG(), (def.getB() << 8) | def.getB());
-        if ( def.getType() != eek::ColorDef::RGB ) {
+        if ( previewMap.find(this) == previewMap.end() ){
+            eek_preview_set_color( preview, (def.getR() << 8) | def.getR(),
+                                   (def.getG() << 8) | def.getG(),
+                                   (def.getB() << 8) | def.getB());
+        } else {
+            guchar* px = previewMap[this];
+            int width = 128;
+            int height = 16;
+            GdkPixbuf* pixbuf = gdk_pixbuf_new_from_data( px, GDK_COLORSPACE_RGB, FALSE, 8,
+                                                          width, height, width * 3,
+                                                          0, // add delete function
+                                                          0 );
+            eek_preview_set_pixbuf( preview, pixbuf );
+        }
+        if ( def.getType() != ege::PaintDef::RGB ) {
             using Inkscape::IO::Resource::get_path;
             using Inkscape::IO::Resource::ICONS;
             using Inkscape::IO::Resource::SYSTEM;
@@ -601,23 +846,31 @@ void ColorItem::buttonClicked(bool secondary)
         SPCSSAttr *css = sp_repr_css_attr_new();
         Glib::ustring descr;
         switch (def.getType()) {
-            case eek::ColorDef::CLEAR: {
+            case ege::PaintDef::CLEAR: {
                 // TODO actually make this clear
                 sp_repr_css_set_property( css, attrName, "none" );
                 descr = secondary? _("Remove stroke color") : _("Remove fill color");
                 break;
             }
-            case eek::ColorDef::NONE: {
+            case ege::PaintDef::NONE: {
                 sp_repr_css_set_property( css, attrName, "none" );
                 descr = secondary? _("Set stroke color to none") : _("Set fill color to none");
                 break;
             }
-            case eek::ColorDef::RGB: {
-                gchar c[64];
-                guint32 rgba = (def.getR() << 24) | (def.getG() << 16) | (def.getB() << 8) | 0xff;
-                sp_svg_write_color(c, sizeof(c), rgba);
-
-                sp_repr_css_set_property( css, attrName, c );
+            case ege::PaintDef::RGB: {
+                Glib::ustring colorspec;
+                if ( gradMap.find(this) == gradMap.end() ){
+                    gchar c[64];
+                    guint32 rgba = (def.getR() << 24) | (def.getG() << 16) | (def.getB() << 8) | 0xff;
+                    sp_svg_write_color(c, sizeof(c), rgba);
+                    colorspec = c;
+                } else {
+                    SPGradient* grad = gradMap[this];
+                    colorspec = "url(#";
+                    colorspec += grad->id;
+                    colorspec += ")";
+                }
+                sp_repr_css_set_property( css, attrName, colorspec.c_str() );
                 descr = secondary? _("Set stroke color from swatch") : _("Set fill color from swatch");
                 break;
             }
@@ -997,8 +1250,11 @@ SwatchesPanel::SwatchesPanel(gchar const* prefsPath) :
 {
     Gtk::RadioMenuItem* hotItem = 0;
     _holder = new PreviewHolder();
-    _clear = new ColorItem( eek::ColorDef::CLEAR );
-    _remove = new ColorItem( eek::ColorDef::NONE );
+    _clear = new ColorItem( ege::PaintDef::CLEAR );
+    _clear->ptr = this;
+    _remove = new ColorItem( ege::PaintDef::NONE );
+    _remove->ptr = this;
+#if USE_DOCUMENT_PALETTE
     {
         JustForNow *docPalette = new JustForNow();
 
@@ -1007,6 +1263,7 @@ SwatchesPanel::SwatchesPanel(gchar const* prefsPath) :
 
         _ptr = docPalette;
     }
+#endif // USE_DOCUMENT_PALETTE
     loadEmUp();
     if ( !possible.empty() ) {
         JustForNow* first = 0;
@@ -1065,6 +1322,9 @@ SwatchesPanel::~SwatchesPanel()
 {
     _documentConnection.disconnect();
     _resourceConnection.disconnect();
+    _selChanged.disconnect();
+    _setModified.disconnect();
+    _subselChanged.disconnect();
 
     if ( _clear ) {
         delete _clear;
@@ -1093,15 +1353,25 @@ void SwatchesPanel::setDesktop( SPDesktop* desktop )
     if ( desktop != _currentDesktop ) {
         if ( _currentDesktop ) {
             _documentConnection.disconnect();
+            _selChanged.disconnect();
+            _setModified.disconnect();
+            _subselChanged.disconnect();
         }
 
         _currentDesktop = desktop;
 
         if ( desktop ) {
-            sigc::bound_mem_functor1<void, Inkscape::UI::Dialogs::SwatchesPanel, SPDocument*> first = sigc::mem_fun(*this, &SwatchesPanel::_setDocument);
+            _currentDesktop->selection->connectChanged(
+                sigc::hide(sigc::mem_fun(*this, &SwatchesPanel::_updateFromSelection)));
 
-            sigc::slot<void, SPDocument*> base2 = first;
+            _currentDesktop->selection->connectModified(
+                sigc::hide(sigc::hide(sigc::mem_fun(*this, &SwatchesPanel::_updateFromSelection))));
 
+            _currentDesktop->connectToolSubselectionChanged(
+                sigc::hide(sigc::mem_fun(*this, &SwatchesPanel::_updateFromSelection)));
+
+            sigc::bound_mem_functor1<void, Inkscape::UI::Dialogs::SwatchesPanel, SPDocument*> first = sigc::mem_fun(*this, &SwatchesPanel::_setDocument);
+            sigc::slot<void, SPDocument*> base2 = first;
             sigc::slot<void,SPDesktop*, SPDocument*> slot2 = sigc::hide<0>( base2 );
             _documentConnection = desktop->connectDocumentReplaced( slot2 );
 
@@ -1122,14 +1392,14 @@ void SwatchesPanel::_setDocument( SPDocument *document )
         if ( _currentDocument ) {
             _resourceConnection = sp_document_resources_changed_connect(document,
                                                                         "gradient",
-                                                                        sigc::mem_fun(*this, &SwatchesPanel::_handleGradientsChange));
+                                                                        sigc::mem_fun(*this, &SwatchesPanel::handleGradientsChange));
         }
 
-        _handleGradientsChange();
+        handleGradientsChange();
     }
 }
 
-void SwatchesPanel::_handleGradientsChange()
+void SwatchesPanel::handleGradientsChange()
 {
     std::vector<SPGradient*> newList;
 
@@ -1141,6 +1411,7 @@ void SwatchesPanel::_handleGradientsChange()
         }
     }
 
+#if USE_DOCUMENT_PALETTE
     if ( _ptr ) {
         JustForNow *docPalette = reinterpret_cast<JustForNow *>(_ptr);
         // TODO delete pointed to objects
@@ -1148,24 +1419,49 @@ void SwatchesPanel::_handleGradientsChange()
         if ( !newList.empty() ) {
             for ( std::vector<SPGradient*>::iterator it = newList.begin(); it != newList.end(); ++it )
             {
-                if ( (*it)->vector.stops.size() == 2 ) {
-                    SPGradientStop first = (*it)->vector.stops[0];
+                SPGradient* grad = *it;
+                if ( grad->repr->attribute("osb:paint") ) {
+                    sp_gradient_ensure_vector( grad );
+                    SPGradientStop first = grad->vector.stops[0];
+                    SPColor color = first.color;
+                    guint32 together = color.toRGBA32(first.opacity);
+
+                    // At the moment we can't trust the count of 1 vs 2 stops.
                     SPGradientStop second = (*it)->vector.stops[1];
-                    if ((first.offset <0.0001) && (static_cast<int>(second.offset * 100.0f) == 100)) {
-                        SPColor color = first.color;
-                        guint32 together = color.toRGBA32(0);
-
-                        // Pick only single-color gradients for now
-                        SPColor color2 = second.color;
-                        guint32 together2 = color2.toRGBA32(0);
-                        if ( together == together2 ) {
-                            Glib::ustring name((*it)->id);
-                            unsigned int r = SP_RGBA32_R_U(together);
-                            unsigned int g = SP_RGBA32_G_U(together);
-                            unsigned int b = SP_RGBA32_B_U(together);
-                            ColorItem* item = new ColorItem( r, g, b, name );
-                            docPalette->_colors.push_back(item);
-                        }
+                    SPColor color2 = second.color;
+                    guint32 together2 = color2.toRGBA32(second.opacity);
+
+                    if ( (grad->vector.stops.size() <= 2) && (together == together2) ) {
+                        // Treat as solid-color
+                        Glib::ustring name( grad->id );
+                        unsigned int r = SP_RGBA32_R_U(together);
+                        unsigned int g = SP_RGBA32_G_U(together);
+                        unsigned int b = SP_RGBA32_B_U(together);
+                        ColorItem* item = new ColorItem( r, g, b, name );
+                        item->ptr = this;
+                        docPalette->_colors.push_back(item);
+                        gradMap[item] = grad;
+                    } else {
+                        // Treat as gradient
+                        Glib::ustring name( grad->id );
+                        unsigned int r = SP_RGBA32_R_U(together);
+                        unsigned int g = SP_RGBA32_G_U(together);
+                        unsigned int b = SP_RGBA32_B_U(together);
+                        ColorItem* item = new ColorItem( r, g, b, name );
+                        item->ptr = this;
+                        docPalette->_colors.push_back(item);
+
+                        gint width = 128;
+                        gint height = VBLOCK;
+                        guchar* px = g_new( guchar, 3 * height * width );
+                        nr_render_checkerboard_rgb( px, width, VBLOCK, 3 * width, 0, 0 );
+
+                        sp_gradient_render_vector_block_rgb( grad,
+                                                             px, width, height, 3 * width,
+                                                             0, width, TRUE );
+
+                        previewMap[item] = px;
+                        gradMap[item] = grad;
                     }
                 }
             }
@@ -1175,6 +1471,90 @@ void SwatchesPanel::_handleGradientsChange()
             _rebuild();
         }
     }
+#endif // USE_DOCUMENT_PALETTE
+}
+
+void SwatchesPanel::_updateFromSelection()
+{
+#if USE_DOCUMENT_PALETTE
+    if ( _ptr ) {
+        JustForNow *docPalette = reinterpret_cast<JustForNow *>(_ptr);
+
+        Glib::ustring fillId;
+        Glib::ustring strokeId;
+
+        SPStyle *tmpStyle = sp_style_new( sp_desktop_document(_currentDesktop) );
+        int result = sp_desktop_query_style( _currentDesktop, tmpStyle, QUERY_STYLE_PROPERTY_FILL );
+        switch (result) {
+            case QUERY_STYLE_SINGLE:
+            case QUERY_STYLE_MULTIPLE_AVERAGED:
+            case QUERY_STYLE_MULTIPLE_SAME:
+            {
+                if (tmpStyle->fill.set && tmpStyle->fill.isPaintserver()) {
+                    SPPaintServer* server = tmpStyle->getFillPaintServer();
+                    if ( SP_IS_GRADIENT(server) ) {
+                        SPGradient* target = 0;
+                        SPGradient* grad = SP_GRADIENT(server);
+                        if (grad->repr->attribute("osb:paint")) {
+                            target = grad;
+                        } else if ( grad->ref ) {
+                            SPGradient *tmp = grad->ref->getObject();
+                            if ( tmp && tmp->repr->attribute("osb:paint") ) {
+                                target = tmp;
+                            }
+                        }
+                        if ( target ) {
+                            gchar const* id = target->repr->attribute("id");
+                            if ( id ) {
+                                fillId = id;
+                            }
+                        }
+                    }
+                }
+                break;
+            }
+        }
+
+        result = sp_desktop_query_style( _currentDesktop, tmpStyle, QUERY_STYLE_PROPERTY_STROKE );
+        switch (result) {
+            case QUERY_STYLE_SINGLE:
+            case QUERY_STYLE_MULTIPLE_AVERAGED:
+            case QUERY_STYLE_MULTIPLE_SAME:
+            {
+                if (tmpStyle->stroke.set && tmpStyle->stroke.isPaintserver()) {
+                    SPPaintServer* server = tmpStyle->getStrokePaintServer();
+                    if ( SP_IS_GRADIENT(server) ) {
+                        SPGradient* target = 0;
+                        SPGradient* grad = SP_GRADIENT(server);
+                        if (grad->repr->attribute("osb:paint")) {
+                            target = grad;
+                        } else if ( grad->ref ) {
+                            SPGradient *tmp = grad->ref->getObject();
+                            if ( tmp && tmp->repr->attribute("osb:paint") ) {
+                                target = tmp;
+                            }
+                        }
+                        if ( target ) {
+                            gchar const* id = target->repr->attribute("id");
+                            if ( id ) {
+                                strokeId = id;
+                            }
+                        }
+                    }
+                }
+                break;
+            }
+        }
+        sp_style_unref(tmpStyle);
+
+        for ( std::vector<ColorItem*>::iterator it = docPalette->_colors.begin(); it != docPalette->_colors.end(); ++it ) {
+            ColorItem* item = *it;
+            bool isFill = (fillId == item->def.descr);
+            bool isStroke = (strokeId == item->def.descr);
+            item->setState( isFill, isStroke );
+        }
+    }
+#endif // USE_DOCUMENT_PALETTE
 }
 
 void SwatchesPanel::_handleAction( int setId, int itemId )