summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLiam P. White <inkscapebronyat-signgmaildotcom>2014-03-04 23:05:52 +0000
committerLiam P. White <inkscapebronyat-signgmaildotcom>2014-03-04 23:05:52 +0000
commit12971e975dae83c23e89cdbff99e990d3916b6ff (patch)
treef16e505e187693567e75503dc8095ffecf2bad12 /src
parentRemove tag dialog temporarily (diff)
downloadinkscape-12971e975dae83c23e89cdbff99e990d3916b6ff.tar.gz
inkscape-12971e975dae83c23e89cdbff99e990d3916b6ff.zip
Added some basic swatch stuff (does not compile)
(bzr r13090.1.14)
Diffstat (limited to 'src')
-rw-r--r--src/ui/dialog/swatches.cpp2938
-rw-r--r--src/ui/dialog/swatches.h155
2 files changed, 2156 insertions, 937 deletions
diff --git a/src/ui/dialog/swatches.cpp b/src/ui/dialog/swatches.cpp
index 711bcfe2d..a0c79b8ac 100644
--- a/src/ui/dialog/swatches.cpp
+++ b/src/ui/dialog/swatches.cpp
@@ -43,10 +43,10 @@
#include "path-prefix.h"
#include "preferences.h"
#include "sp-item.h"
+#include "sp-gradient-fns.h"
#include "sp-gradient.h"
#include "sp-gradient-vector.h"
#include "style.h"
-#include "ui/previewholder.h"
#include "widgets/desktop-widget.h"
#include "widgets/gradient-vector.h"
#include "widgets/eek-preview.h"
@@ -57,7 +57,6 @@
#include "verbs.h"
#include "gradient-chemistry.h"
#include "helper/action.h"
-#include "helper/action-context.h"
#include "xml/node-observer.h"
#include "xml/repr.h"
#include "sp-pattern.h"
@@ -68,1172 +67,2255 @@
#include "svg/svg-color.h"
#include "sp-radial-gradient.h"
#include "color-rgba.h"
-#include "event-context.h"
+#include "svg/css-ostringstream.h"
+//#include "event-context.h" //no longer exists
#include <queue>
-//sorry!
#ifdef WIN32
#include <windows.h>
#endif
+guint get_group0_keyval(GdkEventKey *event);
+void sp_desktop_set_gradient(SPDesktop *desktop, SPGradient* gradient, bool fill);
+
namespace Inkscape {
namespace UI {
namespace Dialogs {
-#define VBLOCK 16
-#define PREVIEW_PIXBUF_WIDTH 128
#define SWATCHES_FILE_NAME "swatches.svg"
-void _loadPaletteFile( gchar const *filename, gboolean user=FALSE );
-
-std::list<SwatchPage*> userSwatchPages;
-std::list<SwatchPage*> systemSwatchPages;
-static std::map<SPDocument*, SwatchPage*> docPalettes;
-static std::vector<DocTrack*> docTrackings;
-static std::map<SwatchesPanel*, SPDocument*> docPerPanel;
-
-
-class SwatchesPanelHook : public SwatchesPanel
-{
-public:
- static void convertGradient( GtkMenuItem *menuitem, gpointer userData );
- static void deleteGradient( GtkMenuItem *menuitem, gpointer userData );
-};
+static char* trim( char* str ) {
+ char* ret = str;
+ while ( *str && (*str == ' ' || *str == '\t') ) {
+ str++;
+ }
+ ret = str;
+ while ( *str ) {
+ str++;
+ }
+ str--;
+ while ( str > ret && (( *str == ' ' || *str == '\t' ) || *str == '\r' || *str == '\n') ) {
+ *str-- = 0;
+ }
+ return ret;
+}
-static void handleClick( GtkWidget* /*widget*/, gpointer callback_data ) {
- ColorItem* item = reinterpret_cast<ColorItem*>(callback_data);
- if ( item ) {
- item->buttonClicked(false);
+static void skipWhitespace( char*& str ) {
+ while ( *str == ' ' || *str == '\t' ) {
+ str++;
}
}
-static void handleSecondaryClick( GtkWidget* /*widget*/, gint /*arg1*/, gpointer callback_data ) {
- ColorItem* item = reinterpret_cast<ColorItem*>(callback_data);
- if ( item ) {
- item->buttonClicked(true);
+static bool parseNum( char*& str, int& val ) {
+ val = 0;
+ while ( '0' <= *str && *str <= '9' ) {
+ val = val * 10 + (*str - '0');
+ str++;
}
+ bool retval = !(*str == 0 || *str == ' ' || *str == '\t' || *str == '\r' || *str == '\n');
+ return retval;
}
-static GtkWidget* popupMenu = 0;
-static GtkWidget *popupSubHolder = 0;
-static GtkWidget *popupSub = 0;
-static std::vector<Glib::ustring> popupItems;
-static std::vector<GtkWidget*> popupExtras;
-static ColorItem* bounceTarget = 0;
-static SwatchesPanel* bouncePanel = 0;
+static char * SwatchFile;
+static SPDocument * SwatchDocument;
+static unsigned int page_suffix;
-static void redirClick( GtkMenuItem *menuitem, gpointer /*user_data*/ )
+static void loadPalletFile()
{
- if ( bounceTarget ) {
- handleClick( GTK_WIDGET(menuitem), bounceTarget );
+ if (!SwatchDocument) {
+ SwatchFile=g_build_filename(INKSCAPE_PALETTESDIR, _("swatches.svg"), NULL);
+ SwatchDocument=SPDocument::createNewDoc (SwatchFile, TRUE);
+ if (!SwatchDocument) {
+ SwatchDocument = SPDocument::createNewDoc(NULL, TRUE, true);
+ sp_repr_save_file(SwatchDocument->getReprDoc(), SwatchFile, SP_SVG_NS_URI);
+ }
}
}
-static void redirSecondaryClick( GtkMenuItem *menuitem, gpointer /*user_data*/ )
+static void addStop( Inkscape::XML::Node *parent, Glib::ustring const &color, gfloat opacity, gchar const *offset )
{
- if ( bounceTarget ) {
- handleSecondaryClick( GTK_WIDGET(menuitem), 0, bounceTarget );
+#ifdef SP_GR_VERBOSE
+ g_message("addStop(%p, %s, %d, %s)", parent, color.c_str(), opacity, offset);
+#endif
+ Inkscape::XML::Node *stop = parent->document()->createElement("svg:stop");
+ {
+ gchar *tmp = g_strdup_printf( "stop-color:%s;stop-opacity:%f;", color.c_str(), opacity < 0.0 ? 0.0 : (opacity > 1.0 ? 1.0 : opacity) );
+ stop->setAttribute( "style", tmp );
+ g_free(tmp);
}
+
+ stop->setAttribute( "offset", offset );
+
+ parent->appendChild(stop);
+ Inkscape::GC::release(stop);
}
-static void editGradientImpl( SPDesktop* desktop, SPGradient* gr )
+static SPGroup* importGPL(SPDocument* doc, const gchar* full)
{
- if ( gr ) {
- bool shown = false;
- if ( desktop && desktop->doc() ) {
- Inkscape::Selection *selection = sp_desktop_selection( desktop );
- GSList const *items = selection->itemList();
- if (items) {
- SPStyle *query = sp_style_new( desktop->doc() );
- int result = objects_query_fillstroke(const_cast<GSList *>(items), query, true);
- if ( (result == QUERY_STYLE_MULTIPLE_SAME) || (result == QUERY_STYLE_SINGLE) ) {
- // could be pertinent
- if (query->fill.isPaintserver()) {
- SPPaintServer* server = query->getFillPaintServer();
- if ( SP_IS_GRADIENT(server) ) {
- SPGradient* grad = SP_GRADIENT(server);
- if ( grad->isSwatch() && grad->getId() == gr->getId()) {
- desktop->_dlg_mgr->showDialog("FillAndStroke");
- shown = true;
+ SPGroup* ret = NULL;
+ if ( !Inkscape::IO::file_test( full, G_FILE_TEST_IS_DIR ) ) {
+
+ /*Load the pallet file here*/
+ char block[1024];
+ FILE *f = Inkscape::IO::fopen_utf8name( full, "r" );
+ if ( f ) {
+ char* result = fgets( block, sizeof(block), f );
+ if ( result ) {
+ if ( strncmp( "GIMP Palette", block, 12 ) == 0 ) {
+ bool inHeader = true;
+ bool hasErr = false;
+
+ Inkscape::XML::Node * page = doc->getReprDoc()->createElement("svg:g");
+ gchar *id=NULL;
+ do {
+ g_free(id);
+ id = g_strdup_printf("page%d", page_suffix++);
+ } while (doc->getObjectById(id));
+
+ page->setAttribute("id", id);
+
+ do {
+ result = fgets( block, sizeof(block), f );
+ block[sizeof(block) - 1] = 0;
+ if ( result ) {
+ if ( block[0] == '#' ) {
+ // ignore comment
+ } else {
+ char *ptr = block;
+ // very simple check for header versus entry
+ while ( *ptr == ' ' || *ptr == '\t' ) {
+ ptr++;
+ }
+ if ( (*ptr == 0) || (*ptr == '\r') || (*ptr == '\n') ) {
+ // blank line. skip it.
+ } else if ( '0' <= *ptr && *ptr <= '9' ) {
+ // should be an entry link
+ inHeader = false;
+ ptr = block;
+ Glib::ustring name("");
+ skipWhitespace(ptr);
+ if ( *ptr ) {
+ int r = 0;
+ int g = 0;
+ int b = 0;
+ hasErr = parseNum(ptr, r);
+ if ( !hasErr ) {
+ skipWhitespace(ptr);
+ hasErr = parseNum(ptr, g);
+ }
+ if ( !hasErr ) {
+ skipWhitespace(ptr);
+ hasErr = parseNum(ptr, b);
+ }
+ if ( !hasErr && *ptr ) {
+ char* n = trim(ptr);
+ if (n != NULL) {
+ name = g_dpgettext2(NULL, "Palette", n);
+ }
+ }
+ if ( !hasErr ) {
+ // Add the entry now
+
+ Inkscape::XML::Node *grad = doc->getReprDoc()->createElement("svg:linearGradient");
+ grad->setAttribute("inkscape:label", name.c_str());
+ grad->setAttribute( "osb:paint", "solid", 0 );
+ SPColor color((float)r / 255, (float)g / 255, (float)b / 255);
+ addStop(grad, color.toString(), 1, "0");
+ page->appendChild(grad);
+ Inkscape::GC::release(grad);
+ }
+ } else {
+ hasErr = true;
+ }
+ } else {
+ if ( !inHeader ) {
+ // Hmmm... probably bad. Not quite the format we want?
+ hasErr = true;
+ } else {
+ char* sep = strchr(result, ':');
+ if ( sep ) {
+ *sep = 0;
+ char* val = trim(sep + 1);
+ char* name = trim(result);
+ if ( *name ) {
+ if ( strcmp( "Name", name ) == 0 )
+ {
+ page->setAttribute("inkscape:label", val);
+ }
+ } else {
+ // error
+ hasErr = true;
+ }
+ } else {
+ // error
+ hasErr = true;
+ }
+ }
+ }
}
}
+ } while ( result && !hasErr );
+ if ( !hasErr ) {
+ doc->getDefs()->appendChild(page);
+ Inkscape::GC::release(page);
+ SPObject* obj = doc->getObjectByRepr(page);
+ if (SP_IS_GROUP(obj)) {
+ ret = SP_GROUP(obj);
+ }
+ #if ENABLE_MAGIC_COLORS
+ ColorItem::_wireMagicColors( onceMore );
+ #endif // ENABLE_MAGIC_COLORS
+ } else {
+ delete page;
}
}
- sp_style_unref(query);
}
- }
- if (!shown) {
- Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- if (prefs->getBool("/dialogs/gradienteditor/showlegacy", false)) {
- // Legacy gradient dialog
- GtkWidget *dialog = sp_gradient_vector_editor_new( gr );
- gtk_widget_show( dialog );
- } else {
- // Invoke the gradient tool
- Inkscape::Verb *verb = Inkscape::Verb::get( SP_VERB_CONTEXT_GRADIENT );
- if ( verb ) {
- SPAction *action = verb->get_action( Inkscape::ActionContext( ( Inkscape::UI::View::View * ) SP_ACTIVE_DESKTOP ) );
- if ( action ) {
- sp_action_perform( action, NULL );
- }
- }
- }
+ fclose(f);
}
+ /* end loading the pallet file*/
}
+ return ret;
}
-static void editGradient( GtkMenuItem */*menuitem*/, gpointer /*user_data*/ )
+SwatchesPanel& SwatchesPanel::getInstance()
{
- if ( bounceTarget ) {
- SwatchesPanel* swp = bouncePanel;
- SPDesktop* desktop = swp ? swp->getDesktop() : 0;
- SPDocument *doc = desktop ? desktop->doc() : 0;
- if (doc) {
- std::string targetName(bounceTarget->def.descr);
- const GSList *gradients = doc->getResourceList("gradient");
- for (const GSList *item = gradients; item; item = item->next) {
- SPGradient* grad = SP_GRADIENT(item->data);
- if ( targetName == grad->getId() ) {
- editGradientImpl( desktop, grad );
- break;
+ return *new SwatchesPanel();
+}
+
+class SwatchesPanel::StopWatcher : public Inkscape::XML::NodeObserver {
+public:
+ StopWatcher(SwatchesPanel* pnl, SPStop* obj) :
+ _pnl(pnl),
+ _obj(obj),
+ _repr(obj->getRepr())
+ {
+ _repr->addObserver(*this);
+ }
+
+ ~StopWatcher() {
+ _repr->removeObserver(*this);
+ }
+
+ virtual void notifyChildAdded( Inkscape::XML::Node &/*node*/, Inkscape::XML::Node &/*child*/, Inkscape::XML::Node */*prev*/ ){}
+ virtual void notifyChildRemoved( Inkscape::XML::Node &/*node*/, Inkscape::XML::Node &/*child*/, Inkscape::XML::Node */*prev*/ ){}
+ virtual void notifyChildOrderChanged( Inkscape::XML::Node &/*node*/, Inkscape::XML::Node &/*child*/, Inkscape::XML::Node */*old_prev*/, Inkscape::XML::Node */*new_prev*/ ){}
+ virtual void notifyContentChanged( Inkscape::XML::Node &/*node*/, Util::ptr_shared<char> /*old_content*/, Util::ptr_shared<char> /*new_content*/ ) {}
+
+ virtual void notifyAttributeChanged( Inkscape::XML::Node &/*node*/, GQuark name, Util::ptr_shared<char> /*old_value*/, Util::ptr_shared<char> /*new_value*/ ) {
+ if (_pnl && _obj) {
+ _pnl->_defsChanged( );
+ }
+ }
+
+ SwatchesPanel* _pnl;
+ SPStop* _obj;
+ Inkscape::XML::Node* _repr;
+};
+
+class SwatchesPanel::GradientWatcher : public Inkscape::XML::NodeObserver {
+public:
+ GradientWatcher(SwatchesPanel* pnl, SPGradient* obj) :
+ _pnl(pnl),
+ _obj(obj),
+ _repr(obj->getRepr()),
+ _labelAttr(g_quark_from_string("inkscape:label")),
+ _swatchAttr(g_quark_from_string("osb:paint"))
+ {
+ _repr->addObserver(*this);
+ }
+
+ ~GradientWatcher() {
+ _repr->removeObserver(*this);
+ }
+
+ virtual void notifyChildAdded( Inkscape::XML::Node &/*node*/, Inkscape::XML::Node &/*child*/, Inkscape::XML::Node */*prev*/ )
+ {
+ if ( _pnl && _obj && _obj->isSwatch()) {
+ _pnl->_defsChanged( );
+ }
+ }
+ virtual void notifyChildRemoved( Inkscape::XML::Node &/*node*/, Inkscape::XML::Node &/*child*/, Inkscape::XML::Node */*prev*/ )
+ {
+ if ( _pnl && _obj && _obj->isSwatch() ) {
+ _pnl->_defsChanged( );
+ }
+ }
+ virtual void notifyChildOrderChanged( Inkscape::XML::Node &/*node*/, Inkscape::XML::Node &/*child*/, Inkscape::XML::Node */*old_prev*/, Inkscape::XML::Node */*new_prev*/ )
+ {
+ if ( _pnl && _obj && _obj->isSwatch() ) {
+ _pnl->_defsChanged( );
+ }
+ }
+ virtual void notifyContentChanged( Inkscape::XML::Node &/*node*/, Util::ptr_shared<char> /*old_content*/, Util::ptr_shared<char> /*new_content*/ ) {}
+ virtual void notifyAttributeChanged( Inkscape::XML::Node &/*node*/, GQuark name, Util::ptr_shared<char> /*old_value*/, Util::ptr_shared<char> /*new_value*/ ) {
+ if (_pnl && _obj && ((_obj->isSwatch() && name == _labelAttr) || name == _swatchAttr)) {
+ _pnl->_defsChanged( );
+ }
+ }
+
+ SwatchesPanel* _pnl;
+ SPGradient* _obj;
+ Inkscape::XML::Node* _repr;
+ GQuark _labelAttr;
+ GQuark _swatchAttr;
+};
+
+class SwatchesPanel::SwatchWatcher : public Inkscape::XML::NodeObserver {
+public:
+ SwatchWatcher(SwatchesPanel* pnl, SPObject* obj, bool builtIn) :
+ _pnl(pnl),
+ _obj(obj),
+ _builtIn(builtIn),
+ _repr(obj->getRepr()),
+ _labelAttr(g_quark_from_string("inkscape:label")),
+ _swatchAttr(g_quark_from_string("osb:paint"))
+ {
+ _repr->addObserver(*this);
+ }
+
+ ~SwatchWatcher() {
+ _repr->removeObserver(*this);
+ }
+
+ virtual void notifyChildAdded( Inkscape::XML::Node &/*node*/, Inkscape::XML::Node &child, Inkscape::XML::Node */*prev*/ )
+ {
+ if ( _pnl && _obj) {
+ SPObject *childobj = _builtIn ? SwatchDocument->getObjectByRepr(&child) : (_pnl->_currentDocument ? _pnl->_currentDocument->getObjectByRepr(&child) : 0);
+ if (childobj && ((SP_IS_GRADIENT(childobj) && SP_GRADIENT(childobj)->hasStops()) || SP_IS_GROUP(childobj))) {
+ if (_builtIn) {
+ _pnl->_swatchesChanged( );
+ } else {
+ _pnl->_defsChanged( );
}
}
}
}
-}
-
-void SwatchesPanelHook::convertGradient( GtkMenuItem * /*menuitem*/, gpointer userData )
-{
- if ( bounceTarget ) {
- SwatchesPanel* swp = bouncePanel;
- SPDesktop* desktop = swp ? swp->getDesktop() : 0;
- SPDocument *doc = desktop ? desktop->doc() : 0;
- gint index = GPOINTER_TO_INT(userData);
- if ( doc && (index >= 0) && (static_cast<guint>(index) < popupItems.size()) ) {
- Glib::ustring targetName = popupItems[index];
-
- const GSList *gradients = doc->getResourceList("gradient");
- for (const GSList *item = gradients; item; item = item->next) {
- SPGradient* grad = SP_GRADIENT(item->data);
- if ( targetName == grad->getId() ) {
- grad->setSwatch();
- DocumentUndo::done(doc, SP_VERB_CONTEXT_GRADIENT,
- _("Add gradient stop"));
- break;
+ virtual void notifyChildRemoved( Inkscape::XML::Node &/*node*/, Inkscape::XML::Node &child, Inkscape::XML::Node */*prev*/ )
+ {
+ if ( _pnl && _obj) {
+ if (_builtIn) {
+ _pnl->_swatchesChanged( );
+ } else {
+ _pnl->_defsChanged( );
+ }
+ }
+ }
+ virtual void notifyChildOrderChanged( Inkscape::XML::Node &/*node*/, Inkscape::XML::Node &child, Inkscape::XML::Node */*old_prev*/, Inkscape::XML::Node */*new_prev*/ )
+ {
+ if ( _pnl && _obj) {
+ SPObject *childobj = _builtIn ? SwatchDocument->getObjectByRepr(&child) : (_pnl->_currentDocument ? _pnl->_currentDocument->getObjectByRepr(&child) : 0);
+ if (childobj && ((SP_IS_GRADIENT(childobj) && SP_GRADIENT(childobj)->hasStops()) || SP_IS_GROUP(childobj))) {
+ if (_builtIn) {
+ _pnl->_swatchesChanged( );
+ } else {
+ _pnl->_defsChanged( );
}
}
}
}
-}
+ virtual void notifyContentChanged( Inkscape::XML::Node &/*node*/, Util::ptr_shared<char> /*old_content*/, Util::ptr_shared<char> /*new_content*/ ) {}
+ virtual void notifyAttributeChanged( Inkscape::XML::Node &/*node*/, GQuark name, Util::ptr_shared<char> /*old_value*/, Util::ptr_shared<char> /*new_value*/ ) {
+ if (_pnl && _obj && name == _labelAttr) {
+ if (_builtIn) {
+ _pnl->_swatchesChanged( );
+ } else {
+ _pnl->_defsChanged( );
+ }
+ }
+ }
-void SwatchesPanelHook::deleteGradient( GtkMenuItem */*menuitem*/, gpointer /*userData*/ )
+ SwatchesPanel* _pnl;
+ SPObject* _obj;
+ bool _builtIn;
+ Inkscape::XML::Node* _repr;
+ GQuark _labelAttr;
+ GQuark _swatchAttr;
+};
+
+class SwatchesPanel::ModelColumns : public Gtk::TreeModel::ColumnRecord
{
- if ( bounceTarget ) {
- SwatchesPanel* swp = bouncePanel;
- SPDesktop* desktop = swp ? swp->getDesktop() : 0;
- sp_gradient_unset_swatch(desktop, bounceTarget->def.descr);
+public:
+
+ ModelColumns()
+ {
+ add(_colObject);
+ add(_colLabel);
}
-}
+ virtual ~ModelColumns() {}
+
+ Gtk::TreeModelColumn<SPObject*> _colObject;
+ Gtk::TreeModelColumn<Glib::ustring> _colLabel;
+};
-static SwatchesPanel* findContainingPanel( GtkWidget *widget )
+class SwatchesPanel::ModelColumnsDoc : public Gtk::TreeModel::ColumnRecord
{
- SwatchesPanel *swp = 0;
+public:
- std::map<GtkWidget*, SwatchesPanel*> rawObjects;
- for (std::map<SwatchesPanel*, SPDocument*>::iterator it = docPerPanel.begin(); it != docPerPanel.end(); ++it) {
- rawObjects[GTK_WIDGET(it->first->gobj())] = it->first;
+ ModelColumnsDoc()
+ {
+ add(_colObject);
+ add(_colLabel);
+ add(_colPixbuf);
}
+ virtual ~ModelColumnsDoc() {}
+
+ Gtk::TreeModelColumn<SPObject*> _colObject;
+ Gtk::TreeModelColumn<Glib::ustring> _colLabel;
+ Gtk::TreeModelColumn<Glib::RefPtr<Gdk::Pixbuf> > _colPixbuf;
+};
- for (GtkWidget* curr = widget; curr && !swp; curr = gtk_widget_get_parent(curr)) {
- if (rawObjects.find(curr) != rawObjects.end()) {
- swp = rawObjects[curr];
+static void StripChildGroups(Inkscape::XML::Node * node, SPObject* addTo)
+{
+ for (Inkscape::XML::Node * it = node->firstChild(); it != NULL;) {
+ if (!strcmp(it->name(), "svg:g")) {
+ Inkscape::XML::Node * todel = it;
+ it = it->next();
+ node->removeChild(todel);
+ } else {
+ it = it->next();
}
}
-
- return swp;
+ addTo->appendChildRepr(node);
}
-static void removeit( GtkWidget *widget, gpointer data )
+static void BubbleChildGroups(Inkscape::XML::Node * node, SPObject* addTo)
{
- gtk_container_remove( GTK_CONTAINER(data), widget );
+ std::queue<Inkscape::XML::Node *> groups;
+ for (Inkscape::XML::Node * it = node->firstChild(); it != NULL; ) {
+ if (!strcmp(it->name(), "svg:g")) {
+ groups.push(it->duplicate(addTo->document->getReprDoc()));
+ Inkscape::XML::Node * todel = it;
+ it = it->next();
+ node->removeChild(todel);
+ } else {
+ it = it->next();
+ }
+ }
+ addTo->appendChildRepr(node);
+ while (!groups.empty()) {
+ Inkscape::XML::Node * it = groups.front();
+ groups.pop();
+ BubbleChildGroups(it, addTo);
+ Inkscape::GC::release(it);
+ }
}
-/* extern'ed from colot-item.cpp */
-gboolean colorItemHandleButtonPress( GtkWidget* widget, GdkEventButton* event, gpointer user_data );
+void SwatchesPanel::_addSwatchButtonClicked(SPGroup* swatch, bool recurse)
+{
+ if (_currentDocument) {
+ if (swatch && SP_IS_GROUP(swatch) ) {
+ Inkscape::XML::Node * copy = swatch->getRepr()->duplicate(_currentDocument->getReprDoc());
+ if (recurse) {
+ BubbleChildGroups(copy, _currentDocument->getDefs());
+ } else {
+ StripChildGroups(copy, _currentDocument->getDefs());
+ }
+ Inkscape::GC::release(copy);
+ DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Add swatches to document"));
+ }
+ }
+}
-gboolean colorItemHandleButtonPress( GtkWidget* widget, GdkEventButton* event, gpointer user_data )
+void SwatchesPanel::_importButtonClicked(bool addToDoc, bool addToBI)
{
- gboolean handled = FALSE;
-
- if ( event && (event->button == 3) && (event->type == GDK_BUTTON_PRESS) ) {
- SwatchesPanel* swp = findContainingPanel( widget );
-
- if ( !popupMenu ) {
- popupMenu = gtk_menu_new();
- GtkWidget* child = 0;
-
- //TRANSLATORS: An item in context menu on a colour in the swatches
- child = gtk_menu_item_new_with_label(_("Set fill"));
- g_signal_connect( G_OBJECT(child),
- "activate",
- G_CALLBACK(redirClick),
- user_data);
- gtk_menu_shell_append(GTK_MENU_SHELL(popupMenu), child);
-
- //TRANSLATORS: An item in context menu on a colour in the swatches
- child = gtk_menu_item_new_with_label(_("Set stroke"));
-
- g_signal_connect( G_OBJECT(child),
- "activate",
- G_CALLBACK(redirSecondaryClick),
- user_data);
- gtk_menu_shell_append(GTK_MENU_SHELL(popupMenu), 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(_("Delete"));
- g_signal_connect( G_OBJECT(child),
- "activate",
- G_CALLBACK(SwatchesPanelHook::deleteGradient),
- user_data );
- 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 );
+ if (addToDoc || addToBI) {
+ //# Get the current directory for finding files
+ static Glib::ustring open_path;
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+
+ if(open_path.empty())
+ {
+ Glib::ustring attr = prefs->getString("/dialogs/open/path");
+ if (!attr.empty()) open_path = attr;
+ }
+
+ //# Test if the open_path directory exists
+ if (!Inkscape::IO::file_test(open_path.c_str(),
+ (GFileTest)(G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)))
+ open_path = "";
+
+ #ifdef WIN32
+ //# If no open path, default to our win32 documents folder
+ if (open_path.empty())
+ {
+ // The path to the My Documents folder is read from the
+ // value "HKEY_CURRENT_USER\Software\Windows\CurrentVersion\Explorer\Shell Folders\Personal"
+ HKEY key = NULL;
+ if(RegOpenKeyExA(HKEY_CURRENT_USER,
+ "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders",
+ 0, KEY_QUERY_VALUE, &key) == ERROR_SUCCESS)
{
- popupSubHolder = child;
- popupSub = gtk_menu_new();
- gtk_menu_item_set_submenu( GTK_MENU_ITEM(child), popupSub );
+ WCHAR utf16path[_MAX_PATH];
+ DWORD value_type;
+ DWORD data_size = sizeof(utf16path);
+ if(RegQueryValueExW(key, L"Personal", NULL, &value_type,
+ (BYTE*)utf16path, &data_size) == ERROR_SUCCESS)
+ {
+ g_assert(value_type == REG_SZ);
+ gchar *utf8path = g_utf16_to_utf8(
+ (const gunichar2*)utf16path, -1, NULL, NULL, NULL);
+ if(utf8path)
+ {
+ open_path = Glib::ustring(utf8path);
+ g_free(utf8path);
+ }
+ }
}
+ }
+ #endif
- gtk_widget_show_all(popupMenu);
+ //# If no open path, default to our home directory
+ if (open_path.empty())
+ {
+ open_path = g_get_home_dir();
+ open_path.append(G_DIR_SEPARATOR_S);
}
- if ( user_data ) {
- ColorItem* item = reinterpret_cast<ColorItem*>(user_data);
- bool show = swp && (swp->getSelectedIndex() == 0);
- for ( std::vector<GtkWidget*>::iterator it = popupExtras.begin(); it != popupExtras.end(); ++ it) {
- gtk_widget_set_sensitive(*it, show);
- }
+ Gtk::Window * parent = SP_ACTIVE_DESKTOP->getToplevel();
+ //# Create a dialog
+ Inkscape::UI::Dialog::FileOpenDialog *openDialogInstance =
+ Inkscape::UI::Dialog::FileOpenDialog::create(
+ *parent, open_path,
+ Inkscape::UI::Dialog::SWATCH_TYPES,
+ _("Select file to open"));
- bounceTarget = item;
- bouncePanel = swp;
- popupItems.clear();
- if ( popupMenu ) {
- gtk_container_foreach(GTK_CONTAINER(popupSub), removeit, popupSub);
- bool processed = false;
- GtkWidget *wdgt = gtk_widget_get_ancestor(widget, SP_TYPE_DESKTOP_WIDGET);
- if ( wdgt ) {
- SPDesktopWidget *dtw = SP_DESKTOP_WIDGET(wdgt);
- if ( dtw && dtw->desktop ) {
- // Pick up all gradients with vectors
- const GSList *gradients = (dtw->desktop->doc())->getResourceList("gradient");
- gint index = 0;
- for (const GSList *curr = gradients; curr; curr = curr->next) {
- SPGradient* grad = SP_GRADIENT(curr->data);
- if ( grad->hasStops() && !grad->isSwatch() ) {
- //gl = g_slist_prepend(gl, curr->data);
- processed = true;
- GtkWidget *child = gtk_menu_item_new_with_label(grad->getId());
- gtk_menu_shell_append(GTK_MENU_SHELL(popupSub), child);
-
- popupItems.push_back(grad->getId());
- g_signal_connect( G_OBJECT(child),
- "activate",
- G_CALLBACK(SwatchesPanelHook::convertGradient),
- GINT_TO_POINTER(index) );
- index++;
- }
- }
+ //# Show the dialog
+ bool const success = openDialogInstance->show();
- gtk_widget_show_all(popupSub);
- }
- }
- gtk_widget_set_sensitive( popupSubHolder, processed );
+ //# Save the folder the user selected for later
+ open_path = openDialogInstance->getCurrentDirectory();
- gtk_menu_popup(GTK_MENU(popupMenu), NULL, NULL, NULL, NULL, event->button, event->time);
- handled = TRUE;
- }
+ if (!success)
+ {
+ delete openDialogInstance;
+ return;
}
- }
- return handled;
-}
+ //# User selected something. Get name and type
+ Glib::ustring fileName = openDialogInstance->getFilename();
+ //# We no longer need the file dialog object - delete it
+ delete openDialogInstance;
+ openDialogInstance = NULL;
-static char* trim( char* str ) {
- char* ret = str;
- while ( *str && (*str == ' ' || *str == '\t') ) {
- str++;
- }
- ret = str;
- while ( *str ) {
- str++;
- }
- str--;
- while ( str > ret && (( *str == ' ' || *str == '\t' ) || *str == '\r' || *str == '\n') ) {
- *str-- = 0;
- }
- return ret;
-}
-static void skipWhitespace( char*& str ) {
- while ( *str == ' ' || *str == '\t' ) {
- str++;
- }
-}
+ if (!fileName.empty())
+ {
+ Glib::ustring newFileName = Glib::filename_to_utf8(fileName);
+
+ if ( newFileName.size() > 0)
+ fileName = newFileName;
+ else
+ g_warning( "ERROR CONVERTING OPEN FILENAME TO UTF-8" );
+
+ open_path = Glib::path_get_dirname (fileName);
+ open_path.append(G_DIR_SEPARATOR_S);
+ prefs->setString("/dialogs/open/path", open_path);
+
+ SPDocument* importdoc = SPDocument::createNewDoc(fileName.c_str(), true);
+ Inkscape::XML::Node * page = NULL;
+ if (importdoc && importdoc->getDefs()) {
+ if (addToBI) {
+ page = SwatchDocument->getReprDoc()->createElement("svg:g");
+ gchar *id=NULL;
+ do {
+ g_free(id);
+ id = g_strdup_printf("page%d", page_suffix++);
+ } while (SwatchDocument->getObjectById(id));
+
+ page->setAttribute("id", id);
+ gchar* name = g_path_get_basename(importdoc->getName());
+ page->setAttribute("inkscape:label", name);
+ g_free(name);
+ }
-static bool parseNum( char*& str, int& val ) {
- val = 0;
- while ( '0' <= *str && *str <= '9' ) {
- val = val * 10 + (*str - '0');
- str++;
+ for (SPObject* it = importdoc->getDefs()->firstChild(); it != NULL; it = it->next) {
+ if (SP_IS_GROUP(it)) {
+ if (page) {
+ Inkscape::XML::Node * copy = it->getRepr()->duplicate(SwatchDocument->getReprDoc());
+ page->appendChild(copy);
+ }
+ if (addToDoc) {
+ _addSwatchButtonClicked(SP_GROUP(it), false);
+ }
+ }
+ }
+ if (page) {
+ SwatchDocument->getDefs()->appendChildRepr(page);
+ sp_repr_save_file(SwatchDocument->getReprDoc(), SwatchFile, SP_SVG_NS_URI);
+ }
+
+ importdoc->doUnref();
+ } else {
+ SPGroup* g = importGPL(addToBI ? SwatchDocument : _currentDocument, fileName.c_str());
+ if (addToBI) {
+ if (addToDoc) {
+ _addSwatchButtonClicked(g, false);
+ }
+ sp_repr_save_file(SwatchDocument->getReprDoc(), SwatchFile, SP_SVG_NS_URI);
+ } else {
+ DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Add swatches to document"));
+ }
+ }
+ }
}
- bool retval = !(*str == 0 || *str == ' ' || *str == '\t' || *str == '\r' || *str == '\n');
- return retval;
}
-
-void _loadPaletteFile( gchar const *filename, gboolean user/*=FALSE*/ )
+void SwatchesPanel::SetSelectedFill(SPGradient* swatch)
{
- char block[1024];
- FILE *f = Inkscape::IO::fopen_utf8name( filename, "r" );
- if ( f ) {
- char* result = fgets( block, sizeof(block), f );
- if ( result ) {
- if ( strncmp( "GIMP Palette", block, 12 ) == 0 ) {
- bool inHeader = true;
- bool hasErr = false;
-
- SwatchPage *onceMore = new SwatchPage();
-
- do {
- result = fgets( block, sizeof(block), f );
- block[sizeof(block) - 1] = 0;
- if ( result ) {
- if ( block[0] == '#' ) {
- // ignore comment
- } else {
- char *ptr = block;
- // very simple check for header versus entry
- while ( *ptr == ' ' || *ptr == '\t' ) {
- ptr++;
+ if (_currentDesktop && _currentDocument) {
+ SPItem* it = _currentDesktop->selection->singleItem();
+ if (it) {
+ if (it->style->fill.isSet()) {
+ if (it->style->fill.isPaintserver()) {
+ SPPaintServer * server = it->style->getFillPaintServer();
+ if (SP_IS_GRADIENT(server)) {
+ SPGradient *grad = SP_GRADIENT(server)->getVector();
+ Inkscape::XML::Node * repr = grad->getRepr();
+ Inkscape::XML::Node * drepr = swatch->getRepr();
+ if (repr != drepr && grad != swatch) {
+ while (SPStop* olds = swatch->getFirstStop()) {
+ olds->deleteObject();
}
- if ( (*ptr == 0) || (*ptr == '\r') || (*ptr == '\n') ) {
- // blank line. skip it.
- } else if ( '0' <= *ptr && *ptr <= '9' ) {
- // should be an entry link
- inHeader = false;
- ptr = block;
- Glib::ustring name("");
- skipWhitespace(ptr);
- if ( *ptr ) {
- int r = 0;
- int g = 0;
- int b = 0;
- hasErr = parseNum(ptr, r);
- if ( !hasErr ) {
- skipWhitespace(ptr);
- hasErr = parseNum(ptr, g);
- }
- if ( !hasErr ) {
- skipWhitespace(ptr);
- hasErr = parseNum(ptr, b);
- }
- if ( !hasErr && *ptr ) {
- char* n = trim(ptr);
- if (n != NULL) {
- name = g_dpgettext2(NULL, "Palette", n);
- }
- }
- if ( !hasErr ) {
- // Add the entry now
- Glib::ustring nameStr(name);
- ColorItem* item = new ColorItem( r, g, b, nameStr );
- onceMore->_colors.push_back(item);
- }
- } else {
- hasErr = true;
- }
- } else {
- if ( !inHeader ) {
- // Hmmm... probably bad. Not quite the format we want?
- hasErr = true;
- } else {
- char* sep = strchr(result, ':');
- if ( sep ) {
- *sep = 0;
- char* val = trim(sep + 1);
- char* name = trim(result);
- if ( *name ) {
- if ( strcmp( "Name", name ) == 0 )
- {
- onceMore->_name = val;
- }
- else if ( strcmp( "Columns", name ) == 0 )
- {
- gchar* endPtr = 0;
- guint64 numVal = g_ascii_strtoull( val, &endPtr, 10 );
- if ( (numVal == G_MAXUINT64) && (ERANGE == errno) ) {
- // overflow
- } else if ( (numVal == 0) && (endPtr == val) ) {
- // failed conversion
- } else {
- onceMore->_prefWidth = numVal;
- }
- }
- } else {
- // error
- hasErr = true;
- }
- } else {
- // error
- hasErr = true;
- }
- }
+ for (SPStop* news = grad->getVector()->getFirstStop(); news != NULL; news = news->getNextStop()) {
+ Inkscape::XML::Node* clone = news->getRepr()->duplicate(_currentDocument->getReprDoc());
+ swatch->appendChildRepr(clone);
+ Inkscape::GC::release(clone);
+ }
+ swatch->setSwatch();
+ if (!_noLink.get_active()) {
+ sp_item_set_gradient(it, sp_gradient_ensure_vector_normalized(swatch), SP_IS_RADIALGRADIENT(swatch) ? SP_GRADIENT_TYPE_RADIAL : SP_GRADIENT_TYPE_LINEAR, Inkscape::FOR_FILL);
}
+ DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Set Gradient Swatch"));
}
}
- } while ( result && !hasErr );
- if ( !hasErr ) {
- if (user)
- userSwatchPages.push_back(onceMore);
- else
- systemSwatchPages.push_back(onceMore);
-#if ENABLE_MAGIC_COLORS
- ColorItem::_wireMagicColors( onceMore );
-#endif // ENABLE_MAGIC_COLORS
- } else {
- delete onceMore;
+ } else if (it->style->fill.isColor()) {
+ while (SPStop* olds = swatch->getFirstStop()) {
+ olds->deleteObject();
+ }
+ addStop(swatch->getRepr(), it->style->fill.value.color.toString(), SP_SCALE24_TO_FLOAT(it->style->fill_opacity.value), "0");
+ swatch->setSwatch();
+ if (!_noLink.get_active()) {
+ SPGradient* normalized = sp_gradient_ensure_vector_normalized(swatch);
+ sp_item_set_gradient(it, normalized, SP_GRADIENT_TYPE_LINEAR, Inkscape::FOR_FILL);
+ }
+ DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Set Color Swatch"));
}
}
}
-
- fclose(f);
}
}
-static bool
-compare_swatch_names(SwatchPage const *a, SwatchPage const *b) {
-
- return g_utf8_collate(a->_name.c_str(), b->_name.c_str()) < 0;
-}
-
-static void loadEmUp()
+void SwatchesPanel::SetSelectedStroke(SPGradient* swatch)
{
- static bool beenHere = false;
- gboolean userPalete = true;
- if ( !beenHere ) {
- beenHere = true;
-
- std::list<gchar *> sources;
- sources.push_back( profile_path("palettes") );
- sources.push_back( g_strdup(INKSCAPE_PALETTESDIR) );
- sources.push_back( g_strdup(CREATE_PALETTESDIR) );
-
- // Use this loop to iterate through a list of possible document locations.
- while (!sources.empty()) {
- gchar *dirname = sources.front();
- if ( Inkscape::IO::file_test( dirname, G_FILE_TEST_EXISTS )
- && Inkscape::IO::file_test( dirname, G_FILE_TEST_IS_DIR )) {
- GError *err = 0;
- GDir *directory = g_dir_open(dirname, 0, &err);
- if (!directory) {
- gchar *safeDir = Inkscape::IO::sanitizeString(dirname);
- g_warning(_("Palettes directory (%s) is unavailable."), safeDir);
- g_free(safeDir);
- } else {
- gchar *filename = 0;
- while ((filename = (gchar *)g_dir_read_name(directory)) != NULL) {
- gchar* lower = g_ascii_strdown( filename, -1 );
-// if ( g_str_has_suffix(lower, ".gpl") ) {
- if ( !g_str_has_suffix(lower, "~") ) {
- gchar* full = g_build_filename(dirname, filename, NULL);
- if ( !Inkscape::IO::file_test( full, G_FILE_TEST_IS_DIR ) ) {
- _loadPaletteFile(full, userPalete);
+ if (_currentDesktop && _currentDocument) {
+ SPItem* it = _currentDesktop->selection->singleItem();
+ if (it) {
+ if (it->style->stroke.isSet()) {
+ if (it->style->stroke.isPaintserver()) {
+ SPPaintServer * server = it->style->getStrokePaintServer();
+ if (SP_IS_GRADIENT(server)) {
+ SPGradient *grad = SP_GRADIENT(server)->getVector();
+ Inkscape::XML::Node * repr = grad->getRepr();
+ Inkscape::XML::Node * drepr = swatch->getRepr();
+ if (repr != drepr && grad != swatch) {
+ while (SPStop* olds = swatch->getFirstStop()) {
+ olds->deleteObject();
+ }
+ for (SPStop* news = grad->getVector()->getFirstStop(); news != NULL; news = news->getNextStop()) {
+ Inkscape::XML::Node* clone = news->getRepr()->duplicate(_currentDocument->getReprDoc());
+ swatch->appendChildRepr(clone);
+ Inkscape::GC::release(clone);
+ }
+ swatch->setSwatch();
+ if (!_noLink.get_active()) {
+ sp_item_set_gradient(it, sp_gradient_ensure_vector_normalized(swatch), SP_IS_RADIALGRADIENT(swatch) ? SP_GRADIENT_TYPE_RADIAL : SP_GRADIENT_TYPE_LINEAR, Inkscape::FOR_STROKE);
}
- g_free(full);
- }
-// }
- g_free(lower);
+ DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Set Gradient Swatch"));
+ }
+ }
+ } else if (it->style->stroke.isColor()) {
+ while (SPStop* olds = swatch->getFirstStop()) {
+ olds->deleteObject();
}
- g_dir_close(directory);
+ addStop(swatch->getRepr(), it->style->stroke.value.color.toString(), SP_SCALE24_TO_FLOAT(it->style->stroke_opacity.value), "0");
+ swatch->setSwatch();
+ if (!_noLink.get_active()) {
+ SPGradient* normalized = sp_gradient_ensure_vector_normalized(swatch);
+ sp_item_set_gradient(it, normalized, SP_GRADIENT_TYPE_LINEAR, Inkscape::FOR_STROKE);
+ }
+ DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Set Color Swatch"));
}
}
-
- // toss the dirname
- g_free(dirname);
- sources.pop_front();
- userPalete = false;
}
}
-
- // Sort the list of swatches by name, grouped by user/system
- userSwatchPages.sort(compare_swatch_names);
- systemSwatchPages.sort(compare_swatch_names);
-
}
+void SwatchesPanel::MoveSwatchDown(SPGradient* swatch)
+{
+ if (_currentDocument && swatch) {
+ SPObject* next = swatch->next;
+ while (next && (!SP_IS_GRADIENT(next) || !(SP_GRADIENT(next)->isSwatch()))) {
+ next = next->next;
+ }
+ if (next) {
+ Inkscape::XML::Node* repr = swatch->getRepr();
+ repr->parent()->changeOrder(repr, next->getRepr());
+ DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Move Swatch Right"));
+ }
+ }
+}
-
-SwatchesPanel& SwatchesPanel::getInstance()
+void SwatchesPanel::MoveSwatchUp(SPGradient* swatch)
{
- return *new SwatchesPanel();
+ if (_currentDocument && swatch) {
+ SPObject* g = NULL;
+ SPObject* next = swatch->parent->firstChild();
+ while (next && next != swatch) {
+ if (SP_IS_GRADIENT(next) && SP_GRADIENT(next)->isSwatch()) {
+ g = next;
+ }
+ next = next->next;
+ }
+ if (g) {
+ g = g->getPrev();
+ Inkscape::XML::Node* repr = swatch->getRepr();
+ repr->parent()->changeOrder(repr, g ? g->getRepr() : NULL);
+ DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Move Swatch Left"));
+ }
+ }
}
+void SwatchesPanel::RemoveSwatch(SPGradient* swatch)
+{
+ if (_currentDocument) {
+ if (swatch->isReferenced()) {
+ Inkscape::XML::Node * repr = swatch->getRepr();
+ repr->parent()->removeChild(repr);
+ _currentDocument->getDefs()->getRepr()->appendChild(repr);
+ SP_GRADIENT(_currentDocument->getObjectByRepr(repr))->setSwatch(false);
+ } else {
+ swatch->deleteObject(false);
+ }
+ }
+}
-/**
- * Constructor
- */
-SwatchesPanel::SwatchesPanel(gchar const* prefsPath) :
- Inkscape::UI::Widget::Panel("", prefsPath, SP_VERB_DIALOG_SWATCHES, "", true),
- _holder(0),
- _clear(0),
- _remove(0),
- _currentIndex(0),
- _currentDesktop(0),
- _currentDocument(0)
+void SwatchesPanel::_setSelectionSwatch(SPGradient* swatch, bool isStroke)
{
- Gtk::RadioMenuItem* hotItem = 0;
- _holder = new PreviewHolder();
- _clear = new ColorItem( ege::PaintDef::CLEAR );
- _remove = new ColorItem( ege::PaintDef::NONE );
- if (docPalettes.empty()) {
- SwatchPage *docPalette = new SwatchPage();
-
- docPalette->_name = "Auto";
- docPalettes[0] = docPalette;
- }
-
- loadEmUp();
- if ( !systemSwatchPages.empty() ) {
- SwatchPage* first = 0;
- int index = 0;
- Glib::ustring targetName;
- if ( !_prefs_path.empty() ) {
- Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- targetName = prefs->getString(_prefs_path + "/palette");
- if (!targetName.empty()) {
- if (targetName == "Auto") {
- first = docPalettes[0];
+ if (_currentDocument) {
+ if (swatch) {
+ if (_noLink.get_active()) {
+ if (swatch->isSolid()) {
+ ColorRGBA rgba(swatch->getFirstStop()->getEffectiveColor().toRGBA32(swatch->getFirstStop()->opacity));
+ sp_desktop_set_color(_currentDesktop, rgba, false, !isStroke);
} else {
- //index++;
- std::vector<SwatchPage*> pages = _getSwatchSets();
- for ( std::vector<SwatchPage*>::iterator iter = pages.begin(); iter != pages.end(); ++iter ) {
- if ( (*iter)->_name == targetName ) {
- first = *iter;
- break;
- }
- index++;
- }
+ SPCSSAttr *css = sp_repr_css_attr_new();
+ sp_repr_css_set_property(css, isStroke ? "stroke-opacity" : "fill-opacity", "1.0");
+
+ Inkscape::XML::Node * clone = swatch->getRepr()->duplicate(_currentDocument->getReprDoc());
+ _currentDocument->getDefs()->appendChildRepr(clone);
+ SPGradient* grad = SP_GRADIENT(_currentDocument->getObjectByRepr(clone));
+ Inkscape::GC::release(clone);
+ grad->setSwatch(false);
+ SPGradient* normalized = sp_gradient_ensure_vector_normalized(grad);
+// for (GSList const * it = _currentDesktop->selection->itemList(); it != NULL; it = it->next) {
+// sp_desktop_apply_css_recursive(SP_ITEM(it->data), css, true);
+// sp_item_set_gradient(SP_ITEM(it->data), normalized, SP_IS_RADIALGRADIENT(normalized) ? SP_GRADIENT_TYPE_RADIAL : SP_GRADIENT_TYPE_LINEAR, isStroke ? Inkscape::FOR_STROKE : Inkscape::FOR_FILL);
+// }
+ sp_desktop_set_style(_currentDesktop, css);
+ sp_desktop_set_gradient(_currentDesktop, normalized, !isStroke);
+ sp_repr_css_attr_unref (css);
}
+ } else {
+ SPCSSAttr *css = sp_repr_css_attr_new();
+ sp_repr_css_set_property(css, isStroke ? "stroke-opacity" : "fill-opacity", "1.0");
+
+ SPGradient* normalized = sp_gradient_ensure_vector_normalized(swatch);
+// for (GSList const * it = _currentDesktop->selection->itemList(); it != NULL; it = it->next) {
+// sp_desktop_apply_css_recursive(SP_ITEM(it->data), css, true);
+// sp_item_set_gradient(SP_ITEM(it->data), normalized, SP_IS_RADIALGRADIENT(normalized) ? SP_GRADIENT_TYPE_RADIAL : SP_GRADIENT_TYPE_LINEAR, isStroke ? Inkscape::FOR_STROKE : Inkscape::FOR_FILL);
+// }
+ sp_desktop_set_style(_currentDesktop, css);
+ sp_desktop_set_gradient(_currentDesktop, normalized, !isStroke);
+ sp_repr_css_attr_unref (css);
}
+ } else {
+ SPCSSAttr *css = sp_repr_css_attr_new ();
+ sp_repr_css_set_property (css, isStroke ? "stroke" : "fill", "none");
+ sp_desktop_set_style(_currentDesktop, css);
}
-
- if ( !first ) {
- first = docPalettes[0];
- _currentIndex = 0;
+ if (isStroke) {
+ DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Set item stroke swatch"));
} else {
- _currentIndex = index;
+ DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Set item fill swatch"));
}
+ }
+}
- _rebuild();
-
- Gtk::RadioMenuItem::Group groupOne;
-
- int i = 0;
- std::vector<SwatchPage*> swatchSets = _getSwatchSets();
- for ( std::vector<SwatchPage*>::iterator it = swatchSets.begin(); it != swatchSets.end(); ++it) {
- SwatchPage* curr = *it;
- Gtk::RadioMenuItem* single = manage(new Gtk::RadioMenuItem(groupOne, curr->_name));
- if ( curr == first ) {
- hotItem = single;
+void SwatchesPanel::_swatchClicked(GdkEventButton* event, SPGradient* swatch)
+{
+ if (_currentDesktop) {
+ if (event->button == 3) {
+ Gtk::Menu * menu = Gtk::manage(new Gtk::Menu());
+
+ Gtk::MenuItem* mi;
+
+ Glib::ustring us = Glib::ustring::compose("<b>%1</b>", swatch ? (swatch->label() ? swatch->label() : swatch->getId()) : _("[None]"));
+ mi = Gtk::manage(new Gtk::MenuItem(swatch ? (swatch->label() ? swatch->label() : swatch->getId()) : _("[None]")));
+ Gtk::Label* namelbl = dynamic_cast<Gtk::Label*>(mi->get_child());
+ if (namelbl) {
+ namelbl->set_markup(us);
+ }
+ mi->show();
+ mi->set_sensitive(false);
+ menu->append(*mi);
+
+ Gtk::SeparatorMenuItem* sep;
+ sep = manage(new Gtk::SeparatorMenuItem());
+ sep->show();
+ menu->append(*sep);
+
+ mi = Gtk::manage(new Gtk::MenuItem(_("Set Fill")));
+ mi->signal_activate().connect_notify(sigc::bind<SPGradient*, bool>(sigc::mem_fun(*this, &SwatchesPanel::_setSelectionSwatch), swatch, false));
+ mi->show();
+ mi->set_sensitive(_currentDesktop && !_currentDesktop->selection->isEmpty());
+ menu->append(*mi);
+
+ mi = Gtk::manage(new Gtk::MenuItem(_("Set Stroke")));
+ mi->signal_activate().connect_notify(sigc::bind<SPGradient*, bool>(sigc::mem_fun(*this, &SwatchesPanel::_setSelectionSwatch), swatch, true));
+ mi->show();
+ mi->set_sensitive(_currentDesktop && !_currentDesktop->selection->isEmpty());
+ menu->append(*mi);
+
+ if (swatch) {
+ sep = manage(new Gtk::SeparatorMenuItem());
+ sep->show();
+ menu->append(*sep);
+
+ mi = Gtk::manage(new Gtk::MenuItem(_("Set to Selected Fill")));
+ mi->signal_activate().connect_notify(sigc::bind<SPGradient*>(sigc::mem_fun(*this, &SwatchesPanel::SetSelectedFill), swatch));
+ mi->show();
+ mi->set_sensitive(_currentDesktop && _currentDesktop->selection->singleItem());
+ menu->append(*mi);
+
+ mi = Gtk::manage(new Gtk::MenuItem(_("Set to Selected Stroke")));
+ mi->signal_activate().connect_notify(sigc::bind<SPGradient*>(sigc::mem_fun(*this, &SwatchesPanel::SetSelectedStroke), swatch));
+ mi->show();
+ mi->set_sensitive(_currentDesktop && _currentDesktop->selection->singleItem());
+ menu->append(*mi);
+
+
+ sep = manage(new Gtk::SeparatorMenuItem());
+ sep->show();
+ menu->append(*sep);
+
+ mi = Gtk::manage(new Gtk::MenuItem(_("Move Left")));
+ mi->signal_activate().connect_notify(sigc::bind<SPGradient*>(sigc::mem_fun(*this, &SwatchesPanel::MoveSwatchUp), swatch));
+ mi->show();
+ menu->append(*mi);
+
+ mi = Gtk::manage(new Gtk::MenuItem(_("Move Right")));
+ mi->signal_activate().connect_notify(sigc::bind<SPGradient*>(sigc::mem_fun(*this, &SwatchesPanel::MoveSwatchDown), swatch));
+ mi->show();
+ menu->append(*mi);
+
+ sep = manage(new Gtk::SeparatorMenuItem());
+ sep->show();
+ menu->append(*sep);
+
+ mi = Gtk::manage(new Gtk::MenuItem(_("Remove")));
+ mi->signal_activate().connect_notify(sigc::bind<SPGradient*>(sigc::mem_fun(*this, &SwatchesPanel::RemoveSwatch), swatch));
+ mi->show();
+ menu->append(*mi);
}
- _regItem( single, 3, i );
- i++;
+ menu->popup(event->button, event->time);
+ } else if (!_currentDesktop->selection->isEmpty()) {
+ _setSelectionSwatch(swatch, event->state & GDK_SHIFT_MASK);
}
}
+}
- if (Glib::ustring(prefsPath) == "/dialogs/swatches") {
- Gtk::Requisition sreq;
-#if WITH_GTKMM_3_0
- Gtk::Requisition sreq_natural;
- get_preferred_size(sreq_natural, sreq);
-#else
- sreq = size_request();
-#endif
- int minHeight = 60;
- if (sreq.height < minHeight) {
- set_size_request(70, minHeight);
+void SwatchesPanel::MoveDown(SPGroup* page)
+{
+ if (_currentDocument && page) {
+ SPObject* next = page->next;
+ while (next && !SP_IS_GROUP(next)) {
+ next = next->next;
+ }
+ if (next) {
+ Inkscape::XML::Node* repr = page->getRepr();
+ repr->parent()->changeOrder(repr, next->getRepr());
+ DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Move Swatch Down"));
}
}
+}
- _getContents()->pack_start(*_holder, Gtk::PACK_EXPAND_WIDGET);
- _setTargetFillable(_holder);
-
- show_all_children();
-
- restorePanelPrefs();
- if ( hotItem ) {
- hotItem->set_active();
+void SwatchesPanel::MoveUp(SPGroup* page)
+{
+ if (_currentDocument && page) {
+ SPObject* g = NULL;
+ SPObject* next = page->parent->firstChild();
+ while (next && next != page) {
+ if (SP_IS_GROUP(next)) {
+ g = next;
+ }
+ next = next->next;
+ }
+ if (g) {
+ g = g->getPrev();
+ Inkscape::XML::Node* repr = page->getRepr();
+ repr->parent()->changeOrder(repr, g ? g->getRepr() : NULL);
+ DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Move Swatch Up"));
+ }
}
}
-SwatchesPanel::~SwatchesPanel()
+void SwatchesPanel::Remove(SPGroup* page)
{
- _trackDocument( this, 0 );
+ if (_currentDocument && page) {
+ std::vector<Inkscape::XML::Node*> toMove;
+ for(SPObject* obj = page->firstChild(); obj != NULL; obj = obj->next) {
+ if (SP_IS_GRADIENT(obj)) {
+ SPGradient* grad = SP_GRADIENT(obj);
+ if (grad->isReferenced()) {
+ toMove.push_back(grad->getRepr());
+ }
+ }
+ }
+ while (!toMove.empty()) {
+ Inkscape::XML::Node * repr = toMove.back();
+ toMove.pop_back();
+ repr->parent()->removeChild(repr);
+ _currentDocument->getDefs()->getRepr()->appendChild(repr);
+ SP_GRADIENT(_currentDocument->getObjectByRepr(repr))->setSwatch(false);
+ }
+ page->deleteObject(false);
+ DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Remove Swatch Group"));
+ }
+}
- _documentConnection.disconnect();
- _selChanged.disconnect();
+void SwatchesPanel::AddSelectedFill(SPGroup* page)
+{
+ if (_currentDesktop && _currentDocument) {
+ SPItem* it = _currentDesktop->selection->singleItem();
+ if (it) {
+ if (it->style->fill.isSet()) {
+ if (it->style->fill.isPaintserver()) {
+ SPPaintServer * server = it->style->getFillPaintServer();
+ if (SP_IS_GRADIENT(server)) {
+ SPGradient *grad = SP_GRADIENT(server)->getVector();
+ if (_noLink.get_active()) {
+ Inkscape::XML::Node * clone = grad->getRepr()->duplicate(_currentDocument->getReprDoc());
+ clone->setAttribute( "osb:paint", "gradient", 0 );
+ if (page) {
+ page->appendChildRepr(clone);
+ } else {
+ _currentDocument->getDefs()->appendChildRepr(clone);
+ }
+ Inkscape::GC::release(clone);
+ DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Add Gradient Swatch"));
+ } else if (grad->isSwatch()) {
+ Inkscape::XML::Node * repr = grad->getRepr();
+ Inkscape::XML::Node * clone = repr->duplicate(_currentDocument->getReprDoc());
+ if (page) {
+ page->appendChildRepr(clone);
+ } else {
+ _currentDocument->getDefs()->appendChildRepr(clone);
+ }
+ SPGradient *newgrad = SP_GRADIENT(_currentDocument->getObjectByRepr(clone));
+
+ sp_item_set_gradient(it, sp_gradient_ensure_vector_normalized(newgrad), SP_IS_RADIALGRADIENT(newgrad) ? SP_GRADIENT_TYPE_RADIAL : SP_GRADIENT_TYPE_LINEAR, Inkscape::FOR_FILL);
+ Inkscape::GC::release(clone);
+ DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Add Gradient Swatch"));
+ } else {
+ Inkscape::XML::Node * repr = grad->getRepr();
+ Inkscape::XML::Node * drepr = page ? page->getRepr() : _currentDocument->getDefs()->getRepr();
+ if (repr->parent() != drepr) {
+ repr->parent()->removeChild(repr);
+ drepr->appendChild(repr);
+ }
+ SP_GRADIENT(_currentDocument->getObjectByRepr(repr))->setSwatch();
+ DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Add Gradient Swatch"));
+ }
+ }
+ } else if (it->style->fill.isColor()) {
+ Inkscape::XML::Node *grad = _currentDocument->getReprDoc()->createElement("svg:linearGradient");
+ grad->setAttribute( "osb:paint", "solid", 0 );
+ addStop(grad, it->style->fill.value.color.toString(), SP_SCALE24_TO_FLOAT(it->style->fill_opacity.value), "0");
+ if (page) {
+ page->appendChild(grad);
+ } else {
+ _currentDocument->getDefs()->appendChild(grad);
+ }
+ SPGradient* normalized = sp_gradient_ensure_vector_normalized(SP_GRADIENT(_currentDocument->getObjectByRepr(grad)));
+ Inkscape::GC::release(grad);
+ if (!_noLink.get_active()) {
+ sp_item_set_gradient(it, normalized, SP_GRADIENT_TYPE_LINEAR, Inkscape::FOR_FILL);
+ }
+ DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Add Color Swatch"));
+ }
+ }
+ }
+ }
+}
- if ( _clear ) {
- delete _clear;
+void SwatchesPanel::AddSelectedStroke(SPGroup* page)
+{
+ if (_currentDesktop && _currentDocument) {
+ SPItem* it = _currentDesktop->selection->singleItem();
+ if (it) {
+ if (it->style->stroke.isSet()) {
+ if (it->style->stroke.isPaintserver()) {
+ SPPaintServer * server = it->style->getStrokePaintServer();
+ if (SP_IS_GRADIENT(server)) {
+ SPGradient *grad = SP_GRADIENT(server)->getVector();
+ if (_noLink.get_active()) {
+ Inkscape::XML::Node * clone = grad->getRepr()->duplicate(_currentDocument->getReprDoc());
+ clone->setAttribute( "osb:paint", "gradient", 0 );
+ if (page) {
+ page->appendChildRepr(clone);
+ } else {
+ _currentDocument->getDefs()->appendChildRepr(clone);
+ }
+ Inkscape::GC::release(clone);
+ DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Add Gradient Swatch"));
+ } else if (grad->isSwatch()) {
+ Inkscape::XML::Node * repr = grad->getRepr();
+ Inkscape::XML::Node * clone = repr->duplicate(_currentDocument->getReprDoc());
+ if (page) {
+ page->appendChildRepr(clone);
+ } else {
+ _currentDocument->getDefs()->appendChildRepr(clone);
+ }
+ SPGradient *newgrad = SP_GRADIENT(_currentDocument->getObjectByRepr(clone));
+
+ sp_item_set_gradient(it, sp_gradient_ensure_vector_normalized(newgrad), SP_IS_RADIALGRADIENT(newgrad) ? SP_GRADIENT_TYPE_RADIAL : SP_GRADIENT_TYPE_LINEAR, Inkscape::FOR_STROKE);
+ Inkscape::GC::release(clone);
+ DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Add Gradient Swatch"));
+ } else {
+ Inkscape::XML::Node * repr = grad->getRepr();
+ Inkscape::XML::Node * drepr = page ? page->getRepr() : _currentDocument->getDefs()->getRepr();
+ if (repr->parent() != drepr) {
+ repr->parent()->removeChild(repr);
+ drepr->appendChild(repr);
+ }
+ SP_GRADIENT(_currentDocument->getObjectByRepr(repr))->setSwatch();
+ DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Add Gradient Swatch"));
+ }
+ }
+ } else if (it->style->stroke.isColor()) {
+ Inkscape::XML::Node *grad = _currentDocument->getReprDoc()->createElement("svg:linearGradient");
+ grad->setAttribute( "osb:paint", "solid", 0 );
+ addStop(grad, it->style->stroke.value.color.toString(), SP_SCALE24_TO_FLOAT(it->style->stroke_opacity.value), "0");
+ if (page) {
+ page->appendChild(grad);
+ } else {
+ _currentDocument->getDefs()->appendChild(grad);
+ }
+ SPGradient* normalized = sp_gradient_ensure_vector_normalized(SP_GRADIENT(_currentDocument->getObjectByRepr(grad)));
+ Inkscape::GC::release(grad);
+ if (!_noLink.get_active()) {
+ sp_item_set_gradient(it, normalized, SP_GRADIENT_TYPE_LINEAR, Inkscape::FOR_STROKE);
+ }
+ DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Add Color Swatch"));
+ }
+ }
+ }
}
- if ( _remove ) {
- delete _remove;
+}
+
+void SwatchesPanel::_addBIButtonClicked(GdkEventButton* event)
+{
+ if (popUpImportMenu) {
+ popUpImportMenu->popup(event->button, event->time);
}
- if ( _holder ) {
- delete _holder;
+}
+
+void SwatchesPanel::NewGroupBI()
+{
+ if (_currentDocument) {
+ Inkscape::XML::Node * page = SwatchDocument->getReprDoc()->createElement("svg:g");
+ gchar *id=NULL;
+ do {
+ g_free(id);
+ id = g_strdup_printf("page%d", page_suffix++);
+ } while (SwatchDocument->getObjectById(id));
+
+ page->setAttribute("id", id);
+
+ SwatchDocument->getDefs()->appendChild(page);
+ sp_repr_save_file(SwatchDocument->getReprDoc(), SwatchFile, SP_SVG_NS_URI);
}
}
-void SwatchesPanel::setOrientation(SPAnchorType how)
+void SwatchesPanel::NewGroup()
{
- // Must call the parent class or bad things might happen
- Inkscape::UI::Widget::Panel::setOrientation( how );
+ if (_currentDocument) {
+ Inkscape::XML::Node * page = _currentDocument->getReprDoc()->createElement("svg:g");
+ gchar *id=NULL;
+ do {
+ g_free(id);
+ id = g_strdup_printf("page%d", page_suffix++);
+ } while (_currentDocument->getObjectById(id));
+
+ page->setAttribute("id", id);
+
+ _currentDocument->getDefs()->appendChild(page);
+ DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("New Swatch Group"));
+ }
+}
- if ( _holder )
- {
- _holder->setOrientation(SP_ANCHOR_SOUTH);
+void SwatchesPanel::SaveAs()
+{
+ if (_currentDocument) {
+ Inkscape::XML::Node * page = _currentDocument->getReprDoc()->createElement("svg:g");
+ gchar *id=NULL;
+ do {
+ g_free(id);
+ id = g_strdup_printf("page%d", page_suffix++);
+ } while (_currentDocument->getObjectById(id));
+
+ page->setAttribute("id", id);
+
+ std::vector<Inkscape::XML::Node*> toMove;
+ for (SPObject *it = _currentDocument->getDefs()->firstChild(); it != NULL; it = it->next) {
+ if (SP_IS_GRADIENT(it)) {
+ SPGradient* grad = SP_GRADIENT(it);
+ if (grad->isSwatch()) {
+ toMove.push_back(grad->getRepr());
+ }
+ }
+ }
+ while (!toMove.empty()) {
+ Inkscape::XML::Node* repr = toMove.back();
+ toMove.pop_back();
+ repr->parent()->removeChild(repr);
+ page->appendChild(repr);
+ }
+ _currentDocument->getDefs()->appendChild(page);
+ DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Save Swatch Group"));
}
}
-void SwatchesPanel::setDesktop( SPDesktop* desktop )
+void SwatchesPanel::Duplicate(SPGroup* oldpage)
{
- if ( desktop != _currentDesktop ) {
- if ( _currentDesktop ) {
- _documentConnection.disconnect();
- _selChanged.disconnect();
+ if (_currentDocument) {
+ Inkscape::XML::Node * page = _currentDocument->getReprDoc()->createElement("svg:g");
+ gchar *id=NULL;
+ do {
+ g_free(id);
+ id = g_strdup_printf("page%d", page_suffix++);
+ } while (_currentDocument->getObjectById(id));
+
+ page->setAttribute("id", id);
+ if (oldpage->label()) page->setAttribute("inkscape:label", oldpage->label());
+
+ for (SPObject *it = oldpage->firstChild(); it != NULL; it = it->next) {
+ if (SP_IS_GRADIENT(it)) {
+ SPGradient* grad = SP_GRADIENT(it);
+ if (grad->isSwatch()) {
+ Inkscape::XML::Node * copy = grad->getRepr()->duplicate(_currentDocument->getReprDoc());
+ page->appendChild(copy);
+ Inkscape::GC::release(copy);
+ }
+ }
}
+ _currentDocument->getDefs()->appendChild(page);
+ DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Duplicate Swatch Group"));
+ }
+}
- _currentDesktop = desktop;
+void SwatchesPanel::_lblClick(GdkEventButton* event, SPGroup* page)
+{
+ Gtk::Menu * menu = Gtk::manage(new Gtk::Menu());
+
+ Gtk::MenuItem* mi;
+ Glib::ustring us = Glib::ustring::compose("<b>%1</b>", page ? (page->label() ? page->label() : page->getId()) : _("[Base]"));
+ mi = Gtk::manage(new Gtk::MenuItem(page ? (page->label() ? page->label() : page->getId()) : _("[Base]")));
+ Gtk::Label* namelbl = dynamic_cast<Gtk::Label*>(mi->get_child());
+ if (namelbl) {
+ namelbl->set_markup(us);
+ }
+ mi->show();
+ mi->set_sensitive(false);
+ menu->append(*mi);
+
+ Gtk::SeparatorMenuItem* sep;
+ sep = manage(new Gtk::SeparatorMenuItem());
+ sep->show();
+ menu->append(*sep);
+
+ mi = Gtk::manage(new Gtk::MenuItem(_("Add Selected Fill")));
+ mi->signal_activate().connect_notify(sigc::bind<SPGroup*>(sigc::mem_fun(*this, &SwatchesPanel::AddSelectedFill), page));
+ mi->show();
+ mi->set_sensitive(_currentDesktop && _currentDesktop->selection->singleItem());
+ menu->append(*mi);
+
+ mi = Gtk::manage(new Gtk::MenuItem(_("Add Selected Stroke")));
+ mi->signal_activate().connect_notify(sigc::bind<SPGroup*>(sigc::mem_fun(*this, &SwatchesPanel::AddSelectedStroke), page));
+ mi->show();
+ mi->set_sensitive(_currentDesktop && _currentDesktop->selection->singleItem());
+ menu->append(*mi);
+
+ sep = manage(new Gtk::SeparatorMenuItem());
+ sep->show();
+ menu->append(*sep);
+
+ if (page) {
+
+ mi = Gtk::manage(new Gtk::MenuItem(_("Move Up")));
+ mi->signal_activate().connect_notify(sigc::bind<SPGroup*>(sigc::mem_fun(*this, &SwatchesPanel::MoveUp), page));
+ mi->show();
+ menu->append(*mi);
+
+ mi = Gtk::manage(new Gtk::MenuItem(_("Move Down")));
+ mi->signal_activate().connect_notify(sigc::bind<SPGroup*>(sigc::mem_fun(*this, &SwatchesPanel::MoveDown), page));
+ mi->show();
+ menu->append(*mi);
+
+ sep = manage(new Gtk::SeparatorMenuItem());
+ sep->show();
+ menu->append(*sep);
+
+ mi = Gtk::manage(new Gtk::MenuItem(_("Duplicate")));
+ mi->signal_activate().connect_notify(sigc::bind<SPGroup*>(sigc::mem_fun(*this, &SwatchesPanel::Duplicate), page));
+ mi->show();
+ menu->append(*mi);
+
+ sep = manage(new Gtk::SeparatorMenuItem());
+ sep->show();
+ menu->append(*sep);
+
+ mi = Gtk::manage(new Gtk::MenuItem(_("Remove")));
+ mi->signal_activate().connect_notify(sigc::bind<SPGroup*>(sigc::mem_fun(*this, &SwatchesPanel::Remove), page));
+ mi->show();
+ menu->append(*mi);
+ } else {
+ mi = Gtk::manage(new Gtk::MenuItem(_("Create New Group")));
+ mi->signal_activate().connect_notify(sigc::mem_fun(*this, &SwatchesPanel::NewGroup));
+ mi->show();
+ menu->append(*mi);
+
+ mi = Gtk::manage(new Gtk::MenuItem(_("Save As New Group")));
+ mi->signal_activate().connect_notify(sigc::mem_fun(*this, &SwatchesPanel::SaveAs));
+ mi->show();
+ menu->append(*mi);
+ }
+
+ menu->popup(event->button, event->time);
+}
- if ( desktop ) {
- _currentDesktop->selection->connectChanged(
- sigc::hide(sigc::mem_fun(*this, &SwatchesPanel::_updateFromSelection)));
+void SwatchesPanel::_defsChanged()
+{
+ if (_storeDoc) {
+ _storeDoc->clear();
+ }
+
+ while (!docWatchers.empty()) {
+ Inkscape::XML::NodeObserver* w = docWatchers.back();
+ docWatchers.pop_back();
+ delete w;
+ }
+
+ std::vector<Gtk::Widget *> tableChildren = _insideTable.get_children();
+ for (std::vector<Gtk::Widget *>::iterator c = tableChildren.begin(); c != tableChildren.end(); ++c) {
+ _insideTable.remove(**c);
+ }
+
+ if (_currentDocument) {
+ Gtk::EventBox* eb;
+ Gtk::Label* lbl;
+ if (_showlabels) {
+ eb = Gtk::manage(new Gtk::EventBox());
+ eb->add_events(Gdk::BUTTON_PRESS_MASK);
+ eb->signal_button_press_event().connect_notify(sigc::bind<SPGroup*>(sigc::mem_fun(*this, &SwatchesPanel::_lblClick), NULL));
+
+ lbl = Gtk::manage(new Gtk::Label(_("[Base]")));
+ eb->add(*lbl);
+ _insideTable.attach( *eb, 0, 1, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND , 5, 0);
+ }
+ Glib::ustring str1 = Glib::ustring(_("[None]"));
+ ColorItem* item = Gtk::manage(new ColorItem(NULL, NULL, NULL, str1));
+ //item->signal_button_press_event().connect_notify(sigc::bind<SPGradient *>(sigc::mem_fun(*this, &SwatchesPanel::_swatchClicked), NULL));
+ item->setName(_("[None]"));
+ _insideTable.attach( *item, _showlabels ? 1 : 0, _showlabels ? 2 : 1, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND );
+
+ unsigned int i = 1;
+ for (SPObject *it = _currentDocument->getDefs()->firstChild(); it != NULL; it = it->next) {
+ if (SP_IS_GRADIENT(it)) {
+ SPGradient* grad = SP_GRADIENT(it);
+ if (grad->hasStops()) {
+
+ GradientWatcher* w = new GradientWatcher(this, grad);
+ docWatchers.push_back(w);
+
+ if (grad->isSwatch()) {
+
+ for (SPStop* s = grad->getFirstStop(); s != NULL; s = s->getNextStop()) {
+ StopWatcher* sw = new StopWatcher(this, s);
+ docWatchers.push_back(sw);
+ }
- _currentDesktop->selection->connectModified(
- sigc::hide(sigc::hide(sigc::mem_fun(*this, &SwatchesPanel::_updateFromSelection))));
+ if (_storeDoc) {
+ Gtk::TreeModel::iterator iter = _storeDoc->append();
+ Gtk::TreeModel::Row row = *iter;
+ row[_modelDoc->_colObject] = grad;
+ row[_modelDoc->_colLabel] = grad->label() ? grad->label() : grad->getId();
+ GdkPixbuf* pixb = sp_gradient_to_pixbuf (grad, 64, 18);
+ row[_modelDoc->_colPixbuf] = Glib::wrap(pixb);
+ }
+ Glib::ustring str2 = Glib::ustring(it->label() ? it->label() : it->getId());
+ item = Gtk::manage(new ColorItem(NULL, NULL, NULL, str2));
+ item->setGradient(grad);
+ //item->colorItemHandleButtonPress().connect_notify(sigc::bind<SPGradient *>(sigc::mem_fun(*this, &SwatchesPanel::_swatchClicked), grad));
+ item->setName(it->label() ? it->label() : it->getId());
+ if (_showlabels) {
+ _insideTable.attach( *item, 1 + (i % 20), 2 + (i % 20), i / 20, i / 20 + 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND );
+ } else {
+ _insideTable.attach( *item, i, i + 1, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND );
+ }
- _currentDesktop->connectToolSubselectionChanged(
- sigc::hide(sigc::mem_fun(*this, &SwatchesPanel::_updateFromSelection)));
+ i++;
+ }
+ }
+ }
+ }
+
+ for (SPObject *it = _currentDocument->getDefs()->firstChild(); it != NULL; it = it->next) {
+ if (SP_IS_GROUP(it)) {
+ SwatchWatcher* w = new SwatchWatcher(this, it, false);
+ docWatchers.push_back(w);
+
+ if (_showlabels) {
+ i += 20 - (i % 20);
+ eb = Gtk::manage(new Gtk::EventBox());
+ eb->add_events(Gdk::BUTTON_PRESS_MASK);
+ eb->signal_button_press_event().connect_notify(sigc::bind<SPGroup*>(sigc::mem_fun(*this, &SwatchesPanel::_lblClick), SP_GROUP(it)));
+ lbl = Gtk::manage(new Gtk::Label(it->label() ? it->label() : it->getId()));
+ eb->add(*lbl);
+ _insideTable.attach( *eb, 0, 1, i / 20, i / 20 + 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND , 5, 0);
+ }
+
+ Gtk::TreeModel::iterator rowiter;
+
+ if (_storeDoc) {
+ rowiter = _storeDoc->append();
+ Gtk::TreeModel::Row row = *rowiter;
+ row[_modelDoc->_colObject] = it;
+ row[_modelDoc->_colLabel] = it->label() ? it->label() : it->getId();
+ }
+
+ for (SPObject *cit = it->firstChild(); cit != NULL; cit = cit->next) {
+ if (SP_IS_GRADIENT(cit)) {
+ SPGradient* grad = SP_GRADIENT(cit);
+
+ if (grad->hasStops()) {
+
+ GradientWatcher* w = new GradientWatcher(this, grad);
+ docWatchers.push_back(w);
+
+ if (grad->isSwatch()) {
+
+ for (SPStop* s = grad->getFirstStop(); s != NULL; s = s->getNextStop()) {
+ StopWatcher* sw = new StopWatcher(this, s);
+ docWatchers.push_back(sw);
+ }
- 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 );
+ if (_storeDoc && rowiter) {
+ Gtk::TreeModel::iterator iter = _storeDoc->append(rowiter->children());
+ Gtk::TreeModel::Row row = *iter;
+ row[_modelDoc->_colObject] = grad;
+ row[_modelDoc->_colLabel] = grad->label() ? grad->label() : grad->getId();
+ GdkPixbuf* pixb = sp_gradient_to_pixbuf (grad, 64, 18);
+ row[_modelDoc->_colPixbuf] = Glib::wrap(pixb);
- _setDocument( desktop->doc() );
- } else {
- _setDocument(0);
+ _editDoc.expand_to_path(_storeDoc->get_path(iter));
+ }
+ Glib::ustring str3= Glib::ustring(cit->label() ? cit->label() : cit->getId());
+ item = Gtk::manage(new ColorItem(NULL, NULL, NULL, str3));
+ item->setGradient(grad);
+ //item->signal_button_press_event().connect_notify(sigc::bind<SPGradient *>(sigc::mem_fun(*this, &SwatchesPanel::_swatchClicked), grad));
+ item->setName(cit->label() ? cit->label() : cit->getId());
+ if (_showlabels) {
+ _insideTable.attach( *item, 1 + (i % 20), 2 + (i % 20), i / 20, i / 20 + 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND );
+ } else {
+ _insideTable.attach( *item, i, i + 1, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND );
+ }
+ i++;
+ }
+ }
+ }
+ }
+ }
}
}
+
+ _scroller.show_all_children();
+ _scroller.queue_draw();
}
-
-class DocTrack
+Gtk::MenuItem* SwatchesPanel::_addSwatchGroup(SPGroup* group, Gtk::TreeModel::Row* parentRow)
{
-public:
- DocTrack(SPDocument *doc, sigc::connection &docDestroy, sigc::connection &gradientRsrcChanged, sigc::connection &defsChanged, sigc::connection &defsModified) :
- doc(doc),
- updatePending(false),
- lastGradientUpdate(0.0),
- docDestroy(docDestroy),
- gradientRsrcChanged(gradientRsrcChanged),
- defsChanged(defsChanged),
- defsModified(defsModified)
- {
- if ( !timer ) {
- timer = new Glib::Timer();
- refreshTimer = Glib::signal_timeout().connect( sigc::ptr_fun(handleTimerCB), 33 );
+ Gtk::MenuItem* mi = manage(new Gtk::MenuItem(group->label() ? group->label() : group->getId(),1));
+ Gtk::Menu* m = NULL;
+
+ Gtk::TreeModel::Row* r;
+ if (_store) {
+ Gtk::TreeModel::iterator iter = parentRow ? _store->append(parentRow->children()) : _store->append();
+ Gtk::TreeModel::Row row = *iter;
+ row[_model->_colObject] = group;
+ row[_model->_colLabel] = group->label() ? group->label() : group->getId();
+
+ if (SP_IS_GROUP(group->parent) && SP_GROUP(group->parent)->expanded()) {
+ _editBI.expand_to_path(_store->get_path(iter));
}
- timerRefCount++;
+ r = &row;
+ } else {
+ r = NULL;
}
-
- ~DocTrack()
+
+ bool hasswatches = false;
+ for (SPObject * obj = group->firstChild(); obj != NULL; obj = obj->next)
{
- timerRefCount--;
- if ( timerRefCount <= 0 ) {
- refreshTimer.disconnect();
- timerRefCount = 0;
- if ( timer ) {
- timer->stop();
- delete timer;
- timer = 0;
+ if (SP_IS_GROUP(obj)) {
+ if (!m) {
+ m = manage(new Gtk::Menu());
+ m->show_all();
+ mi->set_submenu(*m);
+
+ Gtk::MenuItem* basemi = manage(new Gtk::MenuItem(_("[All]")));
+ basemi->show();
+ Gtk::Label* namelbl = dynamic_cast<Gtk::Label*>(basemi->get_child());
+ if (namelbl) {
+ namelbl->set_markup(_("<b>[All]</b>"));
+ }
+ basemi->signal_activate().connect(sigc::bind<SPGroup*, bool>(sigc::mem_fun(*this, &SwatchesPanel::_addSwatchButtonClicked), group, true));
+ m->append(*basemi);
+
+ Gtk::SeparatorMenuItem* sep = manage(new Gtk::SeparatorMenuItem());
+ sep->show();
+ m->append(*sep);
}
+ SwatchWatcher* w = new SwatchWatcher(this, obj, true);
+ rootWatchers.push_back(w);
+ m->append(*_addSwatchGroup(SP_GROUP(obj), r));
+ } else if (SP_IS_GRADIENT(obj)) {
+ hasswatches = true;
}
- if (doc) {
- docDestroy.disconnect();
- gradientRsrcChanged.disconnect();
- defsChanged.disconnect();
- defsModified.disconnect();
- doc = NULL;
+ }
+ if (!m) {
+ mi->signal_activate().connect(sigc::bind<SPGroup*, bool>(sigc::mem_fun(*this, &SwatchesPanel::_addSwatchButtonClicked), group, false));
+ } else if (hasswatches) {
+ Glib::ustring us = Glib::ustring::compose("<b>%1</b>", group->label() ? group->label() : group->getId());
+ Gtk::MenuItem* basemi = manage(new Gtk::MenuItem(group->label() ? group->label() : group->getId()));
+ basemi->show();
+ Gtk::Label* namelbl = dynamic_cast<Gtk::Label*>(basemi->get_child());
+ if (namelbl) {
+ namelbl->set_markup(us);
}
+ basemi->signal_activate().connect(sigc::bind<SPGroup*, bool>(sigc::mem_fun(*this, &SwatchesPanel::_addSwatchButtonClicked), group, false));
+ m->prepend(*basemi);
}
+ mi->show();
+ return mi;
+}
- static bool handleTimerCB();
-
- /**
- * Checks if update should be queued or executed immediately.
- *
- * @return true if the update was queued and should not be immediately executed.
- */
- static bool queueUpdateIfNeeded(SPDocument *doc);
-
- static Glib::Timer *timer;
- static int timerRefCount;
- static sigc::connection refreshTimer;
-
- SPDocument *doc;
- bool updatePending;
- double lastGradientUpdate;
- sigc::connection docDestroy;
- sigc::connection gradientRsrcChanged;
- sigc::connection defsChanged;
- sigc::connection defsModified;
-
-private:
- DocTrack(DocTrack const &); // no copy
- DocTrack &operator=(DocTrack const &); // no assign
-};
-
-Glib::Timer *DocTrack::timer = 0;
-int DocTrack::timerRefCount = 0;
-sigc::connection DocTrack::refreshTimer;
+void SwatchesPanel::_swatchesChanged()
+{
+ while (!rootWatchers.empty()) {
+ Inkscape::XML::NodeObserver* w = rootWatchers.back();
+ rootWatchers.pop_back();
+ delete w;
+ }
-static const double DOC_UPDATE_THREASHOLD = 0.090;
+ std::vector<Gtk::Widget *> menuChildren = popUpMenu->get_children();
+ for (std::vector<Gtk::Widget *>::iterator c = menuChildren.begin(); c != menuChildren.end(); ++c) {
+ popUpMenu->remove(**c);
+ }
+
+ if (_store) {
+ _store->clear();
+ }
+
+ Gtk::MenuItem* mi;
+
+ for (SPObject * obj = SwatchDocument->getDefs()->firstChild(); obj != NULL; obj = obj->next)
+ {
+ if (SP_IS_GROUP(obj)) {
+ SwatchWatcher* w = new SwatchWatcher(this, obj, true);
+ rootWatchers.push_back(w);
+ popUpMenu->append(*_addSwatchGroup(SP_GROUP(obj), NULL));
+
+ }
+ }
+ Gtk::SeparatorMenuItem* sep = manage(new Gtk::SeparatorMenuItem());
+ sep->show();
+ popUpMenu->append(*sep);
+
+ mi = manage(new Gtk::MenuItem(_("New Swatch Group..."),1));
+ mi->signal_activate().connect(sigc::mem_fun(*this, &SwatchesPanel::NewGroup));
+ mi->show();
+ popUpMenu->append(*mi);
+
+ mi = manage(new Gtk::MenuItem(_("Add Swatch File..."),1));
+ mi->signal_activate().connect(sigc::bind<bool, bool>(sigc::mem_fun(*this, &SwatchesPanel::_importButtonClicked), true, false));
+ mi->show();
+ popUpMenu->append(*mi);
+
+ mi = manage(new Gtk::MenuItem(_("Import Swatch File..."),1));
+ mi->signal_activate().connect(sigc::bind<bool, bool>(sigc::mem_fun(*this, &SwatchesPanel::_importButtonClicked), true, true));
+ mi->show();
+ popUpMenu->append(*mi);
+}
-bool DocTrack::handleTimerCB()
+void SwatchesPanel::_styleButton( Gtk::Button& btn, SPDesktop *desktop, unsigned int code, char const* iconName, char const* fallback )
{
- double now = timer->elapsed();
+ bool set = false;
+
+ if ( iconName ) {
+ GtkWidget *child = sp_icon_new( Inkscape::ICON_SIZE_SMALL_TOOLBAR, iconName );
+ gtk_widget_show( child );
+ btn.add( *manage(Glib::wrap(child)) );
+ btn.set_relief(Gtk::RELIEF_NONE);
+ set = true;
+ }
- std::vector<DocTrack *> needCallback;
- for (std::vector<DocTrack *>::iterator it = docTrackings.begin(); it != docTrackings.end(); ++it) {
- DocTrack *track = *it;
- if ( track->updatePending && ( (now - track->lastGradientUpdate) >= DOC_UPDATE_THREASHOLD) ) {
- needCallback.push_back(track);
+ if ( desktop ) {
+ Verb *verb = Verb::get( code );
+ if ( verb ) {
+ SPAction *action = verb->get_action(desktop);
+ if ( !set && action && action->image ) {
+ GtkWidget *child = sp_icon_new( Inkscape::ICON_SIZE_SMALL_TOOLBAR, action->image );
+ gtk_widget_show( child );
+ btn.add( *manage(Glib::wrap(child)) );
+ set = true;
+ }
}
}
+
+ btn.set_tooltip_text (fallback);
+
+ if ( !set ) {
+ btn.set_label( fallback );
+ }
+}
- for (std::vector<DocTrack *>::iterator it = needCallback.begin(); it != needCallback.end(); ++it) {
- DocTrack *track = *it;
- if ( std::find(docTrackings.begin(), docTrackings.end(), track) != docTrackings.end() ) { // Just in case one gets deleted while we are looping
- // Note: calling handleDefsModified will call queueUpdateIfNeeded and thus update the time and flag.
- SwatchesPanel::handleDefsModified(track->doc);
+void SwatchesPanel::_addButtonClicked(GdkEventButton* event) {
+ if ( (event->type == GDK_BUTTON_PRESS) && (event->button == 3 || event->button == 1) ) {
+ if (popUpMenu) {
+ popUpMenu->popup(event->button, event->time);
}
}
+}
- return true;
+void SwatchesPanel::NoLinkToggled() {
+ static Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ Glib::ustring nolink = Glib::ustring::compose("%1/nolink", _prefs_path);
+ prefs->setBool(nolink, _noLink.get_active());
}
-bool DocTrack::queueUpdateIfNeeded( SPDocument *doc )
+bool SwatchesPanel::_handleButtonEvent(GdkEventButton *event)
{
- bool deferProcessing = false;
- for (std::vector<DocTrack*>::iterator it = docTrackings.begin(); it != docTrackings.end(); ++it) {
- DocTrack *track = *it;
- if ( track->doc == doc ) {
- double now = timer->elapsed();
- double elapsed = now - track->lastGradientUpdate;
-
- if ( elapsed < DOC_UPDATE_THREASHOLD ) {
- deferProcessing = true;
- track->updatePending = true;
- } else {
- track->lastGradientUpdate = now;
- track->updatePending = false;
- }
+ static unsigned doubleclick = 0;
+ if ( (event->type == GDK_2BUTTON_PRESS) && (event->button == 1) ) {
+ doubleclick = 1;
+ }
- break;
+ if ( event->type == GDK_BUTTON_RELEASE && doubleclick) {
+ doubleclick = 0;
+ Gtk::TreeModel::Path path;
+ Gtk::TreeViewColumn* col = 0;
+ int x = static_cast<int>(event->x);
+ int y = static_cast<int>(event->y);
+ int x2 = 0;
+ int y2 = 0;
+ if ( _editBI.get_path_at_pos( x, y, path, col, x2, y2 ) && col == _name_columnBI) {
+ // Double click on the Layer name, enable editing
+ _text_rendererBI->property_editable() = true;
+ _editBI.set_cursor (path, *_name_columnBI, true);
+ grab_focus();
}
}
- return deferProcessing;
+
+ return false;
}
-void SwatchesPanel::_trackDocument( SwatchesPanel *panel, SPDocument *document )
+bool SwatchesPanel::_handleKeyEvent(GdkEventKey *event)
{
- SPDocument *oldDoc = NULL;
- if (docPerPanel.find(panel) != docPerPanel.end()) {
- oldDoc = docPerPanel[panel];
- if (!oldDoc) {
- docPerPanel.erase(panel); // Should not be needed, but clean up just in case.
- }
- }
- if (oldDoc != document) {
- if (oldDoc) {
- docPerPanel[panel] = NULL;
- bool found = false;
- for (std::map<SwatchesPanel*, SPDocument*>::iterator it = docPerPanel.begin(); (it != docPerPanel.end()) && !found; ++it) {
- found = (it->second == document);
- }
- if (!found) {
- for (std::vector<DocTrack*>::iterator it = docTrackings.begin(); it != docTrackings.end(); ++it){
- if ((*it)->doc == oldDoc) {
- delete *it;
- docTrackings.erase(it);
- break;
- }
+ switch (get_group0_keyval(event)) {
+ case GDK_KEY_Return:
+ case GDK_KEY_KP_Enter:
+ case GDK_KEY_F2: {
+ Gtk::TreeModel::iterator iter = _editBI.get_selection()->get_selected();
+ if (iter && !_text_rendererBI->property_editable()) {
+ Gtk::TreeRow row = *iter;
+ SPObject * obj = row[_model->_colObject];
+ if (obj) {
+ Gtk::TreeModel::Path *path = new Gtk::TreeModel::Path(iter);
+ // Edit the layer label
+ _text_rendererBI->property_editable() = true;
+ _editBI.set_cursor(*path, *_name_columnBI, true);
+ grab_focus();
+ return true;
}
}
}
-
- if (document) {
- bool found = false;
- for (std::map<SwatchesPanel*, SPDocument*>::iterator it = docPerPanel.begin(); (it != docPerPanel.end()) && !found; ++it) {
- found = (it->second == document);
- }
- docPerPanel[panel] = document;
- if (!found) {
- sigc::connection conn0 = document->connectDestroy(sigc::bind(sigc::ptr_fun(&SwatchesPanel::handleDocumentDestroy), document));
- sigc::connection conn1 = document->connectResourcesChanged( "gradient", sigc::bind(sigc::ptr_fun(&SwatchesPanel::handleGradientsChange), document) );
- sigc::connection conn2 = document->getDefs()->connectRelease( sigc::hide(sigc::bind(sigc::ptr_fun(&SwatchesPanel::handleDefsModified), document)) );
- sigc::connection conn3 = document->getDefs()->connectModified( sigc::hide(sigc::hide(sigc::bind(sigc::ptr_fun(&SwatchesPanel::handleDefsModified), document))) );
-
- DocTrack *dt = new DocTrack(document, conn0, conn1, conn2, conn3);
- docTrackings.push_back(dt);
-
- if (docPalettes.find(document) == docPalettes.end()) {
- SwatchPage *docPalette = new SwatchPage();
- docPalette->_name = "Auto";
- docPalettes[document] = docPalette;
+ case GDK_KEY_Delete: {
+
+ Gtk::TreeModel::iterator iter = _editBI.get_selection()->get_selected();
+ if (iter) {
+ Gtk::TreeRow row = *iter;
+ SPObject * obj = row[_model->_colObject];
+ if (obj) {
+ obj->deleteObject(false);
+ sp_repr_save_file(SwatchDocument->getReprDoc(), SwatchFile, SP_SVG_NS_URI);
}
}
+ return true;
}
+ break;
}
+ return false;
}
-void SwatchesPanel::_setDocument( SPDocument *document )
+void SwatchesPanel::_handleEdited(const Glib::ustring& path, const Glib::ustring& new_text)
{
- if ( document != _currentDocument ) {
- _trackDocument(this, document);
- _currentDocument = document;
- handleGradientsChange( document );
- }
+ Gtk::TreeModel::iterator iter = _editBI.get_model()->get_iter(path);
+ Gtk::TreeModel::Row row = *iter;
+
+ _renameObject(row, new_text);
+ _text_rendererBI->property_editable() = false;
}
-static void recalcSwatchContents(SPDocument* doc,
- boost::ptr_vector<ColorItem> &tmpColors,
- std::map<ColorItem*, cairo_pattern_t*> &previewMappings,
- std::map<ColorItem*, SPGradient*> &gradMappings)
+void SwatchesPanel::_handleEditingCancelled()
{
- std::vector<SPGradient*> newList;
-
- if (doc) {
- const GSList *gradients = doc->getResourceList("gradient");
- for (const GSList *item = gradients; item; item = item->next) {
- SPGradient* grad = SP_GRADIENT(item->data);
- if ( grad->isSwatch() ) {
- newList.push_back(SP_GRADIENT(item->data));
+ _text_rendererBI->property_editable() = false;
+}
+
+void SwatchesPanel::_renameObject(Gtk::TreeModel::Row row, const Glib::ustring& name)
+{
+ if ( row && SwatchDocument) {
+ SPObject* obj = row[_model->_colObject];
+ if ( obj ) {
+ gchar const* oldLabel = obj->label();
+ if ( !name.empty() && (!oldLabel || name != oldLabel) ) {
+ obj->setLabel(name.c_str());
+ sp_repr_save_file(SwatchDocument->getReprDoc(), SwatchFile, SP_SVG_NS_URI);
}
}
}
+}
- if ( !newList.empty() ) {
- std::reverse(newList.begin(), newList.end());
- for ( std::vector<SPGradient*>::iterator it = newList.begin(); it != newList.end(); ++it )
- {
- SPGradient* grad = *it;
-
- cairo_surface_t *preview = cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
- PREVIEW_PIXBUF_WIDTH, VBLOCK);
- cairo_t *ct = cairo_create(preview);
-
- Glib::ustring name( grad->getId() );
- ColorItem* item = new ColorItem( 0, 0, 0, name );
-
- cairo_pattern_t *check = ink_cairo_pattern_create_checkerboard();
- cairo_pattern_t *gradient = sp_gradient_create_preview_pattern(grad, PREVIEW_PIXBUF_WIDTH);
- cairo_set_source(ct, check);
- cairo_paint(ct);
- cairo_set_source(ct, gradient);
- cairo_paint(ct);
-
- cairo_destroy(ct);
- cairo_pattern_destroy(gradient);
- cairo_pattern_destroy(check);
-
- cairo_pattern_t *prevpat = cairo_pattern_create_for_surface(preview);
- cairo_surface_destroy(preview);
+void SwatchesPanel::_setCollapsed(SPGroup * group)
+{
+ group->setExpanded(false);
+ group->updateRepr(SP_OBJECT_WRITE_NO_CHILDREN | SP_OBJECT_WRITE_EXT);
+ for (SPObject *iter = group->children; iter != NULL; iter = iter->next)
+ {
+ if (SP_IS_GROUP(iter)) _setCollapsed(SP_GROUP(iter));
+ }
+}
- previewMappings[item] = prevpat;
+void SwatchesPanel::_setExpanded(const Gtk::TreeModel::iterator& iter, const Gtk::TreeModel::Path& /*path*/, bool isexpanded)
+{
+ Gtk::TreeModel::Row row = *iter;
- tmpColors.push_back(item);
- gradMappings[item] = grad;
+ SPObject* obj = row[_model->_colObject];
+ if (obj && SP_IS_GROUP(obj))
+ {
+ if (isexpanded)
+ {
+ SP_GROUP(obj)->setExpanded(isexpanded);
+ obj->updateRepr(SP_OBJECT_WRITE_NO_CHILDREN | SP_OBJECT_WRITE_EXT);
+ }
+ else
+ {
+ _setCollapsed(SP_GROUP(obj));
}
}
+ sp_repr_save_file(SwatchDocument->getReprDoc(), SwatchFile, SP_SVG_NS_URI);
}
-void SwatchesPanel::handleDocumentDestroy(SPDocument *document)
+void SwatchesPanel::_deleteButtonClicked()
{
- if (document) {
- for (std::vector<DocTrack*>::iterator it = docTrackings.begin(); it != docTrackings.end(); ++it){
- if ((*it)->doc == document) {
- delete *it;
- docTrackings.erase(it);
- break;
- }
+ Gtk::TreeModel::iterator iter = _editBI.get_selection()->get_selected();
+ if (iter) {
+ Gtk::TreeModel::Row row = *iter;
+ SPObject* obj = row[_model->_colObject];
+ if (obj) {
+ obj->deleteObject(false);
+ sp_repr_save_file(SwatchDocument->getReprDoc(), SwatchFile, SP_SVG_NS_URI);
}
+ }
+}
- if (docPalettes.find(document) != docPalettes.end()) {
- docPalettes.erase(document);
+bool SwatchesPanel::_handleButtonEventDoc(GdkEventButton* event)
+{
+ static unsigned doubleclick = 0;
+
+ if ( (event->type == GDK_BUTTON_PRESS) && (event->button == 3) ) {
+ // TODO - fix to a better is-popup function
+ Gtk::TreeModel::Path path;
+ int x = static_cast<int>(event->x);
+ int y = static_cast<int>(event->y);
+ if ( _editDoc.get_path_at_pos( x, y, path ) ) {
+ Gtk::TreeModel::Children::iterator iter = _editDoc.get_model()->get_iter(path);
+ Gtk::TreeModel::Row row = *iter;
+
+ SPObject* obj = row[_modelDoc->_colObject];
+ if (SP_IS_GRADIENT(obj)) {
+ _swatchClicked(event, SP_GRADIENT(obj));
+ } else if (SP_IS_GROUP(obj)) {
+ _lblClick(event, SP_GROUP(obj));
+ } else {
+ _lblClick(event, NULL);
+ }
+ } else {
+ _lblClick(event, NULL);
}
+ }
+
+ if ( (event->type == GDK_2BUTTON_PRESS) && (event->button == 1) ) {
+ doubleclick = 1;
+ }
- for (std::map<SwatchesPanel*, SPDocument*>::iterator it = docPerPanel.begin(); it != docPerPanel.end(); ++it) {
- if (it->second == document) {
- SwatchesPanel* swp = it->first;
- std::vector<SwatchPage*> pages = swp->_getSwatchSets();
- if ((swp->_currentIndex >= static_cast<int>(pages.size())) && (pages.size() > 0))
- {
- swp->_setSelectedIndex(swp->_getSwatchSets().size() - 1);
- }
- swp->_rebuild();
- docPerPanel.erase(it);
- break;
- }
+ if ( event->type == GDK_BUTTON_RELEASE && doubleclick) {
+ doubleclick = 0;
+ Gtk::TreeModel::Path path;
+ Gtk::TreeViewColumn* col = 0;
+ int x = static_cast<int>(event->x);
+ int y = static_cast<int>(event->y);
+ int x2 = 0;
+ int y2 = 0;
+ if ( _editDoc.get_path_at_pos( x, y, path, col, x2, y2 ) && col == _name_columnDoc) {
+ // Double click on the Layer name, enable editing
+ _text_rendererDoc->property_editable() = true;
+ _editDoc.set_cursor (path, *_name_columnDoc, true);
+ grab_focus();
}
}
+
+ return false;
}
-void SwatchesPanel::handleGradientsChange(SPDocument *document)
+void SwatchesPanel::_deleteButtonClickedDoc()
{
- SwatchPage *docPalette = (docPalettes.find(document) != docPalettes.end()) ? docPalettes[document] : 0;
- if (docPalette) {
- boost::ptr_vector<ColorItem> tmpColors;
- std::map<ColorItem*, cairo_pattern_t*> tmpPrevs;
- std::map<ColorItem*, SPGradient*> tmpGrads;
- recalcSwatchContents(document, tmpColors, tmpPrevs, tmpGrads);
-
- for (std::map<ColorItem*, cairo_pattern_t*>::iterator it = tmpPrevs.begin(); it != tmpPrevs.end(); ++it) {
- it->first->setPattern(it->second);
- cairo_pattern_destroy(it->second);
+ Gtk::TreeModel::iterator iter = _editDoc.get_selection()->get_selected();
+ if (iter) {
+ Gtk::TreeRow row = *iter;
+ SPObject * obj = row[_modelDoc->_colObject];
+ if (SP_IS_GRADIENT(obj)) {
+ RemoveSwatch(SP_GRADIENT(obj));
+ } else if (SP_IS_GROUP(obj)) {
+ Remove(SP_GROUP(obj));
}
+ }
+}
- for (std::map<ColorItem*, SPGradient*>::iterator it = tmpGrads.begin(); it != tmpGrads.end(); ++it) {
- it->first->setGradient(it->second);
- }
-
- docPalette->_colors.swap(tmpColors);
-
- // Figure out which SwatchesPanel instances are affected and update them.
-
- for (std::map<SwatchesPanel*, SPDocument*>::iterator it = docPerPanel.begin(); it != docPerPanel.end(); ++it) {
- if (it->second == document) {
- SwatchesPanel* swp = it->first;
- std::vector<SwatchPage*> pages = swp->_getSwatchSets();
- SwatchPage* curr = pages[swp->_currentIndex];
- if (curr == docPalette) {
- swp->_rebuild();
+bool SwatchesPanel::_handleKeyEventDoc(GdkEventKey *event)
+{
+ switch (get_group0_keyval(event)) {
+ case GDK_KEY_Return:
+ case GDK_KEY_KP_Enter:
+ case GDK_KEY_F2: {
+ Gtk::TreeModel::iterator iter = _editDoc.get_selection()->get_selected();
+ if (iter && !_text_rendererDoc->property_editable()) {
+ Gtk::TreeRow row = *iter;
+ SPObject * obj = row[_modelDoc->_colObject];
+ if (obj) {
+ Gtk::TreeModel::Path *path = new Gtk::TreeModel::Path(iter);
+ // Edit the layer label
+ _text_rendererDoc->property_editable() = true;
+ _editDoc.set_cursor(*path, *_name_columnDoc, true);
+ grab_focus();
+ return true;
}
}
}
+ case GDK_KEY_Delete: {
+
+ _deleteButtonClickedDoc();
+ return true;
+ }
+ break;
}
+ return false;
}
-void SwatchesPanel::handleDefsModified(SPDocument *document)
+void SwatchesPanel::_renameObjectDoc(Gtk::TreeModel::Row row, const Glib::ustring& name)
{
- SwatchPage *docPalette = (docPalettes.find(document) != docPalettes.end()) ? docPalettes[document] : 0;
- if (docPalette && !DocTrack::queueUpdateIfNeeded(document) ) {
- boost::ptr_vector<ColorItem> tmpColors;
- std::map<ColorItem*, cairo_pattern_t*> tmpPrevs;
- std::map<ColorItem*, SPGradient*> tmpGrads;
- recalcSwatchContents(document, tmpColors, tmpPrevs, tmpGrads);
-
- if ( tmpColors.size() != docPalette->_colors.size() ) {
- handleGradientsChange(document);
- } else {
- int cap = std::min(docPalette->_colors.size(), tmpColors.size());
- for (int i = 0; i < cap; i++) {
- ColorItem *newColor = &tmpColors[i];
- ColorItem *oldColor = &docPalette->_colors[i];
- if ( (newColor->def.getType() != oldColor->def.getType()) ||
- (newColor->def.getR() != oldColor->def.getR()) ||
- (newColor->def.getG() != oldColor->def.getG()) ||
- (newColor->def.getB() != oldColor->def.getB()) ) {
- oldColor->def.setRGB(newColor->def.getR(), newColor->def.getG(), newColor->def.getB());
- }
- if (tmpGrads.find(newColor) != tmpGrads.end()) {
- oldColor->setGradient(tmpGrads[newColor]);
- }
- if ( tmpPrevs.find(newColor) != tmpPrevs.end() ) {
- oldColor->setPattern(tmpPrevs[newColor]);
- }
+ if ( row && SwatchDocument) {
+ SPObject* obj = row[_modelDoc->_colObject];
+ if ( obj ) {
+ gchar const* oldLabel = obj->label();
+ if ( !name.empty() && (!oldLabel || name != oldLabel) ) {
+ obj->setLabel(name.c_str());
}
}
-
- for (std::map<ColorItem*, cairo_pattern_t*>::iterator it = tmpPrevs.begin(); it != tmpPrevs.end(); ++it) {
- cairo_pattern_destroy(it->second);
- }
}
}
+void SwatchesPanel::_handleEditedDoc(const Glib::ustring& path, const Glib::ustring& new_text)
+{
+ Gtk::TreeModel::iterator iter = _editDoc.get_model()->get_iter(path);
+ Gtk::TreeModel::Row row = *iter;
-std::vector<SwatchPage*> SwatchesPanel::_getSwatchSets() const
+ _renameObjectDoc(row, new_text);
+ _text_rendererDoc->property_editable() = false;
+}
+
+void SwatchesPanel::_handleEditingCancelledDoc()
+{
+ _text_rendererDoc->property_editable() = false;
+}
+
+/*
+ * Drap and drop within the tree
+ * Save the drag source and drop target SPObjects and if its a drag between layers or into (sublayer) a layer
+ */
+bool SwatchesPanel::_handleDragDrop(const Glib::RefPtr<Gdk::DragContext>& context, int x, int y, guint time)
{
- std::vector<SwatchPage*> tmp;
- if (docPalettes.find(_currentDocument) != docPalettes.end()) {
- tmp.push_back(docPalettes[_currentDocument]);
+ int cell_x = 0, cell_y = 0;
+ Gtk::TreeModel::Path target_path;
+ Gtk::TreeView::Column *target_column;
+
+ bool _dnd_top = false;
+ _dnd_into = false;
+ _dnd_target = SwatchDocument->getDefs()->lastChild();
+ Gtk::TreeModel::iterator itersel = _editBI.get_selection()->get_selected();
+ if (!itersel) {
+ return true;
}
+ Gtk::TreeModel::Row rowsel = *itersel;
+ _dnd_source = rowsel[_model->_colObject];
- tmp.insert(tmp.end(), userSwatchPages.begin(), userSwatchPages.end());
- tmp.insert(tmp.end(), systemSwatchPages.begin(), systemSwatchPages.end());
+ if (!_dnd_source) {
+ return true;
+ }
+
+ if (_editBI.get_path_at_pos (x, y, target_path, target_column, cell_x, cell_y)) {
+ // Are we before, inside or after the drop layer
+ Gdk::Rectangle rect;
+ _editBI.get_background_area (target_path, *target_column, rect);
+ int cell_height = rect.get_height();
+ _dnd_into = (cell_y > (int)(cell_height * 1/3) && cell_y <= (int)(cell_height * 2/3));
+ if (cell_y < (int)(cell_height * 1/3)) {
+ Gtk::TreeModel::Path next_path = target_path;
+ if (next_path.prev()) {
+ target_path = next_path;
+ } else {
+ // Dragging to the "end"
+ Gtk::TreeModel::Path up_path = target_path;
+ up_path.up();
+ if (_store->iter_is_valid(_store->get_iter(up_path))) {
+ // Drop into parent
+ target_path = up_path;
+ _dnd_into = true;
+ } else {
+ _dnd_top = true;
+ // Drop into the top level
+ _dnd_target = NULL;
+ }
+ }
+ }
+ if (!_dnd_top) {
+ Gtk::TreeModel::iterator iter = _store->get_iter(target_path);
+ if (_store->iter_is_valid(iter)) {
+ Gtk::TreeModel::Row row = *iter;
+ SPObject *obj = row[_model->_colObject];
+ if (obj) {
+ _dnd_target = obj;
+ }
+ }
+ }
+ }
+
+ if (_dnd_source != _dnd_target) {
+
+ Inkscape::XML::Node *target_ref = _dnd_target ? _dnd_target->getRepr() : NULL;
+ Inkscape::XML::Node *our_ref = _dnd_source->getRepr();
+
+ if (target_ref != our_ref) {
+ if (!target_ref) {
+ target_ref = SwatchDocument->getDefs()->getRepr();
+ if (target_ref != our_ref->parent()) {
+ our_ref->parent()->removeChild(our_ref);
+ target_ref->addChild(our_ref, NULL);
+ } else {
+ our_ref->parent()->changeOrder(our_ref, NULL);
+ }
+ } else if (_dnd_into) {
+ // Move this inside of the target at the end
+ our_ref->parent()->removeChild(our_ref);
+ target_ref->addChild(our_ref, NULL);
+ } else if (target_ref->parent() != our_ref->parent()) {
+ // Change in parent, need to remove and add
+ our_ref->parent()->removeChild(our_ref);
+ target_ref->parent()->addChild(our_ref, target_ref);
+ } else {
+ // Same parent, just move
+ our_ref->parent()->changeOrder(our_ref, target_ref);
+ }
+ }
+ sp_repr_save_file(SwatchDocument->getReprDoc(), SwatchFile, SP_SVG_NS_URI);
+ }
- return tmp;
+ return true;
}
-void SwatchesPanel::_updateFromSelection()
+/*
+ * Drap and drop within the tree
+ * Save the drag source and drop target SPObjects and if its a drag between layers or into (sublayer) a layer
+ */
+bool SwatchesPanel::_handleDragDropDoc(const Glib::RefPtr<Gdk::DragContext>& context, int x, int y, guint time)
{
- SwatchPage *docPalette = (docPalettes.find(_currentDocument) != docPalettes.end()) ? docPalettes[_currentDocument] : 0;
- if ( docPalette ) {
- 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->isSwatch() ) {
- target = grad;
- } else if ( grad->ref ) {
- SPGradient *tmp = grad->ref->getObject();
- if ( tmp && tmp->isSwatch() ) {
- target = tmp;
- }
- }
- if ( target ) {
- //XML Tree being used directly here while it shouldn't be
- gchar const* id = target->getRepr()->attribute("id");
- if ( id ) {
- fillId = id;
- }
- }
- }
+ int cell_x = 0, cell_y = 0;
+ Gtk::TreeModel::Path target_path;
+ Gtk::TreeView::Column *target_column;
+
+ bool _dnd_top = false;
+ _dnd_into = false;
+ _dnd_target = _currentDocument->getDefs()->lastChild();
+ Gtk::TreeModel::iterator itersel = _editDoc.get_selection()->get_selected();
+ if (!itersel) {
+ return true;
+ }
+ Gtk::TreeModel::Row rowsel = *itersel;
+ _dnd_source = rowsel[_modelDoc->_colObject];
+
+ if (!_dnd_source) {
+ return true;
+ }
+
+ if (_editDoc.get_path_at_pos (x, y, target_path, target_column, cell_x, cell_y)) {
+ // Are we before, inside or after the drop layer
+ Gdk::Rectangle rect;
+ _editDoc.get_background_area (target_path, *target_column, rect);
+ int cell_height = rect.get_height();
+ _dnd_into = (cell_y > (int)(cell_height * 1/3) && cell_y <= (int)(cell_height * 2/3));
+ if (cell_y < (int)(cell_height * 1/3)) {
+ Gtk::TreeModel::Path next_path = target_path;
+ if (next_path.prev()) {
+ target_path = next_path;
+ } else {
+ // Dragging to the "end"
+ Gtk::TreeModel::Path up_path = target_path;
+ up_path.up();
+ if (_storeDoc->iter_is_valid(_storeDoc->get_iter(up_path))) {
+ // Drop into parent
+ target_path = up_path;
+ _dnd_into = true;
+ } else {
+ _dnd_top = true;
+ // Drop into the top level
+ _dnd_target = NULL;
}
- 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->isSwatch() ) {
- target = grad;
- } else if ( grad->ref ) {
- SPGradient *tmp = grad->ref->getObject();
- if ( tmp && tmp->isSwatch() ) {
- target = tmp;
- }
- }
- if ( target ) {
- //XML Tree being used directly here while it shouldn't be
- gchar const* id = target->getRepr()->attribute("id");
- if ( id ) {
- strokeId = id;
- }
+ if (!_dnd_top) {
+ Gtk::TreeModel::iterator iter = _storeDoc->get_iter(target_path);
+ if (_storeDoc->iter_is_valid(iter)) {
+ Gtk::TreeModel::Row row = *iter;
+ SPObject *obj = row[_modelDoc->_colObject];
+ if (obj) {
+ _dnd_target = obj;
+ if (SP_IS_GRADIENT(obj)) {
+ _dnd_into = false;
+ if (SP_IS_GROUP(_dnd_source)) {
+ _dnd_target = obj->parent;
}
+ } else if (SP_IS_GROUP(_dnd_source)) {
+ _dnd_into = false;
}
}
- break;
}
}
- sp_style_unref(tmpStyle);
-
- for ( boost::ptr_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 );
+ }
+
+ if (_dnd_source != _dnd_target) {
+
+ Inkscape::XML::Node *target_ref = _dnd_target ? _dnd_target->getRepr() : NULL;
+ Inkscape::XML::Node *our_ref = _dnd_source->getRepr();
+
+ if (target_ref != our_ref) {
+ if (!target_ref) {
+ target_ref = _currentDocument->getDefs()->getRepr();
+ if (target_ref != our_ref->parent()) {
+ our_ref->parent()->removeChild(our_ref);
+ target_ref->addChild(our_ref, NULL);
+ } else {
+ our_ref->parent()->changeOrder(our_ref, NULL);
+ }
+ } else if (_dnd_into) {
+ // Move this inside of the target at the end
+ our_ref->parent()->removeChild(our_ref);
+ target_ref->addChild(our_ref, NULL);
+ } else if (target_ref->parent() != our_ref->parent()) {
+ // Change in parent, need to remove and add
+ our_ref->parent()->removeChild(our_ref);
+ target_ref->parent()->addChild(our_ref, target_ref);
+ } else {
+ // Same parent, just move
+ our_ref->parent()->changeOrder(our_ref, target_ref);
+ }
}
+ DocumentUndo::done( _currentDocument , SP_VERB_DIALOG_SWATCHES,
+ _("Moved Swatches"));
}
+
+ return true;
}
-void SwatchesPanel::_handleAction( int setId, int itemId )
+
+/**
+ * Constructor
+ */
+SwatchesPanel::SwatchesPanel(gchar const* prefsPath, bool showLabels) :
+ Inkscape::UI::Widget::Panel("", prefsPath, SP_VERB_DIALOG_SWATCHES, ""),
+ _scroller(),
+ _insideTable(1, 2),
+ _insideV(),
+ _insideH(),
+ _buttonsRow(),
+ _outsideV(),
+ _noLink(_("Don't Link")),
+ _showlabels(showLabels),
+ _store(0),
+ _scrollerBI(),
+ _editBI(),
+ _buttonsRowBI(),
+ _editBIV(),
+ _storeDoc(0),
+ _scrollerDoc(),
+ _editDoc(),
+ _buttonsRowDoc(),
+ _editDocV(),
+ _notebook(),
+ rootWatcher(0),
+ docWatcher(0),
+ _currentDesktop(0),
+ _currentDocument(0)
{
- switch( setId ) {
- case 3:
+ _insideH.pack_start(_insideTable, Gtk::PACK_SHRINK);
+ if (_showlabels) {
+ _insideV.pack_start(_insideH, Gtk::PACK_SHRINK);
+ _scroller.add(_insideV);
+ } else {
+ _scroller.property_height_request() = 45;
+ _scroller.add(_insideH);
+ }
+
+ popUpMenu = manage( new Gtk::Menu() );
+ popUpMenu->show_all_children();
+
+ Gtk::Button* btn = manage( new Gtk::Button() );
+ _styleButton( *btn, SP_ACTIVE_DESKTOP, SP_VERB_LAYER_NEW, GTK_STOCK_ADD, _("Add Swatch") );
+ btn->signal_button_press_event().connect_notify( sigc::mem_fun(*this, &SwatchesPanel::_addButtonClicked) );
+ _buttonsRow.pack_start(*btn, Gtk::PACK_SHRINK);
+
+// btn = manage( new Gtk::Button() );
+// _styleButton( *btn, SP_ACTIVE_DESKTOP, SP_VERB_LAYER_NEW, GTK_STOCK_DISCONNECT, C_("Unlink", "New") );
+// _buttonsRow.pack_end(*btn, Gtk::PACK_SHRINK);
+
+ static Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ Glib::ustring nolink = Glib::ustring::compose("%1/nolink", prefsPath);
+ _noLink.set_tooltip_text(_("Don't link swatches"));
+ _noLink.set_active(prefs->getBool(nolink, false));
+ _noLink.signal_toggled().connect_notify(sigc::mem_fun(*this, &SwatchesPanel::NoLinkToggled));
+ _buttonsRow.pack_end(_noLink, Gtk::PACK_SHRINK);
+
+ _scroller.set_policy( Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC );
+ _scroller.set_shadow_type(Gtk::SHADOW_NONE);
+
+ if (_showlabels) {
+ _outsideV.pack_end(_buttonsRow, Gtk::PACK_SHRINK);
+ _outsideV.pack_end(_scroller, Gtk::PACK_EXPAND_WIDGET);
+
+ _notebook.append_page(_outsideV, "Use");
+
{
- _setSelectedIndex(itemId);
+ ModelColumnsDoc *zoop = new ModelColumnsDoc();
+ _modelDoc = zoop;
+
+ _storeDoc = Gtk::TreeStore::create( *zoop );
+
+ _editDoc.set_model( _storeDoc );
+ _editDoc.set_headers_visible(false);
+ _editDoc.set_reorderable(true);
+ _editDoc.enable_model_drag_dest (Gdk::ACTION_MOVE);
+
+ Gtk::Button* btn = manage( new Gtk::Button() );
+ _styleButton( *btn, SP_ACTIVE_DESKTOP, SP_VERB_LAYER_NEW, GTK_STOCK_ADD, _("Import Swatch") );
+ btn->signal_button_press_event().connect_notify( sigc::mem_fun(*this, &SwatchesPanel::_addButtonClicked));
+ _buttonsRowDoc.pack_start(*btn, Gtk::PACK_SHRINK);
+
+ btn = manage( new Gtk::Button() );
+ _styleButton( *btn, SP_ACTIVE_DESKTOP, SP_VERB_LAYER_DELETE, GTK_STOCK_DELETE, _("Delete Swatch") );
+ btn->signal_button_press_event().connect_notify( sigc::hide(sigc::mem_fun(*this, &SwatchesPanel::_deleteButtonClickedDoc)));
+ _buttonsRowDoc.pack_start(*btn, Gtk::PACK_SHRINK);
+
+ _pixbuf_rendererDoc = manage(new Gtk::CellRendererPixbuf());
+ int pixbufColNum = _editDoc.append_column("Pixbuf", *_pixbuf_rendererDoc) - 1;
+ _pixbuf_columnDoc = _editDoc.get_column(pixbufColNum);
+ _pixbuf_columnDoc->add_attribute(_pixbuf_rendererDoc->property_pixbuf(), _modelDoc->_colPixbuf);
+
+ _text_rendererDoc = manage(new Gtk::CellRendererText());
+ int nameColNum = _editDoc.append_column("Name", *_text_rendererDoc) - 1;
+ _name_columnDoc = _editDoc.get_column(nameColNum);
+ _name_columnDoc->add_attribute(_text_rendererDoc->property_text(), _modelDoc->_colLabel);
+
+ _text_rendererDoc->signal_edited().connect( sigc::mem_fun(*this, &SwatchesPanel::_handleEditedDoc) );
+ _text_rendererDoc->signal_editing_canceled().connect( sigc::mem_fun(*this, &SwatchesPanel::_handleEditingCancelledDoc) );
+
+ _editDoc.set_expander_column( *_editDoc.get_column(nameColNum) );
+
+ _editDoc.signal_button_press_event().connect( sigc::mem_fun(*this, &SwatchesPanel::_handleButtonEventDoc), false );
+ _editDoc.signal_button_release_event().connect( sigc::mem_fun(*this, &SwatchesPanel::_handleButtonEventDoc), false );
+ _editDoc.signal_key_press_event().connect( sigc::mem_fun(*this, &SwatchesPanel::_handleKeyEventDoc), false );
+
+ _editDoc.signal_drag_drop().connect( sigc::mem_fun(*this, &SwatchesPanel::_handleDragDropDoc), false);
+
+ _scrollerDoc.set_policy( Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC );
+ _scrollerDoc.set_shadow_type(Gtk::SHADOW_IN);
+ _scrollerDoc.add(_editDoc);
+
+ _editDocV.pack_start(_scrollerDoc, Gtk::PACK_EXPAND_WIDGET);
+ _editDocV.pack_end(_buttonsRowDoc, Gtk::PACK_SHRINK);
+
+ _notebook.append_page(_editDocV, "Edit");
}
- break;
+
+ {
+ popUpImportMenu = Gtk::manage(new Gtk::Menu());
+
+ Gtk::MenuItem* mi = Gtk::manage(new Gtk::MenuItem(_("New Swatch Group...")));
+ mi->signal_activate().connect_notify(sigc::mem_fun(*this, &SwatchesPanel::NewGroupBI));
+ mi->show();
+ popUpImportMenu->append(*mi);
+
+ mi = Gtk::manage(new Gtk::MenuItem(_("Import Swatch File...")));
+ mi->signal_activate().connect_notify(sigc::bind<bool, bool>(sigc::mem_fun(*this, &SwatchesPanel::_importButtonClicked), false, true));
+ mi->show();
+ popUpImportMenu->append(*mi);
+
+ ModelColumns *zoop = new ModelColumns();
+ _model = zoop;
+
+ _store = Gtk::TreeStore::create( *zoop );
+
+ _editBI.set_model( _store );
+ _editBI.set_headers_visible(false);
+ _editBI.set_reorderable(true);
+ _editBI.enable_model_drag_dest (Gdk::ACTION_MOVE);
+
+ Gtk::Button* btn = manage( new Gtk::Button() );
+ _styleButton( *btn, SP_ACTIVE_DESKTOP, SP_VERB_LAYER_NEW, GTK_STOCK_ADD, _("Import Swatch") );
+ btn->signal_button_press_event().connect_notify(sigc::mem_fun(*this, &SwatchesPanel::_addBIButtonClicked));
+ _buttonsRowBI.pack_start(*btn, Gtk::PACK_SHRINK);
+
+ btn = manage( new Gtk::Button() );
+ _styleButton( *btn, SP_ACTIVE_DESKTOP, SP_VERB_LAYER_DELETE, GTK_STOCK_DELETE, _("Delete Swatch") );
+ btn->signal_button_press_event().connect_notify( sigc::hide(sigc::mem_fun(*this, &SwatchesPanel::_deleteButtonClicked)));
+ _buttonsRowBI.pack_start(*btn, Gtk::PACK_SHRINK);
+
+ _text_rendererBI = manage(new Gtk::CellRendererText());
+ int nameColNum = _editBI.append_column("Name", *_text_rendererBI) - 1;
+ _name_columnBI = _editBI.get_column(nameColNum);
+ _name_columnBI->add_attribute(_text_rendererBI->property_text(), _model->_colLabel);
+
+ _text_rendererBI->signal_edited().connect( sigc::mem_fun(*this, &SwatchesPanel::_handleEdited) );
+ _text_rendererBI->signal_editing_canceled().connect( sigc::mem_fun(*this, &SwatchesPanel::_handleEditingCancelled) );
+
+ _editBI.set_expander_column( *_editBI.get_column(nameColNum) );
+
+ _editBI.signal_button_press_event().connect( sigc::mem_fun(*this, &SwatchesPanel::_handleButtonEvent), false );
+ _editBI.signal_button_release_event().connect( sigc::mem_fun(*this, &SwatchesPanel::_handleButtonEvent), false );
+ _editBI.signal_key_press_event().connect( sigc::mem_fun(*this, &SwatchesPanel::_handleKeyEvent), false );
+
+ _editBI.signal_drag_drop().connect( sigc::mem_fun(*this, &SwatchesPanel::_handleDragDrop), false);
+ _editBI.signal_row_collapsed().connect( sigc::bind<bool>(sigc::mem_fun(*this, &SwatchesPanel::_setExpanded), false));
+ _editBI.signal_row_expanded().connect( sigc::bind<bool>(sigc::mem_fun(*this, &SwatchesPanel::_setExpanded), true));
+
+ _scrollerBI.set_policy( Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC );
+ _scrollerBI.set_shadow_type(Gtk::SHADOW_IN);
+ _scrollerBI.add(_editBI);
+
+ _editBIV.pack_start(_scrollerBI, Gtk::PACK_EXPAND_WIDGET);
+ _editBIV.pack_end(_buttonsRowBI, Gtk::PACK_SHRINK);
+
+ _notebook.append_page(_editBIV, "Edit Built-In");
+ }
+
+ _getContents()->pack_end(_notebook, Gtk::PACK_EXPAND_WIDGET);
+ } else {
+ //_outsideV.pack_end(_scroller, Gtk::PACK_SHRINK);
+ _buttonsRow.pack_end(_scroller, Gtk::PACK_EXPAND_WIDGET);
+ //_getContents()->pack_end(_outsideV, Gtk::PACK_SHRINK);
+ _getContents()->pack_end(_buttonsRow, Gtk::PACK_SHRINK);
}
+
+ loadPalletFile();
+
+ rootWatcher = new SwatchWatcher(this, SwatchDocument->getDefs(), true);
+ SwatchDocument->getDefs()->getRepr()->addObserver(*rootWatcher);
+ _swatchesChanged();
}
-void SwatchesPanel::_setSelectedIndex( int index )
+SwatchesPanel::~SwatchesPanel()
{
- std::vector<SwatchPage*> pages = _getSwatchSets();
- if ( index >= 0 && index < static_cast<int>(pages.size()) ) {
- _currentIndex = index;
+ if (rootWatcher) {
+ rootWatcher->_repr->removeObserver(*rootWatcher);
+ delete rootWatcher;
+ }
+
+ if (docWatcher) {
+ docWatcher->_repr->removeObserver(*docWatcher);
+ delete docWatcher;
+ }
+
+ _documentConnection.disconnect();
+ _selChanged.disconnect();
+}
- if ( !_prefs_path.empty() ) {
- Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- prefs->setString(_prefs_path + "/palette", pages[_currentIndex]->_name);
+void SwatchesPanel::setDesktop( SPDesktop* desktop )
+{
+ Inkscape::UI::Widget::Panel::setDesktop(desktop);
+ if ( desktop != _currentDesktop ) {
+ if ( _currentDesktop ) {
+ _documentConnection.disconnect();
+ _selChanged.disconnect();
}
- _rebuild();
+ _currentDesktop = desktop;
+
+ if ( desktop ) {
+ //_currentDesktop->selection->connectChanged(sigc::hide(sigc::mem_fun(*this, &SwatchesPanel::_updateFromSelection)));
+
+ _documentConnection = desktop->connectDocumentReplaced(sigc::mem_fun(*this, &SwatchesPanel::_setDocument));
+
+ _setDocument( desktop, desktop->doc() );
+ } else {
+ _setDocument(0, 0);
+ }
}
}
-void SwatchesPanel::_rebuild()
+void SwatchesPanel::_setDocument( SPDesktop* desktop, SPDocument *document )
{
- std::vector<SwatchPage*> pages = _getSwatchSets();
- if (_currentIndex < static_cast<int>(pages.size())) {
- SwatchPage* curr = pages[_currentIndex];
- _holder->clear();
-
- if ( curr->_prefWidth > 0 ) {
- _holder->setColumnPref( curr->_prefWidth );
+ if ( document != _currentDocument ) {
+ if (docWatcher) {
+ docWatcher->_repr->removeObserver(*docWatcher);
+ delete docWatcher;
+ docWatcher = NULL;
}
- _holder->freezeUpdates();
- // TODO restore once 'clear' works _holder->addPreview(_clear);
- _holder->addPreview(_remove);
- for ( boost::ptr_vector<ColorItem>::iterator it = curr->_colors.begin(); it != curr->_colors.end(); ++it) {
- _holder->addPreview(&*it);
+ _currentDocument = document;
+
+ if (_currentDocument) {
+ docWatcher = new SwatchWatcher(this, _currentDocument->getDefs(), false);
+ _currentDocument->getDefs()->getRepr()->addObserver(*docWatcher);
}
- _holder->thawUpdates();
+ _defsChanged();
}
}
@@ -1241,6 +2323,48 @@ void SwatchesPanel::_rebuild()
} //namespace UI
} //namespace Inkscape
+//should be okay to add this here
+guint get_group0_keyval(GdkEventKey *event) {
+ guint keyval = 0;
+ gdk_keymap_translate_keyboard_state(gdk_keymap_get_for_display(
+ gdk_display_get_default()), event->hardware_keycode,
+ (GdkModifierType) event->state, 0 /*event->key.group*/, &keyval,
+ NULL, NULL, NULL);
+ return keyval;
+}
+
+void
+sp_desktop_set_gradient(SPDesktop *desktop, SPGradient* gradient, bool fill)
+{
+
+ bool intercepted = false;
+
+ if (gradient->isSolid()) {
+ ColorRGBA color(gradient->getFirstStop()->getEffectiveColor().toRGBA32(gradient->getFirstStop()->opacity));
+ guint32 rgba = SP_RGBA32_F_COMPOSE(color[0], color[1], color[2], color[3]);
+ gchar b[64];
+ sp_svg_write_color(b, sizeof(b), rgba);
+ SPCSSAttr *css = sp_repr_css_attr_new();
+ if (fill) {
+ sp_repr_css_set_property(css, "fill", b);
+ Inkscape::CSSOStringStream osalpha;
+ osalpha << color[3];
+ sp_repr_css_set_property(css, "fill-opacity", osalpha.str().c_str());
+ } else {
+ sp_repr_css_set_property(css, "stroke", b);
+ Inkscape::CSSOStringStream osalpha;
+ osalpha << color[3];
+ sp_repr_css_set_property(css, "stroke-opacity", osalpha.str().c_str());
+ }
+ intercepted = desktop->_set_style_signal.emit(css);
+ }
+
+ if (!intercepted) {
+ for (const GSList *it = desktop->selection->itemList(); it != NULL; it = it->next) {
+ sp_item_set_gradient(SP_ITEM(it->data), gradient, SP_IS_RADIALGRADIENT(gradient) ? SP_GRADIENT_TYPE_RADIAL : SP_GRADIENT_TYPE_LINEAR, !fill ? Inkscape::FOR_STROKE : Inkscape::FOR_FILL);
+ }
+ }
+}
/*
Local Variables:
diff --git a/src/ui/dialog/swatches.h b/src/ui/dialog/swatches.h
index 3abb81d98..cb8f87962 100644
--- a/src/ui/dialog/swatches.h
+++ b/src/ui/dialog/swatches.h
@@ -12,66 +12,161 @@
#include "ui/widget/panel.h"
#include "enums.h"
+#include "sp-object.h"
+#include "sp-item-group.h"
+#include <gtk/gtk.h>
+#include <gtkmm/radiomenuitem.h>
+#include <gtkmm/menuitem.h>
+#include <gtkmm/scrolledwindow.h>
+#include <gtkmm/table.h>
+#include <gtkmm/box.h>
+#include <gtkmm/menu.h>
+#include <gtkmm/notebook.h>
+#include <gtkmm/treeview.h>
+#include <gtkmm/treestore.h>
+#include <gtkmm/treemodel.h>
+#include "sp-gradient.h"
+#include "xml/node-observer.h"
namespace Inkscape {
namespace UI {
-class PreviewHolder;
-
namespace Dialogs {
-class ColorItem;
-class SwatchPage;
-class DocTrack;
-
/**
* A panel that displays paint swatches.
*/
class SwatchesPanel : public Inkscape::UI::Widget::Panel
{
public:
- SwatchesPanel(gchar const* prefsPath = "/dialogs/swatches");
+ SwatchesPanel(gchar const* prefsPath = "/dialogs/swatches", bool showLabels = true);
virtual ~SwatchesPanel();
-
+
static SwatchesPanel& getInstance();
- virtual void setOrientation(SPAnchorType how);
-
virtual void setDesktop( SPDesktop* desktop );
virtual SPDesktop* getDesktop() {return _currentDesktop;}
- virtual int getSelectedIndex() {return _currentIndex;} // temporary
-
protected:
- static void handleDocumentDestroy(SPDocument *document);
- static void handleGradientsChange(SPDocument *document);
-
- virtual void _updateFromSelection();
- virtual void _handleAction( int setId, int itemId );
- virtual void _setDocument( SPDocument *document );
- virtual void _setSelectedIndex( int index );
- virtual void _rebuild();
- virtual std::vector<SwatchPage*> _getSwatchSets() const;
+ virtual void _setDocument( SPDesktop* desktop, SPDocument *document );
private:
+ class ModelColumns;
+ class ModelColumnsDoc;
+
+ class StopWatcher;
+ class GradientWatcher;
+ class SwatchWatcher;
+
SwatchesPanel(SwatchesPanel const &); // no copy
SwatchesPanel &operator=(SwatchesPanel const &); // no assign
+
+ void _styleButton( Gtk::Button& btn, SPDesktop *desktop, unsigned int code, char const* iconName, char const* fallback );
+
+ void _setSelectionSwatch(SPGradient* swatchItem, bool isStroke);
+
+ void NoLinkToggled();
+ void NewGroup();
+ void NewGroupBI();
+ void _addBIButtonClicked(GdkEventButton* event);
+ void Duplicate(SPGroup* page);
+ void SaveAs();
+ void AddSelectedFill(SPGroup* page);
+ void AddSelectedStroke(SPGroup* page);
+ void MoveUp(SPGroup* page);
+ void MoveDown(SPGroup* page);
+ void Remove(SPGroup* page);
+
+ void SetSelectedFill(SPGradient* swatch);
+ void SetSelectedStroke(SPGradient* swatch);
+ void MoveSwatchUp(SPGradient* swatch);
+ void MoveSwatchDown(SPGradient* swatch);
+ void RemoveSwatch(SPGradient* swatch);
+
+ void _lblClick(GdkEventButton* event, SPGroup* page);
+ void _addSwatchButtonClicked(SPGroup* swatch, bool recurse);
+ void _defsChanged();
+ void _importButtonClicked(bool addToDoc, bool addToBI);
+ void _deleteButtonClicked();
+ void _addButtonClicked(GdkEventButton* event);
+ void _swatchClicked(GdkEventButton* event, SPGradient* swatchItem);
+
+ Gtk::MenuItem* _addSwatchGroup(SPGroup* group, Gtk::TreeModel::Row* parentRow);
+ void _swatchesChanged();
+
+ bool _handleButtonEvent(GdkEventButton *event);
+ bool _handleKeyEvent(GdkEventKey *event);
+
+ void _handleEdited(const Glib::ustring& path, const Glib::ustring& new_text);
+ void _handleEditingCancelled();
+ void _renameObject(Gtk::TreeModel::Row row, const Glib::ustring& name);
+
+ void _setCollapsed(SPGroup * group);
+ void _setExpanded(const Gtk::TreeModel::iterator& iter, const Gtk::TreeModel::Path& /*path*/, bool isexpanded);
+
+ void _deleteButtonClickedDoc();
+ bool _handleButtonEventDoc(GdkEventButton* event);
+ bool _handleKeyEventDoc(GdkEventKey *event);
+
+ void _handleEditedDoc(const Glib::ustring& path, const Glib::ustring& new_text);
+ void _handleEditingCancelledDoc();
+ void _renameObjectDoc(Gtk::TreeModel::Row row, const Glib::ustring& name);
+
+ bool _handleDragDropDoc(const Glib::RefPtr<Gdk::DragContext>& context, int x, int y, guint time);
+ bool _handleDragDrop(const Glib::RefPtr<Gdk::DragContext>& context, int x, int y, guint time);
+
+ Gtk::Menu *popUpMenu;
+ Gtk::Menu *popUpImportMenu;
+
+ Gtk::ScrolledWindow _scroller;
+ Gtk::Table _insideTable;
+ Gtk::VBox _insideV;
+ Gtk::HBox _insideH;
+ Gtk::HBox _buttonsRow;
+ Gtk::VBox _outsideV;
+ Gtk::CheckButton _noLink;
+ bool _showlabels;
+
+ SwatchesPanel::ModelColumns* _model;
+ Glib::RefPtr<Gtk::TreeStore> _store;
+
+ Gtk::CellRendererText *_text_rendererBI;
+ Gtk::TreeView::Column *_name_columnBI;
+ Gtk::ScrolledWindow _scrollerBI;
+ Gtk::TreeView _editBI;
+ Gtk::HBox _buttonsRowBI;
+ Gtk::VBox _editBIV;
+
+ SwatchesPanel::ModelColumnsDoc* _modelDoc;
+ Glib::RefPtr<Gtk::TreeStore> _storeDoc;
+
+ Gtk::CellRendererText *_text_rendererDoc;
+ Gtk::CellRendererPixbuf *_pixbuf_rendererDoc;
+ Gtk::TreeView::Column *_name_columnDoc;
+ Gtk::TreeView::Column *_pixbuf_columnDoc;
+ Gtk::ScrolledWindow _scrollerDoc;
+ Gtk::TreeView _editDoc;
+ Gtk::HBox _buttonsRowDoc;
+ Gtk::VBox _editDocV;
+
+ Gtk::Notebook _notebook;
+
+ SwatchWatcher* rootWatcher;
+ std::vector<Inkscape::XML::NodeObserver*> rootWatchers;
+
+ std::vector<Inkscape::XML::NodeObserver*> docWatchers;
+ SwatchWatcher* docWatcher;
- static void _trackDocument( SwatchesPanel *panel, SPDocument *document );
- static void handleDefsModified(SPDocument *document);
-
- PreviewHolder* _holder;
- ColorItem* _clear;
- ColorItem* _remove;
- int _currentIndex;
SPDesktop* _currentDesktop;
SPDocument* _currentDocument;
+
+ bool _dnd_into;
+ SPObject* _dnd_source;
+ SPObject* _dnd_target;
sigc::connection _documentConnection;
sigc::connection _selChanged;
-
- friend class DocTrack;
};
} //namespace Dialogs