Code

Move app-specific logic and file operations up from the lower level.
[inkscape.git] / src / dialogs / swatches.cpp
index 1ed36e7897f28b67b75f50a57a669cd39308011e..4546efe132e9ef43298bb362646bc178e8611477 100644 (file)
@@ -1,7 +1,7 @@
-/*
- * A simple panel for color swatches
- *
- * Authors:
+/** @file
+ * @brief Color swatches dialog
+ */
+/* Authors:
  *   Jon A. Cruz
  *   John Bintz
  *
@@ -10,9 +10,6 @@
  *
  * Released under GNU GPL, read the file 'COPYING' for more information
  */
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
 
 #include <errno.h>
 
@@ -37,7 +34,7 @@
 #include "path-prefix.h"
 #include "swatches.h"
 #include "sp-item.h"
-#include "prefs-utils.h"
+#include "preferences.h"
 
 #include "eek-preview.h"
 
@@ -45,9 +42,10 @@ namespace Inkscape {
 namespace UI {
 namespace Dialogs {
 
-
+ColorItem::ColorItem() : _isRemove(true){};
 ColorItem::ColorItem( unsigned int r, unsigned int g, unsigned int b, Glib::ustring& name ) :
     def( r, g, b, name ),
+    _isRemove(false),
     _isLive(false),
     _linkIsTone(false),
     _linkPercent(0),
@@ -102,6 +100,12 @@ typedef enum {
     TEXT_DATA
 } colorFlavorType;
 
+//TODO: warning: deprecated conversion from string constant to ‘gchar*’
+//
+//Turn out to be warnings that we should probably leave in place. The
+// pointers/types used need to be read-only. So until we correct the using
+// code, those warnings are actually desired. They say "Hey! Fix this". We
+// definitely don't want to hide/ignore them. --JonCruz
 static const GtkTargetEntry sourceColorEntries[] = {
 #if ENABLE_MAGIC_COLORS
 //    {"application/x-inkscape-color-id", GTK_TARGET_SAME_APP, APP_X_INKY_COLOR_ID},
@@ -200,6 +204,23 @@ static void dragBegin( GtkWidget *widget, GdkDragContext* dc, gpointer data )
     ColorItem* item = reinterpret_cast<ColorItem*>(data);
     if ( item )
     {
+        if (item->isRemove()){
+            GError *error = NULL;
+            gchar *filepath = (gchar *) g_strdup_printf("%s/remove-color.png", INKSCAPE_PIXMAPDIR);
+            gsize bytesRead = 0;
+            gsize bytesWritten = 0;
+            gchar *localFilename = g_filename_from_utf8( filepath,
+                                                 -1,
+                                                 &bytesRead,
+                                                 &bytesWritten,
+                                                 &error);
+            GdkPixbuf* pixbuf = gdk_pixbuf_new_from_file_at_scale(localFilename, 32, 24, FALSE, &error);
+            g_free(localFilename);
+            g_free(filepath);
+            gtk_drag_set_icon_pixbuf( dc, pixbuf, 0, 0 );
+            return;
+        }
+
         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))
@@ -240,25 +261,21 @@ static void handleSecondaryClick( GtkWidget* widget, gint arg1, gpointer callbac
     }
 }
 
-static gboolean handleEnterNotify( GtkWidget* widget, GdkEventCrossing* event, gpointer callback_data ) {
+static gboolean handleEnterNotify( GtkWidget* /*widget*/, GdkEventCrossing* /*event*/, gpointer callback_data ) {
     ColorItem* item = reinterpret_cast<ColorItem*>(callback_data);
     if ( item ) {
         SPDesktop *desktop = SP_ACTIVE_DESKTOP;
         if ( desktop ) {
-            desktop->tipsMessageContext()->set(Inkscape::INFORMATION_MESSAGE, g_strconcat(
-              _("Color: <b>"),
-              item->def.descr.c_str(),
-              _("</b>"),
-              _("; "),
-              _("<b>Click</b> to set fill, <b>Shift+click</b> to set stroke"),
-              NULL
-            ));
+            gchar* msg = g_strdup_printf(_("Color: <b>%s</b>; <b>Click</b> to set fill, <b>Shift+click</b> to set stroke"),
+                                         item->def.descr.c_str());
+            desktop->tipsMessageContext()->set(Inkscape::INFORMATION_MESSAGE, msg);
+            g_free(msg);
         }
     }
     return FALSE;
 }
 
-static gboolean handleLeaveNotify( GtkWidget* widget, GdkEventCrossing* event, gpointer callback_data ) {
+static gboolean handleLeaveNotify( GtkWidget* /*widget*/, GdkEventCrossing* /*event*/, gpointer callback_data ) {
     ColorItem* item = reinterpret_cast<ColorItem*>(callback_data);
     if ( item ) {
         SPDesktop *desktop = SP_ACTIVE_DESKTOP;
@@ -336,6 +353,12 @@ static void dieDieDie( GtkObject *obj, gpointer user_data )
     g_message("die die die %p  %p", obj, user_data );
 }
 
+//TODO: warning: deprecated conversion from string constant to ‘gchar*’
+//
+//Turn out to be warnings that we should probably leave in place. The
+// pointers/types used need to be read-only. So until we correct the using
+// code, those warnings are actually desired. They say "Hey! Fix this". We
+// definitely don't want to hide/ignore them. --JonCruz
 static const GtkTargetEntry destColorTargets[] = {
 #if ENABLE_MAGIC_COLORS
 //    {"application/x-inkscape-color-id", GTK_TARGET_SAME_APP, APP_X_INKY_COLOR_ID},
@@ -539,7 +562,7 @@ void ColorItem::_colorDefChanged(void* data)
 Gtk::Widget* ColorItem::getPreview(PreviewStyle style, ViewType view, ::PreviewSize size, guint ratio)
 {
     Gtk::Widget* widget = 0;
-    if ( style == PREVIEW_STYLE_BLURB ) {
+    if ( style == PREVIEW_STYLE_BLURB) {
         Gtk::Label *lbl = new Gtk::Label(def.descr);
         lbl->set_alignment(Gtk::ALIGN_LEFT, Gtk::ALIGN_CENTER);
         widget = lbl;
@@ -554,6 +577,25 @@ Gtk::Widget* ColorItem::getPreview(PreviewStyle style, ViewType view, ::PreviewS
         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 ( _isRemove ) {
+            GError *error = NULL;
+            gchar *filepath = (gchar *) g_strdup_printf("%s/remove-color.png", INKSCAPE_PIXMAPDIR);
+            gsize bytesRead = 0;
+            gsize bytesWritten = 0;
+            gchar *localFilename = g_filename_from_utf8( filepath,
+                                                 -1,
+                                                 &bytesRead,
+                                                 &bytesWritten,
+                                                 &error);
+            GdkPixbuf* pixbuf = gdk_pixbuf_new_from_file(localFilename, &error);
+            if (!pixbuf) {
+                g_warning("Null pixbuf for %p [%s]", localFilename, localFilename );
+            }
+            g_free(localFilename);
+            g_free(filepath);
+
+            eek_preview_set_pixbuf( preview, pixbuf );
+        }
 
         eek_preview_set_details( preview, (::PreviewStyle)style, (::ViewType)view, (::PreviewSize)size, ratio );
         eek_preview_set_linked( preview, (LinkType)((_linkSrc ? PREVIEW_LINK_IN:0)
@@ -665,25 +707,29 @@ Gtk::Widget* ColorItem::getPreview(PreviewStyle style, ViewType view, ::PreviewS
 void ColorItem::buttonClicked(bool secondary)
 {
     SPDesktop *desktop = SP_ACTIVE_DESKTOP;
-    if (desktop) {
-        char const * attrName = secondary ? "stroke" : "fill";
+    if (!desktop) return;
+    char const * attrName = secondary ? "stroke" : "fill";
+
+    gchar c[64];
+    if (!_isRemove){
         guint32 rgba = (def.getR() << 24) | (def.getG() << 16) | (def.getB() << 8) | 0xff;
-        gchar c[64];
         sp_svg_write_color(c, sizeof(c), rgba);
+    }
 
-        SPCSSAttr *css = sp_repr_css_attr_new();
-        sp_repr_css_set_property( css, attrName, c );
-        sp_desktop_set_style(desktop, css);
+    SPCSSAttr *css = sp_repr_css_attr_new();
+    sp_repr_css_set_property( css, attrName, _isRemove ? "none" : c );
+    sp_desktop_set_style(desktop, css);
+    sp_repr_css_attr_unref(css);
 
-        sp_repr_css_attr_unref(css);
+    if (_isRemove){
+        sp_document_done (sp_desktop_document (desktop), SP_VERB_DIALOG_SWATCHES, 
+                      secondary? _("Remove stroke color") : _("Remove fill color"));
+    } else {
         sp_document_done (sp_desktop_document (desktop), SP_VERB_DIALOG_SWATCHES, 
-                          secondary? _("Set stroke color from swatch") : _("Set fill color from swatch"));
+                      secondary? _("Set stroke color from swatch") : _("Set fill color from swatch"));
     }
 }
 
-
-
-
 static char* trim( char* str ) {
     char* ret = str;
     while ( *str && (*str == ' ' || *str == '\t') ) {
@@ -694,7 +740,7 @@ static char* trim( char* str ) {
         str++;
     }
     str--;
-    while ( str > ret && ( *str == ' ' || *str == '\t' ) || *str == '\r' || *str == '\n' ) {
+    while ( str > ret && (( *str == ' ' || *str == '\t' ) || *str == '\r' || *str == '\n') ) {
         *str-- = 0;
     }
     return ret;
@@ -1046,14 +1092,15 @@ SwatchesPanel::SwatchesPanel(gchar const* prefsPath) :
 {
     Gtk::RadioMenuItem* hotItem = 0;
     _holder = new PreviewHolder();
+    _remove = new ColorItem();
     loadEmUp();
-
     if ( !possible.empty() ) {
         JustForNow* first = 0;
-        gchar const* targetName = 0;
-        if ( _prefs_path ) {
-            targetName = prefs_get_string_attribute( _prefs_path, "palette" );
-            if ( targetName ) {
+        Glib::ustring targetName;
+        if ( !_prefs_path.empty() ) {
+            Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+            targetName = prefs->getString(_prefs_path + "/palette");
+            if (!targetName.empty()) {
                 for ( std::vector<JustForNow*>::iterator iter = possible.begin(); iter != possible.end(); ++iter ) {
                     if ( (*iter)->_name == targetName ) {
                         first = *iter;
@@ -1071,12 +1118,14 @@ SwatchesPanel::SwatchesPanel(gchar const* prefsPath) :
             _holder->setColumnPref( first->_prefWidth );
         }
         _holder->freezeUpdates();
+        _holder->addPreview(_remove);
         for ( std::vector<ColorItem*>::iterator it = first->_colors.begin(); it != first->_colors.end(); it++ ) {
             _holder->addPreview(*it);
         }
         _holder->thawUpdates();
 
         Gtk::RadioMenuItem::Group groupOne;
+
         int i = 0;
         for ( std::vector<JustForNow*>::iterator it = possible.begin(); it != possible.end(); it++ ) {
             JustForNow* curr = *it;
@@ -1087,7 +1136,6 @@ SwatchesPanel::SwatchesPanel(gchar const* prefsPath) :
             _regItem( single, 3, i );
             i++;
         }
-
     }
 
 
@@ -1104,6 +1152,8 @@ SwatchesPanel::SwatchesPanel(gchar const* prefsPath) :
 
 SwatchesPanel::~SwatchesPanel()
 {
+    if (_remove) delete _remove;
+    if (_holder) delete _holder;
 }
 
 void SwatchesPanel::setOrientation( Gtk::AnchorType how )
@@ -1126,14 +1176,16 @@ void SwatchesPanel::_handleAction( int setId, int itemId )
                 _holder->clear();
                 JustForNow* curr = possible[itemId];
 
-                if ( _prefs_path ) {
-                    prefs_set_string_attribute( _prefs_path, "palette", curr->_name.c_str() );
+                if ( !_prefs_path.empty() ) {
+                    Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+                    prefs->setString(_prefs_path + "/palette", curr->_name);
                 }
 
                 if ( curr->_prefWidth > 0 ) {
                     _holder->setColumnPref( curr->_prefWidth );
                 }
                 _holder->freezeUpdates();
+                _holder->addPreview(_remove);
                 for ( std::vector<ColorItem*>::iterator it = curr->_colors.begin(); it != curr->_colors.end(); it++ ) {
                     _holder->addPreview(*it);
                 }