summaryrefslogtreecommitdiffstats
path: root/src/ui
diff options
context:
space:
mode:
authorsu_v <suv-sf@users.sourceforge.net>2012-10-12 17:18:08 +0000
committer~suv <suv-sf@users.sourceforge.net>2012-10-12 17:18:08 +0000
commitd997c6a08a0d1184e8a4aec708033d0f548802f8 (patch)
treee644b11bedb210813006dbfe4fb6a703bb642fae /src/ui
parentmerge from trunk (r11761) (diff)
parentFix for compiling with pre gtkmm 2.24 libraries. (diff)
downloadinkscape-d997c6a08a0d1184e8a4aec708033d0f548802f8.tar.gz
inkscape-d997c6a08a0d1184e8a4aec708033d0f548802f8.zip
merge from trunk (r11787)
(bzr r11668.1.28)
Diffstat (limited to 'src/ui')
-rw-r--r--src/ui/clipboard.cpp50
-rw-r--r--src/ui/clipboard.h2
-rw-r--r--src/ui/dialog/Makefile_insert2
-rw-r--r--src/ui/dialog/dialog-manager.cpp3
-rw-r--r--src/ui/dialog/layer-properties.cpp7
-rw-r--r--src/ui/dialog/layers.cpp62
-rw-r--r--src/ui/dialog/symbols.cpp591
-rw-r--r--src/ui/dialog/symbols.h114
-rw-r--r--src/ui/widget/style-swatch.cpp7
9 files changed, 817 insertions, 21 deletions
diff --git a/src/ui/clipboard.cpp b/src/ui/clipboard.cpp
index f1f6c4ab4..8cdb37f4f 100644
--- a/src/ui/clipboard.cpp
+++ b/src/ui/clipboard.cpp
@@ -7,9 +7,11 @@
* Jon A. Cruz <jon@joncruz.org>
* Incorporates some code from selection-chemistry.cpp, see that file for more credits.
* Abhishek Sharma
+ * Tavmjong Bah
*
* Copyright (C) 2008 authors
* Copyright (C) 2010 Jon A. Cruz
+ * Copyright (C) 2012 Tavmjong Bah (Symbol additions)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -66,6 +68,8 @@
#include "sp-mask.h"
#include "sp-textpath.h"
#include "sp-rect.h"
+#include "sp-use.h"
+#include "sp-symbol.h"
#include "live_effects/lpeobject.h"
#include "live_effects/lpeobject-reference.h"
#include "live_effects/parameter/path.h"
@@ -109,6 +113,7 @@ class ClipboardManagerImpl : public ClipboardManager {
public:
virtual void copy(SPDesktop *desktop);
virtual void copyPathParameter(Inkscape::LivePathEffect::PathParam *);
+ virtual void copySymbol(Inkscape::XML::Node* symbol, gchar const* style);
virtual bool paste(SPDesktop *desktop, bool in_place);
virtual bool pasteStyle(SPDesktop *desktop);
virtual bool pasteSize(SPDesktop *desktop, bool separately, bool apply_x, bool apply_y);
@@ -295,6 +300,43 @@ void ClipboardManagerImpl::copyPathParameter(Inkscape::LivePathEffect::PathParam
}
/**
+ * Copy a symbol from the symbol dialog.
+ * @param symbol The Inkscape::XML::Node for the symbol.
+ */
+void ClipboardManagerImpl::copySymbol(Inkscape::XML::Node* symbol, gchar const* style)
+{
+ //std::cout << "ClipboardManagerImpl::copySymbol" << std::endl;
+ if ( symbol == NULL ) {
+ return;
+ }
+
+ _discardInternalClipboard();
+ _createInternalClipboard();
+
+ // We add "_duplicate" to have a well defined symbol name that
+ // bypasses the "prevent_id_classes" routine. We'll get rid of it
+ // when we paste.
+ Inkscape::XML::Node *repr = symbol->duplicate(_doc);
+ Glib::ustring symbol_name = repr->attribute("id");
+
+ symbol_name += "_inkscape_duplicate";
+ repr->setAttribute("id", symbol_name.c_str());
+ _defs->appendChild(repr);
+
+ Glib::ustring id("#");
+ id += symbol->attribute("id");
+
+ Inkscape::XML::Node *use = _doc->createElement("svg:use");
+ use->setAttribute("xlink:href", id.c_str() );
+ // Set a default style in <use> rather than <symbol> so it can be changed.
+ use->setAttribute("style", style );
+ _root->appendChild(use);
+
+ fit_canvas_to_drawing(_clipboardSPDoc);
+ _setClipboardTargets();
+}
+
+/**
* Paste from the system clipboard into the active desktop.
* @param in_place Whether to put the contents where they were when copied.
*/
@@ -725,6 +767,14 @@ void ClipboardManagerImpl::_copyUsedDefs(SPItem *item)
}
}
+ // Copy symbols: We may want to be more clever...
+ // if (SP_IS_USE(item)) {
+ // SPObject *symbol = SP_USE(item)->child;
+ // if( symbol && SP_IS_SYMBOL(symbol) ) {
+ // _copyNode(symbol->getRepr(), _doc, _defs);
+ // }
+ // }
+
// recurse
for (SPObject *o = item->children ; o != NULL ; o = o->next) {
if (SP_IS_ITEM(o)) {
diff --git a/src/ui/clipboard.h b/src/ui/clipboard.h
index fb28bfc14..b565740c3 100644
--- a/src/ui/clipboard.h
+++ b/src/ui/clipboard.h
@@ -25,6 +25,7 @@
class SPDesktop;
namespace Inkscape {
class Selection;
+namespace XML { class Node; }
namespace LivePathEffect { class PathParam; }
namespace UI {
@@ -43,6 +44,7 @@ class ClipboardManager {
public:
virtual void copy(SPDesktop *desktop) = 0;
virtual void copyPathParameter(Inkscape::LivePathEffect::PathParam *) = 0;
+ virtual void copySymbol(Inkscape::XML::Node* symbol, gchar const* style) = 0;
virtual bool paste(SPDesktop *desktop, bool in_place = false) = 0;
virtual bool pasteStyle(SPDesktop *desktop) = 0;
virtual bool pasteSize(SPDesktop *desktop, bool separately, bool apply_x, bool apply_y) = 0;
diff --git a/src/ui/dialog/Makefile_insert b/src/ui/dialog/Makefile_insert
index ba2f53a9e..580b47522 100644
--- a/src/ui/dialog/Makefile_insert
+++ b/src/ui/dialog/Makefile_insert
@@ -89,6 +89,8 @@ ink_common_sources += \
ui/dialog/svg-fonts-dialog.h \
ui/dialog/swatches.cpp \
ui/dialog/swatches.h \
+ ui/dialog/symbols.cpp \
+ ui/dialog/symbols.h \
ui/dialog/text-edit.cpp \
ui/dialog/text-edit.h \
ui/dialog/tile.cpp \
diff --git a/src/ui/dialog/dialog-manager.cpp b/src/ui/dialog/dialog-manager.cpp
index 60011ca9d..faba47769 100644
--- a/src/ui/dialog/dialog-manager.cpp
+++ b/src/ui/dialog/dialog-manager.cpp
@@ -33,6 +33,7 @@
#include "ui/dialog/memory.h"
#include "ui/dialog/messages.h"
#include "ui/dialog/scriptdialog.h"
+#include "ui/dialog/symbols.h"
#include "ui/dialog/tile.h"
#include "ui/dialog/tracedialog.h"
#include "ui/dialog/transformation.h"
@@ -121,6 +122,7 @@ DialogManager::DialogManager() {
registerFactory("SvgFontsDialog", &create<SvgFontsDialog, FloatingBehavior>);
#endif
registerFactory("Swatches", &create<SwatchesPanel, FloatingBehavior>);
+ registerFactory("Symbols", &create<SymbolsDialog, FloatingBehavior>);
registerFactory("TileDialog", &create<TileDialog, FloatingBehavior>);
registerFactory("Trace", &create<TraceDialog, FloatingBehavior>);
registerFactory("Transformation", &create<Transformation, FloatingBehavior>);
@@ -156,6 +158,7 @@ DialogManager::DialogManager() {
registerFactory("SvgFontsDialog", &create<SvgFontsDialog, DockBehavior>);
#endif
registerFactory("Swatches", &create<SwatchesPanel, DockBehavior>);
+ registerFactory("Symbols", &create<SymbolsDialog, DockBehavior>);
registerFactory("TileDialog", &create<TileDialog, DockBehavior>);
registerFactory("Trace", &create<TraceDialog, DockBehavior>);
registerFactory("Transformation", &create<Transformation, DockBehavior>);
diff --git a/src/ui/dialog/layer-properties.cpp b/src/ui/dialog/layer-properties.cpp
index 35a235dbc..4f9edf774 100644
--- a/src/ui/dialog/layer-properties.cpp
+++ b/src/ui/dialog/layer-properties.cpp
@@ -331,8 +331,11 @@ void LayerPropertiesDialog::Rename::perform(LayerPropertiesDialog &dialog) {
void LayerPropertiesDialog::Create::setup(LayerPropertiesDialog &dialog) {
dialog.set_title(_("Add Layer"));
- //TODO: find an unused layer number, forming name from _("Layer ") + "%d"
- dialog._layer_name_entry.set_text(_("Layer"));
+
+ // Set the initial name to the "next available" layer name
+ LayerManager *mgr = dialog._desktop->layer_manager;
+ Glib::ustring newName = mgr->getNextLayerName(NULL, dialog._desktop->currentLayer()->label());
+ dialog._layer_name_entry.set_text(newName.c_str());
dialog._apply_button.set_label(_("_Add"));
dialog._setup_position_controls();
}
diff --git a/src/ui/dialog/layers.cpp b/src/ui/dialog/layers.cpp
index 70cf7075c..55a2f19a5 100644
--- a/src/ui/dialog/layers.cpp
+++ b/src/ui/dialog/layers.cpp
@@ -69,6 +69,9 @@ enum {
BUTTON_SOLO,
BUTTON_SHOW_ALL,
BUTTON_HIDE_ALL,
+ BUTTON_LOCK_OTHERS,
+ BUTTON_LOCK_ALL,
+ BUTTON_UNLOCK_ALL,
DRAGNDROP
};
@@ -263,6 +266,21 @@ bool LayersPanel::_executeAction()
_fireAction( SP_VERB_LAYER_HIDE_ALL );
}
break;
+ case BUTTON_LOCK_OTHERS:
+ {
+ _fireAction( SP_VERB_LAYER_LOCK_OTHERS );
+ }
+ break;
+ case BUTTON_LOCK_ALL:
+ {
+ _fireAction( SP_VERB_LAYER_LOCK_ALL );
+ }
+ break;
+ case BUTTON_UNLOCK_ALL:
+ {
+ _fireAction( SP_VERB_LAYER_UNLOCK_ALL );
+ }
+ break;
case DRAGNDROP:
{
_doTreeMove( );
@@ -544,26 +562,36 @@ void LayersPanel::_handleButtonEvent(GdkEventButton* event)
{
static unsigned doubleclick = 0;
- // TODO - fix to a better is-popup function
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 ( _tree.get_path_at_pos( x, y, path ) ) {
+ _checkTreeSelection();
+ _popupMenu.popup(event->button, event->time);
+ }
+ }
- {
- 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 ( _tree.get_path_at_pos( x, y,
- path, col,
- x2, y2 ) ) {
- _checkTreeSelection();
- _popupMenu.popup(event->button, event->time);
+ if ( event->type == GDK_BUTTON_RELEASE && (event->button == 1)
+ && (event->state & GDK_SHIFT_MASK)) {
+ // Shift left click on the visible/lock columns toggles "solo" mode
+ 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 ( _tree.get_path_at_pos( x, y, path, col, x2, y2 ) ) {
+ if (col == _tree.get_column(COL_VISIBLE-1)) {
+ _takeAction(BUTTON_SOLO);
+ } else if (col == _tree.get_column(COL_LOCKED-1)) {
+ _takeAction(BUTTON_LOCK_OTHERS);
}
}
-
}
+
if ( (event->type == GDK_2BUTTON_PRESS) && (event->button == 1) ) {
doubleclick = 1;
}
@@ -876,6 +904,12 @@ LayersPanel::LayersPanel() :
_popupMenu.append(*manage(new Gtk::SeparatorMenuItem()));
+ _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_LOCK_OTHERS, 0, "Lock Others", (int)BUTTON_LOCK_OTHERS ) );
+ _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_LOCK_ALL, 0, "Lock All", (int)BUTTON_LOCK_ALL ) );
+ _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_UNLOCK_ALL, 0, "Unlock All", (int)BUTTON_UNLOCK_ALL ) );
+
+ _popupMenu.append(*manage(new Gtk::SeparatorMenuItem()));
+
_watchingNonTop.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_RAISE, GTK_STOCK_GO_UP, "Up", (int)BUTTON_UP ) );
_watchingNonBottom.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_LOWER, GTK_STOCK_GO_DOWN, "Down", (int)BUTTON_DOWN ) );
diff --git a/src/ui/dialog/symbols.cpp b/src/ui/dialog/symbols.cpp
new file mode 100644
index 000000000..21a178b57
--- /dev/null
+++ b/src/ui/dialog/symbols.cpp
@@ -0,0 +1,591 @@
+/**
+ * @file
+ * Symbols dialog.
+ */
+/* Authors:
+ * Copyright (C) 2012 Tavmjong Bah
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <iostream>
+#include <algorithm>
+
+#include <gtkmm/buttonbox.h>
+#include <gtkmm/label.h>
+#include <gtkmm/table.h>
+#include <gtkmm/scrolledwindow.h>
+#include <gtkmm/comboboxtext.h>
+#include <gtkmm/iconview.h>
+#include <gtkmm/liststore.h>
+#include <gtkmm/treemodelcolumn.h>
+#include <gtkmm/clipboard.h>
+
+#include "path-prefix.h"
+#include "io/sys.h"
+
+#include "ui/cache/svg_preview_cache.h"
+#include "ui/clipboard.h"
+
+#include "symbols.h"
+
+#include "desktop.h"
+#include "desktop-handles.h"
+#include "document.h"
+#include "inkscape.h"
+#include "sp-root.h"
+#include "sp-use.h"
+#include "sp-symbol.h"
+
+#include "verbs.h"
+#include "xml/repr.h"
+
+namespace Inkscape {
+namespace UI {
+
+static Cache::SvgPreview svg_preview_cache;
+
+namespace Dialog {
+
+ // See: http://developer.gnome.org/gtkmm/stable/classGtk_1_1TreeModelColumnRecord.html
+class SymbolColumns : public Gtk::TreeModel::ColumnRecord
+{
+public:
+
+ Gtk::TreeModelColumn<Glib::ustring> symbol_id;
+ Gtk::TreeModelColumn<Glib::ustring> symbol_title;
+ Gtk::TreeModelColumn< Glib::RefPtr<Gdk::Pixbuf> > symbol_image;
+
+ SymbolColumns() {
+ add(symbol_id);
+ add(symbol_title);
+ add(symbol_image);
+ }
+};
+
+SymbolColumns* SymbolsDialog::getColumns()
+{
+ SymbolColumns* columns = new SymbolColumns();
+ return columns;
+}
+
+/**
+ * Constructor
+ */
+SymbolsDialog::SymbolsDialog( gchar const* prefsPath ) :
+ UI::Widget::Panel("", prefsPath, SP_VERB_DIALOG_SYMBOLS),
+ store(Gtk::ListStore::create(*getColumns())),
+ iconView(0),
+ previewScale(0),
+ previewSize(0),
+ currentDesktop(0),
+ deskTrack(),
+ currentDocument(0),
+ previewDocument(0),
+ instanceConns()
+{
+
+ /******************** Table *************************/
+ // Replace by Grid for GTK 3.0
+ Gtk::Table *table = new Gtk::Table(2, 4, false);
+ // panel is a cloked Gtk::VBox
+ _getContents()->pack_start(*Gtk::manage(table), Gtk::PACK_EXPAND_WIDGET);
+ guint row = 0;
+
+ /******************** Symbol Sets *************************/
+ Gtk::Label* labelSet = new Gtk::Label("Symbol set: ");
+ table->attach(*Gtk::manage(labelSet),0,1,row,row+1,Gtk::SHRINK,Gtk::SHRINK);
+
+ symbolSet = new Gtk::ComboBoxText(); // Fill in later
+#if WITH_GTKMM_2_24
+ symbolSet->append("Current Document");
+#else
+ symbolSet->append_text("Current Document");
+#endif
+ symbolSet->set_active_text("Current Document");
+ table->attach(*Gtk::manage(symbolSet),1,2,row,row+1,Gtk::FILL|Gtk::EXPAND,Gtk::SHRINK);
+
+ sigc::connection connSet =
+ symbolSet->signal_changed().connect(sigc::mem_fun(*this, &SymbolsDialog::rebuild));
+ instanceConns.push_back(connSet);
+
+ ++row;
+
+ /********************* Icon View **************************/
+ SymbolColumns* columns = getColumns();
+
+ iconView = new Gtk::IconView(static_cast<Glib::RefPtr<Gtk::TreeModel> >(store));
+ //iconView->set_text_column( columns->symbol_id );
+ iconView->set_tooltip_column( 1 );
+ iconView->set_pixbuf_column( columns->symbol_image );
+
+ sigc::connection connIconChanged;
+ connIconChanged =
+ iconView->signal_selection_changed().connect(sigc::mem_fun(*this, &SymbolsDialog::iconChanged));
+ instanceConns.push_back(connIconChanged);
+
+ Gtk::ScrolledWindow *scroller = new Gtk::ScrolledWindow();
+ scroller->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_ALWAYS);
+ scroller->add(*Gtk::manage(iconView));
+ table->attach(*Gtk::manage(scroller),0,2,row,row+1,Gtk::EXPAND|Gtk::FILL,Gtk::EXPAND|Gtk::FILL);
+
+ ++row;
+
+ /******************** Preview Scale ***********************/
+ Gtk::Label* labelScale = new Gtk::Label("Preview scale: ");
+ table->attach(*Gtk::manage(labelScale),0,1,row,row+1,Gtk::SHRINK,Gtk::SHRINK);
+
+ previewScale = new Gtk::ComboBoxText();
+ const gchar *scales[] =
+ {"Fit", "Fit to width", "Fit to height", "0.1", "0.2", "0.5", "1.0", "2.0", "5.0", NULL};
+ for( int i = 0; scales[i]; ++i ) {
+#if WITH_GTKMM_2_24
+ previewScale->append(scales[i]);
+#else
+ previewScale->append_text(scales[i]);
+#endif
+ }
+ previewScale->set_active_text(scales[0]);
+ table->attach(*Gtk::manage(previewScale),1,2,row,row+1,Gtk::FILL|Gtk::EXPAND,Gtk::SHRINK);
+
+ sigc::connection connScale =
+ previewScale->signal_changed().connect(sigc::mem_fun(*this, &SymbolsDialog::rebuild));
+ instanceConns.push_back(connScale);
+
+ ++row;
+
+ /******************** Preview Size ************************/
+ Gtk::Label* labelSize = new Gtk::Label("Preview size: ");
+ table->attach(*Gtk::manage(labelSize),0,1,row,row+1,Gtk::SHRINK,Gtk::SHRINK);
+
+ previewSize = new Gtk::ComboBoxText();
+ const gchar *sizes[] = {"16", "24", "32", "48", "64", NULL};
+ for( int i = 0; sizes[i]; ++i ) {
+#if WITH_GTKMM_2_24
+ previewSize->append(sizes[i]);
+#else
+ previewSize->append_text(sizes[i]);
+#endif
+
+ }
+ previewSize->set_active_text(sizes[2]);
+ table->attach(*Gtk::manage(previewSize),1,2,row,row+1,Gtk::FILL|Gtk::EXPAND,Gtk::SHRINK);
+
+ sigc::connection connSize =
+ previewSize->signal_changed().connect(sigc::mem_fun(*this, &SymbolsDialog::rebuild));
+ instanceConns.push_back(connSize);
+
+ ++row;
+
+ /**********************************************************/
+ currentDesktop = inkscape_active_desktop();
+ currentDocument = sp_desktop_document(currentDesktop);
+
+ previewDocument = symbols_preview_doc(); /* Template to render symbols in */
+ previewDocument->ensureUpToDate(); /* Necessary? */
+
+ key = SPItem::display_key_new(1);
+ renderDrawing.setRoot(previewDocument->getRoot()->invoke_show(renderDrawing, key, SP_ITEM_SHOW_DISPLAY ));
+
+ get_symbols();
+ draw_symbols( currentDocument ); /* Defaults to current document */
+
+ desktopChangeConn =
+ deskTrack.connectDesktopChanged( sigc::mem_fun(*this, &SymbolsDialog::setTargetDesktop) );
+ instanceConns.push_back( desktopChangeConn );
+ deskTrack.connect(GTK_WIDGET(gobj()));
+}
+
+SymbolsDialog::~SymbolsDialog()
+{
+ for (std::vector<sigc::connection>::iterator it = instanceConns.begin(); it != instanceConns.end(); ++it) {
+ it->disconnect();
+ }
+ instanceConns.clear();
+ deskTrack.disconnect();
+}
+
+SymbolsDialog& SymbolsDialog::getInstance()
+{
+ return *new SymbolsDialog();
+}
+
+void SymbolsDialog::rebuild() {
+
+ store->clear();
+ Glib::ustring symbolSetString = symbolSet->get_active_text();
+
+ SPDocument* symbolDocument = symbolSets[symbolSetString];
+ if( !symbolDocument ) {
+ // Symbol must be from Current Document (this method of
+ // checking should be language independent).
+ symbolDocument = currentDocument;
+ }
+ draw_symbols( symbolDocument );
+}
+
+void SymbolsDialog::iconChanged() {
+#if WITH_GTKMM_3_0
+ std::vector<Gtk::TreePath> iconArray = iconView->get_selected_items();
+#else
+ Gtk::IconView::ArrayHandle_TreePaths iconArray = iconView->get_selected_items();
+#endif
+
+ if( iconArray.empty() ) {
+ //std::cout << " iconArray empty: huh? " << std::endl;
+ } else {
+ Gtk::TreeModel::Path const & path = *iconArray.begin();
+ Gtk::ListStore::iterator row = store->get_iter(path);
+ Glib::ustring symbol_id = (*row)[getColumns()->symbol_id];
+
+ /* OK, we know symbol name... now we need to copy it to clipboard, bon chance! */
+ Glib::ustring symbolSetString = symbolSet->get_active_text();
+
+ SPDocument* symbolDocument = symbolSets[symbolSetString];
+ if( !symbolDocument ) {
+ // Symbol must be from Current Document (this method of
+ // checking should be language independent).
+ symbolDocument = currentDocument;
+ }
+
+ SPObject* symbol = symbolDocument->getObjectById(symbol_id);
+ if( symbol ) {
+
+ // Find style for use in <use>
+ // First look for default style stored in <symbol>
+ gchar const* style = symbol->getAttribute("inkscape:symbol-style");
+ if( !style ) {
+ // If no default style in <symbol>, look in documents.
+ if( symbolDocument == currentDocument ) {
+ style = style_from_use( symbol_id.c_str(), currentDocument );
+ } else {
+ style = symbolDocument->getReprRoot()->attribute("style");
+ }
+ }
+
+ ClipboardManager *cm = ClipboardManager::get();
+ cm->copySymbol(symbol->getRepr(), style);
+ }
+ }
+}
+
+/* Hunts preference directories for symbol files */
+void SymbolsDialog::get_symbols() {
+
+ std::list<Glib::ustring> directories;
+
+ if( Inkscape::IO::file_test( INKSCAPE_SYMBOLSDIR, G_FILE_TEST_EXISTS ) &&
+ Inkscape::IO::file_test( INKSCAPE_SYMBOLSDIR, G_FILE_TEST_IS_DIR ) ) {
+ directories.push_back( INKSCAPE_SYMBOLSDIR );
+ }
+ if( Inkscape::IO::file_test( profile_path("symbols"), G_FILE_TEST_EXISTS ) &&
+ Inkscape::IO::file_test( profile_path("symbols"), G_FILE_TEST_IS_DIR ) ) {
+ directories.push_back( profile_path("symbols") );
+ }
+
+ std::list<Glib::ustring>::iterator it;
+ for( it = directories.begin(); it != directories.end(); ++it ) {
+
+ GError *err = 0;
+ GDir *dir = g_dir_open( (*it).c_str(), 0, &err );
+ if( dir ) {
+
+ gchar *filename = 0;
+ while( (filename = (gchar *)g_dir_read_name( dir ) ) != NULL) {
+
+ gchar *fullname = g_build_filename((*it).c_str(), filename, NULL);
+
+ if ( !Inkscape::IO::file_test( fullname, G_FILE_TEST_IS_DIR ) ) {
+
+ SPDocument* symbol_doc = SPDocument::createNewDoc( fullname, FALSE );
+ if( symbol_doc ) {
+ symbolSets[Glib::ustring(filename)]= symbol_doc;
+#if WITH_GTKMM_2_24
+ symbolSet->append(filename);
+#else
+ symbolSet->append_text(filename);
+#endif
+ }
+ }
+ g_free( fullname );
+ }
+ g_dir_close( dir );
+ }
+ }
+}
+
+GSList* SymbolsDialog::symbols_in_doc_recursive (SPObject *r, GSList *l)
+{
+
+ // Stop multiple counting of same symbol
+ if( SP_IS_USE(r) ) {
+ return l;
+ }
+
+ if( SP_IS_SYMBOL(r) ) {
+ l = g_slist_prepend (l, r);
+ }
+
+ for (SPObject *child = r->firstChild(); child; child = child->getNext()) {
+ l = symbols_in_doc_recursive( child, l );
+ }
+
+ return l;
+}
+
+GSList* SymbolsDialog::symbols_in_doc( SPDocument* symbolDocument ) {
+
+ GSList *l = NULL;
+ l = symbols_in_doc_recursive (symbolDocument->getRoot(), l );
+ return l;
+}
+
+GSList* SymbolsDialog::use_in_doc_recursive (SPObject *r, GSList *l)
+{
+
+ if( SP_IS_USE(r) ) {
+ l = g_slist_prepend (l, r);
+ }
+
+ for (SPObject *child = r->firstChild(); child; child = child->getNext()) {
+ l = use_in_doc_recursive( child, l );
+ }
+
+ return l;
+}
+
+GSList* SymbolsDialog::use_in_doc( SPDocument* useDocument ) {
+
+ GSList *l = NULL;
+ l = use_in_doc_recursive (useDocument->getRoot(), l );
+ return l;
+}
+
+// Returns style from first <use> element found that references id.
+// This is a last ditch effort to find a style.
+gchar const* SymbolsDialog::style_from_use( gchar const* id, SPDocument* document) {
+
+ gchar const* style = 0;
+ GSList* l = use_in_doc( document );
+ for( ; l != NULL; l = l->next ) {
+ SPObject* use = SP_OBJECT(l->data);
+ if( SP_IS_USE( use ) ) {
+ gchar const *href = use->getRepr()->attribute("xlink:href");
+ if( href ) {
+ Glib::ustring href2(href);
+ Glib::ustring id2(id);
+ id2 = "#" + id2;
+ if( !href2.compare(id2) ) {
+ style = use->getRepr()->attribute("style");
+ break;
+ }
+ }
+ }
+ }
+ return style;
+}
+
+void SymbolsDialog::draw_symbols( SPDocument* symbolDocument ) {
+
+
+ SymbolColumns* columns = getColumns();
+
+ GSList* l = symbols_in_doc( symbolDocument );
+ for( ; l != NULL; l = l->next ) {
+
+ SPObject* symbol = SP_OBJECT(l->data);
+ if (!SP_IS_SYMBOL(symbol)) {
+ //std::cout << " Error: not symbol" << std::endl;
+ continue;
+ }
+
+ gchar const *id = symbol->getRepr()->attribute("id");
+ gchar const *title = symbol->title(); // From title element
+ if( !title ) {
+ title = id;
+ }
+
+ Glib::RefPtr<Gdk::Pixbuf> pixbuf = create_symbol_image(id, symbolDocument, &renderDrawing, key );
+ if( pixbuf ) {
+
+ Gtk::ListStore::iterator row = store->append();
+ (*row)[columns->symbol_id] = Glib::ustring( id );
+ (*row)[columns->symbol_title] = Glib::ustring( title );
+ (*row)[columns->symbol_image] = pixbuf;
+ }
+ }
+}
+
+/*
+ * Returns image of symbol.
+ *
+ * Symbols normally are not visible. They must be referenced by a
+ * <use> element. A temporary document is created with a dummy
+ * <symbol> element and a <use> element that references the symbol
+ * element. Each real symbol is swapped in for the dummy symbol and
+ * the temporary document is rendered.
+ */
+Glib::RefPtr<Gdk::Pixbuf>
+SymbolsDialog::create_symbol_image(gchar const *symbol_id,
+ SPDocument *source,
+ Inkscape::Drawing* drawing,
+ unsigned /*visionkey*/)
+{
+
+ // Retrieve the symbol named 'symbol_id' from the source SVG document
+ SPObject const* symbol = source->getObjectById(symbol_id);
+ if (symbol == NULL) {
+ //std::cout << " Failed to find symbol: " << symbol_id << std::endl;
+ //return 0;
+ }
+
+ // Create a copy repr of the symbol with id="the_symbol"
+ Inkscape::XML::Document *xml_doc = previewDocument->getReprDoc();
+ Inkscape::XML::Node *repr = symbol->getRepr()->duplicate(xml_doc);
+ repr->setAttribute("id", "the_symbol");
+
+ // Replace old "the_symbol" in previewDocument by new.
+ Inkscape::XML::Node *root = previewDocument->getReprRoot();
+ SPObject *symbol_old = previewDocument->getObjectById("the_symbol");
+ if (symbol_old) {
+ symbol_old->deleteObject(false);
+ }
+
+ // First look for default style stored in <symbol>
+ gchar const* style = repr->attribute("inkscape:symbol-style");
+ if( !style ) {
+ // If no default style in <symbol>, look in documents.
+ if( source == currentDocument ) {
+ style = style_from_use( symbol_id, source );
+ } else {
+ style = source->getReprRoot()->attribute("style");
+ }
+ }
+
+ // This is for display in Symbols dialog only
+ if( style ) {
+ repr->setAttribute( "style", style );
+ }
+
+ // BUG: Symbols don't work if defined outside of <defs>. Causes Inkscape
+ // crash when trying to read in such a file.
+ root->appendChild(repr);
+ //defsrepr->appendChild(repr);
+ Inkscape::GC::release(repr);
+
+ // Uncomment this to get the previewDocument documents saved (useful for debugging)
+ // FILE *fp = fopen (g_strconcat(symbol_id, ".svg", NULL), "w");
+ // sp_repr_save_stream(previewDocument->getReprDoc(), fp);
+ // fclose (fp);
+
+ // Make sure previewDocument is up-to-date.
+ previewDocument->getRoot()->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
+ previewDocument->ensureUpToDate();
+
+ // Make sure we have symbol in previewDocument
+ SPObject *object_temp = previewDocument->getObjectById( "the_use" );
+ previewDocument->getRoot()->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
+ previewDocument->ensureUpToDate();
+
+ // if( object_temp == NULL || !SP_IS_ITEM(object_temp) ) {
+ // //std::cout << " previewDocument broken?" << std::endl;
+ // //return 0;
+ // }
+
+ SPItem *item = SP_ITEM(object_temp);
+
+ // Find object's bbox in document.
+ // Note symbols can have own viewport... ignore for now.
+ //Geom::OptRect dbox = item->geometricBounds();
+ Geom::OptRect dbox = item->documentVisualBounds();
+ // if (!dbox) {
+ // //std::cout << " No dbox" << std::endl;
+ // //return NULL;
+ // }
+
+ Glib::ustring previewSizeString = previewSize->get_active_text();
+ unsigned psize = atol( previewSizeString.c_str() );
+
+ Glib::ustring previewScaleString = previewScale->get_active_text();
+ int previewScaleRow = previewScale->get_active_row_number();
+
+ /* Update to renderable state */
+ Glib::ustring key = svg_preview_cache.cache_key(previewDocument->getURI(), symbol_id, psize);
+ //std::cout << " Key: " << key << std::endl;
+ // FIX ME
+ //Glib::RefPtr<Gdk::Pixbuf> pixbuf = Glib::wrap(svg_preview_cache.get_preview_from_cache(key));
+ Glib::RefPtr<Gdk::Pixbuf> pixbuf = Glib::RefPtr<Gdk::Pixbuf>(0);
+
+ if (!pixbuf) {
+
+ /* Scale symbols to fit */
+ double scale = 1.0;
+ switch (previewScaleRow) {
+ case 0:
+ /* Fit */
+ scale = psize/std::max(dbox->width(),dbox->height());
+ break;
+ case 1:
+ /* Fit width */
+ scale = psize/dbox->width();
+ break;
+ case 2:
+ /* Fit height */
+ scale = psize/dbox->height();
+ break;
+ default:
+ scale = atof( previewScaleString.c_str() );
+ }
+
+ pixbuf = Glib::wrap(render_pixbuf(*drawing, scale, *dbox, psize));
+ svg_preview_cache.set_preview_in_cache(key, pixbuf->gobj());
+ }
+
+ return pixbuf;
+}
+
+/*
+ * Return empty doc to render symbols in.
+ * Symbols are by default not rendered so a <use> element is
+ * provided.
+ */
+SPDocument* SymbolsDialog::symbols_preview_doc()
+{
+ // BUG: <symbol> must be inside <defs>
+ gchar const *buffer =
+"<svg xmlns=\"http://www.w3.org/2000/svg\""
+" xmlns:sodipodi=\"http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd\""
+" xmlns:inkscape=\"http://www.inkscape.org/namespaces/inkscape\""
+" xmlns:xlink=\"http://www.w3.org/1999/xlink\""
+" style=\"fill:none;stroke:black;stroke-width:2\">"
+" <defs id=\"defs\">"
+" <symbol id=\"the_symbol\"/>"
+" </defs>"
+" <use id=\"the_use\" xlink:href=\"#the_symbol\"/>"
+"</svg>";
+
+ return SPDocument::createNewDocFromMem( buffer, strlen(buffer), FALSE );
+}
+
+void SymbolsDialog::setTargetDesktop(SPDesktop *desktop)
+{
+ if (this->currentDesktop != desktop) {
+ this->currentDesktop = desktop;
+ if( !symbolSets[symbolSet->get_active_text()] ) {
+ // Symbol set is from Current document, update
+ rebuild();
+ }
+ }
+}
+
+
+} //namespace Dialogs
+} //namespace UI
+} //namespace Inkscape
+
+
+
diff --git a/src/ui/dialog/symbols.h b/src/ui/dialog/symbols.h
new file mode 100644
index 000000000..c2bb4448e
--- /dev/null
+++ b/src/ui/dialog/symbols.h
@@ -0,0 +1,114 @@
+/** @file
+ * @brief Symbols dialog
+ */
+/* Authors:
+ * Tavmjong Bah
+ *
+ * Copyright (C) 2012 Tavmjong Bah
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifndef INKSCAPE_UI_DIALOG_SYMBOLS_H
+#define INKSCAPE_UI_DIALOG_SYMBOLS_H
+
+#include "ui/widget/panel.h"
+#include "ui/widget/button.h"
+
+#include "ui/dialog/desktop-tracker.h"
+
+#include "display/drawing.h"
+
+#include <glib.h>
+#include <gtkmm/treemodel.h>
+
+#include <vector>
+
+class SPObject;
+
+namespace Inkscape {
+namespace UI {
+namespace Dialog {
+
+class SymbolColumns; // For Gtk::ListStore
+
+/**
+ * A dialog that displays selectable symbols.
+ */
+class SymbolsDialog : public UI::Widget::Panel {
+
+public:
+ SymbolsDialog( gchar const* prefsPath = "/dialogs/symbols" );
+ virtual ~SymbolsDialog();
+
+ static SymbolsDialog& getInstance();
+
+protected:
+
+
+private:
+ SymbolsDialog(SymbolsDialog const &); // no copy
+ SymbolsDialog &operator=(SymbolsDialog const &); // no assign
+
+ static SymbolColumns *getColumns();
+
+ void rebuild();
+ void iconChanged();
+
+ void get_symbols();
+ void draw_symbols( SPDocument* symbol_document );
+ SPDocument* symbols_preview_doc();
+
+ GSList* symbols_in_doc_recursive(SPObject *r, GSList *l);
+ GSList* symbols_in_doc( SPDocument* document );
+ GSList* use_in_doc_recursive(SPObject *r, GSList *l);
+ GSList* use_in_doc( SPDocument* document );
+ gchar const* style_from_use( gchar const* id, SPDocument* document);
+
+ Glib::RefPtr<Gdk::Pixbuf>
+ create_symbol_image(gchar const *symbol_name,
+ SPDocument *source, Inkscape::Drawing* drawing,
+ unsigned /*visionkey*/);
+
+ /* Keep track of all symbol template documents */
+ std::map<Glib::ustring, SPDocument*> symbolSets;
+
+
+ Glib::RefPtr<Gtk::ListStore> store;
+ Gtk::ComboBoxText* symbolSet;
+ Gtk::IconView* iconView;
+ Gtk::ComboBoxText* previewScale;
+ Gtk::ComboBoxText* previewSize;
+
+ void setTargetDesktop(SPDesktop *desktop);
+ SPDesktop* currentDesktop;
+ DesktopTracker deskTrack;
+ SPDocument* currentDocument;
+ SPDocument* previewDocument; /* Document to render single symbol */
+
+ /* For rendering the template drawing */
+ unsigned key;
+ Inkscape::Drawing renderDrawing;
+
+ std::vector<sigc::connection> instanceConns;
+ sigc::connection desktopChangeConn;
+
+};
+
+} //namespace Dialogs
+} //namespace UI
+} //namespace Inkscape
+
+
+#endif // INKSCAPE_UI_DIALOG_SYMBOLS_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/ui/widget/style-swatch.cpp b/src/ui/widget/style-swatch.cpp
index 857ae7019..60d5f6ecc 100644
--- a/src/ui/widget/style-swatch.cpp
+++ b/src/ui/widget/style-swatch.cpp
@@ -340,15 +340,12 @@ void StyleSwatch::setStyle(SPStyle *query)
if (op != 1) {
{
gchar *str;
- if (op == 0)
- str = g_strdup_printf(_("O:%.3g"), op);
- else
- str = g_strdup_printf(_("O:.%d"), (int) (op*10));
+ str = g_strdup_printf(_("O: %2.0f"), (op*100.0));
_opacity_value.set_markup (str);
g_free (str);
}
{
- gchar *str = g_strdup_printf(_("Opacity: %.3g"), op);
+ gchar *str = g_strdup_printf(_("Opacity: %2.1f %%"), (op*100.0));
_opacity_place.set_tooltip_text(str);
g_free (str);
}