Code

more unreffing temporary styles properly
[inkscape.git] / src / ui / dialog / filter-effects-dialog.cpp
1 /**
2  * \brief Filter Effects dialog
3  *
4  * Authors:
5  *   Nicholas Bishop <nicholasbishop@gmail.org>
6  *
7  * Copyright (C) 2007 Authors
8  *
9  * Released under GNU GPL.  Read the file 'COPYING' for more information.
10  */
12 #ifdef HAVE_CONFIG_H
13 # include <config.h>
14 #endif
16 #include <gtk/gtktreeview.h>
17 #include <gtkmm/cellrenderertext.h>
18 #include <gtkmm/paned.h>
19 #include <gtkmm/scale.h>
20 #include <gtkmm/scrolledwindow.h>
21 #include <gtkmm/spinbutton.h>
22 #include <gtkmm/stock.h>
23 #include <glibmm/i18n.h>
25 #include "application/application.h"
26 #include "application/editor.h"
27 #include "desktop.h"
28 #include "desktop-handles.h"
29 #include "dialog-manager.h"
30 #include "document.h"
31 #include "filter-chemistry.h"
32 #include "filter-effects-dialog.h"
33 #include "inkscape.h"
34 #include "sp-filter-primitive.h"
35 #include "sp-gaussian-blur.h"
36 #include "sp-feoffset.h"
37 #include "verbs.h"
38 #include "xml/node.h"
39 #include "xml/repr.h"
40 #include <sstream>
42 #include <iostream>
44 namespace Inkscape {
45 namespace UI {
46 namespace Dialog {
48 Glib::RefPtr<Gtk::Menu> create_popup_menu(Gtk::Widget& parent, sigc::slot<void> dup,
49                                           sigc::slot<void> rem)
50 {
51     Glib::RefPtr<Gtk::Menu> menu(new Gtk::Menu);
53     menu->items().push_back(Gtk::Menu_Helpers::MenuElem(_("_Duplicate"), dup));
54     Gtk::MenuItem* mi = Gtk::manage(new Gtk::ImageMenuItem(Gtk::Stock::REMOVE));
55     menu->append(*mi);
56     mi->signal_activate().connect(rem);
57     mi->show();
58     menu->accelerate(parent);
60     return menu;
61 }
63 static void try_id_change(SPObject* ob, const Glib::ustring& text)
64 {
65     // FIXME: this needs more serious error checking...
66     if(ob && !SP_ACTIVE_DOCUMENT->getObjectById(text.c_str())) {
67         SPException ex;
68         SP_EXCEPTION_INIT(&ex);
69         sp_object_setAttribute(ob, "id", text.c_str(), &ex);
70         sp_document_done(SP_ACTIVE_DOCUMENT, SP_VERB_DIALOG_FILTER_EFFECTS, _("Set object ID"));
71     }
72 }
74 /*** FilterModifier ***/
75 FilterEffectsDialog::FilterModifier::FilterModifier()
76     : _add(Gtk::Stock::ADD)
77 {
78     Gtk::ScrolledWindow* sw = Gtk::manage(new Gtk::ScrolledWindow);
79     pack_start(*sw);
80     pack_start(_add, false, false);
81     sw->add(_list);
83     _list.set_model(_model);
84     _list.append_column_editable(_("_Filter"), _columns.id);
85     ((Gtk::CellRendererText*)_list.get_column(0)->get_first_cell_renderer())->
86         signal_edited().connect(sigc::mem_fun(*this, &FilterEffectsDialog::FilterModifier::filter_name_edited));
88     sw->set_policy(Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
89     sw->set_shadow_type(Gtk::SHADOW_IN);
90     show_all_children();
91     _add.signal_clicked().connect(sigc::mem_fun(*this, &FilterModifier::add_filter));
92     _list.signal_button_press_event().connect_notify(
93         sigc::mem_fun(*this, &FilterModifier::filter_list_button_press));
94     _menu = create_popup_menu(*this, sigc::mem_fun(*this, &FilterModifier::duplicate_filter),
95                               sigc::mem_fun(*this, &FilterModifier::remove_filter));
97     update_filters();
98 }
100 Glib::SignalProxy0<void> FilterEffectsDialog::FilterModifier::signal_selection_changed()
102     return _list.get_selection()->signal_changed();
105 SPFilter* FilterEffectsDialog::FilterModifier::get_selected_filter()
107     if(_list.get_selection()) {
108         Gtk::TreeModel::iterator i = _list.get_selection()->get_selected();
110         if(i)
111             return (*i)[_columns.filter];
112     }
114     return 0;
117 void FilterEffectsDialog::FilterModifier::select_filter(const SPFilter* filter)
119     if(filter) {
120         for(Gtk::TreeModel::iterator i = _model->children().begin();
121             i != _model->children().end(); ++i) {
122             if((*i)[_columns.filter] == filter) {
123                 _list.get_selection()->select(i);
124                 break;
125             }
126         }
127     }
130 void FilterEffectsDialog::FilterModifier::filter_list_button_press(GdkEventButton* event)
132     if((event->type == GDK_BUTTON_PRESS) && (event->button == 3)) {
133         const bool sensitive = get_selected_filter() != NULL;
134         _menu->items()[0].set_sensitive(sensitive);
135         _menu->items()[1].set_sensitive(sensitive);
136         _menu->popup(event->button, event->time);
137     }
140 void FilterEffectsDialog::FilterModifier::add_filter()
142     SPDocument* doc = sp_desktop_document(SP_ACTIVE_DESKTOP);
143     SPFilter* filter = new_filter(doc);
145     update_filters();
147     select_filter(filter);
149     sp_document_done(doc, SP_VERB_DIALOG_FILTER_EFFECTS, _("Add filter"));
152 void FilterEffectsDialog::FilterModifier::remove_filter()
154     SPFilter *filter = get_selected_filter();
156     if(filter) {
157         SPDocument* doc = filter->document;
158         sp_repr_unparent(filter->repr);
160         sp_document_done(doc, SP_VERB_DIALOG_FILTER_EFFECTS, _("Remove filter"));
162         update_filters();
163     }
166 void FilterEffectsDialog::FilterModifier::duplicate_filter()
168     SPFilter *filter = get_selected_filter();
170     if(filter) {
171         //SPFilter *dupfilter = filter_duplicate(sp_desktop_document(SP_ACTIVE_DESKTOP), filter);
173         sp_document_done(filter->document, SP_VERB_DIALOG_FILTER_EFFECTS, _("Duplicate filter"));
175         update_filters();
176     }
179 void FilterEffectsDialog::FilterModifier::filter_name_edited(const Glib::ustring& path, const Glib::ustring& text)
181     Gtk::TreeModel::iterator i = _model->get_iter(path);
183     if(i)
184         try_id_change((SPObject*)(*i)[_columns.filter], text);
187 /*** SettingsFrame ***/
188 FilterEffectsDialog::SettingsFrame::SettingsFrame()
189     : _where(0)
191      set_col_spacings(12);
192      show();
195 void FilterEffectsDialog::SettingsFrame::init(Gtk::VBox& box)
197     box.pack_start(*this, false, false);
200 void FilterEffectsDialog::SettingsFrame::add_setting(Gtk::Widget& w, const Glib::ustring& label)
202     Gtk::Label *lbl = new Gtk::Label(label + ":", Gtk::ALIGN_LEFT);
204     attach(*Gtk::manage(lbl), 0, 1, _where, _where + 1, Gtk::FILL, Gtk::FILL);
205     attach(w, 1, 2, _where, _where + 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL);
207     lbl->show();
208     w.show();
210     ++_where;
213 /*** FilterEffectsDialog ***/
215 FilterEffectsDialog::FilterEffectsDialog() 
216     : Dialog ("dialogs.filtereffects", SP_VERB_DIALOG_FILTER_EFFECTS),
217       _add_primitive_type(FPConverter),
218       _add_primitive(Gtk::Stock::ADD),
219       _empty_settings("No primitive selected", Gtk::ALIGN_LEFT),
220       _blend_mode(BlendModeConverter),
221       _gaussianblur_stddeviation(1, 0, 100, 1, 0.01, 1),
222       _morphology_radius(1, 0, 100, 1, 0.01, 1),
223       _offset_dx(0, -100, 100, 1, 0.01, 1),
224       _offset_dy(0, -100, 100, 1, 0.01, 1),
225       _turbulence_basefrequency(1, 0, 100, 1, 0.01, 1),
226       _turbulence_numoctaves(1, 0, 100, 1, 0.01, 1),
227       _turbulence_seed(1, 0, 100, 1, 0.01, 1)
229     // Initialize widget hierarchy
230     Gtk::HPaned* hpaned = Gtk::manage(new Gtk::HPaned);
231     Gtk::VBox* vb_prims = Gtk::manage(new Gtk::VBox);
232     Gtk::ScrolledWindow* sw_prims = Gtk::manage(new Gtk::ScrolledWindow);
233     Gtk::HBox* hb_prims = Gtk::manage(new Gtk::HBox);
234     Gtk::Frame* fr_settings = Gtk::manage(new Gtk::Frame("<b>Settings</b>"));
235     Gtk::Alignment* al_settings = Gtk::manage(new Gtk::Alignment);
236     get_vbox()->add(*hpaned);
237     hpaned->pack1(_filter_modifier);
238     hpaned->pack2(*vb_prims);
239     vb_prims->pack_start(*sw_prims);
240     vb_prims->pack_start(*hb_prims, false, false);
241     sw_prims->add(_primitive_list);
242     hb_prims->pack_end(_add_primitive, false, false);
243     hb_prims->pack_end(_add_primitive_type, false, false);
244     get_vbox()->pack_start(*fr_settings, false, false);
245     fr_settings->add(*al_settings);
246     al_settings->add(_settings);
248     // Primitive list
249     _primitive_model = Gtk::ListStore::create(_primitive_columns);
250     _primitive_list.set_reorderable(true);
251     _primitive_list.set_model(_primitive_model);
252     //_primitive_list.append_column_editable(_("_Primitive"), _primitive_columns.id);
253     _primitive_list.append_column("Type", _primitive_columns.type);
254     ((Gtk::CellRendererText*)_primitive_list.get_column(0)->get_first_cell_renderer())->
255         signal_edited().connect(sigc::mem_fun(*this, &FilterEffectsDialog::primitive_name_edited));
256     _filter_modifier.signal_selection_changed().connect(
257         sigc::mem_fun(*this, &FilterEffectsDialog::update_primitive_list));
258     _primitive_list.get_selection()->signal_changed().connect(
259         sigc::mem_fun(*this, &FilterEffectsDialog::update_settings_view));
260     _primitive_list.signal_button_press_event().connect_notify(
261         sigc::mem_fun(*this, &FilterEffectsDialog::primitive_list_button_press));
262     _primitive_list.signal_drag_end().connect(
263         sigc::mem_fun(*this, &FilterEffectsDialog::primitive_list_drag_end));
265     // Other widgets
266     sw_prims->set_policy(Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
267     sw_prims->set_shadow_type(Gtk::SHADOW_IN);
268     al_settings->set_padding(0, 0, 12, 0);
269     fr_settings->set_shadow_type(Gtk::SHADOW_NONE);
270     ((Gtk::Label*)fr_settings->get_label_widget())->set_use_markup();
271     _add_primitive.signal_clicked().connect(sigc::mem_fun(*this, &FilterEffectsDialog::add_primitive));
272     _primitive_menu = create_popup_menu(*this, sigc::mem_fun(*this, &FilterEffectsDialog::duplicate_primitive),
273                                         sigc::mem_fun(*this, &FilterEffectsDialog::remove_primitive));
274     
275     show_all_children();
276     init_settings_widgets();
277     update_primitive_list();
278     update_settings_view();
281 FilterEffectsDialog::~FilterEffectsDialog()
285 void FilterEffectsDialog::primitive_list_button_press(GdkEventButton* event)
287     if((event->type == GDK_BUTTON_PRESS) && (event->button == 3)) {
288         const bool sensitive = get_selected_primitive() != NULL;
289         _primitive_menu->items()[0].set_sensitive(sensitive);
290         _primitive_menu->items()[1].set_sensitive(sensitive);
291         _primitive_menu->popup(event->button, event->time);
292     }
295 // Reorder the filter primitives to match the list order
296 void FilterEffectsDialog::primitive_list_drag_end(const Glib::RefPtr<Gdk::DragContext>&)
298     int ndx = 0;
299     SPFilter* filter = _filter_modifier.get_selected_filter();
301     for(Gtk::TreeModel::iterator iter = _primitive_model->children().begin();
302         iter != _primitive_model->children().end(); ++iter) {
303         SPFilterPrimitive* prim = (*iter)[_primitive_columns.primitive];
304         if(prim)
305             ;//reorder_primitive(filter, prim->repr->position(), ndx); /* FIXME */
306         std::cout << prim->repr->position();
307     }
309     sp_document_done(filter->document, SP_VERB_DIALOG_FILTER_EFFECTS, _("Reorder filter primitive"));
312 void FilterEffectsDialog::init_settings_widgets()
314     _empty_settings.set_sensitive(false);
315     _settings.pack_start(_empty_settings);
317     _blend.init(_settings);
318     _blend.add_setting(_blend_mode, "Mode");
319     _blend_mode.signal_changed().connect(
320         sigc::bind(sigc::mem_fun(*this, &FilterEffectsDialog::set_attr), SP_ATTR_MODE));
322     _colormatrix.init(_settings);
323     _colormatrix.add_setting(_colormatrix_type, "Type");
325     _componenttransfer.init(_settings);
327     _composite.init(_settings);
329     _convolvematrix.init(_settings);
330     
331     _diffuselighting.init(_settings);
333     _displacementmap.init(_settings);
335     _flood.init(_settings);
337     _gaussianblur.init(_settings);
338     _gaussianblur.add_setting(_gaussianblur_stddeviation, "Standard Deviation");
339     _gaussianblur_stddeviation.signal_value_changed().connect(
340         sigc::bind(sigc::mem_fun(*this, &FilterEffectsDialog::set_attr), SP_ATTR_STDDEVIATION));
342     _image.init(_settings);
343     
344     _merge.init(_settings);
346     _morphology.init(_settings);
347     _morphology.add_setting(_morphology_operator, "Operator");
348     _morphology.add_setting(_morphology_radius, "Radius");
350     _offset.init(_settings);
351     _offset.add_setting(_offset_dx, "Delta X");
352     _offset_dx.signal_value_changed().connect(
353         sigc::bind(sigc::mem_fun(*this, &FilterEffectsDialog::set_attr), SP_ATTR_DX));
354     _offset.add_setting(_offset_dy, "Delta Y");
355     _offset_dy.signal_value_changed().connect(
356         sigc::bind(sigc::mem_fun(*this, &FilterEffectsDialog::set_attr), SP_ATTR_DY));
358     _specularlighting.init(_settings);
360     _tile.init(_settings);
362     _turbulence.init(_settings);
363     _turbulence.add_setting(_turbulence_basefrequency, "Base Frequency");
364     _turbulence.add_setting(_turbulence_numoctaves, "Octaves");
365     _turbulence.add_setting(_turbulence_seed, "Seed");
366     _turbulence.add_setting(_turbulence_stitchtiles, "Stitch Tiles");
367     _turbulence.add_setting(_turbulence_type, "Type");    
370 void FilterEffectsDialog::add_primitive()
372     SPFilter* filter = _filter_modifier.get_selected_filter();
373     const EnumData<NR::FilterPrimitiveType>* data = _add_primitive_type.get_active_data();
374     
375     if(filter && data) {
376         SPFilterPrimitive* prim = filter_add_primitive(filter, data->name.c_str());
378         // Set default values
379         switch(data->id) {
380             case NR::NR_FILTER_BLEND:
381                 sp_object_set(prim, SP_ATTR_MODE, BlendModeConverter.get_name(NR::BLEND_NORMAL).c_str());
382                 break;
383             case NR::NR_FILTER_COLORMATRIX:
384                 break;
385             case NR::NR_FILTER_COMPONENTTRANSFER:
386                 break;
387             case NR::NR_FILTER_COMPOSITE:
388                 break;
389             case NR::NR_FILTER_CONVOLVEMATRIX:
390                 break;
391             case NR::NR_FILTER_DIFFUSELIGHTING:
392                 break;
393             case NR::NR_FILTER_DISPLACEMENTMAP:
394                 break;
395             case NR::NR_FILTER_FLOOD:
396                 break;
397             case NR::NR_FILTER_GAUSSIANBLUR:
398                 sp_object_set(prim, SP_ATTR_STDDEVIATION, "1");
399                 break;
400             case NR::NR_FILTER_IMAGE:
401                 break;
402             case NR::NR_FILTER_MERGE:
403                 break;
404             case NR::NR_FILTER_MORPHOLOGY:
405                 break;
406             case NR::NR_FILTER_OFFSET:
407                 sp_object_set(prim, SP_ATTR_DX, "0");
408                 sp_object_set(prim, SP_ATTR_DY, "0");
409                 break;
410             case NR::NR_FILTER_SPECULARLIGHTING:
411                 break;
412             case NR::NR_FILTER_TILE:
413                 break;
414             case NR::NR_FILTER_TURBULENCE:
415                 break;
416             default:
417                 break;
418         }
420         update_primitive_list();
421         select_primitive(prim);
423         sp_document_done(filter->document, SP_VERB_DIALOG_FILTER_EFFECTS, _("Add filter primitive"));
424     }
427 void FilterEffectsDialog::remove_primitive()
429     Gtk::TreeModel::iterator i = _primitive_list.get_selection()->get_selected();
431     if(i) {
432         SPFilterPrimitive* prim = (*i)[_primitive_columns.primitive];
433        
434         sp_repr_unparent(prim->repr);
436         sp_document_done(sp_desktop_document(SP_ACTIVE_DESKTOP), SP_VERB_DIALOG_FILTER_EFFECTS,
437                          _("Remove filter primitive"));
439         update_primitive_list();
440     }
443 void FilterEffectsDialog::duplicate_primitive()
445     SPFilter* filter = _filter_modifier.get_selected_filter();
446     SPFilterPrimitive* origprim = get_selected_primitive();
448     if(filter && origprim) {
449         Inkscape::XML::Node *repr;
450         repr = SP_OBJECT_REPR(origprim)->duplicate(SP_OBJECT_REPR(origprim)->document());
451         SP_OBJECT_REPR(filter)->appendChild(repr);
453         sp_document_done(filter->document, SP_VERB_DIALOG_FILTER_EFFECTS, _("Duplicate filter primitive"));
455         update_primitive_list();
456     }
459 // Edits the id of the primitive at path
460 void FilterEffectsDialog::primitive_name_edited(const Glib::ustring& path, const Glib::ustring& text)
462     Gtk::TreeModel::iterator i = _primitive_model->get_iter(path);
464     if(i)
465         try_id_change((*i)[_primitive_columns.primitive], text);
467   
468 void FilterEffectsDialog::set_attr(const SPAttributeEnum attr)
470     Gtk::TreeModel::iterator i = _primitive_list.get_selection()->get_selected();
472     if(i) {
473         SPFilter *filter = _filter_modifier.get_selected_filter();
474         SPFilterPrimitive* prim = (*i)[_primitive_columns.primitive];
475         std::ostringstream os;
476         Glib::ustring val;
478         if(attr == SP_ATTR_MODE) {
479             val = _blend_mode.get_active_data()->name;
480         }
481         else if(attr == SP_ATTR_STDDEVIATION) {
482             os << _gaussianblur_stddeviation.get_value();
483             val = os.str();
484         }
485         else if(attr == SP_ATTR_DX) {
486             os << _offset_dx.get_value();
487             val = os.str();
488         }
489         else if(attr == SP_ATTR_DY) {
490             os << _offset_dy.get_value();
491             val = os.str();
492         }
494         sp_object_set(prim, attr, val.c_str());
495         filter->requestModified(SP_OBJECT_MODIFIED_FLAG);
497         sp_document_done(filter->document, SP_VERB_DIALOG_FILTER_EFFECTS, _("Set filter primitive attribute"));
498     }
501 /* Add all filter primitives in the current to the list.
502    Keeps the same selection if possible, otherwise selects the first element */
503 void FilterEffectsDialog::update_primitive_list()
505     SPFilter* f = _filter_modifier.get_selected_filter();
506     const SPFilterPrimitive* active_prim = get_selected_primitive();
507     bool active_found = false;
509     _primitive_model->clear();
511     if(f) {
512         _primitive_box.set_sensitive(true);
514         for(SPObject *prim_obj = f->children;
515                 prim_obj && SP_IS_FILTER_PRIMITIVE(prim_obj);
516                 prim_obj = prim_obj->next) {
517             SPFilterPrimitive *prim = SP_FILTER_PRIMITIVE(prim_obj);
518             if(prim) {
519                 Gtk::TreeModel::Row row = *_primitive_model->append();
520                 row[_primitive_columns.primitive] = prim;
521                 row[_primitive_columns.type_id] = FPConverter.get_id_from_name(prim->repr->name());
522                 row[_primitive_columns.type] = FPConverter.get_label(row[_primitive_columns.type_id]);
523                 row[_primitive_columns.id] = SP_OBJECT_ID(prim);
525                 if(prim == active_prim) {
526                     _primitive_list.get_selection()->select(row);
527                     active_found = true;
528                 }
529             }
530         }
532         if(!active_found && _primitive_model->children().begin())
533             _primitive_list.get_selection()->select(_primitive_model->children().begin());
534     }
535     else {
536         _primitive_box.set_sensitive(false);
537     }
540 void FilterEffectsDialog::update_settings_view()
542     SPFilterPrimitive* prim = get_selected_primitive();
544     // Hide all the settings except for common
545     Glib::ListHandle<Widget*> c = _settings.get_children();
546     for(Glib::ListHandle<Widget*>::iterator iter = c.begin();
547         iter != c.end(); ++iter) {
548         (*iter)->hide();
549     }
551     _settings.set_sensitive(false);
552     _empty_settings.show();
554     if(prim) {
555         const NR::FilterPrimitiveType tid = FPConverter.get_id_from_name(prim->repr->name());
556         if(tid == NR::NR_FILTER_BLEND) {
557             _blend.show();
558             const gchar* val = prim->repr->attribute("mode");
559             if(val)
560                 _blend_mode.set_active(BlendModeConverter.get_id_from_name(val));
561         }
562         else if(tid == NR::NR_FILTER_COLORMATRIX)
563             _colormatrix.show();
564         else if(tid == NR::NR_FILTER_COMPONENTTRANSFER)
565             _componenttransfer.show();
566         else if(tid == NR::NR_FILTER_COMPOSITE)
567             _composite.show();
568         else if(tid == NR::NR_FILTER_CONVOLVEMATRIX)
569             _convolvematrix.show();
570         else if(tid == NR::NR_FILTER_DIFFUSELIGHTING)
571             _diffuselighting.show();
572         else if(tid == NR::NR_FILTER_DISPLACEMENTMAP)
573             _displacementmap.show();
574         else if(tid == NR::NR_FILTER_FLOOD)
575             _flood.show();
576         else if(tid == NR::NR_FILTER_GAUSSIANBLUR) {
577             _gaussianblur.show();
578             _gaussianblur_stddeviation.set_value(((SPGaussianBlur*)prim)->stdDeviation.getNumber());
579         }
580         else if(tid == NR::NR_FILTER_IMAGE)
581             _image.show();
582         else if(tid == NR::NR_FILTER_MERGE)
583             _merge.show();
584         else if(tid == NR::NR_FILTER_MORPHOLOGY)
585             _morphology.show();
586         else if(tid == NR::NR_FILTER_OFFSET) {
587             _offset.show();
588             _offset_dx.set_value(((SPFeOffset*)prim)->dx);
589             _offset_dy.set_value(((SPFeOffset*)prim)->dy);
590         }
591         else if(tid == NR::NR_FILTER_SPECULARLIGHTING)
592             _specularlighting.show();
593         else if(tid == NR::NR_FILTER_TILE)
594             _tile.show();
595         else if(tid == NR::NR_FILTER_TURBULENCE)
596             _turbulence.show();
598         _settings.set_sensitive(true);
599         _empty_settings.hide();
600     }
603 SPFilterPrimitive* FilterEffectsDialog::get_selected_primitive()
605     if(_filter_modifier.get_selected_filter()) {
606         Gtk::TreeModel::iterator i = _primitive_list.get_selection()->get_selected();
607         if(i)
608             return (*i)[_primitive_columns.primitive];
609     }
611     return 0;
614 void FilterEffectsDialog::select_primitive(SPFilterPrimitive* prim)
616     for(Gtk::TreeIter i = _primitive_model->children().begin();
617         i != _primitive_model->children().end(); ++i) {
618         if((*i)[_primitive_columns.primitive] == prim)
619             _primitive_list.get_selection()->select(i);
620     }
623 } // namespace Dialog
624 } // namespace UI
625 } // namespace Inkscape
627 /*
628   Local Variables:
629   mode:c++
630   c-file-style:"stroustrup"
631   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
632   indent-tabs-mode:nil
633   fill-column:99
634   End:
635 */
636 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :