diff options
Diffstat (limited to 'src/ui/dialog/symbols.cpp')
| -rw-r--r-- | src/ui/dialog/symbols.cpp | 762 |
1 files changed, 762 insertions, 0 deletions
diff --git a/src/ui/dialog/symbols.cpp b/src/ui/dialog/symbols.cpp new file mode 100644 index 000000000..dfc92774c --- /dev/null +++ b/src/ui/dialog/symbols.cpp @@ -0,0 +1,762 @@ +/** + * @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 <locale> +#include <functional> +#include <sstream> + +#include <gtkmm/buttonbox.h> +#include <gtkmm/label.h> + +#if WITH_GTKMM_3_0 +# include <gtkmm/grid.h> +#else +# include <gtkmm/table.h> +#endif + +#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 <glibmm/i18n.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" + +#ifdef WITH_LIBVISIO +#include <libvisio/libvisio.h> +#include <libwpd-stream/libwpd-stream.h> +#endif + +#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 *************************/ +#if WITH_GTKMM_3_0 + Gtk::Grid *table = new Gtk::Grid(); +#else + Gtk::Table *table = new Gtk::Table(2, 4, false); +#endif + + // 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: ")); + +#if WITH_GTKMM_3_0 + table->attach(*Gtk::manage(labelSet),0,row,1,1); +#else + table->attach(*Gtk::manage(labelSet),0,1,row,row+1,Gtk::SHRINK,Gtk::SHRINK); +#endif + + symbolSet = new Gtk::ComboBoxText(); // Fill in later + symbolSet->append(_("Current Document")); + symbolSet->set_active_text(_("Current Document")); + +#if WITH_GTKMM_3_0 + symbolSet->set_hexpand(); + table->attach(*Gtk::manage(symbolSet),1,row,1,1); +#else + table->attach(*Gtk::manage(symbolSet),1,2,row,row+1,Gtk::FILL|Gtk::EXPAND,Gtk::SHRINK); +#endif + + 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 ); + + std::vector< Gtk::TargetEntry > targets; + targets.push_back(Gtk::TargetEntry( "application/x-inkscape-paste")); + + iconView->enable_model_drag_source (targets, Gdk::BUTTON1_MASK, Gdk::ACTION_COPY); + iconView->signal_drag_data_get().connect(sigc::mem_fun(*this, &SymbolsDialog::iconDragDataGet)); + + 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)); + +#if WITH_GTKMM_3_0 + scroller->set_hexpand(); + scroller->set_vexpand(); + table->attach(*Gtk::manage(scroller),0,row,2,1); +#else + table->attach(*Gtk::manage(scroller),0,2,row,row+1,Gtk::EXPAND|Gtk::FILL,Gtk::EXPAND|Gtk::FILL); +#endif + + ++row; + + /******************** Preview Scale ***********************/ + Gtk::Label* labelScale = new Gtk::Label(_("Preview scale: ")); + +#if WITH_GTKMM_3_0 + table->attach(*Gtk::manage(labelScale),0,row,1,1); +#else + table->attach(*Gtk::manage(labelScale),0,1,row,row+1,Gtk::SHRINK,Gtk::SHRINK); +#endif + + 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 ) { + previewScale->append(scales[i]); + } + previewScale->set_active_text(scales[0]); + +#if WITH_GTKMM_3_0 + previewScale->set_hexpand(); + table->attach(*Gtk::manage(previewScale),1,row,1,1); +#else + table->attach(*Gtk::manage(previewScale),1,2,row,row+1,Gtk::FILL|Gtk::EXPAND,Gtk::SHRINK); +#endif + + 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: ")); + +#if WITH_GTKMM_3_0 + table->attach(*Gtk::manage(labelSize),0,row,1,1); +#else + table->attach(*Gtk::manage(labelSize),0,1,row,row+1,Gtk::SHRINK,Gtk::SHRINK); +#endif + + previewSize = new Gtk::ComboBoxText(); + const gchar *sizes[] = {"16", "24", "32", "48", "64", NULL}; + for( int i = 0; sizes[i]; ++i ) { + previewSize->append(sizes[i]); + } + previewSize->set_active_text(sizes[2]); + +#if WITH_GTKMM_3_0 + previewSize->set_hexpand(); + table->attach(*Gtk::manage(previewSize),1,row,1,1); +#else + table->attach(*Gtk::manage(previewSize),1,2,row,row+1,Gtk::FILL|Gtk::EXPAND,Gtk::SHRINK); +#endif + + 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::iconDragDataGet(const Glib::RefPtr<Gdk::DragContext>& /*context*/, Gtk::SelectionData& data, guint /*info*/, guint /*time*/) +{ +#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]; + + GdkAtom dataAtom = gdk_atom_intern( "application/x-inkscape-paste", FALSE ); + gtk_selection_data_set( data.gobj(), dataAtom, 9, (guchar*)symbol_id.c_str(), symbol_id.length() ); + } + +} + +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); + } + } +} + +#ifdef WITH_LIBVISIO +// Read Visio stencil files +SPDocument* read_vss( gchar* fullname, gchar* filename ) { + + WPXFileStream input(fullname); + + if (!libvisio::VisioDocument::isSupported(&input)) { + return NULL; + } + + libvisio::VSDStringVector output; + if (!libvisio::VisioDocument::generateSVGStencils(&input, output)) { + return NULL; + } + + if (output.empty()) { + return NULL; + } + + Glib::ustring tmpSVGOutput; + tmpSVGOutput += "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n"; + tmpSVGOutput += "<svg\n"; + tmpSVGOutput += " xmlns=\"http://www.w3.org/2000/svg\"\n"; + tmpSVGOutput += " xmlns:svg=\"http://www.w3.org/2000/svg\"\n"; + tmpSVGOutput += " xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n"; + tmpSVGOutput += " version=\"1.1\"\n"; + tmpSVGOutput += " style=\"fill:none;stroke:#000000;stroke-width:2\">\n"; + tmpSVGOutput += " <title>"; + tmpSVGOutput += filename; + tmpSVGOutput += "</title>\n"; + tmpSVGOutput += " <defs>\n"; + + // Create a string we can use for the symbol id (libvisio doesn't give us a name) + std::string sanitized( filename ); + sanitized.erase( sanitized.find_last_of(".vss")-3 ); + sanitized.erase( std::remove_if( sanitized.begin(), sanitized.end(), ispunct ), sanitized.end() ); + std::replace( sanitized.begin(), sanitized.end(), ' ', '_' ); + // std::cout << filename << " |" << sanitized << "|" << std::endl; + + // Each "symbol" is in it's own SVG file, we wrap with <symbol> and merge into one file. + for (unsigned i=0; i<output.size(); ++i) { + + std::stringstream ss; + ss << i; + + tmpSVGOutput += " <symbol id=\""; + tmpSVGOutput += sanitized; + tmpSVGOutput += "_"; + tmpSVGOutput += ss.str(); + tmpSVGOutput += "\">\n"; + + std::istringstream iss( output[i].cstr() ); + std::string line; + while( std::getline( iss, line ) ) { + // std::cout << line << std::endl; + if( line.find( "svg:svg" ) == std::string::npos ) { + tmpSVGOutput += line; + tmpSVGOutput += "\n"; + } + } + + tmpSVGOutput += " </symbol>\n"; + } + + tmpSVGOutput += " </defs>\n"; + tmpSVGOutput += "</svg>\n"; + + return SPDocument::createNewDocFromMem( tmpSVGOutput.c_str(), strlen( tmpSVGOutput.c_str()), 0 ); + +} +#endif + +/* 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 ) ) { + + Glib::ustring fn( filename ); + Glib::ustring tag = fn.substr( fn.find_last_of(".") + 1 ); + + SPDocument* symbol_doc = NULL; + +#ifdef WITH_LIBVISIO + if( tag.compare( "vss" ) == 0 ) { + + symbol_doc = read_vss( fullname, filename ); + if( symbol_doc ) { + symbolSets[Glib::ustring(filename)]= symbol_doc; + symbolSet->append(filename); + } + } +#endif + // Try to read all remaining files as SVG + if( !symbol_doc ) { + + symbol_doc = SPDocument::createNewDoc( fullname, FALSE ); + if( symbol_doc ) { + symbolSets[Glib::ustring(filename)]= symbol_doc; + symbolSet->append(filename); + } + } + + } + g_free( fullname ); + } + g_dir_close( dir ); + } + } +} + +GSList* SymbolsDialog::symbols_in_doc_recursive (SPObject *r, GSList *l) +{ + if (!r) { + return 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; + } + } + + delete columns; +} + +/* + * 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"); + } + } + // Last ditch effort to provide some default styling + if( !style ) style = "fill:#bbbbbb;stroke:#808080"; + + // 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); + + 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); + + // 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 pixbuf; + } + + if (!pixbuf) { + + /* Scale symbols to fit */ + double scale = 1.0; + double width = dbox->width(); + double height = dbox->height(); + if( width == 0.0 ) { + width = 1.0; + } + if( height == 0.0 ) { + height = 1.0; + } + + switch (previewScaleRow) { + case 0: + /* Fit */ + scale = psize/std::max(width,height); + break; + case 1: + /* Fit width */ + scale = psize/width; + break; + case 2: + /* Fit height */ + scale = psize/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\">" +" <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 |
