summaryrefslogtreecommitdiffstats
path: root/src/ui
diff options
context:
space:
mode:
authorJabier Arraiza Cenoz <jabier.arraiza@marker.es>2015-07-24 23:26:11 +0000
committerJabiertxof <jtx@jtx.marker.es>2015-07-24 23:26:11 +0000
commit7b6ffd82650ee1e20a53b0631d5c2dddef58e8d5 (patch)
tree48cae26bf789b11d79f72efc16a6676f960eaaa6 /src/ui
parentupdate to trunk (diff)
parent3D box tool: the shift key must not prevent snapping of the vanishing point. ... (diff)
downloadinkscape-7b6ffd82650ee1e20a53b0631d5c2dddef58e8d5.tar.gz
inkscape-7b6ffd82650ee1e20a53b0631d5c2dddef58e8d5.zip
update to trunk
(bzr r12588.1.45)
Diffstat (limited to 'src/ui')
-rw-r--r--src/ui/CMakeLists.txt23
-rw-r--r--src/ui/Makefile_insert2
-rw-r--r--src/ui/clipboard.cpp33
-rw-r--r--src/ui/dialog/align-and-distribute.cpp86
-rw-r--r--src/ui/dialog/clonetiler.cpp16
-rw-r--r--src/ui/dialog/document-properties.cpp4
-rw-r--r--src/ui/dialog/export.cpp36
-rw-r--r--src/ui/dialog/filter-effects-dialog.cpp58
-rw-r--r--src/ui/dialog/filter-effects-dialog.h4
-rw-r--r--src/ui/dialog/find.cpp92
-rw-r--r--src/ui/dialog/find.h10
-rw-r--r--src/ui/dialog/floating-behavior.cpp2
-rw-r--r--src/ui/dialog/font-substitution.cpp28
-rw-r--r--src/ui/dialog/font-substitution.h5
-rw-r--r--src/ui/dialog/glyphs.cpp12
-rw-r--r--src/ui/dialog/grid-arrange-tab.cpp70
-rw-r--r--src/ui/dialog/icon-preview.cpp10
-rw-r--r--src/ui/dialog/inkscape-preferences.cpp26
-rw-r--r--src/ui/dialog/inkscape-preferences.h1
-rw-r--r--src/ui/dialog/layers.cpp14
-rw-r--r--src/ui/dialog/lpe-fillet-chamfer-properties.cpp27
-rw-r--r--src/ui/dialog/lpe-fillet-chamfer-properties.h8
-rw-r--r--src/ui/dialog/lpe-powerstroke-properties.cpp20
-rw-r--r--src/ui/dialog/lpe-powerstroke-properties.h14
-rw-r--r--src/ui/dialog/object-attributes.cpp2
-rw-r--r--src/ui/dialog/object-properties.cpp10
-rw-r--r--src/ui/dialog/objects.cpp108
-rw-r--r--src/ui/dialog/objects.h18
-rw-r--r--src/ui/dialog/pixelartdialog.cpp8
-rw-r--r--src/ui/dialog/polar-arrange-tab.cpp14
-rw-r--r--src/ui/dialog/print.cpp2
-rw-r--r--src/ui/dialog/svg-fonts-dialog.cpp4
-rw-r--r--src/ui/dialog/swatches.cpp6
-rw-r--r--src/ui/dialog/tags.cpp13
-rw-r--r--src/ui/dialog/text-edit.cpp57
-rw-r--r--src/ui/dialog/text-edit.h17
-rw-r--r--src/ui/dialog/transformation.cpp44
-rw-r--r--src/ui/interface.cpp19
-rw-r--r--src/ui/selected-color.cpp163
-rw-r--r--src/ui/selected-color.h96
-rw-r--r--src/ui/tool/control-point.cpp15
-rw-r--r--src/ui/tool/control-point.h6
-rw-r--r--src/ui/tool/curve-drag-point.cpp29
-rw-r--r--src/ui/tool/curve-drag-point.h6
-rw-r--r--src/ui/tool/multi-path-manipulator.cpp8
-rw-r--r--src/ui/tool/multi-path-manipulator.h1
-rw-r--r--src/ui/tool/node.cpp16
-rw-r--r--src/ui/tool/node.h4
-rw-r--r--src/ui/tool/path-manipulator.cpp71
-rw-r--r--src/ui/tool/path-manipulator.h6
-rw-r--r--src/ui/tool/selector.cpp4
-rw-r--r--src/ui/tool/selector.h1
-rw-r--r--src/ui/tools/box3d-tool.cpp2
-rw-r--r--src/ui/tools/calligraphic-tool.cpp3
-rw-r--r--src/ui/tools/connector-tool.cpp8
-rw-r--r--src/ui/tools/dropper-tool.cpp3
-rw-r--r--src/ui/tools/eraser-tool.cpp57
-rw-r--r--src/ui/tools/flood-tool.cpp2
-rw-r--r--src/ui/tools/gradient-tool.cpp39
-rw-r--r--src/ui/tools/lpe-tool.cpp8
-rw-r--r--src/ui/tools/measure-tool.cpp6
-rw-r--r--src/ui/tools/mesh-tool.cpp29
-rw-r--r--src/ui/tools/node-tool.cpp140
-rw-r--r--src/ui/tools/node-tool.h59
-rw-r--r--src/ui/tools/pen-tool.cpp55
-rw-r--r--src/ui/tools/pencil-tool.cpp16
-rw-r--r--src/ui/tools/rect-tool.cpp1
-rw-r--r--src/ui/tools/select-tool.cpp6
-rw-r--r--src/ui/tools/spray-tool.cpp86
-rw-r--r--src/ui/tools/spray-tool.h17
-rw-r--r--src/ui/tools/text-tool.cpp7
-rw-r--r--src/ui/tools/tool-base.cpp6
-rw-r--r--src/ui/tools/tool-base.h7
-rw-r--r--src/ui/tools/tweak-tool.cpp28
-rw-r--r--src/ui/widget/Makefile_insert18
-rw-r--r--src/ui/widget/color-entry.cpp114
-rw-r--r--src/ui/widget/color-entry.h54
-rw-r--r--src/ui/widget/color-icc-selector.cpp1079
-rw-r--r--src/ui/widget/color-icc-selector.h78
-rw-r--r--src/ui/widget/color-notebook.cpp379
-rw-r--r--src/ui/widget/color-notebook.h99
-rw-r--r--src/ui/widget/color-picker.cpp70
-rw-r--r--src/ui/widget/color-picker.h8
-rw-r--r--src/ui/widget/color-scales.cpp677
-rw-r--r--src/ui/widget/color-scales.h112
-rw-r--r--src/ui/widget/color-slider.cpp633
-rw-r--r--src/ui/widget/color-slider.h110
-rw-r--r--src/ui/widget/color-wheel-selector.cpp302
-rw-r--r--src/ui/widget/color-wheel-selector.h101
-rw-r--r--src/ui/widget/entity-entry.cpp3
-rw-r--r--src/ui/widget/font-variants.cpp719
-rw-r--r--src/ui/widget/font-variants.h162
-rw-r--r--src/ui/widget/object-composite-settings.cpp3
-rw-r--r--src/ui/widget/page-sizer.cpp6
-rw-r--r--src/ui/widget/preferences-widget.cpp1
-rw-r--r--src/ui/widget/preferences-widget.h1
-rw-r--r--src/ui/widget/style-subject.cpp42
-rw-r--r--src/ui/widget/style-subject.h13
98 files changed, 5909 insertions, 809 deletions
diff --git a/src/ui/CMakeLists.txt b/src/ui/CMakeLists.txt
index 991d11feb..58af7d935 100644
--- a/src/ui/CMakeLists.txt
+++ b/src/ui/CMakeLists.txt
@@ -6,6 +6,7 @@ set(ui_SRC
interface.cpp
object-edit.cpp
previewholder.cpp
+ selected-color.cpp
shape-editor.cpp
tool-factory.cpp
tools-switch.cpp
@@ -115,13 +116,20 @@ set(ui_SRC
widget/anchor-selector.cpp
widget/button.cpp
widget/clipmaskicon.cpp
+ widget/color-entry.cpp
+ widget/color-icc-selector.cpp
+ widget/color-notebook.cpp
widget/color-picker.cpp
widget/color-preview.cpp
+ widget/color-scales.cpp
+ widget/color-slider.cpp
+ widget/color-wheel-selector.cpp
widget/dock-item.cpp
widget/dock.cpp
widget/entity-entry.cpp
widget/entry.cpp
widget/filter-effect-chooser.cpp
+ widget/font-variants.cpp
widget/frame.cpp
widget/gimpcolorwheel.c
widget/gimpspinscale.c
@@ -174,6 +182,7 @@ set(ui_SRC
previewable.h
previewfillable.h
previewholder.h
+ selected-color.h
shape-editor.h
tool-factory.h
tools-switch.h
@@ -217,6 +226,7 @@ set(ui_SRC
dialog/livepatheffect-add.h
dialog/livepatheffect-editor.h
dialog/lpe-fillet-chamfer-properties.h
+ dialog/lpe-powerstroke-properties.h
dialog/memory.h
dialog/messages.h
dialog/new-from-template.h
@@ -233,6 +243,7 @@ set(ui_SRC
dialog/svg-fonts-dialog.h
dialog/swatches.h
dialog/symbols.h
+ dialog/tags.h
dialog/template-load-tab.h
dialog/template-widget.h
dialog/text-edit.h
@@ -284,24 +295,36 @@ set(ui_SRC
tools/tweak-tool.h
tools/zoom-tool.h
+ widget/addtoicon.h
widget/anchor-selector.h
widget/attr-widget.h
widget/button.h
+ widget/clipmaskicon.h
+ widget/color-entry.h
+ widget/color-icc-selector.h
+ widget/color-notebook.h
widget/color-picker.h
widget/color-preview.h
+ widget/color-scales.h
+ widget/color-slider.h
+ widget/color-wheel-selector.h
widget/combo-enums.h
widget/dock-item.h
widget/dock.h
widget/entity-entry.h
widget/entry.h
widget/filter-effect-chooser.h
+ widget/font-variants.h
widget/frame.h
widget/gimpspinscale.h
widget/gimpcolorwheel.h
+ widget/highlight-picker.h
+ widget/insertordericon.h
widget/imageicon.h
widget/imagetoggler.h
widget/labelled.h
widget/layer-selector.h
+ widget/layertypeicon.h
widget/licensor.h
widget/notebook-page.h
widget/object-composite-settings.h
diff --git a/src/ui/Makefile_insert b/src/ui/Makefile_insert
index f94cba4e9..bbfdb532c 100644
--- a/src/ui/Makefile_insert
+++ b/src/ui/Makefile_insert
@@ -19,6 +19,8 @@ ink_common_sources += \
ui/previewfillable.h \
ui/previewholder.cpp \
ui/previewholder.h \
+ ui/selected-color.h \
+ ui/selected-color.cpp \
ui/shape-editor.cpp \
ui/shape-editor.h \
ui/tool-factory.cpp \
diff --git a/src/ui/clipboard.cpp b/src/ui/clipboard.cpp
index f1d0ff576..d6cf1f980 100644
--- a/src/ui/clipboard.cpp
+++ b/src/ui/clipboard.cpp
@@ -523,8 +523,9 @@ bool ClipboardManagerImpl::pasteSize(SPDesktop *desktop, bool separately, bool a
// resize each object in the selection
if (separately) {
- for (GSList *i = const_cast<GSList*>(selection->itemList()) ; i ; i = i->next) {
- SPItem *item = dynamic_cast<SPItem *>(static_cast<SPObject *>(i->data));
+ std::vector<SPItem*> itemlist=selection->itemList();
+ for(std::vector<SPItem*>::const_iterator i=itemlist.begin();i!=itemlist.end();i++){
+ SPItem *item = *i;
if (item) {
Geom::OptRect obj_size = item->desktopVisualBounds();
if ( obj_size ) {
@@ -578,8 +579,9 @@ bool ClipboardManagerImpl::pastePathEffect(SPDesktop *desktop)
desktop->doc()->importDefs(tempdoc);
// make sure all selected items are converted to paths first (i.e. rectangles)
sp_selected_to_lpeitems(desktop);
- for (GSList *itemptr = const_cast<GSList *>(selection->itemList()) ; itemptr ; itemptr = itemptr->next) {
- SPItem *item = reinterpret_cast<SPItem*>(itemptr->data);
+ std::vector<SPItem*> itemlist=selection->itemList();
+ for(std::vector<SPItem*>::const_iterator i=itemlist.begin();i!=itemlist.end();i++){
+ SPItem *item = *i;
_applyPathEffect(item, effectstack);
}
@@ -659,10 +661,10 @@ Glib::ustring ClipboardManagerImpl::getShapeOrTextObjectId(SPDesktop *desktop)
*/
void ClipboardManagerImpl::_copySelection(Inkscape::Selection *selection)
{
- GSList const *items = selection->itemList();
// copy the defs used by all items
- for (GSList *i = const_cast<GSList *>(items) ; i != NULL ; i = i->next) {
- SPItem *item = dynamic_cast<SPItem *>(static_cast<SPObject *>(i->data));
+ std::vector<SPItem*> itemlist=selection->itemList();
+ for(std::vector<SPItem*>::const_iterator i=itemlist.begin();i!=itemlist.end();i++){
+ SPItem *item = *i;
if (item) {
_copyUsedDefs(item);
} else {
@@ -671,11 +673,11 @@ void ClipboardManagerImpl::_copySelection(Inkscape::Selection *selection)
}
// copy the representation of the items
- GSList *sorted_items = g_slist_copy(const_cast<GSList *>(items));
- sorted_items = g_slist_sort(sorted_items, (GCompareFunc) sp_object_compare_position);
+ std::vector<SPItem*> sorted_items(itemlist);
+ sort(sorted_items.begin(),sorted_items.end(),sp_object_compare_position_bool);
- for (GSList *i = sorted_items ; i ; i = i->next) {
- SPItem *item = dynamic_cast<SPItem *>(static_cast<SPObject *>(i->data));
+ for(std::vector<SPItem*>::const_iterator i=sorted_items.begin();i!=sorted_items.end();i++){
+ SPItem *item = *i;
if (item) {
Inkscape::XML::Node *obj = item->getRepr();
Inkscape::XML::Node *obj_copy = _copyNode(obj, _doc, _root);
@@ -703,8 +705,8 @@ void ClipboardManagerImpl::_copySelection(Inkscape::Selection *selection)
}
// copy style for Paste Style action
- if (sorted_items) {
- SPObject *object = static_cast<SPObject *>(sorted_items->data);
+ if (!sorted_items.empty()) {
+ SPObject *object = sorted_items[0];
SPItem *item = dynamic_cast<SPItem *>(object);
if (item) {
SPCSSAttr *style = take_style_from_item(item);
@@ -727,7 +729,6 @@ void ClipboardManagerImpl::_copySelection(Inkscape::Selection *selection)
sp_repr_set_point(_clipnode, "max", size->max());
}
- g_slist_free(sorted_items);
}
@@ -1164,8 +1165,8 @@ void ClipboardManagerImpl::_onGet(Gtk::SelectionData &sel, guint /*info*/)
sp_repr_get_double(nv, "inkscape:pageopacity", &opacity);
bgcolor |= SP_COLOR_F_TO_U(opacity);
}
-
- sp_export_png_file(_clipboardSPDoc, filename, area, width, height, dpi, dpi, bgcolor, NULL, NULL, true, NULL);
+ std::vector<SPItem*> x;
+ sp_export_png_file(_clipboardSPDoc, filename, area, width, height, dpi, dpi, bgcolor, NULL, NULL, true, x);
}
else
{
diff --git a/src/ui/dialog/align-and-distribute.cpp b/src/ui/dialog/align-and-distribute.cpp
index 65bc94011..882427912 100644
--- a/src/ui/dialog/align-and-distribute.cpp
+++ b/src/ui/dialog/align-and-distribute.cpp
@@ -97,9 +97,7 @@ void ActionAlign::do_action(SPDesktop *desktop, int index)
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
bool sel_as_group = prefs->getBool("/dialogs/align/sel-as-groups");
- using Inkscape::Util::GSListConstIterator;
- std::list<SPItem *> selected;
- selected.insert<GSListConstIterator<SPItem *> >(selected.end(), selection->itemList(), NULL);
+ std::vector<SPItem*> selected(selection->itemList());
if (selected.empty()) return;
const Coeffs &a = _allCoeffs[index];
@@ -149,18 +147,19 @@ void ActionAlign::do_action(SPDesktop *desktop, int index)
b = selection->preferredBounds();
//Move each item in the selected list separately
- for (std::list<SPItem *>::iterator it(selected.begin());
+ for (std::vector<SPItem*>::iterator it(selected.begin());
it != selected.end(); ++it)
{
+ SPItem* item= *it;
desktop->getDocument()->ensureUpToDate();
if (!sel_as_group)
- b = (*it)->desktopPreferredBounds();
- if (b && (!focus || (*it) != focus)) {
+ b = (item)->desktopPreferredBounds();
+ if (b && (!focus || (item) != focus)) {
Geom::Point const sp(a.sx0 * b->min()[Geom::X] + a.sx1 * b->max()[Geom::X],
a.sy0 * b->min()[Geom::Y] + a.sy1 * b->max()[Geom::Y]);
Geom::Point const mp_rel( mp - sp );
if (LInfty(mp_rel) > 1e-9) {
- sp_item_move_rel(*it, Geom::Translate(mp_rel));
+ sp_item_move_rel(item, Geom::Translate(mp_rel));
changed = true;
}
}
@@ -250,26 +249,24 @@ private :
Inkscape::Selection *selection = desktop->getSelection();
if (!selection) return;
- using Inkscape::Util::GSListConstIterator;
- std::list<SPItem *> selected;
- selected.insert<GSListConstIterator<SPItem *> >(selected.end(), selection->itemList(), NULL);
+ std::vector<SPItem*> selected(selection->itemList());
if (selected.empty()) return;
//Check 2 or more selected objects
- std::list<SPItem *>::iterator second(selected.begin());
+ std::vector<SPItem*>::iterator second(selected.begin());
++second;
if (second == selected.end()) return;
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
int prefs_bbox = prefs->getBool("/tools/bounding_box");
std::vector< BBoxSort > sorted;
- for (std::list<SPItem *>::iterator it(selected.begin());
+ for (std::vector<SPItem*>::iterator it(selected.begin());
it != selected.end();
- ++it)
- {
- Geom::OptRect bbox = !prefs_bbox ? (*it)->desktopVisualBounds() : (*it)->desktopGeometricBounds();
+ ++it){
+ SPItem *item = *it;
+ Geom::OptRect bbox = !prefs_bbox ? (item)->desktopVisualBounds() : (item)->desktopGeometricBounds();
if (bbox) {
- sorted.push_back(BBoxSort(*it, *bbox, _orientation, _kBegin, _kEnd));
+ sorted.push_back(BBoxSort(item, *bbox, _orientation, _kBegin, _kEnd));
}
}
//sort bbox by anchors
@@ -549,9 +546,7 @@ private :
Inkscape::Selection *selection = desktop->getSelection();
if (!selection) return;
- using Inkscape::Util::GSListConstIterator;
- std::list<SPItem *> selected;
- selected.insert<GSListConstIterator<SPItem *> >(selected.end(), selection->itemList(), NULL);
+ std::vector<SPItem*> selected(selection->itemList());
if (selected.empty()) return;
//Check 2 or more selected objects
@@ -569,15 +564,17 @@ private :
} else { // sorting by ZOrder is outomatically done by not setting the center
center.reset();
}
- selected.sort(ActionExchangePositions::sort_compare);
+ sort(selected.begin(),selected.end(),sort_compare);
}
- std::list<SPItem *>::iterator it(selected.begin());
- Geom::Point p1 = (*it)->getCenter();
+ std::vector<SPItem*>::iterator it(selected.begin());
+ SPItem* item = *it;
+ Geom::Point p1 = item->getCenter();
for (++it ;it != selected.end(); ++it)
{
- Geom::Point p2 = (*it)->getCenter();
+ item = *it;
+ Geom::Point p2 = item->getCenter();
Geom::Point delta = p1 - p2;
- sp_item_move_rel((*it),Geom::Translate(delta[Geom::X],delta[Geom::Y] ));
+ sp_item_move_rel(item,Geom::Translate(delta[Geom::X],delta[Geom::Y] ));
p1 = p2;
}
Geom::Point p2 = selected.front()->getCenter();
@@ -615,8 +612,8 @@ private :
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
int saved_compensation = prefs->getInt("/options/clonecompensation/value", SP_CLONE_COMPENSATION_UNMOVED);
prefs->setInt("/options/clonecompensation/value", SP_CLONE_COMPENSATION_UNMOVED);
-
- unclump ((GSList *) _dialog.getDesktop()->getSelection()->itemList());
+ std::vector<SPItem*> x(_dialog.getDesktop()->getSelection()->itemList());
+ unclump (x);
// restore compensation setting
prefs->setInt("/options/clonecompensation/value", saved_compensation);
@@ -646,9 +643,7 @@ private :
Inkscape::Selection *selection = desktop->getSelection();
if (!selection) return;
- using Inkscape::Util::GSListConstIterator;
- std::list<SPItem *> selected;
- selected.insert<GSListConstIterator<SPItem *> >(selected.end(), selection->itemList(), NULL);
+ std::vector<SPItem*> selected(selection->itemList());
if (selected.empty()) return;
//Check 2 or more selected objects
@@ -672,12 +667,13 @@ private :
int saved_compensation = prefs->getInt("/options/clonecompensation/value", SP_CLONE_COMPENSATION_UNMOVED);
prefs->setInt("/options/clonecompensation/value", SP_CLONE_COMPENSATION_UNMOVED);
- for (std::list<SPItem *>::iterator it(selected.begin());
+ for (std::vector<SPItem*>::iterator it(selected.begin());
it != selected.end();
++it)
{
+ SPItem* item = *it;
desktop->getDocument()->ensureUpToDate();
- Geom::OptRect item_box = !prefs_bbox ? (*it)->desktopVisualBounds() : (*it)->desktopGeometricBounds();
+ Geom::OptRect item_box = !prefs_bbox ? (item)->desktopVisualBounds() : (item)->desktopGeometricBounds();
if (item_box) {
// find new center, staying within bbox
double x = _dialog.randomize_bbox->min()[Geom::X] + (*item_box)[Geom::X].extent() /2 +
@@ -686,7 +682,7 @@ private :
g_random_double_range (0, (*_dialog.randomize_bbox)[Geom::Y].extent() - (*item_box)[Geom::Y].extent());
// displacement is the new center minus old:
Geom::Point t = Geom::Point (x, y) - 0.5*(item_box->max() + item_box->min());
- sp_item_move_rel(*it, Geom::Translate(t));
+ sp_item_move_rel(item, Geom::Translate(t));
}
}
@@ -745,9 +741,7 @@ private :
Inkscape::Selection *selection = desktop->getSelection();
if (!selection) return;
- using Inkscape::Util::GSListConstIterator;
- std::list<SPItem *> selected;
- selected.insert<GSListConstIterator<SPItem *> >(selected.end(), selection->itemList(), NULL);
+ std::vector<SPItem*> selected(selection->itemList());
if (selected.empty()) return;
//Check 2 or more selected objects
@@ -758,20 +752,21 @@ private :
std::vector<Baselines> sorted;
- for (std::list<SPItem *>::iterator it(selected.begin());
+ for (std::vector<SPItem*>::iterator it(selected.begin());
it != selected.end();
++it)
{
- if (SP_IS_TEXT (*it) || SP_IS_FLOWTEXT (*it)) {
- Inkscape::Text::Layout const *layout = te_get_layout(*it);
+ SPItem* item = *it;
+ if (SP_IS_TEXT (item) || SP_IS_FLOWTEXT (item)) {
+ Inkscape::Text::Layout const *layout = te_get_layout(item);
boost::optional<Geom::Point> pt = layout->baselineAnchorPoint();
if (pt) {
- Geom::Point base = *pt * (*it)->i2dt_affine();
+ Geom::Point base = *pt * (item)->i2dt_affine();
if (base[Geom::X] < b_min[Geom::X]) b_min[Geom::X] = base[Geom::X];
if (base[Geom::Y] < b_min[Geom::Y]) b_min[Geom::Y] = base[Geom::Y];
if (base[Geom::X] > b_max[Geom::X]) b_max[Geom::X] = base[Geom::X];
if (base[Geom::Y] > b_max[Geom::Y]) b_max[Geom::Y] = base[Geom::Y];
- Baselines b (*it, base, _orientation);
+ Baselines b (item, base, _orientation);
sorted.push_back(b);
}
}
@@ -801,18 +796,19 @@ private :
}
} else {
- for (std::list<SPItem *>::iterator it(selected.begin());
+ for (std::vector<SPItem*>::iterator it(selected.begin());
it != selected.end();
++it)
{
- if (SP_IS_TEXT (*it) || SP_IS_FLOWTEXT (*it)) {
- Inkscape::Text::Layout const *layout = te_get_layout(*it);
+ SPItem* item = *it;
+ if (SP_IS_TEXT (item) || SP_IS_FLOWTEXT (item)) {
+ Inkscape::Text::Layout const *layout = te_get_layout(item);
boost::optional<Geom::Point> pt = layout->baselineAnchorPoint();
if (pt) {
- Geom::Point base = *pt * (*it)->i2dt_affine();
+ Geom::Point base = *pt * (item)->i2dt_affine();
Geom::Point t(0.0, 0.0);
t[_orientation] = b_min[_orientation] - base[_orientation];
- sp_item_move_rel(*it, Geom::Translate(t));
+ sp_item_move_rel(item, Geom::Translate(t));
changed = true;
}
}
diff --git a/src/ui/dialog/clonetiler.cpp b/src/ui/dialog/clonetiler.cpp
index bd3ad0254..f84a2ffd6 100644
--- a/src/ui/dialog/clonetiler.cpp
+++ b/src/ui/dialog/clonetiler.cpp
@@ -1359,7 +1359,7 @@ void CloneTiler::clonetiler_change_selection(Inkscape::Selection *selection, Gtk
return;
}
- if (g_slist_length ((GSList *) selection->itemList()) > 1) {
+ if (selection->itemList().size() > 1) {
gtk_widget_set_sensitive (buttons, FALSE);
gtk_label_set_markup (GTK_LABEL(status), _("<small>More than one object selected.</small>"));
return;
@@ -2096,7 +2096,7 @@ void CloneTiler::clonetiler_unclump(GtkWidget */*widget*/, void *)
Inkscape::Selection *selection = desktop->getSelection();
// check if something is selected
- if (selection->isEmpty() || g_slist_length((GSList *) selection->itemList()) > 1) {
+ if (selection->isEmpty() || selection->itemList().size() > 1) {
desktop->getMessageStack()->flash(Inkscape::WARNING_MESSAGE, _("Select <b>one object</b> whose tiled clones to unclump."));
return;
}
@@ -2104,20 +2104,18 @@ void CloneTiler::clonetiler_unclump(GtkWidget */*widget*/, void *)
SPObject *obj = selection->singleItem();
SPObject *parent = obj->parent;
- GSList *to_unclump = NULL; // not including the original
+ std::vector<SPItem*> to_unclump; // not including the original
for (SPObject *child = parent->firstChild(); child != NULL; child = child->next) {
if (clonetiler_is_a_clone_of (child, obj)) {
- to_unclump = g_slist_prepend (to_unclump, child);
+ to_unclump.push_back((SPItem*)child);
}
}
desktop->getDocument()->ensureUpToDate();
-
+ reverse(to_unclump.begin(),to_unclump.end());
unclump (to_unclump);
- g_slist_free (to_unclump);
-
DocumentUndo::done(desktop->getDocument(), SP_VERB_DIALOG_CLONETILER,
_("Unclump tiled clones"));
}
@@ -2147,7 +2145,7 @@ void CloneTiler::clonetiler_remove(GtkWidget */*widget*/, GtkWidget *dlg, bool d
Inkscape::Selection *selection = desktop->getSelection();
// check if something is selected
- if (selection->isEmpty() || g_slist_length((GSList *) selection->itemList()) > 1) {
+ if (selection->isEmpty() || selection->itemList().size() > 1) {
desktop->getMessageStack()->flash(Inkscape::WARNING_MESSAGE, _("Select <b>one object</b> whose tiled clones to remove."));
return;
}
@@ -2225,7 +2223,7 @@ void CloneTiler::clonetiler_apply(GtkWidget */*widget*/, GtkWidget *dlg)
}
// Check if more than one object is selected.
- if (g_slist_length((GSList *) selection->itemList()) > 1) {
+ if (selection->itemList().size() > 1) {
desktop->getMessageStack()->flash(Inkscape::ERROR_MESSAGE, _("If you want to clone several objects, <b>group</b> them and <b>clone the group</b>."));
return;
}
diff --git a/src/ui/dialog/document-properties.cpp b/src/ui/dialog/document-properties.cpp
index c381ed755..b04e8ecc1 100644
--- a/src/ui/dialog/document-properties.cpp
+++ b/src/ui/dialog/document-properties.cpp
@@ -1672,10 +1672,10 @@ void DocumentProperties::onDocUnitChange()
Inkscape::XML::Node *repr = getDesktop()->getNamedView()->getRepr();
- Inkscape::Util::Unit const *old_doc_unit = unit_table.getUnit("px");
+ /*Inkscape::Util::Unit const *old_doc_unit = unit_table.getUnit("px");
if(repr->attribute("inkscape:document-units")) {
old_doc_unit = unit_table.getUnit(repr->attribute("inkscape:document-units"));
- }
+ }*/
Inkscape::Util::Unit const *doc_unit = _rum_deflt.getUnit();
// Set document unit
diff --git a/src/ui/dialog/export.cpp b/src/ui/dialog/export.cpp
index 9ac5c24fe..1edfdfe80 100644
--- a/src/ui/dialog/export.cpp
+++ b/src/ui/dialog/export.cpp
@@ -601,7 +601,7 @@ void Export::onBatchClicked ()
void Export::updateCheckbuttons ()
{
- gint num = g_slist_length((GSList *) SP_ACTIVE_DESKTOP->getSelection()->itemList());
+ gint num = SP_ACTIVE_DESKTOP->getSelection()->itemList().size();
if (num >= 2) {
batch_export.set_sensitive(true);
batch_export.set_label(g_strdup_printf (ngettext("B_atch export %d selected object","B_atch export %d selected objects",num), num));
@@ -813,9 +813,9 @@ void Export::onAreaToggled ()
one that's nice */
if (filename.empty()) {
const gchar * id = "object";
- const GSList * reprlst = SP_ACTIVE_DESKTOP->getSelection()->reprList();
- for(; reprlst != NULL; reprlst = reprlst->next) {
- Inkscape::XML::Node * repr = (Inkscape::XML::Node *)reprlst->data;
+ const std::vector<XML::Node*> reprlst = SP_ACTIVE_DESKTOP->getSelection()->reprList();
+ for(std::vector<XML::Node*>::const_iterator i=reprlst.begin(); reprlst.end() != i; i++) {
+ Inkscape::XML::Node * repr = *i;
if (repr->attribute("id")) {
id = repr->attribute("id");
break;
@@ -945,17 +945,19 @@ Gtk::Dialog * Export::create_progress_dialog (Glib::ustring progress_text) {
Glib::ustring Export::filename_add_extension (Glib::ustring filename, Glib::ustring extension)
{
Glib::ustring::size_type dot;
+ Glib::ustring::size_type dot_ext;
dot = filename.find_last_of(".");
- if ( !dot )
+ dot_ext = filename.lowercase().rfind("." + extension.lowercase());
+ if ( dot == std::string::npos )
{
return filename = filename + "." + extension;
}
else
{
- if (dot==filename.find_last_of(Glib::ustring::compose(".", extension)))
+ if (dot == dot_ext)
{
- return filename;
+ return filename = filename;
}
else
{
@@ -1006,7 +1008,7 @@ void Export::onExport ()
if (batch_export.get_active ()) {
// Batch export of selected objects
- gint num = g_slist_length(const_cast<GSList *>(desktop->getSelection()->itemList()));
+ gint num = (desktop->getSelection()->itemList()).size();
gint n = 0;
if (num < 1) {
@@ -1020,8 +1022,9 @@ void Export::onExport ()
gint export_count = 0;
- for (GSList *i = const_cast<GSList *>(desktop->getSelection()->itemList()); i && !interrupted; i = i->next) {
- SPItem *item = reinterpret_cast<SPItem *>(i->data);
+ std::vector<SPItem*> itemlist=desktop->getSelection()->itemList();
+ for(std::vector<SPItem*>::const_iterator i = itemlist.begin();i!=itemlist.end() && !interrupted ;i++){
+ SPItem *item = *i;
prog_dlg->set_data("current", GINT_TO_POINTER(n));
prog_dlg->set_data("total", GINT_TO_POINTER(num));
@@ -1059,13 +1062,13 @@ void Export::onExport ()
_("Exporting file <b>%s</b>..."), safeFile), desktop);
MessageCleaner msgFlashCleanup(desktop->messageStack()->flashF(Inkscape::IMMEDIATE_MESSAGE,
_("Exporting file <b>%s</b>..."), safeFile), desktop);
-
+ std::vector<SPItem*> x;
if (!sp_export_png_file (doc, path.c_str(),
*area, width, height, dpi, dpi,
nv->pagecolor,
onProgressCallback, (void*)prog_dlg,
TRUE, // overwrite without asking
- hide ? const_cast<GSList *>(desktop->getSelection()->itemList()) : NULL
+ hide ? (desktop->getSelection()->itemList()) : x
)) {
gchar * error = g_strdup_printf(_("Could not export to filename %s.\n"), safeFile);
@@ -1149,12 +1152,13 @@ void Export::onExport ()
prog_dlg->set_data("total", GINT_TO_POINTER(0));
/* Do export */
+ std::vector<SPItem*> x;
ExportResult status = sp_export_png_file(desktop->getDocument(), path.c_str(),
Geom::Rect(Geom::Point(x0, y0), Geom::Point(x1, y1)), width, height, xdpi, ydpi,
nv->pagecolor,
onProgressCallback, (void*)prog_dlg,
FALSE,
- hide ? const_cast<GSList *>(desktop->getSelection()->itemList()) : NULL
+ hide ? (desktop->getSelection()->itemList()) : x
);
if (status == EXPORT_ERROR) {
gchar * safeFile = Inkscape::IO::sanitizeString(path.c_str());
@@ -1220,7 +1224,7 @@ void Export::onExport ()
break;
}
case SELECTION_SELECTION: {
- const GSList * reprlst;
+ std::vector<XML::Node*> reprlst;
SPDocument * doc = SP_ACTIVE_DOCUMENT;
bool modified = false;
@@ -1228,8 +1232,8 @@ void Export::onExport ()
DocumentUndo::setUndoSensitive(doc, false);
reprlst = desktop->getSelection()->reprList();
- for(; reprlst != NULL; reprlst = reprlst->next) {
- Inkscape::XML::Node * repr = static_cast<Inkscape::XML::Node *>(reprlst->data);
+ for(std::vector<Inkscape::XML::Node*>::const_iterator i=reprlst.begin(); reprlst.end() != i; i++) {
+ Inkscape::XML::Node * repr = *i;
const gchar * temp_string;
Glib::ustring dir = Glib::path_get_dirname(filename.c_str());
const gchar* docURI=SP_ACTIVE_DOCUMENT->getURI();
diff --git a/src/ui/dialog/filter-effects-dialog.cpp b/src/ui/dialog/filter-effects-dialog.cpp
index 077c6f5ca..1ff9e4a1b 100644
--- a/src/ui/dialog/filter-effects-dialog.cpp
+++ b/src/ui/dialog/filter-effects-dialog.cpp
@@ -8,6 +8,7 @@
* Felipe C. da S. Sanches <juca@members.fsf.org>
* Jon A. Cruz <jon@joncruz.org>
* Abhishek Sharma
+ * insaner
*
* Copyright (C) 2007 Authors
*
@@ -690,7 +691,7 @@ private:
void select_svg_element(){
Inkscape::Selection* sel = _desktop->getSelection();
if (sel->isEmpty()) return;
- Inkscape::XML::Node* node = (Inkscape::XML::Node*) g_slist_nth_data((GSList *)sel->reprList(), 0);
+ Inkscape::XML::Node* node = sel->reprList()[0];
if (!node || !node->matchAttributeName("id")) return;
std::ostringstream xlikhref;
@@ -1360,8 +1361,15 @@ FilterEffectsDialog::FilterModifier::FilterModifier(FilterEffectsDialog& d)
((Gtk::CellRendererText*)_list.get_column(1)->get_first_cell())->
signal_edited().connect(sigc::mem_fun(*this, &FilterEffectsDialog::FilterModifier::on_name_edited));
+ _list.append_column("#", _columns.count);
+ _list.get_column(2)->set_sizing(Gtk::TREE_VIEW_COLUMN_AUTOSIZE);
+ _list.get_column(2)->set_expand(false);
+
sw->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
_list.get_column(1)->set_resizable(true);
+ _list.get_column(1)->set_sizing(Gtk::TREE_VIEW_COLUMN_AUTOSIZE);
+ _list.get_column(1)->set_expand(true);
+
_list.set_reorderable(true);
_list.enable_model_drag_dest (Gdk::ACTION_MOVE);
@@ -1465,9 +1473,9 @@ void FilterEffectsDialog::FilterModifier::update_selection(Selection *sel)
}
std::set<SPObject*> used;
-
- for (GSList const *i = sel->itemList(); i != NULL; i = i->next) {
- SPObject *obj = SP_OBJECT (i->data);
+ std::vector<SPItem*> itemlist=sel->itemList();
+ for(std::vector<SPItem*>::const_iterator i=itemlist.begin(); itemlist.end() != i; i++) {
+ SPObject *obj = *i;
SPStyle *style = obj->style;
if (!style || !SP_IS_ITEM(obj)) {
continue;
@@ -1494,6 +1502,7 @@ void FilterEffectsDialog::FilterModifier::update_selection(Selection *sel)
(*iter)[_columns.sel] = 0;
}
}
+ update_counts();
}
void FilterEffectsDialog::FilterModifier::on_filter_selection_changed()
@@ -1545,10 +1554,9 @@ void FilterEffectsDialog::FilterModifier::on_selection_toggled(const Glib::ustri
if((*iter)[_columns.sel] == 1)
filter = 0;
- GSList const *items = sel->itemList();
-
- for (GSList const *i = items; i != NULL; i = i->next) {
- SPItem * item = SP_ITEM(i->data);
+ std::vector<SPItem*> itemlist=sel->itemList();
+ for(std::vector<SPItem*>::const_iterator i=itemlist.begin(); itemlist.end() != i; i++) {
+ SPItem * item = *i;
SPStyle *style = item->style;
g_assert(style != NULL);
@@ -1566,6 +1574,15 @@ void FilterEffectsDialog::FilterModifier::on_selection_toggled(const Glib::ustri
}
}
+
+void FilterEffectsDialog::FilterModifier::update_counts()
+{
+ for(Gtk::TreeModel::iterator i = _model->children().begin(); i != _model->children().end(); ++i) {
+ SPFilter* f = SP_FILTER((*i)[_columns.filter]);
+ (*i)[_columns.count] = f->getRefCount();
+ }
+}
+
/* Add all filters in the document to the combobox.
Keeps the same selection if possible, otherwise selects the first element */
void FilterEffectsDialog::FilterModifier::update_filters()
@@ -1650,12 +1667,13 @@ void FilterEffectsDialog::FilterModifier::remove_filter()
SPDocument* doc = filter->document;
// Delete all references to this filter
- GSList *all = get_all_items(NULL, _desktop->currentRoot(), _desktop, false, false, true, NULL);
- for (GSList *i = all; i != NULL; i = i->next) {
- if (!SP_IS_ITEM(i->data)) {
+ std::vector<SPItem*> x,y;
+ std::vector<SPItem*> all = get_all_items(x, _desktop->currentRoot(), _desktop, false, false, true, y);
+ for(std::vector<SPItem*>::const_iterator i=all.begin(); all.end() != i; i++) {
+ if (!SP_IS_ITEM(*i)) {
continue;
}
- SPItem *item = SP_ITEM(i->data);
+ SPItem *item = *i;
if (!item->style) {
continue;
}
@@ -1668,9 +1686,6 @@ void FilterEffectsDialog::FilterModifier::remove_filter()
}
}
}
- if (all) {
- g_slist_free(all);
- }
//XML Tree being used directly here while it shouldn't be.
sp_repr_unparent(filter->getRepr());
@@ -2422,7 +2437,7 @@ bool FilterEffectsDialog::PrimitiveList::on_motion_notify_event(GdkEventMotion*
get_visible_rect(vis);
int vis_x, vis_y;
- int vis_x2, vis_y2; // NOTE: insaner added -- necessary to get the scrolling while dragging to work
+ int vis_x2, vis_y2;
convert_widget_to_tree_coords(vis.get_x(), vis.get_y(), vis_x2, vis_y2);
convert_tree_to_widget_coords(vis.get_x(), vis.get_y(), vis_x, vis_y);
@@ -2442,7 +2457,6 @@ bool FilterEffectsDialog::PrimitiveList::on_motion_notify_event(GdkEventMotion*
else
_autoscroll_y = 0;
- // NOTE: insaner added -- necessary to get the scrolling while dragging to work
double e2 = ( e->x - vis_x2/2);
// horizontal scrolling
if(e2 < vis_x)
@@ -2755,20 +2769,22 @@ FilterEffectsDialog::FilterEffectsDialog()
Gtk::ScrolledWindow* sw_infobox = Gtk::manage(new Gtk::ScrolledWindow);
Gtk::HBox* infobox = Gtk::manage(new Gtk::HBox(/*homogeneous:*/false, /*spacing:*/4));
Gtk::HBox* hb_prims = Gtk::manage(new Gtk::HBox);
+ Gtk::VBox* vb_prims = Gtk::manage(new Gtk::VBox);
_getContents()->add(*hpaned);
hpaned->pack1(_filter_modifier);
hpaned->pack2(_primitive_box);
_primitive_box.pack_start(*sw_prims);
- _primitive_box.pack_start(*hb_prims, false, false);
_primitive_box.pack_start(*sw_infobox, false, false);
sw_prims->add(_primitive_list);
- sw_infobox->add(*infobox);
+ sw_infobox->add(*vb_prims);
infobox->pack_start(_infobox_icon, false, false);
infobox->pack_start(_infobox_desc, false, false);
_infobox_desc.set_line_wrap(true);
- _infobox_desc.set_size_request(200, -1);
+ _infobox_desc.set_size_request(250, -1);
+ vb_prims->pack_start(*hb_prims);
+ vb_prims->pack_start(*infobox);
hb_prims->pack_start(_add_primitive, false, false);
hb_prims->pack_start(_add_primitive_type, false, false);
@@ -2784,7 +2800,7 @@ FilterEffectsDialog::FilterEffectsDialog()
_add_primitive_type.signal_changed().connect(
sigc::mem_fun(*this, &FilterEffectsDialog::update_primitive_infobox));
- sw_prims->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC); /* NOTE: insaner -- SCROLL the connections panel thing!!! */
+ sw_prims->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
sw_prims->set_shadow_type(Gtk::SHADOW_IN);
sw_infobox->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_NEVER);
diff --git a/src/ui/dialog/filter-effects-dialog.h b/src/ui/dialog/filter-effects-dialog.h
index 3fc19e7de..a067cd70c 100644
--- a/src/ui/dialog/filter-effects-dialog.h
+++ b/src/ui/dialog/filter-effects-dialog.h
@@ -4,6 +4,7 @@
/* Authors:
* Nicholas Bishop <nicholasbishop@gmail.com>
* Rodrigo Kumpera <kumpera@gmail.com>
+ * insaner
*
* Copyright (C) 2007 Authors
*
@@ -69,11 +70,13 @@ private:
add(filter);
add(label);
add(sel);
+ add(count);
}
Gtk::TreeModelColumn<SPFilter*> filter;
Gtk::TreeModelColumn<Glib::ustring> label;
Gtk::TreeModelColumn<int> sel;
+ Gtk::TreeModelColumn<int> count;
};
void setTargetDesktop(SPDesktop *desktop);
@@ -89,6 +92,7 @@ private:
bool on_filter_move(const Glib::RefPtr<Gdk::DragContext>& /*context*/, int x, int y, guint /*time*/);
void on_selection_toggled(const Glib::ustring&);
+ void update_counts();
void update_filters();
void filter_list_button_release(GdkEventButton*);
void add_filter();
diff --git a/src/ui/dialog/find.cpp b/src/ui/dialog/find.cpp
index 951cb01ea..a8ac42a1b 100644
--- a/src/ui/dialog/find.cpp
+++ b/src/ui/dialog/find.cpp
@@ -549,7 +549,7 @@ bool Find::item_font_match(SPItem *item, const gchar *text, bool exact, bool cas
}
-GSList *Find::filter_fields (GSList *l, bool exact, bool casematch)
+std::vector<SPItem*> Find::filter_fields (std::vector<SPItem*> &l, bool exact, bool casematch)
{
Glib::ustring tmp = entry_find.getEntry()->get_text();
if (tmp.empty()) {
@@ -557,17 +557,17 @@ GSList *Find::filter_fields (GSList *l, bool exact, bool casematch)
}
gchar* text = g_strdup(tmp.c_str());
- GSList *in = l;
- GSList *out = NULL;
+ std::vector<SPItem*> in = l;
+ std::vector<SPItem*> out;
if (check_searchin_text.get_active()) {
- for (GSList *i = in; i != NULL; i = i->next) {
- SPObject *obj = reinterpret_cast<SPObject *>(i->data);
+ for(std::vector<SPItem*>::const_reverse_iterator i=in.rbegin(); in.rend() != i; i++) {
+ SPObject *obj = *i;
SPItem *item = dynamic_cast<SPItem *>(obj);
g_assert(item != NULL);
if (item_text_match(item, text, exact, casematch)) {
- if (!g_slist_find(out, i->data)) {
- out = g_slist_prepend (out, i->data);
+ if (out.end()==find(out.begin(),out.end(), *i)) {
+ out.push_back(*i);
if (_action_replace) {
item_text_match(item, text, exact, casematch, _action_replace);
}
@@ -584,12 +584,12 @@ GSList *Find::filter_fields (GSList *l, bool exact, bool casematch)
bool attrvalue = check_attributevalue.get_active();
if (ids) {
- for (GSList *i = in; i != NULL; i = i->next) {
- SPObject *obj = reinterpret_cast<SPObject *>(i->data);
+ for(std::vector<SPItem*>::const_reverse_iterator i=in.rbegin(); in.rend() != i; i++) {
+ SPObject *obj = *i;
SPItem *item = dynamic_cast<SPItem *>(obj);
if (item_id_match(item, text, exact, casematch)) {
- if (!g_slist_find(out, i->data)) {
- out = g_slist_prepend (out, i->data);
+ if (out.end()==find(out.begin(),out.end(), *i)) {
+ out.push_back(*i);
if (_action_replace) {
item_id_match(item, text, exact, casematch, _action_replace);
}
@@ -600,14 +600,13 @@ GSList *Find::filter_fields (GSList *l, bool exact, bool casematch)
if (style) {
- for (GSList *i = in; i != NULL; i = i->next) {
- SPObject *obj = reinterpret_cast<SPObject *>(i->data);
+ for(std::vector<SPItem*>::const_reverse_iterator i=in.rbegin(); in.rend() != i; i++) {
+ SPObject *obj = *i;
SPItem *item = dynamic_cast<SPItem *>(obj);
g_assert(item != NULL);
if (item_style_match(item, text, exact, casematch)) {
- if (!g_slist_find(out, i->data))
- if (!g_slist_find(out, i->data)) {
- out = g_slist_prepend (out, i->data);
+ if (out.end()==find(out.begin(),out.end(), *i)){
+ out.push_back(*i);
if (_action_replace) {
item_style_match(item, text, exact, casematch, _action_replace);
}
@@ -618,13 +617,13 @@ GSList *Find::filter_fields (GSList *l, bool exact, bool casematch)
if (attrname) {
- for (GSList *i = in; i != NULL; i = i->next) {
- SPObject *obj = reinterpret_cast<SPObject *>(i->data);
+ for(std::vector<SPItem*>::const_reverse_iterator i=in.rbegin(); in.rend() != i; i++) {
+ SPObject *obj = *i;
SPItem *item = dynamic_cast<SPItem *>(obj);
g_assert(item != NULL);
if (item_attr_match(item, text, exact, casematch)) {
- if (!g_slist_find(out, i->data)) {
- out = g_slist_prepend (out, i->data);
+ if (out.end()==find(out.begin(),out.end(), *i)) {
+ out.push_back(*i);
if (_action_replace) {
item_attr_match(item, text, exact, casematch, _action_replace);
}
@@ -635,13 +634,13 @@ GSList *Find::filter_fields (GSList *l, bool exact, bool casematch)
if (attrvalue) {
- for (GSList *i = in; i != NULL; i = i->next) {
- SPObject *obj = reinterpret_cast<SPObject *>(i->data);
+ for(std::vector<SPItem*>::const_reverse_iterator i=in.rbegin(); in.rend() != i; i++) {
+ SPObject *obj = *i;
SPItem *item = dynamic_cast<SPItem *>(obj);
g_assert(item != NULL);
if (item_attrvalue_match(item, text, exact, casematch)) {
- if (!g_slist_find(out, i->data)) {
- out = g_slist_prepend (out, i->data);
+ if (out.end()==find(out.begin(),out.end(), *i)) {
+ out.push_back(*i);
if (_action_replace) {
item_attrvalue_match(item, text, exact, casematch, _action_replace);
}
@@ -652,13 +651,13 @@ GSList *Find::filter_fields (GSList *l, bool exact, bool casematch)
if (font) {
- for (GSList *i = in; i != NULL; i = i->next) {
- SPObject *obj = reinterpret_cast<SPObject *>(i->data);
+ for(std::vector<SPItem*>::const_reverse_iterator i=in.rbegin(); in.rend() != i; i++) {
+ SPObject *obj = *i;
SPItem *item = dynamic_cast<SPItem *>(obj);
g_assert(item != NULL);
if (item_font_match(item, text, exact, casematch)) {
- if (!g_slist_find(out, i->data)) {
- out = g_slist_prepend (out, i->data);
+ if (out.end()==find(out.begin(),out.end(),*i)) {
+ out.push_back(*i);
if (_action_replace) {
item_font_match(item, text, exact, casematch, _action_replace);
}
@@ -716,29 +715,29 @@ bool Find::item_type_match (SPItem *item)
return false;
}
-GSList *Find::filter_types (GSList *l)
+std::vector<SPItem*> Find::filter_types (std::vector<SPItem*> &l)
{
- GSList *n = NULL;
- for (GSList *i = l; i != NULL; i = i->next) {
- SPObject *obj = reinterpret_cast<SPObject *>(i->data);
+ std::vector<SPItem*> n;
+ for(std::vector<SPItem*>::const_reverse_iterator i=l.rbegin(); l.rend() != i; i++) {
+ SPObject *obj = *i;
SPItem *item = dynamic_cast<SPItem *>(obj);
g_assert(item != NULL);
if (item_type_match(item)) {
- n = g_slist_prepend (n, i->data);
+ n.push_back(*i);
}
}
return n;
}
-GSList *Find::filter_list (GSList *l, bool exact, bool casematch)
+std::vector<SPItem*> &Find::filter_list (std::vector<SPItem*> &l, bool exact, bool casematch)
{
l = filter_types (l);
l = filter_fields (l, exact, casematch);
return l;
}
-GSList *Find::all_items (SPObject *r, GSList *l, bool hidden, bool locked)
+std::vector<SPItem*> &Find::all_items (SPObject *r, std::vector<SPItem*> &l, bool hidden, bool locked)
{
if (dynamic_cast<SPDefs *>(r)) {
return l; // we're not interested in items in defs
@@ -752,7 +751,7 @@ GSList *Find::all_items (SPObject *r, GSList *l, bool hidden, bool locked)
SPItem *item = dynamic_cast<SPItem *>(child);
if (item && !child->cloned && !desktop->isLayer(item)) {
if ((hidden || !desktop->itemIsHidden(item)) && (locked || !item->isLocked())) {
- l = g_slist_prepend (l, child);
+ l.insert(l.begin(),(SPItem*)child);
}
}
l = all_items (child, l, hidden, locked);
@@ -760,16 +759,17 @@ GSList *Find::all_items (SPObject *r, GSList *l, bool hidden, bool locked)
return l;
}
-GSList *Find::all_selection_items (Inkscape::Selection *s, GSList *l, SPObject *ancestor, bool hidden, bool locked)
+std::vector<SPItem*> &Find::all_selection_items (Inkscape::Selection *s, std::vector<SPItem*> &l, SPObject *ancestor, bool hidden, bool locked)
{
- for (GSList *i = (GSList *) s->itemList(); i != NULL; i = i->next) {
- SPObject *obj = reinterpret_cast<SPObject *>(i->data);
+ std::vector<SPItem*> itemlist=s->itemList();
+ for(std::vector<SPItem*>::const_reverse_iterator i=itemlist.rbegin(); itemlist.rend() != i; i++) {
+ SPObject *obj = *i;
SPItem *item = dynamic_cast<SPItem *>(obj);
g_assert(item != NULL);
if (item && !item->cloned && !desktop->isLayer(item)) {
if (!ancestor || ancestor->isAncestorOf(item)) {
if ((hidden || !desktop->itemIsHidden(item)) && (locked || !item->isLocked())) {
- l = g_slist_prepend (l, i->data);
+ l.push_back(*i);
}
}
}
@@ -817,7 +817,7 @@ void Find::onAction()
bool casematch = check_case_sensitive.get_active();
blocked = true;
- GSList *l = NULL;
+ std::vector<SPItem*> l;
if (check_scope_selection.get_active()) {
if (check_scope_layer.get_active()) {
l = all_selection_items (desktop->selection, l, desktop->currentLayer(), hidden, locked);
@@ -831,12 +831,12 @@ void Find::onAction()
l = all_items(desktop->getDocument()->getRoot(), l, hidden, locked);
}
}
- guint all = g_slist_length (l);
+ guint all = l.size();
- GSList *n = filter_list (l, exact, casematch);
+ std::vector<SPItem*> n = filter_list (l, exact, casematch);
- if (n != NULL) {
- int count = g_slist_length (n);
+ if (!n.empty()) {
+ int count = n.size();
desktop->messageStack()->flashF(Inkscape::NORMAL_MESSAGE,
// TRANSLATORS: "%s" is replaced with "exact" or "partial" when this string is displayed
ngettext("<b>%d</b> object found (out of <b>%d</b>), %s match.",
@@ -857,7 +857,7 @@ void Find::onAction()
Inkscape::Selection *selection = desktop->getSelection();
selection->clear();
selection->setList(n);
- SPObject *obj = reinterpret_cast<SPObject *>(n->data);
+ SPObject *obj = n[0];
SPItem *item = dynamic_cast<SPItem *>(obj);
g_assert(item != NULL);
scroll_to_show_item(desktop, item);
diff --git a/src/ui/dialog/find.h b/src/ui/dialog/find.h
index c0c635f94..4bcb900b6 100644
--- a/src/ui/dialog/find.h
+++ b/src/ui/dialog/find.h
@@ -148,10 +148,10 @@ protected:
/**
* Function to filter a list of items based on the item type by calling each item_XXX_match function
*/
- GSList * filter_fields (GSList *l, bool exact, bool casematch);
+ std::vector<SPItem*> filter_fields (std::vector<SPItem*> &l, bool exact, bool casematch);
bool item_type_match (SPItem *item);
- GSList * filter_types (GSList *l);
- GSList * filter_list (GSList *l, bool exact, bool casematch);
+ std::vector<SPItem*> filter_types (std::vector<SPItem*> &l);
+ std::vector<SPItem*> & filter_list (std::vector<SPItem*> &l, bool exact, bool casematch);
/**
* Find a string within a string and returns true if found with options for exact and casematching
@@ -172,12 +172,12 @@ protected:
* recursive function to return a list of all the items in the SPObject tree
*
*/
- GSList * all_items (SPObject *r, GSList *l, bool hidden, bool locked);
+ std::vector<SPItem*> & all_items (SPObject *r, std::vector<SPItem*> &l, bool hidden, bool locked);
/**
* to return a list of all the selected items
*
*/
- GSList * all_selection_items (Inkscape::Selection *s, GSList *l, SPObject *ancestor, bool hidden, bool locked);
+ std::vector<SPItem*> & all_selection_items (Inkscape::Selection *s, std::vector<SPItem*> &l, SPObject *ancestor, bool hidden, bool locked);
/**
* Shrink the dialog size when the expander widget is closed
diff --git a/src/ui/dialog/floating-behavior.cpp b/src/ui/dialog/floating-behavior.cpp
index 740acd989..55ef0c5bb 100644
--- a/src/ui/dialog/floating-behavior.cpp
+++ b/src/ui/dialog/floating-behavior.cpp
@@ -112,7 +112,7 @@ bool FloatingBehavior::_trans_timer (void) {
}
float goal, current;
- goal = current = _d->get_opacity();
+ current = _d->get_opacity();
if (_dialog_active.get_value()) {
goal = _trans_focus;
diff --git a/src/ui/dialog/font-substitution.cpp b/src/ui/dialog/font-substitution.cpp
index 2ef61978f..19506c6a3 100644
--- a/src/ui/dialog/font-substitution.cpp
+++ b/src/ui/dialog/font-substitution.cpp
@@ -66,19 +66,15 @@ FontSubstitution::checkFontSubstitutions(SPDocument* doc)
int show_dlg = prefs->getInt("/options/font/substitutedlg", 0);
if (show_dlg) {
Glib::ustring out;
- GSList *l = getFontReplacedItems(doc, &out);
+ std::vector<SPItem*> l = getFontReplacedItems(doc, &out);
if (out.length() > 0) {
show(out, l);
}
- if (l) {
- g_slist_free(l);
- l = NULL;
- }
}
}
void
-FontSubstitution::show(Glib::ustring out, GSList *l)
+FontSubstitution::show(Glib::ustring out, std::vector<SPItem*> &l)
{
Gtk::MessageDialog warning(_("\nSome fonts are not available and have been substituted."),
false, Gtk::MESSAGE_INFO, Gtk::BUTTONS_OK, true);
@@ -148,20 +144,18 @@ FontSubstitution::show(Glib::ustring out, GSList *l)
* b. Build up a list of the objects rendered fonts - taken for the objects layout/spans
* If there are fonts in a. that are not in b. then those fonts have been substituted.
*/
-GSList * FontSubstitution::getFontReplacedItems(SPDocument* doc, Glib::ustring *out)
+std::vector<SPItem*> FontSubstitution::getFontReplacedItems(SPDocument* doc, Glib::ustring *out)
{
SPDesktop *desktop = SP_ACTIVE_DESKTOP;
- GSList *allList = NULL;
- GSList *outList = NULL;
+ std::vector<SPItem*> allList;
+ std::vector<SPItem*> outList,x,y;
std::set<Glib::ustring> setErrors;
std::set<Glib::ustring> setFontSpans;
std::map<SPItem *, Glib::ustring> mapFontStyles;
- allList = get_all_items(NULL, doc->getRoot(), desktop, false, false, true, NULL);
-
- for (GSList *i = allList; i != NULL; i = i->next) {
-
- SPItem *item = SP_ITEM(i->data);
+ allList = get_all_items(x, doc->getRoot(), desktop, false, false, true, y);
+ for(std::vector<SPItem*>::const_iterator i = allList.begin();i!=allList.end();i++){
+ SPItem *item = *i;
SPStyle *style = item->style;
Glib::ustring family = "";
@@ -216,8 +210,8 @@ GSList * FontSubstitution::getFontReplacedItems(SPDocument* doc, Glib::ustring *
}
// Check if any document styles are not in the actual layout
- std::map<SPItem *, Glib::ustring>::const_iterator mapIter;
- for (mapIter = mapFontStyles.begin(); mapIter != mapFontStyles.end(); ++mapIter) {
+ std::map<SPItem *, Glib::ustring>::const_reverse_iterator mapIter;
+ for (mapIter = mapFontStyles.rbegin(); mapIter != mapFontStyles.rend(); ++mapIter) {
SPItem *item = mapIter->first;
Glib::ustring fonts = mapIter->second;
@@ -250,7 +244,7 @@ GSList * FontSubstitution::getFontReplacedItems(SPDocument* doc, Glib::ustring *
Glib::ustring err = Glib::ustring::compose(
_("Font '%1' substituted with '%2'"), fonts.c_str(), subName.c_str());
setErrors.insert(err);
- outList = g_slist_prepend (outList, item);
+ outList.push_back(item);
}
}
diff --git a/src/ui/dialog/font-substitution.h b/src/ui/dialog/font-substitution.h
index 1c445081b..0818d778c 100644
--- a/src/ui/dialog/font-substitution.h
+++ b/src/ui/dialog/font-substitution.h
@@ -14,6 +14,7 @@
#include <glibmm/ustring.h>
+class SPItem;
class SPDocument;
namespace Inkscape {
@@ -25,13 +26,13 @@ public:
FontSubstitution();
virtual ~FontSubstitution();
void checkFontSubstitutions(SPDocument* doc);
- void show(Glib::ustring out, GSList *l);
+ void show(Glib::ustring out, std::vector<SPItem*> &l);
static FontSubstitution &getInstance() { return *new FontSubstitution(); }
Glib::ustring getSubstituteFontName (Glib::ustring font);
protected:
- GSList *getFontReplacedItems(SPDocument* doc, Glib::ustring *out);
+ std::vector<SPItem*> getFontReplacedItems(SPDocument* doc, Glib::ustring *out);
private:
FontSubstitution(FontSubstitution const &d);
diff --git a/src/ui/dialog/glyphs.cpp b/src/ui/dialog/glyphs.cpp
index 2b9053da9..7ca277ea2 100644
--- a/src/ui/dialog/glyphs.cpp
+++ b/src/ui/dialog/glyphs.cpp
@@ -578,9 +578,10 @@ void GlyphsPanel::setTargetDesktop(SPDesktop *desktop)
void GlyphsPanel::insertText()
{
SPItem *textItem = 0;
- for (const GSList *item = targetDesktop->selection->itemList(); item; item = item->next ) {
- if (SP_IS_TEXT(item->data) || SP_IS_FLOWTEXT(item->data)) {
- textItem = SP_ITEM(item->data);
+ std::vector<SPItem*> itemlist=targetDesktop->selection->itemList();
+ for(std::vector<SPItem*>::const_iterator i=itemlist.begin(); itemlist.end() != i; i++) {
+ if (SP_IS_TEXT(*i) || SP_IS_FLOWTEXT(*i)) {
+ textItem = *i;
break;
}
}
@@ -687,8 +688,9 @@ void GlyphsPanel::selectionModifiedCB(guint flags)
void GlyphsPanel::calcCanInsert()
{
int items = 0;
- for (const GSList *item = targetDesktop->selection->itemList(); item; item = item->next ) {
- if (SP_IS_TEXT(item->data) || SP_IS_FLOWTEXT(item->data)) {
+ std::vector<SPItem*> itemlist=targetDesktop->selection->itemList();
+ for(std::vector<SPItem*>::const_iterator i=itemlist.begin(); itemlist.end() != i; i++) {
+ if (SP_IS_TEXT(*i) || SP_IS_FLOWTEXT(*i)) {
++items;
}
}
diff --git a/src/ui/dialog/grid-arrange-tab.cpp b/src/ui/dialog/grid-arrange-tab.cpp
index d3ccb9bde..ccd23a572 100644
--- a/src/ui/dialog/grid-arrange-tab.cpp
+++ b/src/ui/dialog/grid-arrange-tab.cpp
@@ -48,7 +48,7 @@
* 0 *elem1 == *elem2
* >0 *elem1 goes after *elem2
*/
-static int sp_compare_x_position(SPItem *first, SPItem *second)
+static bool sp_compare_x_position(SPItem *first, SPItem *second)
{
using Geom::X;
using Geom::Y;
@@ -58,7 +58,7 @@ static int sp_compare_x_position(SPItem *first, SPItem *second)
if ( !a || !b ) {
// FIXME?
- return 0;
+ return false;
}
double const a_height = a->dimensions()[Y];
@@ -76,40 +76,41 @@ static int sp_compare_x_position(SPItem *first, SPItem *second)
}
if (!a_in_b_vert) {
- return -1;
+ return true;
}
if (a_in_b_vert && a->min()[X] > b->min()[X]) {
- return 1;
+ return false;
}
if (a_in_b_vert && a->min()[X] < b->min()[X]) {
- return -1;
+ return true;
}
- return 0;
+ return false;
}
/*
* Sort items by their y co-ordinates.
*/
-static int sp_compare_y_position(SPItem *first, SPItem *second)
+static bool sp_compare_y_position(SPItem *first, SPItem *second)
{
Geom::OptRect a = first->documentVisualBounds();
Geom::OptRect b = second->documentVisualBounds();
if ( !a || !b ) {
// FIXME?
- return 0;
+ return false;
}
if (a->min()[Geom::Y] > b->min()[Geom::Y]) {
- return 1;
+ return false;
}
if (a->min()[Geom::Y] < b->min()[Geom::Y]) {
- return -1;
+ return true;
}
- return 0;
+ return false;
}
+
namespace Inkscape {
namespace UI {
namespace Dialog {
@@ -168,10 +169,9 @@ void GridArrangeTab::arrange()
desktop->getDocument()->ensureUpToDate();
Inkscape::Selection *selection = desktop->getSelection();
- const GSList *items = selection ? selection->itemList() : 0;
- cnt=0;
- for (; items != NULL; items = items->next) {
- SPItem *item = SP_ITEM(items->data);
+ const std::vector<SPItem*> items = selection ? selection->itemList() : std::vector<SPItem*>();
+ for(std::vector<SPItem*>::const_iterator i = items.begin();i!=items.end();i++){
+ SPItem *item = *i;
Geom::OptRect b = item->documentVisualBounds();
if (!b) {
continue;
@@ -198,20 +198,18 @@ void GridArrangeTab::arrange()
// require the sorting done before we can calculate row heights etc.
g_return_if_fail(selection);
- const GSList *items2 = selection->itemList();
- GSList *rev = g_slist_copy(const_cast<GSList *>(items2));
- GSList *sorted = NULL;
- rev = g_slist_sort(rev, (GCompareFunc) sp_compare_y_position);
- sorted = g_slist_sort(rev, (GCompareFunc) sp_compare_x_position);
+ std::vector<SPItem*> sorted(selection->itemList());
+ sort(sorted.begin(),sorted.end(),sp_compare_y_position);
+ sort(sorted.begin(),sorted.end(),sp_compare_x_position);
// Calculate individual Row and Column sizes if necessary
cnt=0;
- const GSList *sizes = sorted;
- for (; sizes != NULL; sizes = sizes->next) {
- SPItem *item = SP_ITEM(sizes->data);
+ const std::vector<SPItem*> sizes(sorted);
+ for (std::vector<SPItem*>::const_iterator i = sizes.begin();i!=sizes.end();i++) {
+ SPItem *item = *i;
Geom::OptRect b = item->documentVisualBounds();
if (b) {
width = b->dimensions()[Geom::X];
@@ -308,12 +306,14 @@ g_print("\n row = %f col = %f selection x= %f selection y = %f", total_row_h
}
cnt=0;
- for (row_cnt=0; ((sorted != NULL) && (row_cnt<NoOfRows)); row_cnt++) {
+ std::vector<SPItem*>::iterator it = sorted.begin();
+ for (row_cnt=0; ((it != sorted.end()) && (row_cnt<NoOfRows)); row_cnt++) {
GSList *current_row = NULL;
- for (col_cnt = 0; ((sorted != NULL) && (col_cnt<NoOfCols)); col_cnt++) {
- current_row = g_slist_append (current_row, sorted->data);
- sorted = sorted->next;
+ col_cnt = 0;
+ for(;it!=sorted.end()&&col_cnt<NoOfCols;it++) {
+ current_row = g_slist_append (current_row, *it);
+ col_cnt++;
}
for (; current_row != NULL; current_row = current_row->next) {
@@ -374,8 +374,8 @@ void GridArrangeTab::on_row_spinbutton_changed()
Inkscape::Selection *selection = desktop ? desktop->selection : 0;
g_return_if_fail( selection );
- GSList const *items = selection->itemList();
- int selcount = g_slist_length((GSList *)items);
+ std::vector<SPItem*> const items = selection->itemList();
+ int selcount = items.size();
double PerCol = ceil(selcount / NoOfColsSpinner.get_value());
NoOfRowsSpinner.set_value(PerCol);
@@ -400,8 +400,7 @@ void GridArrangeTab::on_col_spinbutton_changed()
Inkscape::Selection *selection = desktop ? desktop->selection : 0;
g_return_if_fail(selection);
- GSList const *items = selection->itemList();
- int selcount = g_slist_length((GSList *)items);
+ int selcount = selection->itemList().size();
double PerRow = ceil(selcount / NoOfRowsSpinner.get_value());
NoOfColsSpinner.set_value(PerRow);
@@ -538,10 +537,10 @@ void GridArrangeTab::updateSelection()
updating = true;
SPDesktop *desktop = Parent->getDesktop();
Inkscape::Selection *selection = desktop ? desktop->selection : 0;
- GSList const *items = selection ? selection->itemList() : 0;
+ std::vector<SPItem*> const items = selection ? selection->itemList() : std::vector<SPItem*>();
- if (items) {
- int selcount = g_slist_length((GSList *)items);
+ if (!items.empty()) {
+ int selcount = items.size();
if (NoOfColsSpinner.get_value() > 1 && NoOfRowsSpinner.get_value() > 1){
// Update the number of rows assuming number of columns wanted remains same.
@@ -609,8 +608,7 @@ GridArrangeTab::GridArrangeTab(ArrangeDialog *parent)
g_return_if_fail( selection );
int selcount = 1;
if (!selection->isEmpty()) {
- GSList const *items = selection->itemList();
- selcount = g_slist_length((GSList *)items);
+ selcount = selection->itemList().size();
}
diff --git a/src/ui/dialog/icon-preview.cpp b/src/ui/dialog/icon-preview.cpp
index 069b61cb7..77f120e1a 100644
--- a/src/ui/dialog/icon-preview.cpp
+++ b/src/ui/dialog/icon-preview.cpp
@@ -312,7 +312,7 @@ void IconPreviewPanel::setDesktop( SPDesktop* desktop )
if ( this->desktop ) {
docReplacedConn = this->desktop->connectDocumentReplaced(sigc::hide<0>(sigc::mem_fun(this, &IconPreviewPanel::setDocument)));
if ( this->desktop->selection && Inkscape::Preferences::get()->getBool("/iconpreview/autoRefresh", true) ) {
- selChangedConn = desktop->selection->connectChanged(sigc::hide(sigc::mem_fun(this, &IconPreviewPanel::queueRefresh)));
+ selChangedConn = this->desktop->selection->connectChanged(sigc::hide(sigc::mem_fun(this, &IconPreviewPanel::queueRefresh)));
}
}
}
@@ -362,16 +362,14 @@ void IconPreviewPanel::refreshPreview()
if ( sel ) {
//g_message("found a selection to play with");
- GSList const *items = sel->itemList();
- while ( items && !target ) {
- SPItem* item = SP_ITEM( items->data );
+ std::vector<SPItem*> const items = sel->itemList();
+ for(std::vector<SPItem*>::const_iterator i=items.begin();!target && i!=items.end();i++){
+ SPItem* item = *i;
gchar const *id = item->getId();
if ( id ) {
targetId = id;
target = item;
}
-
- items = g_slist_next(items);
}
}
}
diff --git a/src/ui/dialog/inkscape-preferences.cpp b/src/ui/dialog/inkscape-preferences.cpp
index 3b0731953..98695e080 100644
--- a/src/ui/dialog/inkscape-preferences.cpp
+++ b/src/ui/dialog/inkscape-preferences.cpp
@@ -1229,26 +1229,38 @@ void InkscapePreferences::initPageBehavior()
this->AddPage(_page_scrolling, _("Scrolling"), iter_behavior, PREFS_PAGE_BEHAVIOR_SCROLLING);
// Snapping options
+ _page_snapping.add_group_header( _("Snap indicator"));
+
_snap_indicator.init( _("Enable snap indicator"), "/options/snapindicator/value", true);
- _page_snapping.add_line( false, "", _snap_indicator, "",
+ _page_snapping.add_line( true, "", _snap_indicator, "",
_("After snapping, a symbol is drawn at the point that has snapped"));
- _snap_delay.init("/options/snapdelay/value", 0, 1000, 50, 100, 300, 0);
- _page_snapping.add_line( false, _("_Delay (in ms):"), _snap_delay, "",
- _("Postpone snapping as long as the mouse is moving, and then wait an additional fraction of a second. This additional delay is specified here. When set to zero or to a very small number, snapping will be immediate."), true);
+ _snap_indicator.changed_signal.connect( sigc::mem_fun(_snap_persistence, &Gtk::Widget::set_sensitive) );
+
+ _snap_persistence.init("/options/snapindicatorpersistence/value", 0.1, 10, 0.1, 1, 2, 1);
+ _page_snapping.add_line( true, _("Snap indicator persistence (in seconds):"), _snap_persistence, "",
+ _("Controls how long the snap indicator message will be shown, before it disappears"), true);
+
+ _page_snapping.add_group_header( _("What should snap"));
_snap_closest_only.init( _("Only snap the node closest to the pointer"), "/options/snapclosestonly/value", false);
- _page_snapping.add_line( false, "", _snap_closest_only, "",
+ _page_snapping.add_line( true, "", _snap_closest_only, "",
_("Only try to snap the node that is initially closest to the mouse pointer"));
_snap_weight.init("/options/snapweight/value", 0, 1, 0.1, 0.2, 0.5, 1);
- _page_snapping.add_line( false, _("_Weight factor:"), _snap_weight, "",
+ _page_snapping.add_line( true, _("_Weight factor:"), _snap_weight, "",
_("When multiple snap solutions are found, then Inkscape can either prefer the closest transformation (when set to 0), or prefer the node that was initially the closest to the pointer (when set to 1)"), true);
_snap_mouse_pointer.init( _("Snap the mouse pointer when dragging a constrained knot"), "/options/snapmousepointer/value", false);
- _page_snapping.add_line( false, "", _snap_mouse_pointer, "",
+ _page_snapping.add_line( true, "", _snap_mouse_pointer, "",
_("When dragging a knot along a constraint line, then snap the position of the mouse pointer instead of snapping the projection of the knot onto the constraint line"));
+ _page_snapping.add_group_header( _("Delayed snap"));
+
+ _snap_delay.init("/options/snapdelay/value", 0, 1, 0.1, 0.2, 0.3, 1);
+ _page_snapping.add_line( true, _("Delay (in seconds):"), _snap_delay, "",
+ _("Postpone snapping as long as the mouse is moving, and then wait an additional fraction of a second. This additional delay is specified here. When set to zero or to a very small number, snapping will be immediate."), true);
+
this->AddPage(_page_snapping, _("Snapping"), iter_behavior, PREFS_PAGE_BEHAVIOR_SNAPPING);
// Steps options
diff --git a/src/ui/dialog/inkscape-preferences.h b/src/ui/dialog/inkscape-preferences.h
index dcea91741..7e0184c55 100644
--- a/src/ui/dialog/inkscape-preferences.h
+++ b/src/ui/dialog/inkscape-preferences.h
@@ -322,6 +322,7 @@ protected:
UI::Widget::PrefCheckButton _importexport_import_res_override;
UI::Widget::PrefSlider _snap_delay;
UI::Widget::PrefSlider _snap_weight;
+ UI::Widget::PrefSlider _snap_persistence;
UI::Widget::PrefCheckButton _font_dialog;
UI::Widget::PrefCombo _font_unit_type;
UI::Widget::PrefCheckButton _font_output_px;
diff --git a/src/ui/dialog/layers.cpp b/src/ui/dialog/layers.cpp
index 65351cb68..3f5e80f8d 100644
--- a/src/ui/dialog/layers.cpp
+++ b/src/ui/dialog/layers.cpp
@@ -713,13 +713,21 @@ bool LayersPanel::_handleDragDrop(const Glib::RefPtr<Gdk::DragContext>& /*contex
*/
void LayersPanel::_doTreeMove( )
{
- if (_dnd_source ) {
+ if (_dnd_source && _dnd_source->getRepr() ) {
+ if(!_dnd_target){
+ _dnd_source->doWriteTransform(_dnd_source->getRepr(), _dnd_source->document->getRoot()->i2doc_affine().inverse() * _dnd_source->i2doc_affine());
+ }else{
+ SPItem* parent = _dnd_into ? _dnd_target : dynamic_cast<SPItem*>(_dnd_target->parent);
+ if(parent){
+ Geom::Affine move = parent->i2doc_affine().inverse() * _dnd_source->i2doc_affine();
+ _dnd_source->doWriteTransform(_dnd_source->getRepr(), move);
+ }
+ }
_dnd_source->moveTo(_dnd_target, _dnd_into);
_selectLayer(_dnd_source);
_dnd_source = NULL;
DocumentUndo::done( _desktop->doc() , SP_VERB_NONE,
- _("Moved layer"));
-
+ _("Move layer"));
}
}
diff --git a/src/ui/dialog/lpe-fillet-chamfer-properties.cpp b/src/ui/dialog/lpe-fillet-chamfer-properties.cpp
index f63b19e86..5ccee103c 100644
--- a/src/ui/dialog/lpe-fillet-chamfer-properties.cpp
+++ b/src/ui/dialog/lpe-fillet-chamfer-properties.cpp
@@ -27,7 +27,7 @@
#include "selection-chemistry.h"
#include "ui/icon-names.h"
#include "ui/widget/imagetoggler.h"
-#include "util/units.h"
+#include "live_effects/parameter/parameter.h"
#include <cmath>
//#include "event-context.h"
@@ -48,7 +48,7 @@ FilletChamferPropertiesDialog::FilletChamferPropertiesDialog()
_fillet_chamfer_position_numeric.set_digits(4);
_fillet_chamfer_position_numeric.set_increments(1,1);
//todo: get tha max aloable infinity freeze the widget
- _fillet_chamfer_position_numeric.set_range(0., 999999999999999999.);
+ _fillet_chamfer_position_numeric.set_range(0., SCALARPARAM_G_MAXDOUBLE);
_fillet_chamfer_position_label.set_label(_("Radius (pixels):"));
_fillet_chamfer_position_label.set_alignment(1.0, 0.5);
@@ -60,7 +60,7 @@ FilletChamferPropertiesDialog::FilletChamferPropertiesDialog()
_fillet_chamfer_chamfer_subdivisions.set_digits(0);
_fillet_chamfer_chamfer_subdivisions.set_increments(1,1);
//todo: get tha max aloable infinity freeze the widget
- _fillet_chamfer_chamfer_subdivisions.set_range(0, 999999999999999999.0);
+ _fillet_chamfer_chamfer_subdivisions.set_range(0, SCALARPARAM_G_MAXDOUBLE);
_fillet_chamfer_chamfer_subdivisions_label.set_label(_("Chamfer subdivisions:"));
_fillet_chamfer_chamfer_subdivisions_label.set_alignment(1.0, 0.5);
@@ -122,18 +122,14 @@ void FilletChamferPropertiesDialog::showDialog(
SPDesktop *desktop, Geom::Point knotpoint,
const Inkscape::LivePathEffect::
FilletChamferPointArrayParamKnotHolderEntity *pt,
- const gchar *unit,
bool use_distance,
- bool aprox_radius,
- Glib::ustring documentUnit)
+ bool aprox_radius)
{
FilletChamferPropertiesDialog *dialog = new FilletChamferPropertiesDialog();
dialog->_set_desktop(desktop);
- dialog->_set_unit(unit);
dialog->_set_use_distance(use_distance);
dialog->_set_aprox(aprox_radius);
- dialog->_set_document_unit(documentUnit);
dialog->_set_knot_point(knotpoint);
dialog->_set_pt(pt);
@@ -168,7 +164,6 @@ void FilletChamferPropertiesDialog::_apply()
}
d_pos = _index + (d_pos / 100);
} else {
- d_pos = Inkscape::Util::Quantity::convert(d_pos, unit, document_unit);
d_pos = d_pos * -1;
}
_knotpoint->knot_set_offset(Geom::Point(d_pos, d_width));
@@ -218,11 +213,9 @@ void FilletChamferPropertiesDialog::_set_knot_point(Geom::Point knotpoint)
_fillet_chamfer_position_label.set_label(_("Position (%):"));
} else {
_flexible = false;
- std::string posConcat = Glib::ustring::compose (_("%1 (%2):"), distance_or_radius, unit);
+ std::string posConcat = Glib::ustring::compose (_("%1:"), distance_or_radius);
_fillet_chamfer_position_label.set_label(_(posConcat.c_str()));
position = knotpoint[Geom::X] * -1;
-
- position = Inkscape::Util::Quantity::convert(position, document_unit, unit);
}
_fillet_chamfer_position_numeric.set_value(position);
if (knotpoint.y() == 1) {
@@ -247,16 +240,6 @@ void FilletChamferPropertiesDialog::_set_pt(
pt);
}
-void FilletChamferPropertiesDialog::_set_unit(const gchar *abbr)
-{
- unit = abbr;
-}
-
-void FilletChamferPropertiesDialog::_set_document_unit(Glib::ustring abbr)
-{
- document_unit = abbr;
-}
-
void FilletChamferPropertiesDialog::_set_use_distance(bool use_knot_distance)
{
use_distance = use_knot_distance;
diff --git a/src/ui/dialog/lpe-fillet-chamfer-properties.h b/src/ui/dialog/lpe-fillet-chamfer-properties.h
index 870a1734f..99494bd63 100644
--- a/src/ui/dialog/lpe-fillet-chamfer-properties.h
+++ b/src/ui/dialog/lpe-fillet-chamfer-properties.h
@@ -30,10 +30,8 @@ public:
static void showDialog(SPDesktop *desktop, Geom::Point knotpoint,
const Inkscape::LivePathEffect::
FilletChamferPointArrayParamKnotHolderEntity *pt,
- const gchar *unit,
bool use_distance,
- bool aprox_radius,
- Glib::ustring documentUnit);
+ bool aprox_radius);
protected:
@@ -68,15 +66,11 @@ protected:
void _set_desktop(SPDesktop *desktop);
void _set_pt(const Inkscape::LivePathEffect::
FilletChamferPointArrayParamKnotHolderEntity *pt);
- void _set_unit(const gchar *abbr);
- void _set_document_unit(Glib::ustring abbr);
void _set_use_distance(bool use_knot_distance);
void _set_aprox(bool aprox_radius);
void _apply();
void _close();
bool _flexible;
- const gchar *unit;
- Glib::ustring document_unit;
bool use_distance;
bool aprox;
void _set_knot_point(Geom::Point knotpoint);
diff --git a/src/ui/dialog/lpe-powerstroke-properties.cpp b/src/ui/dialog/lpe-powerstroke-properties.cpp
index 0cf3e9706..cfc972547 100644
--- a/src/ui/dialog/lpe-powerstroke-properties.cpp
+++ b/src/ui/dialog/lpe-powerstroke-properties.cpp
@@ -36,6 +36,7 @@
#include "selection-chemistry.h"
#include "ui/icon-names.h"
#include "ui/widget/imagetoggler.h"
+#include "live_effects/parameter/parameter.h"
//#include "event-context.h"
namespace Inkscape {
@@ -52,10 +53,16 @@ PowerstrokePropertiesDialog::PowerstrokePropertiesDialog()
// Layer name widgets
_powerstroke_position_entry.set_activates_default(true);
+ _powerstroke_position_entry.set_digits(4);
+ _powerstroke_position_entry.set_increments(1,1);
+ _powerstroke_position_entry.set_range(-SCALARPARAM_G_MAXDOUBLE, SCALARPARAM_G_MAXDOUBLE);
_powerstroke_position_label.set_label(_("Position:"));
_powerstroke_position_label.set_alignment(1.0, 0.5);
_powerstroke_width_entry.set_activates_default(true);
+ _powerstroke_width_entry.set_digits(4);
+ _powerstroke_width_entry.set_increments(1,1);
+ _powerstroke_width_entry.set_range(-SCALARPARAM_G_MAXDOUBLE, SCALARPARAM_G_MAXDOUBLE);
_powerstroke_width_label.set_label(_("Width:"));
_powerstroke_width_label.set_alignment(1.0, 0.5);
@@ -126,12 +133,9 @@ void PowerstrokePropertiesDialog::showDialog(SPDesktop *desktop, Geom::Point kno
void
PowerstrokePropertiesDialog::_apply()
{
- std::istringstream i_pos(_powerstroke_position_entry.get_text());
- std::istringstream i_width(_powerstroke_width_entry.get_text());
- double d_pos, d_width;
- if ((i_pos >> d_pos) && i_width >> d_width) {
- _knotpoint->knot_set_offset(Geom::Point(d_pos, d_width));
- }
+ double d_pos = _powerstroke_position_entry.get_value();
+ double d_width = _powerstroke_width_entry.get_value();
+ _knotpoint->knot_set_offset(Geom::Point(d_pos, d_width));
_close();
}
@@ -171,8 +175,8 @@ void PowerstrokePropertiesDialog::_handleButtonEvent(GdkEventButton* event)
void PowerstrokePropertiesDialog::_setKnotPoint(Geom::Point knotpoint)
{
- _powerstroke_position_entry.set_text(boost::lexical_cast<std::string>(knotpoint.x()));
- _powerstroke_width_entry.set_text(boost::lexical_cast<std::string>(knotpoint.y()));
+ _powerstroke_position_entry.set_value(knotpoint.x());
+ _powerstroke_width_entry.set_value(knotpoint.y());
}
void PowerstrokePropertiesDialog::_setPt(const Inkscape::LivePathEffect::PowerStrokePointArrayParamKnotHolderEntity *pt)
diff --git a/src/ui/dialog/lpe-powerstroke-properties.h b/src/ui/dialog/lpe-powerstroke-properties.h
index c53eac0d9..1e4c1df5b 100644
--- a/src/ui/dialog/lpe-powerstroke-properties.h
+++ b/src/ui/dialog/lpe-powerstroke-properties.h
@@ -13,15 +13,7 @@
#define INKSCAPE_DIALOG_POWERSTROKE_PROPERTIES_H
#include <2geom/point.h>
-#include <gtkmm/dialog.h>
-#include <gtkmm/entry.h>
-#include <gtkmm/label.h>
-#include <gtkmm/table.h>
-#include <gtkmm/combobox.h>
-#include <gtkmm/liststore.h>
-#include <gtkmm/treeview.h>
-#include <gtkmm/treestore.h>
-#include <gtkmm/scrolledwindow.h>
+#include <gtkmm.h>
#include "live_effects/parameter/powerstrokepointarray.h"
class SPDesktop;
@@ -45,9 +37,9 @@ protected:
Inkscape::LivePathEffect::PowerStrokePointArrayParamKnotHolderEntity *_knotpoint;
Gtk::Label _powerstroke_position_label;
- Gtk::Entry _powerstroke_position_entry;
+ Gtk::SpinButton _powerstroke_position_entry;
Gtk::Label _powerstroke_width_label;
- Gtk::Entry _powerstroke_width_entry;
+ Gtk::SpinButton _powerstroke_width_entry;
Gtk::Table _layout_table;
bool _position_visible;
diff --git a/src/ui/dialog/object-attributes.cpp b/src/ui/dialog/object-attributes.cpp
index f43a15225..1bc570f43 100644
--- a/src/ui/dialog/object-attributes.cpp
+++ b/src/ui/dialog/object-attributes.cpp
@@ -127,7 +127,7 @@ void ObjectAttributes::widget_setup (void)
blocked = true;
// CPPIFY
- SPObject *obj = SP_OBJECT(item); //to get the selected item
+ SPObject *obj = item; //to get the selected item
// GObjectClass *klass = G_OBJECT_GET_CLASS(obj); //to deduce the object's type
// GType type = G_TYPE_FROM_CLASS(klass);
const SPAttrDesc *desc;
diff --git a/src/ui/dialog/object-properties.cpp b/src/ui/dialog/object-properties.cpp
index dfe211e94..75430ed44 100644
--- a/src/ui/dialog/object-properties.cpp
+++ b/src/ui/dialog/object-properties.cpp
@@ -467,14 +467,14 @@ void ObjectProperties::_labelChanged()
gchar *id = g_strdup(_entry_id.get_text().c_str());
g_strcanon(id, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_.:", '_');
if (strcmp(id, item->getId()) == 0) {
- _label_id.set_markup_with_mnemonic(_("_ID:"));
+ _label_id.set_markup_with_mnemonic(_("_ID:") + Glib::ustring(" "));
} else if (!*id || !isalnum (*id)) {
_label_id.set_text(_("Id invalid! "));
} else if (SP_ACTIVE_DOCUMENT->getObjectById(id) != NULL) {
_label_id.set_text(_("Id exists! "));
} else {
SPException ex;
- _label_id.set_markup_with_mnemonic(_("_ID:"));
+ _label_id.set_markup_with_mnemonic(_("_ID:") + Glib::ustring(" "));
SP_EXCEPTION_INIT(&ex);
item->setAttribute("id", id, &ex);
DocumentUndo::done(SP_ACTIVE_DOCUMENT, SP_VERB_DIALOG_ITEM, _("Set object ID"));
@@ -529,10 +529,12 @@ void ObjectProperties::_imageRenderingChanged()
SPCSSAttr *css = sp_repr_css_attr_new();
sp_repr_css_set_property(css, "image-rendering", scale.c_str());
Inkscape::XML::Node *image_node = item->getRepr();
- if( image_node ) {
+ if (image_node) {
sp_repr_css_change(image_node, css, "style");
+ DocumentUndo::done(SP_ACTIVE_DOCUMENT, SP_VERB_DIALOG_ITEM,
+ _("Set image rendering option"));
}
- sp_repr_css_attr_unref( css );
+ sp_repr_css_attr_unref(css);
_blocked = false;
}
diff --git a/src/ui/dialog/objects.cpp b/src/ui/dialog/objects.cpp
index 9db0285d7..835ecf35b 100644
--- a/src/ui/dialog/objects.cpp
+++ b/src/ui/dialog/objects.cpp
@@ -45,6 +45,7 @@
#include "style.h"
#include "ui/tools-switch.h"
#include "ui/icon-names.h"
+#include "ui/selected-color.h"
#include "ui/widget/imagetoggler.h"
#include "ui/widget/layertypeicon.h"
#include "ui/widget/insertordericon.h"
@@ -53,7 +54,7 @@
#include "ui/tools/node-tool.h"
#include "ui/tools/tool-base.h"
#include "verbs.h"
-#include "widgets/sp-color-notebook.h"
+#include "ui/widget/color-notebook.h"
#include "widgets/icon.h"
#include "xml/node.h"
#include "xml/node-observer.h"
@@ -477,15 +478,15 @@ void ObjectsPanel::_objectsSelected( Selection *sel ) {
_selectedConnection.block();
_tree.get_selection()->unselect_all();
SPItem *item = NULL;
- for (const GSList * iter = sel->itemList(); iter != NULL; iter = iter->next)
- {
- item = reinterpret_cast<SPItem *>(iter->data);
+ std::vector<SPItem*> const items = sel->itemList();
+ for(std::vector<SPItem*>::const_iterator i=items.begin(); i!=items.end();i++){
+ item = *i;
if (setOpacity)
{
_setCompositingValues(item);
setOpacity = false;
}
- _store->foreach(sigc::bind<SPItem *, bool>( sigc::mem_fun(*this, &ObjectsPanel::_checkForSelected), item, iter->next == NULL));
+ _store->foreach(sigc::bind<SPItem *, bool>( sigc::mem_fun(*this, &ObjectsPanel::_checkForSelected), item, (*i)==items.back()));
}
if (!item) {
if (_desktop->currentLayer() && SP_IS_ITEM(_desktop->currentLayer())) {
@@ -928,12 +929,12 @@ bool ObjectsPanel::_handleButtonEvent(GdkEventButton* event)
//If the current item is not selected, store only it in the highlight source
_storeHighlightTarget(iter);
}
- if (_colorSelector)
+ if (_selectedColor)
{
//Set up the color selector
SPColor color;
color.set( row[_model->_colHighlight] );
- _colorSelector->base->setColorAlpha(color, SP_RGBA32_A_F(row[_model->_colHighlight]));
+ _selectedColor->setColorAlpha(color, SP_RGBA32_A_F(row[_model->_colHighlight]));
}
//Show the color selector dialog
_colorSelectorDialog.show();
@@ -1440,17 +1441,16 @@ void ObjectsPanel::_setExpanded(const Gtk::TreeModel::iterator& iter, const Gtk:
* @param csel Color selector
* @param cp Objects panel
*/
-void sp_highlight_picker_color_mod(SPColorSelector *csel, GObject * cp)
+void ObjectsPanel::_highlightPickerColorMod()
{
SPColor color;
float alpha = 0;
- csel->base->getColorAlpha(color, alpha);
+ _selectedColor->colorAlpha(color, alpha);
+
guint32 rgba = color.toRGBA32( alpha );
-
- ObjectsPanel *ptr = reinterpret_cast<ObjectsPanel *>(cp);
//Set the highlight color for all items in the _highlight_target (all selected items)
- for (std::vector<SPItem *>::iterator iter = ptr->_highlight_target.begin(); iter != ptr->_highlight_target.end(); ++iter)
+ for (std::vector<SPItem *>::iterator iter = _highlight_target.begin(); iter != _highlight_target.end(); ++iter)
{
SPItem * target = *iter;
target->setHighlightColor(rgba);
@@ -1614,6 +1614,12 @@ ObjectsPanel::ObjectsPanel() :
_pending(0),
_toggleEvent(0),
_defer_target(),
+ _visibleHeader(_("V")),
+ _lockHeader(_("L")),
+ _typeHeader(_("T")),
+ _clipmaskHeader(_("CM")),
+ _highlightHeader(_("HL")),
+ _nameHeader(_("Label")),
_composite_vbox(false, 0),
_opacity_vbox(false, 0),
_opacity_label(_("Opacity:")),
@@ -1641,7 +1647,7 @@ ObjectsPanel::ObjectsPanel() :
//Set up the tree
_tree.set_model( _store );
- _tree.set_headers_visible(false);
+ _tree.set_headers_visible(true);
_tree.set_reorderable(true);
_tree.enable_model_drag_dest (Gdk::ACTION_MOVE);
@@ -1654,6 +1660,10 @@ ObjectsPanel::ObjectsPanel() :
Gtk::TreeViewColumn* col = _tree.get_column(visibleColNum);
if ( col ) {
col->add_attribute( eyeRenderer->property_active(), _model->_colVisible );
+ // In order to get tooltips on header, we must create our own label.
+ _visibleHeader.set_tooltip_text(_("Toggle visibility of Layer, Group, or Object."));
+ _visibleHeader.show();
+ col->set_widget( _visibleHeader );
}
//Locked
@@ -1664,6 +1674,9 @@ ObjectsPanel::ObjectsPanel() :
col = _tree.get_column(lockedColNum);
if ( col ) {
col->add_attribute( renderer->property_active(), _model->_colLocked );
+ _lockHeader.set_tooltip_text(_("Toggle lock of Layer, Group, or Object."));
+ _lockHeader.show();
+ col->set_widget( _lockHeader );
}
//Type
@@ -1673,6 +1686,9 @@ ObjectsPanel::ObjectsPanel() :
col = _tree.get_column(typeColNum);
if ( col ) {
col->add_attribute( typeRenderer->property_active(), _model->_colType );
+ _typeHeader.set_tooltip_text(_("Type: Layer, Group, or Object. Clicking on Layer or Group icon, toggles between the two types."));
+ _typeHeader.show();
+ col->set_widget( _typeHeader );
}
//Insert order (LiamW: unused)
@@ -1689,6 +1705,9 @@ ObjectsPanel::ObjectsPanel() :
col = _tree.get_column(clipColNum);
if ( col ) {
col->add_attribute( clipRenderer->property_active(), _model->_colClipMask );
+ _clipmaskHeader.set_tooltip_text(_("Is object clipped and/or masked?"));
+ _clipmaskHeader.show();
+ col->set_widget( _clipmaskHeader );
}
//Highlight
@@ -1697,13 +1716,21 @@ ObjectsPanel::ObjectsPanel() :
col = _tree.get_column(highlightColNum);
if ( col ) {
col->add_attribute( highlightRenderer->property_active(), _model->_colHighlight );
+ _highlightHeader.set_tooltip_text(_("Highlight color of outline in Node tool. Click to set. If alpha is zero, use inherited color."));
+ _highlightHeader.show();
+ col->set_widget( _highlightHeader );
}
//Label
_text_renderer = Gtk::manage(new Gtk::CellRendererText());
int nameColNum = _tree.append_column("Name", *_text_renderer) - 1;
_name_column = _tree.get_column(nameColNum);
- _name_column->add_attribute(_text_renderer->property_text(), _model->_colLabel);
+ if( _name_column ) {
+ _name_column->add_attribute(_text_renderer->property_text(), _model->_colLabel);
+ _nameHeader.set_tooltip_text(_("Layer/Group/Object label (inkscape:label). Double-click to set. Default value is object 'id'."));
+ _nameHeader.show();
+ _name_column->set_widget( _nameHeader );
+ }
//Set the expander and search columns
_tree.set_expander_column( *_tree.get_column(nameColNum) );
@@ -1858,46 +1885,46 @@ ObjectsPanel::ObjectsPanel() :
//Set up the pop-up menu
// -------------------------------------------------------
{
- _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_RENAME, 0, "Rename", (int)BUTTON_RENAME ) );
- _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_EDIT_DUPLICATE, 0, "Duplicate", (int)BUTTON_DUPLICATE ) );
- _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_NEW, 0, "New", (int)BUTTON_NEW ) );
+ _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_RENAME, 0, _("Rename"), (int)BUTTON_RENAME ) );
+ _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_EDIT_DUPLICATE, 0, _("Duplicate"), (int)BUTTON_DUPLICATE ) );
+ _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_NEW, 0, _("New"), (int)BUTTON_NEW ) );
_popupMenu.append(*Gtk::manage(new Gtk::SeparatorMenuItem()));
- _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_SOLO, 0, "Solo", (int)BUTTON_SOLO ) );
- _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_SHOW_ALL, 0, "Show All", (int)BUTTON_SHOW_ALL ) );
- _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_HIDE_ALL, 0, "Hide All", (int)BUTTON_HIDE_ALL ) );
+ _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_SOLO, 0, _("Solo"), (int)BUTTON_SOLO ) );
+ _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_SHOW_ALL, 0, _("Show All"), (int)BUTTON_SHOW_ALL ) );
+ _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_HIDE_ALL, 0, _("Hide All"), (int)BUTTON_HIDE_ALL ) );
_popupMenu.append(*Gtk::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 ) );
+ _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(*Gtk::manage(new Gtk::SeparatorMenuItem()));
- _watchingNonTop.push_back( &_addPopupItem( targetDesktop, SP_VERB_SELECTION_RAISE, GTK_STOCK_GO_UP, "Up", (int)BUTTON_UP ) );
- _watchingNonBottom.push_back( &_addPopupItem( targetDesktop, SP_VERB_SELECTION_LOWER, GTK_STOCK_GO_DOWN, "Down", (int)BUTTON_DOWN ) );
+ _watchingNonTop.push_back( &_addPopupItem( targetDesktop, SP_VERB_SELECTION_RAISE, GTK_STOCK_GO_UP, _("Up"), (int)BUTTON_UP ) );
+ _watchingNonBottom.push_back( &_addPopupItem( targetDesktop, SP_VERB_SELECTION_LOWER, GTK_STOCK_GO_DOWN, _("Down"), (int)BUTTON_DOWN ) );
_popupMenu.append(*Gtk::manage(new Gtk::SeparatorMenuItem()));
- _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_SELECTION_GROUP, 0, "Group", (int)BUTTON_GROUP ) );
- _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_SELECTION_UNGROUP, 0, "Ungroup", (int)BUTTON_UNGROUP ) );
+ _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_SELECTION_GROUP, 0, _("Group"), (int)BUTTON_GROUP ) );
+ _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_SELECTION_UNGROUP, 0, _("Ungroup"), (int)BUTTON_UNGROUP ) );
_popupMenu.append(*Gtk::manage(new Gtk::SeparatorMenuItem()));
- _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_OBJECT_SET_CLIPPATH, 0, "Set Clip", (int)BUTTON_SETCLIP ) );
+ _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_OBJECT_SET_CLIPPATH, 0, _("Set Clip"), (int)BUTTON_SETCLIP ) );
- _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_OBJECT_CREATE_CLIP_GROUP, 0, "Create Clip Group", (int)BUTTON_CLIPGROUP ) );
+ _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_OBJECT_CREATE_CLIP_GROUP, 0, _("Create Clip Group"), (int)BUTTON_CLIPGROUP ) );
//will never be implemented
//_watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_OBJECT_SET_INVERSE_CLIPPATH, 0, "Set Inverse Clip", (int)BUTTON_SETINVCLIP ) );
- _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_OBJECT_UNSET_CLIPPATH, 0, "Unset Clip", (int)BUTTON_UNSETCLIP ) );
+ _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_OBJECT_UNSET_CLIPPATH, 0, _("Unset Clip"), (int)BUTTON_UNSETCLIP ) );
_popupMenu.append(*Gtk::manage(new Gtk::SeparatorMenuItem()));
- _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_OBJECT_SET_MASK, 0, "Set Mask", (int)BUTTON_SETMASK ) );
- _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_OBJECT_UNSET_MASK, 0, "Unset Mask", (int)BUTTON_UNSETMASK ) );
+ _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_OBJECT_SET_MASK, 0, _("Set Mask"), (int)BUTTON_SETMASK ) );
+ _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_OBJECT_UNSET_MASK, 0, _("Unset Mask"), (int)BUTTON_UNSETMASK ) );
_popupMenu.show_all_children();
}
@@ -1922,18 +1949,16 @@ ObjectsPanel::ObjectsPanel() :
_colorSelectorDialog.set_title (_("Select Highlight Color"));
_colorSelectorDialog.set_border_width (4);
_colorSelectorDialog.property_modal() = true;
- _colorSelector = SP_COLOR_SELECTOR(sp_color_selector_new(SP_TYPE_COLOR_NOTEBOOK));
+ _selectedColor.reset(new Inkscape::UI::SelectedColor);
+ Gtk::Widget *color_selector = Gtk::manage(new Inkscape::UI::Widget::ColorNotebook(*_selectedColor));
_colorSelectorDialog.get_vbox()->pack_start (
- *Glib::wrap(&_colorSelector->vbox), true, true, 0);
+ *color_selector, true, true, 0);
- g_signal_connect(G_OBJECT(_colorSelector), "dragged",
- G_CALLBACK(sp_highlight_picker_color_mod), (void *)this);
- g_signal_connect(G_OBJECT(_colorSelector), "released",
- G_CALLBACK(sp_highlight_picker_color_mod), (void *)this);
- g_signal_connect(G_OBJECT(_colorSelector), "changed",
- G_CALLBACK(sp_highlight_picker_color_mod), (void *)this);
+ _selectedColor->signal_dragged.connect(sigc::mem_fun(*this, &ObjectsPanel::_highlightPickerColorMod));
+ _selectedColor->signal_released.connect(sigc::mem_fun(*this, &ObjectsPanel::_highlightPickerColorMod));
+ _selectedColor->signal_changed.connect(sigc::mem_fun(*this, &ObjectsPanel::_highlightPickerColorMod));
- gtk_widget_show(GTK_WIDGET(_colorSelector));
+ color_selector->show();
setDesktop( targetDesktop );
@@ -1951,7 +1976,6 @@ ObjectsPanel::~ObjectsPanel()
{
//Close the highlight selection dialog
_colorSelectorDialog.hide();
- _colorSelector = NULL;
//Set the desktop to null, which will disconnect all object watchers
setDesktop(NULL);
diff --git a/src/ui/dialog/objects.h b/src/ui/dialog/objects.h
index 1842fea11..9b9a6025a 100644
--- a/src/ui/dialog/objects.h
+++ b/src/ui/dialog/objects.h
@@ -16,6 +16,7 @@
# include <config.h>
#endif
+#include <boost/scoped_ptr.hpp>
#include <gtkmm/box.h>
#include <gtkmm/treeview.h>
#include <gtkmm/treestore.h>
@@ -36,6 +37,9 @@ struct SPColorSelector;
namespace Inkscape {
namespace UI {
+
+class SelectedColor;
+
namespace Dialog {
@@ -143,7 +147,14 @@ private:
Gtk::Menu _popupMenu;
Inkscape::UI::Widget::SpinButton _spinBtn;
Gtk::VBox _page;
-
+
+ Gtk::Label _visibleHeader;
+ Gtk::Label _lockHeader;
+ Gtk::Label _typeHeader;
+ Gtk::Label _clipmaskHeader;
+ Gtk::Label _highlightHeader;
+ Gtk::Label _nameHeader;
+
/* Composite Settings */
Gtk::VBox _composite_vbox;
Gtk::VBox _opacity_vbox;
@@ -166,8 +177,7 @@ private:
Gtk::Alignment _blur_alignment;
Gtk::Dialog _colorSelectorDialog;
- SPColorSelector *_colorSelector;
-
+ boost::scoped_ptr<Inkscape::UI::SelectedColor> _selectedColor;
//Methods:
@@ -233,7 +243,7 @@ private:
void setupDialog(const Glib::ustring &title);
- friend void sp_highlight_picker_color_mod(SPColorSelector *csel, GObject *cp);
+ void _highlightPickerColorMod();
};
diff --git a/src/ui/dialog/pixelartdialog.cpp b/src/ui/dialog/pixelartdialog.cpp
index 5113f172a..760391df6 100644
--- a/src/ui/dialog/pixelartdialog.cpp
+++ b/src/ui/dialog/pixelartdialog.cpp
@@ -372,12 +372,12 @@ void PixelArtDialogImpl::vectorize()
return;
}
- for ( GSList const *list = desktop->selection->itemList() ; list
- ; list = list->next ) {
- if ( !SP_IS_IMAGE(list->data) )
+ std::vector<SPItem*> const items = desktop->selection->itemList();
+ for(std::vector<SPItem*>::const_iterator i=items.begin(); i!=items.end();i++){
+ if ( !SP_IS_IMAGE(*i) )
continue;
- SPImage *img = SP_IMAGE(list->data);
+ SPImage *img = SP_IMAGE(*i);
Input input;
input.pixbuf = Glib::wrap(img->pixbuf->getPixbufRaw(), true);
input.x = img->x;
diff --git a/src/ui/dialog/polar-arrange-tab.cpp b/src/ui/dialog/polar-arrange-tab.cpp
index 281958998..af1386e27 100644
--- a/src/ui/dialog/polar-arrange-tab.cpp
+++ b/src/ui/dialog/polar-arrange-tab.cpp
@@ -297,19 +297,18 @@ static void moveToPoint(int anchor, SPItem *item, Geom::Point p)
void PolarArrangeTab::arrange()
{
Inkscape::Selection *selection = parent->getDesktop()->getSelection();
- const GSList *items, *tmp;
- tmp = items = selection->itemList();
+ const std::vector<SPItem*> tmp(selection->itemList());
SPGenericEllipse *referenceEllipse = NULL; // Last ellipse in selection
bool arrangeOnEllipse = !arrangeOnParametersRadio.get_active();
bool arrangeOnFirstEllipse = arrangeOnEllipse && arrangeOnFirstCircleRadio.get_active();
int count = 0;
- while(tmp)
+ for(std::vector<SPItem*>::const_iterator i=tmp.begin();i!=tmp.end();i++)
{
if(arrangeOnEllipse)
{
- SPItem *item = SP_ITEM(tmp->data);
+ SPItem *item = *i;
if(arrangeOnFirstEllipse)
{
@@ -322,7 +321,6 @@ void PolarArrangeTab::arrange()
referenceEllipse = SP_GENERICELLIPSE(item);
}
}
- tmp = tmp->next;
++count;
}
@@ -374,11 +372,10 @@ void PolarArrangeTab::arrange()
Geom::Point realCenter = Geom::Point(cx, cy) * transformation;
- tmp = items;
int i = 0;
- while(tmp)
+ for(std::vector<SPItem*>::const_iterator it=tmp.begin();it!=tmp.end();it++)
{
- SPItem *item = SP_ITEM(tmp->data);
+ SPItem *item = *it;
// Ignore the reference ellipse if any
if(item != referenceEllipse)
@@ -396,7 +393,6 @@ void PolarArrangeTab::arrange()
++i;
}
- tmp = tmp->next;
}
DocumentUndo::done(parent->getDesktop()->getDocument(), SP_VERB_SELECTION_ARRANGE,
diff --git a/src/ui/dialog/print.cpp b/src/ui/dialog/print.cpp
index ad979b570..c44d645a5 100644
--- a/src/ui/dialog/print.cpp
+++ b/src/ui/dialog/print.cpp
@@ -81,7 +81,7 @@ static void draw_page(
width, height,
(unsigned long)(Inkscape::Util::Quantity::convert(width, "px", "in") * dpi),
(unsigned long)(Inkscape::Util::Quantity::convert(height, "px", "in") * dpi),
- dpi, dpi, bgcolor, NULL, NULL, true, NULL);
+ dpi, dpi, bgcolor, NULL, NULL, true, std::vector<SPItem*>());
// This doesn't seem to work:
//context->set_cairo_context ( Cairo::Context::create (Cairo::ImageSurface::create_from_png (tmp_png) ), dpi, dpi );
diff --git a/src/ui/dialog/svg-fonts-dialog.cpp b/src/ui/dialog/svg-fonts-dialog.cpp
index bc228633d..12b423602 100644
--- a/src/ui/dialog/svg-fonts-dialog.cpp
+++ b/src/ui/dialog/svg-fonts-dialog.cpp
@@ -524,7 +524,7 @@ void SvgFontsDialog::set_glyph_description_from_selected_path(){
return;
}
- Inkscape::XML::Node* node = (Inkscape::XML::Node*) g_slist_nth_data((GSList *)sel->reprList(), 0);
+ Inkscape::XML::Node* node = sel->reprList().front();
if (!node) return;//TODO: should this be an assert?
if (!node->matchAttributeName("d") || !node->attribute("d")){
char *msg = _("The selected object does not have a <b>path</b> description.");
@@ -566,7 +566,7 @@ void SvgFontsDialog::missing_glyph_description_from_selected_path(){
return;
}
- Inkscape::XML::Node* node = (Inkscape::XML::Node*) g_slist_nth_data((GSList *)sel->reprList(), 0);
+ Inkscape::XML::Node* node = sel->reprList().front();
if (!node) return;//TODO: should this be an assert?
if (!node->matchAttributeName("d") || !node->attribute("d")){
char *msg = _("The selected object does not have a <b>path</b> description.");
diff --git a/src/ui/dialog/swatches.cpp b/src/ui/dialog/swatches.cpp
index 8759039c3..72677c07e 100644
--- a/src/ui/dialog/swatches.cpp
+++ b/src/ui/dialog/swatches.cpp
@@ -123,10 +123,10 @@ static void editGradientImpl( SPDesktop* desktop, SPGradient* gr )
bool shown = false;
if ( desktop && desktop->doc() ) {
Inkscape::Selection *selection = desktop->getSelection();
- GSList const *items = selection->itemList();
- if (items) {
+ std::vector<SPItem*> const items = selection->itemList();
+ if (!items.empty()) {
SPStyle query( desktop->doc() );
- int result = objects_query_fillstroke(const_cast<GSList *>(items), &query, true);
+ int result = objects_query_fillstroke((items), &query, true);
if ( (result == QUERY_STYLE_MULTIPLE_SAME) || (result == QUERY_STYLE_SINGLE) ) {
// could be pertinent
if (query.fill.isPaintserver()) {
diff --git a/src/ui/dialog/tags.cpp b/src/ui/dialog/tags.cpp
index 7d3edaffb..f36e3f18d 100644
--- a/src/ui/dialog/tags.cpp
+++ b/src/ui/dialog/tags.cpp
@@ -51,7 +51,7 @@
#include "ui/tools/tool-base.h" //"event-context.h"
#include "selection.h"
//#include "dialogs/dialog-events.h"
-#include "widgets/sp-color-notebook.h"
+#include "ui/widget/color-notebook.h"
#include "style.h"
#include "filter-chemistry.h"
#include "filters/blend.h"
@@ -352,9 +352,10 @@ void TagsPanel::_objectsSelected( Selection *sel ) {
_selectedConnection.block();
_tree.get_selection()->unselect_all();
- for (const GSList * iter = sel->list(); iter != NULL; iter = iter->next)
+ std::vector<SPObject*> tmp=sel->list();
+ for(std::vector<SPObject*>::const_iterator i=tmp.begin();i!=tmp.end();i++)
{
- SPObject *obj = reinterpret_cast<SPObject *>(iter->data);
+ SPObject *obj = *i;
_store->foreach(sigc::bind<SPObject *>( sigc::mem_fun(*this, &TagsPanel::_checkForSelected), obj));
}
_selectedConnection.unblock();
@@ -649,9 +650,9 @@ bool TagsPanel::_handleButtonEvent(GdkEventButton* event)
if (col == _tree.get_column(COL_ADD - 1) && down_at_add) {
if (SP_IS_TAG(obj)) {
bool wasadded = false;
- for (const GSList * iter = _desktop->selection->itemList(); iter != NULL; iter = iter->next)
- {
- SPObject *newobj = reinterpret_cast<SPObject *>(iter->data);
+ std::vector<SPItem*> items=_desktop->selection->itemList();
+ for(std::vector<SPItem*>::const_iterator i=items.begin();i!=items.end();i++){
+ SPObject *newobj = *i;
bool addchild = true;
for ( SPObject *child = obj->children; child != NULL; child = child->next) {
if (SP_IS_TAG_USE(child) && SP_TAG_USE(child)->ref->getObject() == newobj) {
diff --git a/src/ui/dialog/text-edit.cpp b/src/ui/dialog/text-edit.cpp
index a8be8b543..7575cc854 100644
--- a/src/ui/dialog/text-edit.cpp
+++ b/src/ui/dialog/text-edit.cpp
@@ -69,6 +69,7 @@ TextEdit::TextEdit()
font_label(_("_Font"), true),
layout_frame(),
text_label(_("_Text"), true),
+ vari_label(_("_Variants"), true),
setasdefault_button(_("Set as _default")),
close_button(Gtk::Stock::CLOSE),
apply_button(Gtk::Stock::APPLY),
@@ -195,7 +196,8 @@ TextEdit::TextEdit()
notebook.append_page(font_vbox, font_label);
notebook.append_page(text_vbox, text_label);
-
+ notebook.append_page(vari_vbox, vari_label);
+
/* Buttons */
setasdefault_button.set_use_underline(true);
apply_button.set_can_default();
@@ -216,6 +218,7 @@ TextEdit::TextEdit()
setasdefault_button.signal_clicked().connect(sigc::mem_fun(*this, &TextEdit::onSetDefault));
apply_button.signal_clicked().connect(sigc::mem_fun(*this, &TextEdit::onApply));
close_button.signal_clicked().connect(sigc::bind(_signal_response.make_slot(), GTK_RESPONSE_CLOSE));
+ fontVariantChangedConn = vari_vbox.connectChanged(sigc::bind(sigc::ptr_fun(&onFontVariantChange), this));
desktopChangeConn = deskTrack.connectDesktopChanged( sigc::mem_fun(*this, &TextEdit::setTargetDesktop) );
deskTrack.connect(GTK_WIDGET(gobj()));
@@ -230,6 +233,7 @@ TextEdit::~TextEdit()
selectChangedConn.disconnect();
desktopChangeConn.disconnect();
deskTrack.disconnect();
+ fontVariantChangedConn.disconnect();
}
void TextEdit::styleButton(Gtk::RadioButton *button, gchar const *tooltip, gchar const *icon_name, Gtk::RadioButton *group_button )
@@ -384,6 +388,13 @@ void TextEdit::onReadSelection ( gboolean dostyle, gboolean /*docontent*/ )
gtk_entry_set_text ((GtkEntry *) gtk_bin_get_child ((GtkBin *) spacing_combo), sstr);
g_free(sstr);
+ // Update font variant widget
+ //int result_variants =
+ sp_desktop_query_style (SP_ACTIVE_DESKTOP, &query, QUERY_STYLE_PROPERTY_FONTVARIANTS);
+ int result_features =
+ sp_desktop_query_style (SP_ACTIVE_DESKTOP, &query, QUERY_STYLE_PROPERTY_FONTFEATURESETTINGS);
+ vari_vbox.update( &query, result_features == QUERY_STYLE_MULTIPLE_DIFFERENT, fontspec );
+
}
blocked = false;
}
@@ -418,12 +429,11 @@ SPItem *TextEdit::getSelectedTextItem (void)
if (!SP_ACTIVE_DESKTOP)
return NULL;
- for (const GSList *item = SP_ACTIVE_DESKTOP->getSelection()->itemList();
- item != NULL;
- item = item->next)
+ std::vector<SPItem*> tmp=SP_ACTIVE_DESKTOP->getSelection()->itemList();
+ for(std::vector<SPItem*>::const_iterator i=tmp.begin();i!=tmp.end();i++)
{
- if (SP_IS_TEXT(item->data) || SP_IS_FLOWTEXT(item->data))
- return SP_ITEM (item->data);
+ if (SP_IS_TEXT(*i) || SP_IS_FLOWTEXT(*i))
+ return *i;
}
return NULL;
@@ -437,11 +447,10 @@ unsigned TextEdit::getSelectedTextCount (void)
unsigned int items = 0;
- for (const GSList *item = SP_ACTIVE_DESKTOP->getSelection()->itemList();
- item != NULL;
- item = item->next)
+ std::vector<SPItem*> tmp=SP_ACTIVE_DESKTOP->getSelection()->itemList();
+ for(std::vector<SPItem*>::const_iterator i=tmp.begin();i!=tmp.end();i++)
{
- if (SP_IS_TEXT(item->data) || SP_IS_FLOWTEXT(item->data))
+ if (SP_IS_TEXT(*i) || SP_IS_FLOWTEXT(*i))
++items;
}
@@ -512,12 +521,15 @@ SPCSSAttr *TextEdit::fillTextStyle ()
sp_repr_css_set_property (css, "writing-mode", "tb");
}
- // Note that CSS 1.1 does not support line-height; we set it for consistency, but also set
+ // Note that SVG 1.1 does not support line-height; we set it for consistency, but also set
// sodipodi:linespacing for backwards compatibility; in 1.2 we use line-height for flowtext
const gchar *sstr = gtk_combo_box_text_get_active_text ((GtkComboBoxText *) spacing_combo);
sp_repr_css_set_property (css, "line-height", sstr);
+ // Font variants
+ vari_vbox.fill_css( css );
+
return css;
}
@@ -542,20 +554,20 @@ void TextEdit::onApply()
SPDesktop *desktop = SP_ACTIVE_DESKTOP;
unsigned items = 0;
- const GSList *item_list = desktop->getSelection()->itemList();
+ const std::vector<SPItem*> item_list = desktop->getSelection()->itemList();
SPCSSAttr *css = fillTextStyle ();
sp_desktop_set_style(desktop, css, true);
- for (; item_list != NULL; item_list = item_list->next) {
+ for(std::vector<SPItem*>::const_iterator i=item_list.begin();i!=item_list.end();i++){
// apply style to the reprs of all text objects in the selection
- if (SP_IS_TEXT (item_list->data)) {
+ if (SP_IS_TEXT (*i)) {
// backwards compatibility:
- reinterpret_cast<SPObject*>(item_list->data)->getRepr()->setAttribute("sodipodi:linespacing", sp_repr_css_property (css, "line-height", NULL));
+ (*i)->getRepr()->setAttribute("sodipodi:linespacing", sp_repr_css_property (css, "line-height", NULL));
++items;
}
- else if (SP_IS_FLOWTEXT (item_list->data))
+ else if (SP_IS_FLOWTEXT (*i))
// no need to set sodipodi:linespacing, because Inkscape never supported it on flowtext
++items;
}
@@ -648,6 +660,19 @@ void TextEdit::onFontChange(SPFontSelector * /*fontsel*/, gchar* fontspec, TextE
}
+void TextEdit::onFontVariantChange(TextEdit *self)
+{
+ if( self->blocked )
+ return;
+
+ SPItem *text = self->getSelectedTextItem ();
+
+ if (text) {
+ self->apply_button.set_sensitive ( true );
+ }
+ self->setasdefault_button.set_sensitive ( true );
+}
+
void TextEdit::onStartOffsetChange(GtkTextBuffer * /*text_buffer*/, TextEdit *self)
{
SPItem *text = self->getSelectedTextItem();
diff --git a/src/ui/dialog/text-edit.h b/src/ui/dialog/text-edit.h
index 117ad2e28..cfe612268 100644
--- a/src/ui/dialog/text-edit.h
+++ b/src/ui/dialog/text-edit.h
@@ -32,9 +32,11 @@
#include "ui/widget/panel.h"
#include "ui/widget/frame.h"
#include "ui/dialog/desktop-tracker.h"
+#include "ui/widget/font-variants.h"
class SPItem;
struct SPFontSelector;
+//class FontVariants;
class font_instance;
class SPCSSAttr;
@@ -111,6 +113,17 @@ protected:
static void onFontChange (SPFontSelector *fontsel, gchar* fontspec, TextEdit *self);
/**
+ * Callback invoked when the user modifies the font variant through the dialog.
+ *
+ * onFontChange updates the dialog UI. The subfunction setPreviewText updates the preview label.
+ *
+ * @param fontsel pointer to FontVariant (currently not used).
+ * @param fontspec for the text to be previewed.
+ * @param self pointer to the current instance of the dialog.
+ */
+ static void onFontVariantChange (TextEdit *self);
+
+ /**
* Callback invoked when the user modifies the startOffset of text on a path.
*
* @param text_buffer pointer to the GtkTextBuffer with the text of the selected text object.
@@ -213,6 +226,9 @@ private:
GtkWidget *text_view; // TODO - Convert this to a Gtk::TextView, but GtkSpell doesn't seem to work with it
GtkTextBuffer *text_buffer;
+ Inkscape::UI::Widget::FontVariants vari_vbox;
+ Gtk::Label vari_label;
+
Gtk::HBox button_row;
Gtk::Button setasdefault_button;
Gtk::Button close_button;
@@ -224,6 +240,7 @@ private:
sigc::connection selectChangedConn;
sigc::connection subselChangedConn;
sigc::connection selectModifiedConn;
+ sigc::connection fontVariantChangedConn;
bool blocked;
const Glib::ustring samplephrase;
diff --git a/src/ui/dialog/transformation.cpp b/src/ui/dialog/transformation.cpp
index e7ee9529f..498ad7822 100644
--- a/src/ui/dialog/transformation.cpp
+++ b/src/ui/dialog/transformation.cpp
@@ -651,7 +651,7 @@ void Transformation::updatePageTransform(Inkscape::Selection *selection)
{
if (selection && !selection->isEmpty()) {
if (_check_replace_matrix.get_active()) {
- Geom::Affine current (SP_ITEM(selection->itemList()->data)->transform); // take from the first item in selection
+ Geom::Affine current (selection->itemList()[0]->transform); // take from the first item in selection
Geom::Affine new_displayed = current;
@@ -736,20 +736,19 @@ void Transformation::applyPageMove(Inkscape::Selection *selection)
if (_check_move_relative.get_active()) {
// shift each object relatively to the previous one
- using Inkscape::Util::GSListConstIterator;
- std::list<SPItem *> selected;
- selected.insert<GSListConstIterator<SPItem *> >(selected.end(), selection->itemList(), NULL);
+ std::vector<SPItem*> selected(selection->itemList());
if (selected.empty()) return;
if (fabs(x) > 1e-6) {
std::vector< BBoxSort > sorted;
- for (std::list<SPItem *>::iterator it(selected.begin());
+ for (std::vector<SPItem*>::iterator it(selected.begin());
it != selected.end();
++it)
{
- Geom::OptRect bbox = (*it)->desktopPreferredBounds();
+ SPItem* item = *it;
+ Geom::OptRect bbox = item->desktopPreferredBounds();
if (bbox) {
- sorted.push_back(BBoxSort(*it, *bbox, Geom::X, x > 0? 1. : 0., x > 0? 0. : 1.));
+ sorted.push_back(BBoxSort(item, *bbox, Geom::X, x > 0? 1. : 0., x > 0? 0. : 1.));
}
}
//sort bbox by anchors
@@ -767,13 +766,14 @@ void Transformation::applyPageMove(Inkscape::Selection *selection)
}
if (fabs(y) > 1e-6) {
std::vector< BBoxSort > sorted;
- for (std::list<SPItem *>::iterator it(selected.begin());
+ for (std::vector<SPItem*>::iterator it(selected.begin());
it != selected.end();
++it)
{
- Geom::OptRect bbox = (*it)->desktopPreferredBounds();
+ SPItem* item = *it;
+ Geom::OptRect bbox = item->desktopPreferredBounds();
if (bbox) {
- sorted.push_back(BBoxSort(*it, *bbox, Geom::Y, y > 0? 1. : 0., y > 0? 0. : 1.));
+ sorted.push_back(BBoxSort(item, *bbox, Geom::Y, y > 0? 1. : 0., y > 0? 0. : 1.));
}
}
//sort bbox by anchors
@@ -811,8 +811,9 @@ void Transformation::applyPageScale(Inkscape::Selection *selection)
bool transform_stroke = prefs->getBool("/options/transform/stroke", true);
bool preserve = prefs->getBool("/options/preservetransform/value", false);
if (prefs->getBool("/dialogs/transformation/applyseparately")) {
- for (GSList const *l = selection->itemList(); l != NULL; l = l->next) {
- SPItem *item = SP_ITEM(l->data);
+ std::vector<SPItem*> tmp=selection->itemList();
+ for(std::vector<SPItem*>::const_iterator i=tmp.begin();i!=tmp.end();i++){
+ SPItem *item = *i;
Geom::OptRect bbox_pref = item->desktopPreferredBounds();
Geom::OptRect bbox_geom = item->desktopGeometricBounds();
if (bbox_pref && bbox_geom) {
@@ -874,8 +875,9 @@ void Transformation::applyPageRotate(Inkscape::Selection *selection)
}
if (prefs->getBool("/dialogs/transformation/applyseparately")) {
- for (GSList const *l = selection->itemList(); l != NULL; l = l->next) {
- SPItem *item = SP_ITEM(l->data);
+ std::vector<SPItem*> tmp=selection->itemList();
+ for(std::vector<SPItem*>::const_iterator i=tmp.begin();i!=tmp.end();i++){
+ SPItem *item = *i;
sp_item_rotate_rel(item, Geom::Rotate (angle*M_PI/180.0));
}
} else {
@@ -893,8 +895,9 @@ void Transformation::applyPageSkew(Inkscape::Selection *selection)
{
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
if (prefs->getBool("/dialogs/transformation/applyseparately")) {
- for (GSList const *l = selection->itemList(); l != NULL; l = l->next) {
- SPItem *item = SP_ITEM(l->data);
+ std::vector<SPItem*> items=selection->itemList();
+ for(std::vector<SPItem*>::const_iterator i = items.begin();i!=items.end();i++){
+ SPItem *item = *i;
if (!_units_skew.isAbsolute()) { // percentage
double skewX = _scalar_skew_horizontal.getValue("%");
@@ -994,10 +997,11 @@ void Transformation::applyPageTransform(Inkscape::Selection *selection)
}
if (_check_replace_matrix.get_active()) {
- for (GSList const *l = selection->itemList(); l != NULL; l = l->next) {
- SPItem *item = SP_ITEM(l->data);
+ std::vector<SPItem*> tmp=selection->itemList();
+ for(std::vector<SPItem*>::const_iterator i=tmp.begin();i!=tmp.end();i++){
+ SPItem *item = *i;
item->set_item_transform(displayed);
- SP_OBJECT(item)->updateRepr();
+ item->updateRepr();
}
} else {
sp_selection_apply_affine(selection, displayed); // post-multiply each object's transform
@@ -1146,7 +1150,7 @@ void Transformation::onReplaceMatrixToggled()
double f = _scalar_transform_f.getValue();
Geom::Affine displayed (a, b, c, d, e, f);
- Geom::Affine current = SP_ITEM(selection->itemList()->data)->transform; // take from the first item in selection
+ Geom::Affine current = selection->itemList()[0]->transform; // take from the first item in selection
Geom::Affine new_displayed;
if (_check_replace_matrix.get_active()) {
diff --git a/src/ui/interface.cpp b/src/ui/interface.cpp
index 87438ac01..a129d4b92 100644
--- a/src/ui/interface.cpp
+++ b/src/ui/interface.cpp
@@ -439,7 +439,7 @@ sp_ui_dialog_title_string(Inkscape::Verb *verb, gchar *c)
gchar* key = sp_shortcut_get_label(shortcut);
s = g_stpcpy(s, " (");
s = g_stpcpy(s, key);
- s = g_stpcpy(s, ")");
+ g_stpcpy(s, ")");
g_free(key);
}
}
@@ -1906,11 +1906,10 @@ void ContextMenu::ActivateGroup(void)
void ContextMenu::ActivateUngroup(void)
{
- GSList *children = NULL;
+ std::vector<SPItem*> children;
- sp_item_group_ungroup(static_cast<SPGroup*>(_item), &children);
+ sp_item_group_ungroup(static_cast<SPGroup*>(_item), children);
_desktop->selection->setList(children);
- g_slist_free(children);
}
void ContextMenu::MakeAnchorMenu(void)
@@ -1959,10 +1958,9 @@ void ContextMenu::AnchorLinkFollow(void)
void ContextMenu::AnchorLinkRemove(void)
{
- GSList *children = NULL;
- sp_item_group_ungroup(static_cast<SPAnchor*>(_item), &children, false);
+ std::vector<SPItem*> children;
+ sp_item_group_ungroup(static_cast<SPAnchor*>(_item), children, false);
DocumentUndo::done(_desktop->doc(), SP_VERB_NONE, _("Remove link"));
- g_slist_free(children);
}
void ContextMenu::MakeImageMenu (void)
@@ -2051,8 +2049,6 @@ void ContextMenu::ImageEdit(void)
_desktop->selection->set(_item);
}
- GSList const *selected = _desktop->selection->itemList();
-
GError* errThing = 0;
Glib::ustring cmdline = getImageEditorName();
Glib::ustring name;
@@ -2079,8 +2075,9 @@ void ContextMenu::ImageEdit(void)
}
#endif
- for (GSList const *iter = selected; iter != NULL; iter = iter->next) {
- Inkscape::XML::Node *ir = SP_ITEM(iter->data)->getRepr();
+ std::vector<SPItem*> itemlist=_desktop->selection->itemList();
+ for(std::vector<SPItem*>::const_iterator i=itemlist.begin();i!=itemlist.end();i++){
+ Inkscape::XML::Node *ir = (*i)->getRepr();
const gchar *href = ir->attribute("xlink:href");
if (strncmp (href,"file:",5) == 0) {
diff --git a/src/ui/selected-color.cpp b/src/ui/selected-color.cpp
new file mode 100644
index 000000000..8c37ee7e0
--- /dev/null
+++ b/src/ui/selected-color.cpp
@@ -0,0 +1,163 @@
+/** @file
+ * Color selected in color selector widget.
+ * This file was created during the refactoring of SPColorSelector
+ *//*
+ * Authors:
+ * bulia byak <buliabyak@users.sf.net>
+ * Jon A. Cruz <jon@joncruz.org>
+ * Tomasz Boczkowski <penginsbacon@gmail.com>
+ *
+ * Copyright (C) 2014 Authors
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glibmm/ustring.h>
+#include <cmath>
+
+#include "svg/svg-icc-color.h"
+#include "ui/selected-color.h"
+
+namespace Inkscape {
+namespace UI {
+
+double const SelectedColor::_EPSILON = 1e-4;
+
+SelectedColor::SelectedColor()
+ : _color(0)
+ , _alpha(1.0)
+ , _held(false)
+ , _virgin(true)
+ , _updating(false)
+{
+
+}
+
+SelectedColor::~SelectedColor() {
+
+}
+
+void SelectedColor::setColor(SPColor const &color)
+{
+ setColorAlpha( color, _alpha);
+}
+
+SPColor SelectedColor::color() const
+{
+ return _color;
+}
+
+void SelectedColor::setAlpha(gfloat alpha)
+{
+ g_return_if_fail( ( 0.0 <= alpha ) && ( alpha <= 1.0 ) );
+ setColorAlpha( _color, alpha);
+}
+
+gfloat SelectedColor::alpha() const
+{
+ return _alpha;
+}
+
+void SelectedColor::setValue(guint32 value)
+{
+ SPColor color(value);
+ gfloat alpha = SP_RGBA32_A_F(value);
+ setColorAlpha(color, alpha);
+}
+
+guint32 SelectedColor::value() const
+{
+ return color().toRGBA32(_alpha);
+}
+
+void SelectedColor::setColorAlpha(SPColor const &color, gfloat alpha, bool emit_signal)
+{
+#ifdef DUMP_CHANGE_INFO
+ g_message("SelectedColor::setColorAlpha( this=%p, %f, %f, %f, %s, %f, %s)", this, color.v.c[0], color.v.c[1], color.v.c[2], (color.icc?color.icc->colorProfile.c_str():"<null>"), alpha, (emit_signal?"YES":"no"));
+#endif
+ g_return_if_fail( ( 0.0 <= alpha ) && ( alpha <= 1.0 ) );
+
+ if (_updating) {
+ return;
+ }
+
+#ifdef DUMP_CHANGE_INFO
+ g_message("---- SelectedColor::setColorAlpha virgin:%s !close:%s alpha is:%s",
+ (_virgin?"YES":"no"),
+ (!color.isClose( _color, _EPSILON )?"YES":"no"),
+ ((fabs((_alpha) - (alpha)) >= _EPSILON )?"YES":"no")
+ );
+#endif
+
+ if ( _virgin || !color.isClose( _color, _EPSILON ) ||
+ (fabs((_alpha) - (alpha)) >= _EPSILON )) {
+
+ _virgin = false;
+
+ _color = color;
+ _alpha = alpha;
+
+ if (emit_signal)
+ {
+ _updating = true;
+ if (_held) {
+ signal_dragged.emit();
+ } else {
+ signal_changed.emit();
+ }
+ _updating = false;
+ }
+
+#ifdef DUMP_CHANGE_INFO
+ } else {
+ g_message("++++ SelectedColor::setColorAlpha color:%08x ==> _color:%08X isClose:%s", color.toRGBA32(alpha), _color.toRGBA32(_alpha),
+ (color.isClose( _color, _EPSILON )?"YES":"no"));
+#endif
+ }
+}
+
+void SelectedColor::colorAlpha(SPColor &color, gfloat &alpha) const {
+ color = _color;
+ alpha = _alpha;
+}
+
+void SelectedColor::setHeld(bool held) {
+ if (_updating) {
+ return;
+ }
+ bool grabbed = held && !_held;
+ bool released = !held && _held;
+
+ _held = held;
+
+ _updating = true;
+ if (grabbed) {
+ signal_grabbed.emit();
+ }
+
+ if (released) {
+ signal_released.emit();
+ signal_changed.emit();
+ }
+ _updating = false;
+}
+
+void SelectedColor::preserveICC() {
+ _color.icc = _color.icc ? new SVGICCColor(*_color.icc) : 0;
+}
+
+}
+}
+
+/*
+ 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/selected-color.h b/src/ui/selected-color.h
new file mode 100644
index 000000000..e9e702d43
--- /dev/null
+++ b/src/ui/selected-color.h
@@ -0,0 +1,96 @@
+/** @file
+ * Color selected in color selector widget.
+ * This file was created during the refactoring of SPColorSelector
+ *//*
+ * Authors:
+ * bulia byak <buliabyak@users.sf.net>
+ * Jon A. Cruz <jon@joncruz.org>
+ * Tomasz Boczkowski <penginsbacon@gmail.com>
+ *
+ * Copyright (C) 2014 Authors
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+#ifndef SEEN_SELECTED_COLOR
+#define SEEN_SELECTED_COLOR
+
+#include <sigc++/signal.h>
+#include "color.h"
+
+namespace Gtk
+{
+ class Widget;
+}
+
+namespace Inkscape {
+namespace UI {
+
+class SelectedColor {
+public:
+ SelectedColor();
+ virtual ~SelectedColor();
+
+ void setColor(SPColor const &color);
+ SPColor color() const;
+
+ void setAlpha(gfloat alpha);
+ gfloat alpha() const;
+
+ void setValue(guint32 value);
+ guint32 value() const;
+
+ void setColorAlpha(SPColor const &color, gfloat alpha, bool emit_signal = true);
+ void colorAlpha(SPColor &color, gfloat &alpha) const;
+
+ void setHeld(bool held);
+
+ void preserveICC();
+
+ sigc::signal<void> signal_grabbed;
+ sigc::signal<void> signal_dragged;
+ sigc::signal<void> signal_released;
+ sigc::signal<void> signal_changed;
+private:
+ // By default, disallow copy constructor and assignment operator
+ SelectedColor(SelectedColor const &obj);
+ SelectedColor& operator=(SelectedColor const &obj);
+
+ SPColor _color;
+ /**
+ * Color alpha value guaranteed to be in [0, 1].
+ */
+ gfloat _alpha;
+
+ bool _held;
+ /**
+ * This flag is true if no color is set yet
+ */
+ bool _virgin;
+
+ bool _updating;
+
+ static double const _EPSILON;
+};
+
+class ColorSelectorFactory {
+public:
+ virtual ~ColorSelectorFactory() {
+ }
+
+ virtual Gtk::Widget* createWidget(SelectedColor &color) const = 0;
+ virtual Glib::ustring modeName() const = 0;
+};
+
+}
+}
+
+#endif
+/*
+ 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/tool/control-point.cpp b/src/ui/tool/control-point.cpp
index bcf5c9fce..636595016 100644
--- a/src/ui/tool/control-point.cpp
+++ b/src/ui/tool/control-point.cpp
@@ -71,7 +71,8 @@ ControlPoint::ControlPoint(SPDesktop *d, Geom::Point const &initial_pos, SPAncho
_cset(cset),
_state(STATE_NORMAL),
_position(initial_pos),
- _lurking(false)
+ _lurking(false),
+ _double_clicked(false)
{
_canvas_item = sp_canvas_item_new(
group ? group : _desktop->getControls(), SP_TYPE_CTRL,
@@ -80,6 +81,7 @@ ControlPoint::ControlPoint(SPDesktop *d, Geom::Point const &initial_pos, SPAncho
"filled", TRUE, "fill_color", _cset.normal.fill,
"stroked", TRUE, "stroke_color", _cset.normal.stroke,
"mode", SP_CTRL_MODE_XOR, NULL);
+
_commonInit();
}
@@ -91,7 +93,8 @@ ControlPoint::ControlPoint(SPDesktop *d, Geom::Point const &initial_pos, SPAncho
_cset(cset),
_state(STATE_NORMAL),
_position(initial_pos),
- _lurking(false)
+ _lurking(false),
+ _double_clicked(false)
{
_canvas_item = ControlManager::getManager().createControl(group ? group : _desktop->getControls(), type);
g_object_set(_canvas_item,
@@ -245,7 +248,8 @@ bool ControlPoint::_eventHandler(Inkscape::UI::Tools::ToolBase *event_context, G
static Geom::Point pointer_offset;
// number of last doubleclicked button
static unsigned next_release_doubleclick = 0;
-
+ _double_clicked = false;
+
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
int drag_tolerance = prefs->getIntLimited("/options/dragtolerance/value", 0, 0, 100);
GdkEventMotion em;
@@ -278,6 +282,7 @@ bool ControlPoint::_eventHandler(Inkscape::UI::Tools::ToolBase *event_context, G
Ca = _desktop->canvas;
em = event->motion;
combine_motion_events(Ca, em, 0);
+
if (_event_grab && ! event_context->space_panning) {
_desktop->snapindicator->remove_snaptarget();
bool transferred = false;
@@ -298,6 +303,7 @@ bool ControlPoint::_eventHandler(Inkscape::UI::Tools::ToolBase *event_context, G
_drag_initiated = true;
}
}
+
if (!transferred) {
// dragging in progress
Geom::Point new_pos = _desktop->w2d(event_point(event->motion)) + pointer_offset;
@@ -305,7 +311,7 @@ bool ControlPoint::_eventHandler(Inkscape::UI::Tools::ToolBase *event_context, G
dragged(new_pos, &em);
move(new_pos);
_updateDragTip(&em); // update dragging tip after moving to new position
-
+
_desktop->scroll_to_point(new_pos);
_desktop->set_coordinate_status(_position);
sp_event_context_snap_delay_handler(event_context, NULL,
@@ -342,6 +348,7 @@ bool ControlPoint::_eventHandler(Inkscape::UI::Tools::ToolBase *event_context, G
} else {
// it is the end of a click
if (next_release_doubleclick) {
+ _double_clicked = true;
return doubleclicked(&event->button);
} else {
return clicked(&event->button);
diff --git a/src/ui/tool/control-point.h b/src/ui/tool/control-point.h
index b3ed9545e..4a01b9f21 100644
--- a/src/ui/tool/control-point.h
+++ b/src/ui/tool/control-point.h
@@ -193,6 +193,8 @@ public:
virtual bool _eventHandler(Inkscape::UI::Tools::ToolBase *event_context, GdkEvent *event);
SPDesktop *const _desktop; ///< The desktop this control point resides on.
+ bool doubleClicked() {return _double_clicked;}
+
protected:
struct ColorEntry {
@@ -361,6 +363,8 @@ protected:
/** Events which should be captured when a handle is being dragged. */
static int const _grab_event_mask;
+ static bool _drag_initiated;
+
private:
ControlPoint(ControlPoint const &other);
@@ -397,7 +401,7 @@ private:
static bool _event_grab;
- static bool _drag_initiated;
+ bool _double_clicked;
};
diff --git a/src/ui/tool/curve-drag-point.cpp b/src/ui/tool/curve-drag-point.cpp
index 23640456e..e460b0fb7 100644
--- a/src/ui/tool/curve-drag-point.cpp
+++ b/src/ui/tool/curve-drag-point.cpp
@@ -15,6 +15,8 @@
#include "ui/tool/multi-path-manipulator.h"
#include "ui/tool/path-manipulator.h"
#include "ui/tool/node.h"
+#include "sp-namedview.h"
+#include "snap.h"
namespace Inkscape {
namespace UI {
@@ -77,6 +79,16 @@ void CurveDragPoint::dragged(Geom::Point &new_pos, GdkEventMotion *event)
return;
}
+ if (_drag_initiated && !(event->state & GDK_SHIFT_MASK)) {
+ SnapManager &m = _desktop->namedview->snap_manager;
+ SPItem *path = static_cast<SPItem *>(_pm._path);
+ m.setup(_desktop, true, path); // We will not try to snap to "path" itself
+ Inkscape::SnapCandidatePoint scp(new_pos, Inkscape::SNAPSOURCE_OTHER_HANDLE);
+ Inkscape::SnappedPoint sp = m.freeSnap(scp, Geom::OptRect(), false);
+ new_pos = sp.getPoint();
+ m.unSetup();
+ }
+
// Magic Bezier Drag Equations follow!
// "weight" describes how the influence of the drag should be distributed
// among the handles; 0 = front handle only, 1 = back handle only.
@@ -166,14 +178,8 @@ void CurveDragPoint::_insertNode(bool take_selection)
// Otherwise clicks on the new node would only work after the user moves the mouse a bit.
// PathManipulator will restore visibility when necessary.
setVisible(false);
- NodeList::iterator inserted = _pm.subdivideSegment(first, _t);
- if (take_selection) {
- _pm._selection.clear();
- }
- _pm._selection.insert(inserted.ptr());
- _pm.update(true);
- _pm._commit(_("Add node"));
+ _pm.insertNode(first, _t, take_selection);
}
Glib::ustring CurveDragPoint::_getTip(unsigned state) const
@@ -181,6 +187,10 @@ Glib::ustring CurveDragPoint::_getTip(unsigned state) const
if (_pm.empty()) return "";
if (!first || !first.next()) return "";
bool linear = first->front()->isDegenerate() && first.next()->back()->isDegenerate();
+ if(state_held_shift(state) && _pm._isBSpline()){
+ return C_("Path segment tip",
+ "<b>Shift</b>: drag to open or move BSpline handles");
+ }
if (state_held_shift(state)) {
return C_("Path segment tip",
"<b>Shift</b>: click to toggle segment selection");
@@ -189,6 +199,11 @@ Glib::ustring CurveDragPoint::_getTip(unsigned state) const
return C_("Path segment tip",
"<b>Ctrl+Alt</b>: click to insert a node");
}
+ if(_pm._isBSpline()){
+ return C_("Path segment tip",
+ "<b>BSpline segment</b>: drag to shape the segment, doubleclick to insert node, "
+ "click to select (more: Shift, Ctrl+Alt)");
+ }
if (linear) {
return C_("Path segment tip",
"<b>Linear segment</b>: drag to convert to a Bezier segment, "
diff --git a/src/ui/tool/curve-drag-point.h b/src/ui/tool/curve-drag-point.h
index ea83978e0..c1d40575f 100644
--- a/src/ui/tool/curve-drag-point.h
+++ b/src/ui/tool/curve-drag-point.h
@@ -34,7 +34,9 @@ public:
CurveDragPoint(PathManipulator &pm);
void setSize(double sz) { _setSize(sz); }
void setTimeValue(double t) { _t = t; }
+ double getTimeValue() { return _t; }
void setIterator(NodeList::iterator i) { first = i; }
+ NodeList::iterator getIterator() { return first; }
virtual bool _eventHandler(Inkscape::UI::Tools::ToolBase *event_context, GdkEvent *event);
protected:
@@ -47,9 +49,6 @@ protected:
virtual bool doubleclicked(GdkEventButton *);
private:
-
- void _insertNode(bool take_selection);
-
double _t;
PathManipulator &_pm;
NodeList::iterator first;
@@ -57,6 +56,7 @@ private:
static bool _drags_stroke;
static bool _segment_was_degenerate;
static Geom::Point _stroke_drag_origin;
+ void _insertNode(bool take_selection);
};
} // namespace UI
diff --git a/src/ui/tool/multi-path-manipulator.cpp b/src/ui/tool/multi-path-manipulator.cpp
index f53cef5f4..46c6246a1 100644
--- a/src/ui/tool/multi-path-manipulator.cpp
+++ b/src/ui/tool/multi-path-manipulator.cpp
@@ -339,6 +339,14 @@ void MultiPathManipulator::insertNodesAtExtrema(ExtremumType extremum)
_done(_("Add extremum nodes"));
}
+void MultiPathManipulator::insertNode(Geom::Point pt)
+{
+ // When double clicking to insert nodes, we might not have a selection of nodes (and we don't need one)
+ // so don't check for "_selection.empty()" here, contrary to the other methods above and below this one
+ invokeForAll(&PathManipulator::insertNode, pt);
+ _done(_("Add nodes"));
+}
+
void MultiPathManipulator::duplicateNodes()
{
if (_selection.empty()) return;
diff --git a/src/ui/tool/multi-path-manipulator.h b/src/ui/tool/multi-path-manipulator.h
index 1bbcdd7ec..c908cede2 100644
--- a/src/ui/tool/multi-path-manipulator.h
+++ b/src/ui/tool/multi-path-manipulator.h
@@ -53,6 +53,7 @@ public:
void insertNodesAtExtrema(ExtremumType extremum);
void insertNodes();
+ void insertNode(Geom::Point pt);
void alertLPE();
void duplicateNodes();
void joinNodes();
diff --git a/src/ui/tool/node.cpp b/src/ui/tool/node.cpp
index aa5365265..ca6f5abb1 100644
--- a/src/ui/tool/node.cpp
+++ b/src/ui/tool/node.cpp
@@ -356,8 +356,8 @@ void Handle::dragged(Geom::Point &new_pos, GdkEventMotion *event)
Geom::Line perp_line(parent_pos, parent_pos + Geom::rot90(origin - parent_pos));
Geom::Point snap_pos = parent_pos + Geom::constrain_angle(
Geom::Point(0,0), new_pos - parent_pos, snaps, Geom::Point(1,0));
- Geom::Point orig_pos = original_line.pointAt(original_line.nearestPoint(new_pos));
- Geom::Point perp_pos = perp_line.pointAt(perp_line.nearestPoint(new_pos));
+ Geom::Point orig_pos = original_line.pointAt(original_line.nearestTime(new_pos));
+ Geom::Point perp_pos = perp_line.pointAt(perp_line.nearestTime(new_pos));
Geom::Point result = snap_pos;
ctrl_constraint = Inkscape::Snapper::SnapConstraint(parent_pos, parent_pos - snap_pos);
@@ -1464,13 +1464,14 @@ Glib::ustring Node::_getTip(unsigned state) const
// No modifiers: assemble tip from node type
char const *nodetype = node_type_to_localized_string(_type);
+ double power = _pm()._bsplineHandlePosition(h,h2);
if (_selection.transformHandlesEnabled() && selected()) {
if (_selection.size() == 1 && !isBSpline) {
return format_tip(C_("Path node tip",
"<b>%s</b>: drag to shape the path (more: Shift, Ctrl, Alt)"), nodetype);
}else if(_selection.size() == 1){
return format_tip(C_("Path node tip",
- "<b>BSpline node</b>: drag to shape the path (more: Shift, Ctrl, Alt). %g power"),_pm()._bsplineHandlePosition(h,h2));
+ "<b>BSpline node</b>: drag to shape the path (more: Shift, Ctrl, Alt). %g power"), power);
}
return format_tip(C_("Path node tip",
"<b>%s</b>: drag to shape the path, click to toggle scale/rotation handles (more: Shift, Ctrl, Alt)"), nodetype);
@@ -1480,7 +1481,7 @@ Glib::ustring Node::_getTip(unsigned state) const
"<b>%s</b>: drag to shape the path, click to select only this node (more: Shift, Ctrl, Alt)"), nodetype);
}else{
return format_tip(C_("Path node tip",
- "<b>BSpline node</b>: drag to shape the path, click to select only this node (more: Shift, Ctrl, Alt). %g power"),_pm()._bsplineHandlePosition(h,h2));
+ "<b>BSpline node</b>: drag to shape the path, click to select only this node (more: Shift, Ctrl, Alt). %g power"), power);
}
}
@@ -1567,6 +1568,13 @@ NodeList::iterator NodeList::before(double t, double *fracpart)
return ret;
}
+NodeList::iterator NodeList::before(Geom::PathTime const &pvp)
+{
+ iterator ret = begin();
+ std::advance(ret, pvp.curve_index);
+ return ret;
+}
+
NodeList::iterator NodeList::insert(iterator pos, Node *x)
{
ListNode *ins = pos._node;
diff --git a/src/ui/tool/node.h b/src/ui/tool/node.h
index 101af4817..025c460e2 100644
--- a/src/ui/tool/node.h
+++ b/src/ui/tool/node.h
@@ -406,9 +406,13 @@ public:
void setClosed(bool c) { _closed = c; }
iterator before(double t, double *fracpart = NULL);
+ iterator before(Geom::PathTime const &pvp);
const_iterator before(double t, double *fracpart = NULL) const {
return const_iterator(before(t, fracpart)._node);
}
+ const_iterator before(Geom::PathTime const &pvp) const {
+ return const_iterator(before(pvp)._node);
+ }
// list operations
diff --git a/src/ui/tool/path-manipulator.cpp b/src/ui/tool/path-manipulator.cpp
index 6b0c95f68..848b10373 100644
--- a/src/ui/tool/path-manipulator.cpp
+++ b/src/ui/tool/path-manipulator.cpp
@@ -174,7 +174,8 @@ bool PathManipulator::event(Inkscape::UI::Tools::ToolBase * /*event_context*/, G
case GDK_MOTION_NOTIFY:
_updateDragPoint(event_point(event->motion));
break;
- default: break;
+ default:
+ break;
}
return false;
}
@@ -275,6 +276,27 @@ void PathManipulator::insertNodes()
}
}
+void PathManipulator::insertNode(Geom::Point pt)
+{
+ Geom::Coord dist = _updateDragPoint(pt);
+ if (dist < 1e-5) { // 1e-6 is too small, as observed occasionally when inserting a node at a snapped intersection of paths
+ insertNode(_dragpoint->getIterator(), _dragpoint->getTimeValue(), true);
+ }
+}
+
+void PathManipulator::insertNode(NodeList::iterator first, double t, bool take_selection)
+{
+ NodeList::iterator inserted = subdivideSegment(first, t);
+ if (take_selection) {
+ _selection.clear();
+ }
+ _selection.insert(inserted.ptr());
+
+ update(true);
+ _commit(_("Add node"));
+}
+
+
static void
add_or_replace_if_extremum(std::vector< std::pair<NodeList::iterator, double> > &vec,
double & extrvalue, double testvalue, NodeList::iterator const& node, double t)
@@ -996,7 +1018,7 @@ NodeList::iterator PathManipulator::subdivideSegment(NodeList::iterator first, d
Geom::CubicBezier temp(first->position(), first->front()->position(),
second->back()->position(), second->position());
std::pair<Geom::CubicBezier, Geom::CubicBezier> div = temp.subdivide(t);
- std::vector<Geom::Point> seg1 = div.first.points(), seg2 = div.second.points();
+ std::vector<Geom::Point> seg1 = div.first.controlPoints(), seg2 = div.second.controlPoints();
// set new handle positions
Node *n = new Node(_multi_path_manipulator._path_data.node_data, seg2[0]);
@@ -1141,22 +1163,22 @@ void PathManipulator::_createControlPointsFromGeometry()
pathv *= (_edit_transform * _i2d_transform);
// in this loop, we know that there are no zero-segment subpaths
- for (Geom::PathVector::const_iterator pit = pathv.begin(); pit != pathv.end(); ++pit) {
+ for (Geom::PathVector::iterator pit = pathv.begin(); pit != pathv.end(); ++pit) {
// prepare new subpath
SubpathPtr subpath(new NodeList(_subpaths));
_subpaths.push_back(subpath);
Node *previous_node = new Node(_multi_path_manipulator._path_data.node_data, pit->initialPoint());
subpath->push_back(previous_node);
- Geom::Curve const &cseg = pit->back_closed();
- bool fuse_ends = pit->closed()
- && Geom::are_near(cseg.initialPoint(), cseg.finalPoint());
- for (Geom::Path::const_iterator cit = pit->begin(); cit != pit->end_open(); ++cit) {
+
+ bool closed = pit->closed();
+
+ for (Geom::Path::iterator cit = pit->begin(); cit != pit->end(); ++cit) {
Geom::Point pos = cit->finalPoint();
Node *current_node;
// if the closing segment is degenerate and the path is closed, we need to move
// the handle of the first node instead of creating a new one
- if (fuse_ends && cit == --(pit->end_open())) {
+ if (closed && cit == --(pit->end())) {
current_node = subpath->begin().get_pointer();
} else {
/* regardless of segment type, create a new node at the end
@@ -1271,7 +1293,7 @@ double PathManipulator::_bsplineHandlePosition(Handle *h, Handle *h2)
line_inside_nodes->moveto(n->position());
line_inside_nodes->lineto(next_node->position());
if(!are_near(h->position(), n->position())){
- pos = Geom::nearest_point(Geom::Point(h->position()[X] - HANDLE_CUBIC_GAP, h->position()[Y] - HANDLE_CUBIC_GAP), *line_inside_nodes->first_segment());
+ pos = Geom::nearest_time(Geom::Point(h->position()[X] - HANDLE_CUBIC_GAP, h->position()[Y] - HANDLE_CUBIC_GAP), *line_inside_nodes->first_segment());
}
}
if (pos == NO_POWER && !h2){
@@ -1425,7 +1447,7 @@ void PathManipulator::_updateOutline()
Geom::PathVector arrows;
for (Geom::PathVector::iterator i = pv.begin(); i != pv.end(); ++i) {
Geom::Path &path = *i;
- for (Geom::Path::const_iterator j = path.begin(); j != path.end_default(); ++j) {
+ for (Geom::Path::iterator j = path.begin(); j != path.end_default(); ++j) {
Geom::Point at = j->pointAt(0.5);
Geom::Point ut = j->unitTangentAt(0.5);
// rotate the point
@@ -1643,33 +1665,40 @@ void PathManipulator::_commit(Glib::ustring const &annotation, gchar const *key)
/** Update the position of the curve drag point such that it is over the nearest
* point of the path. */
-void PathManipulator::_updateDragPoint(Geom::Point const &evp)
+Geom::Coord PathManipulator::_updateDragPoint(Geom::Point const &evp)
{
+ Geom::Coord dist = HUGE_VAL;
+
Geom::Affine to_desktop = _edit_transform * _i2d_transform;
Geom::PathVector pv = _spcurve->get_pathvector();
- boost::optional<Geom::PathVectorPosition> pvp
- = Geom::nearestPoint(pv, _desktop->w2d(evp) * to_desktop.inverse());
- if (!pvp) return;
- Geom::Point nearest_point = _desktop->d2w(pv.at(pvp->path_nr).pointAt(pvp->t) * to_desktop);
-
- double fracpart;
+
+ boost::optional<Geom::PathVectorTime> pvp =
+ pv.nearestTime(_desktop->w2d(evp) * to_desktop.inverse());
+ if (!pvp) return dist;
+ Geom::Point nearest_pt = _desktop->d2w(pv.pointAt(*pvp) * to_desktop);
+
+ double fracpart = pvp->t;
std::list<SubpathPtr>::iterator spi = _subpaths.begin();
- for (unsigned i = 0; i < pvp->path_nr; ++i, ++spi) {}
- NodeList::iterator first = (*spi)->before(pvp->t, &fracpart);
+ for (unsigned i = 0; i < pvp->path_index; ++i, ++spi) {}
+ NodeList::iterator first = (*spi)->before(pvp->asPathTime());
+ dist = Geom::distance(evp, nearest_pt);
+
double stroke_tolerance = _getStrokeTolerance();
if (first && first.next() &&
fracpart != 0.0 &&
- Geom::distance(evp, nearest_point) < stroke_tolerance)
+ dist < stroke_tolerance)
{
_dragpoint->setVisible(true);
- _dragpoint->setPosition(_desktop->w2d(nearest_point));
+ _dragpoint->setPosition(_desktop->w2d(nearest_pt));
_dragpoint->setSize(2 * stroke_tolerance);
_dragpoint->setTimeValue(fracpart);
_dragpoint->setIterator(first);
} else {
_dragpoint->setVisible(false);
}
+
+ return dist;
}
/// This is called on zoom change to update the direction arrows
diff --git a/src/ui/tool/path-manipulator.h b/src/ui/tool/path-manipulator.h
index 2219af849..4c6f74ba4 100644
--- a/src/ui/tool/path-manipulator.h
+++ b/src/ui/tool/path-manipulator.h
@@ -70,6 +70,8 @@ public:
void insertNodeAtExtremum(ExtremumType extremum);
void insertNodes();
+ void insertNode(Geom::Point);
+ void insertNode(NodeList::iterator first, double t, bool take_selection);
void duplicateNodes();
void weldNodes(NodeList::iterator preserve_pos = NodeList::iterator());
void weldSegments();
@@ -133,7 +135,7 @@ private:
void _removeNodesFromSelection();
void _commit(Glib::ustring const &annotation);
void _commit(Glib::ustring const &annotation, gchar const *key);
- void _updateDragPoint(Geom::Point const &);
+ Geom::Coord _updateDragPoint(Geom::Point const &);
void _updateOutlineOnZoomChange();
double _getStrokeTolerance();
Handle *_chooseHandle(Node *n, int which);
@@ -143,7 +145,7 @@ private:
SPPath *_path; ///< can be an SPPath or an Inkscape::LivePathEffect::Effect !!!
SPCurve *_spcurve; // in item coordinates
SPCanvasItem *_outline;
- CurveDragPoint *_dragpoint; // an invisible control point hoverng over curve
+ CurveDragPoint *_dragpoint; // an invisible control point hovering over curve
PathManipulatorObserver *_observer;
Geom::Affine _d2i_transform; ///< desktop-to-item transform
Geom::Affine _i2d_transform; ///< item-to-desktop transform, inverse of _d2i_transform
diff --git a/src/ui/tool/selector.cpp b/src/ui/tool/selector.cpp
index e4e701785..051cb41ae 100644
--- a/src/ui/tool/selector.cpp
+++ b/src/ui/tool/selector.cpp
@@ -129,6 +129,10 @@ bool Selector::event(Inkscape::UI::Tools::ToolBase *event_context, GdkEvent *eve
return false;
}
+bool Selector::doubleClicked() {
+ return _dragger->doubleClicked();
+}
+
} // namespace UI
} // namespace Inkscape
diff --git a/src/ui/tool/selector.h b/src/ui/tool/selector.h
index dbe751ede..bd8d3e1aa 100644
--- a/src/ui/tool/selector.h
+++ b/src/ui/tool/selector.h
@@ -29,6 +29,7 @@ public:
Selector(SPDesktop *d);
virtual ~Selector();
virtual bool event(Inkscape::UI::Tools::ToolBase *, GdkEvent *);
+ virtual bool doubleClicked();
sigc::signal<void, Geom::Rect const &, GdkEventButton*> signal_area;
sigc::signal<void, Geom::Point const &, GdkEventButton*> signal_point;
diff --git a/src/ui/tools/box3d-tool.cpp b/src/ui/tools/box3d-tool.cpp
index 538e0c7e2..27e755add 100644
--- a/src/ui/tools/box3d-tool.cpp
+++ b/src/ui/tools/box3d-tool.cpp
@@ -165,7 +165,7 @@ bool Box3dTool::item_handler(SPItem* item, GdkEvent* event) {
case GDK_BUTTON_PRESS:
if ( event->button.button == 1 && !this->space_panning) {
Inkscape::setup_for_drag_start(desktop, this, event);
- ret = TRUE;
+ //ret = TRUE;
}
break;
// motion and release are always on root (why?)
diff --git a/src/ui/tools/calligraphic-tool.cpp b/src/ui/tools/calligraphic-tool.cpp
index 15e6527a3..28195eb75 100644
--- a/src/ui/tools/calligraphic-tool.cpp
+++ b/src/ui/tools/calligraphic-tool.cpp
@@ -140,8 +140,7 @@ void CalligraphicTool::setup() {
{
/* TODO: have a look at DropperTool::setup where the same is done.. generalize? */
- Geom::PathVector path;
- Geom::Circle(0, 0, 1).getPath(path);
+ Geom::PathVector path = Geom::Path(Geom::Circle(0,0,1));
SPCurve *c = new SPCurve(path);
diff --git a/src/ui/tools/connector-tool.cpp b/src/ui/tools/connector-tool.cpp
index c3ef19507..0a36877ff 100644
--- a/src/ui/tools/connector-tool.cpp
+++ b/src/ui/tools/connector-tool.cpp
@@ -1303,12 +1303,12 @@ void cc_selection_set_avoid(bool const set_avoid)
Inkscape::Selection *selection = desktop->getSelection();
- GSList *l = const_cast<GSList *>(selection->itemList());
int changes = 0;
- while (l) {
- SPItem *item = SP_ITEM(l->data);
+ std::vector<SPItem*> l = selection->itemList();
+ for(std::vector<SPItem*>::const_iterator i=l.begin();i!=l.end();i++) {
+ SPItem *item = *i;
char const *value = (set_avoid) ? "true" : NULL;
@@ -1317,8 +1317,6 @@ void cc_selection_set_avoid(bool const set_avoid)
item->avoidRef->handleSettingChange();
changes++;
}
-
- l = l->next;
}
if (changes == 0) {
diff --git a/src/ui/tools/dropper-tool.cpp b/src/ui/tools/dropper-tool.cpp
index bda9d8e8a..c838c27d5 100644
--- a/src/ui/tools/dropper-tool.cpp
+++ b/src/ui/tools/dropper-tool.cpp
@@ -84,8 +84,7 @@ void DropperTool::setup() {
ToolBase::setup();
/* TODO: have a look at CalligraphicTool::setup where the same is done.. generalize? */
- Geom::PathVector path;
- Geom::Circle(0, 0, 1).getPath(path);
+ Geom::PathVector path = Geom::Path(Geom::Circle(0,0,1));
SPCurve *c = new SPCurve(path);
diff --git a/src/ui/tools/eraser-tool.cpp b/src/ui/tools/eraser-tool.cpp
index af0cbcb78..e416fd7ef 100644
--- a/src/ui/tools/eraser-tool.cpp
+++ b/src/ui/tools/eraser-tool.cpp
@@ -666,8 +666,7 @@ void EraserTool::set_to_accumulated() {
Geom::OptRect eraserBbox = acid->visualBounds();
Geom::Rect bounds = (*eraserBbox) * desktop->doc2dt();
std::vector<SPItem*> remainingItems;
- GSList* toWorkOn = 0;
-
+ std::vector<SPItem*> toWorkOn;
if (selection->isEmpty()) {
if ( eraserMode ) {
toWorkOn = desktop->getDocument()->getItemsPartiallyInBox(desktop->dkey, bounds);
@@ -675,17 +674,16 @@ void EraserTool::set_to_accumulated() {
Inkscape::Rubberband *r = Inkscape::Rubberband::get(desktop);
toWorkOn = desktop->getDocument()->getItemsAtPoints(desktop->dkey, r->getPoints());
}
-
- toWorkOn = g_slist_remove( toWorkOn, acid );
+ toWorkOn.erase(std::remove(toWorkOn.begin(), toWorkOn.end(), acid), toWorkOn.end());
} else {
- toWorkOn = g_slist_copy(const_cast<GSList*>(selection->itemList()));
+ toWorkOn= selection->itemList();
wasSelection = true;
}
- if ( g_slist_length(toWorkOn) > 0 ) {
+ if ( !toWorkOn.empty() ) {
if ( eraserMode ) {
- for (GSList *i = toWorkOn ; i ; i = i->next ) {
- SPItem *item = SP_ITEM(i->data);
+ for (std::vector<SPItem*>::const_iterator i = toWorkOn.begin(); i != toWorkOn.end(); i++){
+ SPItem *item = *i;
if ( eraserMode ) {
Geom::OptRect bbox = item->visualBounds();
@@ -702,13 +700,10 @@ void EraserTool::set_to_accumulated() {
if ( !selection->isEmpty() ) {
// If the item was not completely erased, track the new remainder.
- GSList *nowSel = g_slist_copy(const_cast<GSList *>(selection->itemList()));
-
- for (GSList const *i2 = nowSel ; i2 ; i2 = i2->next ) {
- remainingItems.push_back(SP_ITEM(i2->data));
+ std::vector<SPItem*> nowSel(selection->itemList());
+ for (std::vector<SPItem*>::const_iterator i2 = nowSel.begin();i2!=nowSel.end();i2++) {
+ remainingItems.push_back(*i2);
}
-
- g_slist_free(nowSel);
}
} else {
remainingItems.push_back(item);
@@ -716,20 +711,18 @@ void EraserTool::set_to_accumulated() {
}
}
} else {
- for (GSList *i = toWorkOn ; i ; i = i->next ) {
- sp_object_ref( SP_ITEM(i->data), 0 );
+ for (std::vector<SPItem*> ::const_iterator i = toWorkOn.begin();i!=toWorkOn.end();i++) {
+ sp_object_ref( *i, 0 );
}
- for (GSList *i = toWorkOn ; i ; i = i->next ) {
- SPItem *item = SP_ITEM(i->data);
+ for (std::vector<SPItem*>::const_iterator i = toWorkOn.begin();i!=toWorkOn.end();i++) {
+ SPItem *item = *i;
item->deleteObject(true);
sp_object_unref(item);
workDone = true;
}
}
- g_slist_free(toWorkOn);
-
if ( !eraserMode ) {
//sp_selection_delete(desktop);
remainingItems.clear();
@@ -796,6 +789,8 @@ add_cap(SPCurve *curve,
}
void EraserTool::accumulate() {
+ // construct a crude outline of the eraser's path.
+ // this desperately needs to be rewritten to use the path outliner...
if ( !this->cal1->is_empty() && !this->cal2->is_empty() ) {
this->accumulated->reset(); /* Is this required ?? */
SPCurve *rev_cal2 = this->cal2->create_reverse();
@@ -805,10 +800,10 @@ void EraserTool::accumulate() {
g_assert( ! this->cal1->first_path()->closed() );
g_assert( ! rev_cal2->first_path()->closed() );
- Geom::CubicBezier const * dc_cal1_firstseg = dynamic_cast<Geom::CubicBezier const *>( this->cal1->first_segment() );
- Geom::CubicBezier const * rev_cal2_firstseg = dynamic_cast<Geom::CubicBezier const *>( rev_cal2->first_segment() );
- Geom::CubicBezier const * dc_cal1_lastseg = dynamic_cast<Geom::CubicBezier const *>( this->cal1->last_segment() );
- Geom::CubicBezier const * rev_cal2_lastseg = dynamic_cast<Geom::CubicBezier const *>( rev_cal2->last_segment() );
+ Geom::BezierCurve const * dc_cal1_firstseg = dynamic_cast<Geom::BezierCurve const *>( this->cal1->first_segment() );
+ Geom::BezierCurve const * rev_cal2_firstseg = dynamic_cast<Geom::BezierCurve const *>( rev_cal2->first_segment() );
+ Geom::BezierCurve const * dc_cal1_lastseg = dynamic_cast<Geom::BezierCurve const *>( this->cal1->last_segment() );
+ Geom::BezierCurve const * rev_cal2_lastseg = dynamic_cast<Geom::BezierCurve const *>( rev_cal2->last_segment() );
g_assert( dc_cal1_firstseg );
g_assert( rev_cal2_firstseg );
@@ -817,11 +812,21 @@ void EraserTool::accumulate() {
this->accumulated->append(this->cal1, FALSE);
- add_cap(this->accumulated, (*dc_cal1_lastseg)[2], (*dc_cal1_lastseg)[3], (*rev_cal2_firstseg)[0], (*rev_cal2_firstseg)[1], this->cap_rounding);
+ add_cap(this->accumulated,
+ dc_cal1_lastseg->finalPoint() - dc_cal1_lastseg->unitTangentAt(1),
+ dc_cal1_lastseg->finalPoint(),
+ rev_cal2_firstseg->initialPoint(),
+ rev_cal2_firstseg->initialPoint() + rev_cal2_firstseg->unitTangentAt(0),
+ this->cap_rounding);
this->accumulated->append(rev_cal2, TRUE);
- add_cap(this->accumulated, (*rev_cal2_lastseg)[2], (*rev_cal2_lastseg)[3], (*dc_cal1_firstseg)[0], (*dc_cal1_firstseg)[1], this->cap_rounding);
+ add_cap(this->accumulated,
+ rev_cal2_lastseg->finalPoint() - rev_cal2_lastseg->unitTangentAt(1),
+ rev_cal2_lastseg->finalPoint(),
+ dc_cal1_firstseg->initialPoint(),
+ dc_cal1_firstseg->initialPoint() + dc_cal1_firstseg->unitTangentAt(0),
+ this->cap_rounding);
this->accumulated->closepath();
diff --git a/src/ui/tools/flood-tool.cpp b/src/ui/tools/flood-tool.cpp
index ffd41d97d..748c82717 100644
--- a/src/ui/tools/flood-tool.cpp
+++ b/src/ui/tools/flood-tool.cpp
@@ -932,7 +932,7 @@ static void sp_flood_do_flood_fill(ToolBase *event_context, GdkEvent *event, boo
std::deque<Geom::Point>::iterator start_sort = fill_queue.begin();
std::deque<Geom::Point>::iterator end_sort = fill_queue.begin();
unsigned int sort_y = (unsigned int)cp[Geom::Y];
- unsigned int current_y = sort_y;
+ unsigned int current_y;
for (std::deque<Geom::Point>::iterator i = fill_queue.begin(); i != fill_queue.end(); ++i) {
Geom::Point current = *i;
diff --git a/src/ui/tools/gradient-tool.cpp b/src/ui/tools/gradient-tool.cpp
index b27859ebb..603458983 100644
--- a/src/ui/tools/gradient-tool.cpp
+++ b/src/ui/tools/gradient-tool.cpp
@@ -106,7 +106,7 @@ void GradientTool::selection_changed(Inkscape::Selection*) {
if (selection == NULL) {
return;
}
- guint n_obj = g_slist_length((GSList *) selection->itemList());
+ guint n_obj = selection->itemList().size();
if (!drag->isNonEmpty() || selection->isEmpty())
return;
@@ -207,7 +207,7 @@ sp_gradient_context_is_over_line (GradientTool *rc, SPItem *item, Geom::Point ev
SPCtrlLine* line = SP_CTRLLINE(item);
Geom::LineSegment ls(line->s, line->e);
- Geom::Point nearest = ls.pointAt(ls.nearestPoint(rc->mousepoint_doc));
+ Geom::Point nearest = ls.pointAt(ls.nearestTime(rc->mousepoint_doc));
double dist_screen = Geom::L2 (rc->mousepoint_doc - nearest) * desktop->current_zoom();
double tolerance = (double) SP_EVENT_CONTEXT(rc)->tolerance;
@@ -492,10 +492,11 @@ bool GradientTool::root_handler(GdkEvent* event) {
if (over_line) {
// we take the first item in selection, because with doubleclick, the first click
// always resets selection to the single object under cursor
- sp_gradient_context_add_stop_near_point(this, SP_ITEM(selection->itemList()->data), this->mousepoint_doc, event->button.time);
+ sp_gradient_context_add_stop_near_point(this, SP_ITEM(selection->itemList().front()), this->mousepoint_doc, event->button.time);
} else {
- for (GSList const* i = selection->itemList(); i != NULL; i = i->next) {
- SPItem *item = SP_ITEM(i->data);
+ std::vector<SPItem*> items=selection->itemList();
+ for (std::vector<SPItem*>::const_iterator i = items.begin();i!=items.end();i++) {
+ SPItem *item = *i;
SPGradientType new_type = (SPGradientType) prefs->getInt("/tools/gradient/newgradient", SP_GRADIENT_TYPE_LINEAR);
Inkscape::PaintTarget fsmode = (prefs->getInt("/tools/gradient/newfillorstroke", 1) != 0) ? Inkscape::FOR_FILL : Inkscape::FOR_STROKE;
@@ -898,32 +899,32 @@ static void sp_gradient_drag(GradientTool &rc, Geom::Point const pt, guint /*sta
} else {
// Starting from empty space:
// Sort items so that the topmost comes last
- GSList *items = g_slist_copy ((GSList *) selection->itemList());
- items = g_slist_sort(items, (GCompareFunc) sp_item_repr_compare_position);
+ std::vector<SPItem*> items(selection->itemList());
+ sort(items.begin(),items.end(),sp_item_repr_compare_position);
// take topmost
- vector = sp_gradient_vector_for_object(document, desktop, SP_ITEM(g_slist_last(items)->data), fill_or_stroke);
- g_slist_free (items);
+ vector = sp_gradient_vector_for_object(document, desktop, SP_ITEM(items.back()), fill_or_stroke);
}
// HACK: reset fill-opacity - that 0.75 is annoying; BUT remove this when we have an opacity slider for all tabs
SPCSSAttr *css = sp_repr_css_attr_new();
sp_repr_css_set_property(css, "fill-opacity", "1.0");
- for (GSList const *i = selection->itemList(); i != NULL; i = i->next) {
+ std::vector<SPItem*> itemlist = selection->itemList();
+ for (std::vector<SPItem*>::const_iterator i = itemlist.begin();i!=itemlist.end();i++) {
//FIXME: see above
- sp_repr_css_change_recursive(SP_OBJECT(i->data)->getRepr(), css, "style");
+ sp_repr_css_change_recursive((*i)->getRepr(), css, "style");
- sp_item_set_gradient(SP_ITEM(i->data), vector, (SPGradientType) type, fill_or_stroke);
+ sp_item_set_gradient(*i, vector, (SPGradientType) type, fill_or_stroke);
if (type == SP_GRADIENT_TYPE_LINEAR) {
- sp_item_gradient_set_coords (SP_ITEM(i->data), POINT_LG_BEGIN, 0, rc.origin, fill_or_stroke, true, false);
- sp_item_gradient_set_coords (SP_ITEM(i->data), POINT_LG_END, 0, pt, fill_or_stroke, true, false);
+ sp_item_gradient_set_coords (*i, POINT_LG_BEGIN, 0, rc.origin, fill_or_stroke, true, false);
+ sp_item_gradient_set_coords (*i, POINT_LG_END, 0, pt, fill_or_stroke, true, false);
} else if (type == SP_GRADIENT_TYPE_RADIAL) {
- sp_item_gradient_set_coords (SP_ITEM(i->data), POINT_RG_CENTER, 0, rc.origin, fill_or_stroke, true, false);
- sp_item_gradient_set_coords (SP_ITEM(i->data), POINT_RG_R1, 0, pt, fill_or_stroke, true, false);
+ sp_item_gradient_set_coords (*i, POINT_RG_CENTER, 0, rc.origin, fill_or_stroke, true, false);
+ sp_item_gradient_set_coords (*i, POINT_RG_R1, 0, pt, fill_or_stroke, true, false);
}
- SP_OBJECT(i->data)->requestModified(SP_OBJECT_MODIFIED_FLAG);
+ (*i)->requestModified(SP_OBJECT_MODIFIED_FLAG);
}
if (ec->_grdrag) {
ec->_grdrag->updateDraggers();
@@ -932,7 +933,7 @@ static void sp_gradient_drag(GradientTool &rc, Geom::Point const pt, guint /*sta
ec->_grdrag->local_change = true;
// give the grab out-of-bounds values of xp/yp because we're already dragging
// and therefore are already out of tolerance
- ec->_grdrag->grabKnot (SP_ITEM(selection->itemList()->data),
+ ec->_grdrag->grabKnot (selection->itemList()[0],
type == SP_GRADIENT_TYPE_LINEAR? POINT_LG_END : POINT_RG_R1,
-1, // ignore number (though it is always 1)
fill_or_stroke, 99999, 99999, etime);
@@ -941,7 +942,7 @@ static void sp_gradient_drag(GradientTool &rc, Geom::Point const pt, guint /*sta
// status text; we do not track coords because this branch is run once, not all the time
// during drag
- int n_objects = g_slist_length((GSList *) selection->itemList());
+ int n_objects = selection->itemList().size();
rc.message_context->setF(Inkscape::NORMAL_MESSAGE,
ngettext("<b>Gradient</b> for %d object; with <b>Ctrl</b> to snap angle",
"<b>Gradient</b> for %d objects; with <b>Ctrl</b> to snap angle", n_objects),
diff --git a/src/ui/tools/lpe-tool.cpp b/src/ui/tools/lpe-tool.cpp
index c0517578d..13e47f3a6 100644
--- a/src/ui/tools/lpe-tool.cpp
+++ b/src/ui/tools/lpe-tool.cpp
@@ -396,10 +396,10 @@ lpetool_create_measuring_items(LpeTool *lc, Inkscape::Selection *selection)
SPCanvasGroup *tmpgrp = lc->desktop->getTempGroup();
gchar *arc_length;
double lengthval;
-
- for (GSList const *i = selection->itemList(); i != NULL; i = i->next) {
- if (SP_IS_PATH(i->data)) {
- path = SP_PATH(i->data);
+ std::vector<SPItem*> items=selection->itemList();
+ for(std::vector<SPItem*>::const_iterator i=items.begin();i!=items.end();i++){
+ if (SP_IS_PATH(*i)) {
+ path = SP_PATH(*i);
curve = path->getCurve();
Geom::Piecewise<Geom::D2<Geom::SBasis> > pwd2 = paths_to_pw(curve->get_pathvector());
canvas_text = (SPCanvasText *) sp_canvastext_new(tmpgrp, lc->desktop, Geom::Point(0,0), "");
diff --git a/src/ui/tools/measure-tool.cpp b/src/ui/tools/measure-tool.cpp
index 0875c29e0..570f3e796 100644
--- a/src/ui/tools/measure-tool.cpp
+++ b/src/ui/tools/measure-tool.cpp
@@ -431,10 +431,10 @@ bool MeasureTool::root_handler(GdkEvent* event) {
// TODO switch to a different variable name. The single letter 'l' is easy to misread.
//select elements crossed by line segment:
- GSList *items = desktop->getDocument()->getItemsAtPoints(desktop->dkey, points);
+ std::vector<SPItem*> items = desktop->getDocument()->getItemsAtPoints(desktop->dkey, points);
std::vector<double> intersection_times;
- for (GSList *l = items; l != NULL; l = l->next) {
- SPItem *item = static_cast<SPItem*>(l->data);
+ for (std::vector<SPItem*>::const_iterator i=items.begin();i!=items.end();i++) {
+ SPItem *item = *i;
if (SP_IS_SHAPE(item)) {
calculate_intersections(desktop, item, lineseg, SP_SHAPE(item)->getCurve(), intersection_times);
diff --git a/src/ui/tools/mesh-tool.cpp b/src/ui/tools/mesh-tool.cpp
index 67ed7aef1..813d6ae5b 100644
--- a/src/ui/tools/mesh-tool.cpp
+++ b/src/ui/tools/mesh-tool.cpp
@@ -103,7 +103,7 @@ void MeshTool::selection_changed(Inkscape::Selection* /*sel*/) {
return;
}
- guint n_obj = g_slist_length((GSList *) selection->itemList());
+ guint n_obj = selection->itemList().size();
if (!drag->isNonEmpty() || selection->isEmpty()) {
return;
@@ -275,7 +275,7 @@ sp_mesh_context_is_over_line (MeshTool *rc, SPItem *item, Geom::Point event_p)
SPCtrlCurve *curve = SP_CTRLCURVE(item);
Geom::BezierCurveN<3> b( curve->p0, curve->p1, curve->p2, curve->p3 );
- Geom::Coord coord = b.nearestPoint( rc->mousepoint_doc ); // Coord == double
+ Geom::Coord coord = b.nearestTime( rc->mousepoint_doc ); // Coord == double
Geom::Point nearest = b( coord );
double dist_screen = Geom::L2 (rc->mousepoint_doc - nearest) * desktop->current_zoom();
@@ -467,11 +467,12 @@ bool MeshTool::root_handler(GdkEvent* event) {
if (over_line) {
// We take the first item in selection, because with doubleclick, the first click
// always resets selection to the single object under cursor
- sp_mesh_context_split_near_point(this, SP_ITEM(selection->itemList()->data), this->mousepoint_doc, event->button.time);
+ sp_mesh_context_split_near_point(this, selection->itemList()[0], this->mousepoint_doc, event->button.time);
} else {
// Create a new gradient with default coordinates.
- for (GSList const* i = selection->itemList(); i != NULL; i = i->next) {
- SPItem *item = SP_ITEM(i->data);
+ std::vector<SPItem*> items=selection->itemList();
+ for(std::vector<SPItem*>::const_iterator i=items.begin();i!=items.end();i++){
+ SPItem *item = *i;
SPGradientType new_type = SP_GRADIENT_TYPE_MESH;
Inkscape::PaintTarget fsmode = (prefs->getInt("/tools/gradient/newfillorstroke", 1) != 0) ? Inkscape::FOR_FILL : Inkscape::FOR_STROKE;
@@ -940,27 +941,27 @@ static void sp_mesh_drag(MeshTool &rc, Geom::Point const /*pt*/, guint /*state*/
} else {
// Starting from empty space:
// Sort items so that the topmost comes last
- GSList *items = g_slist_copy ((GSList *) selection->itemList());
- items = g_slist_sort(items, (GCompareFunc) sp_item_repr_compare_position);
+ std::vector<SPItem*> items(selection->itemList());
+ sort(items.begin(),items.end(),sp_item_repr_compare_position);
// take topmost
- vector = sp_gradient_vector_for_object(document, desktop, SP_ITEM(g_slist_last(items)->data), fill_or_stroke);
- g_slist_free (items);
+ vector = sp_gradient_vector_for_object(document, desktop, SP_ITEM(items.back()), fill_or_stroke);
}
// HACK: reset fill-opacity - that 0.75 is annoying; BUT remove this when we have an opacity slider for all tabs
SPCSSAttr *css = sp_repr_css_attr_new();
sp_repr_css_set_property(css, "fill-opacity", "1.0");
- for (GSList const *i = selection->itemList(); i != NULL; i = i->next) {
+ std::vector<SPItem*> items=selection->itemList();
+ for(std::vector<SPItem*>::const_iterator i=items.begin();i!=items.end();i++){
//FIXME: see above
- sp_repr_css_change_recursive(SP_OBJECT(i->data)->getRepr(), css, "style");
+ sp_repr_css_change_recursive((*i)->getRepr(), css, "style");
- sp_item_set_gradient(SP_ITEM(i->data), vector, (SPGradientType) type, fill_or_stroke);
+ sp_item_set_gradient(*i, vector, (SPGradientType) type, fill_or_stroke);
// We don't need to do anything. Mesh is already sized appropriately.
- SP_OBJECT(i->data)->requestModified(SP_OBJECT_MODIFIED_FLAG);
+ (*i)->requestModified(SP_OBJECT_MODIFIED_FLAG);
}
// if (ec->_grdrag) {
// ec->_grdrag->updateDraggers();
@@ -978,7 +979,7 @@ static void sp_mesh_drag(MeshTool &rc, Geom::Point const /*pt*/, guint /*state*/
// status text; we do not track coords because this branch is run once, not all the time
// during drag
- int n_objects = g_slist_length((GSList *) selection->itemList());
+ int n_objects = selection->itemList().size();
rc.message_context->setF(Inkscape::NORMAL_MESSAGE,
ngettext("<b>Gradient</b> for %d object; with <b>Ctrl</b> to snap angle",
"<b>Gradient</b> for %d objects; with <b>Ctrl</b> to snap angle", n_objects),
diff --git a/src/ui/tools/node-tool.cpp b/src/ui/tools/node-tool.cpp
index a4b903960..6a6ca0b26 100644
--- a/src/ui/tools/node-tool.cpp
+++ b/src/ui/tools/node-tool.cpp
@@ -26,6 +26,8 @@
#include "ui/shape-editor.h" // temporary!
#include "live_effects/effect.h"
#include "display/curve.h"
+#include "snap.h"
+#include "sp-namedview.h"
#include "sp-clippath.h"
#include "sp-item-group.h"
#include "sp-mask.h"
@@ -112,7 +114,7 @@ namespace UI {
namespace Tools {
const std::string& NodeTool::getPrefsPath() {
- return NodeTool::prefsPath;
+ return NodeTool::prefsPath;
}
const std::string NodeTool::prefsPath = "/tools/nodes";
@@ -216,7 +218,7 @@ void NodeTool::setup() {
Inkscape::UI::ControlPoint::signal_mouseover_change.connect(sigc::mem_fun(this, &NodeTool::mouseover_changed));
this->_sizeUpdatedConn = ControlManager::getManager().connectCtrlSizeChanged(
- sigc::mem_fun(this, &NodeTool::handleControlUiStyleChange)
+ sigc::mem_fun(this, &NodeTool::handleControlUiStyleChange)
);
this->_selected_nodes = new Inkscape::UI::ControlPointSelection(this->desktop, this->_transform_handle_group);
@@ -236,14 +238,14 @@ void NodeTool::setup() {
);
this->_selected_nodes->signal_selection_changed.connect(
- // Hide both signal parameters and bind the function parameter to 0
- // sigc::signal<void, SelectableControlPoint *, bool>
- // <=>
- // void update_tip(GdkEvent *event)
- sigc::hide(sigc::hide(sigc::bind(
- sigc::mem_fun(this, &NodeTool::update_tip),
- (GdkEvent*)NULL
- )))
+ // Hide both signal parameters and bind the function parameter to 0
+ // sigc::signal<void, SelectableControlPoint *, bool>
+ // <=>
+ // void update_tip(GdkEvent *event)
+ sigc::hide(sigc::hide(sigc::bind(
+ sigc::mem_fun(this, &NodeTool::update_tip),
+ (GdkEvent*)NULL
+ )))
);
this->helperpath_tmpitem = NULL;
@@ -359,7 +361,7 @@ void NodeTool::set(const Inkscape::Preferences::Entry& value) {
this->edit_masks = value.getBool();
this->selection_changed(this->desktop->selection);
} else {
- ToolBase::set(value);
+ ToolBase::set(value);
}
}
@@ -370,7 +372,7 @@ void gather_items(NodeTool *nt, SPItem *base, SPObject *obj, Inkscape::UI::Shape
using namespace Inkscape::UI;
if (!obj) {
- return;
+ return;
}
//XML Tree being used directly here while it shouldn't be.
@@ -410,10 +412,9 @@ void NodeTool::selection_changed(Inkscape::Selection *sel) {
std::set<ShapeRecord> shapes;
- GSList const *ilist = sel->itemList();
-
- for (GSList *i = const_cast<GSList*>(ilist); i; i = i->next) {
- SPObject *obj = static_cast<SPObject*>(i->data);
+ std::vector<SPItem*> items=sel->itemList();
+ for(std::vector<SPItem*>::const_iterator i=items.begin();i!=items.end();i++){
+ SPObject *obj = *i;
if (SP_IS_ITEM(obj)) {
gather_items(this, NULL, static_cast<SPItem*>(obj), SHAPE_ROLE_NORMAL, shapes);
@@ -447,6 +448,9 @@ void NodeTool::selection_changed(Inkscape::Selection *sel) {
}
}
+ _previous_selection = _current_selection;
+ _current_selection = sel->itemList();
+
this->_multipath->setItems(shapes);
this->update_tip(NULL);
this->desktop->updateNow();
@@ -459,31 +463,47 @@ bool NodeTool::root_handler(GdkEvent* event) {
* 3. some keybindings
*/
using namespace Inkscape::UI; // pull in event helpers
-
+
Inkscape::Selection *selection = desktop->selection;
static Inkscape::Preferences *prefs = Inkscape::Preferences::get();
if (this->_multipath->event(this, event)) {
- return true;
+ return true;
}
if (this->_selector->event(this, event)) {
- return true;
+ return true;
}
if (this->_selected_nodes->event(this, event)) {
- return true;
+ return true;
}
switch (event->type)
{
case GDK_MOTION_NOTIFY: {
- this->update_helperpath();
+ this->update_helperpath();
combine_motion_events(desktop->canvas, event->motion, 0);
this->update_helperpath();
SPItem *over_item = sp_event_context_find_item (desktop, event_point(event->button),
FALSE, TRUE);
+ Geom::Point const motion_w(event->motion.x, event->motion.y);
+ Geom::Point const motion_dt(this->desktop->w2d(motion_w));
+
+ SnapManager &m = this->desktop->namedview->snap_manager;
+
+ // We will show a pre-snap indication for when the user adds a node through double-clicking
+ // Adding a node will only work when a path has been selected; if that's not the case then snapping is useless
+ if (not this->desktop->selection->isEmpty()) {
+ if (!(event->motion.state & GDK_SHIFT_MASK)) {
+ m.setup(this->desktop);
+ Inkscape::SnapCandidatePoint scp(motion_dt, Inkscape::SNAPSOURCE_OTHER_HANDLE);
+ m.preSnap(scp, true);
+ m.unSetup();
+ }
+ }
+
if (over_item != this->_last_over) {
this->_last_over = over_item;
//ink_node_tool_update_tip(nt, event);
@@ -492,11 +512,11 @@ bool NodeTool::root_handler(GdkEvent* event) {
// create pathflash outline
if (prefs->getBool("/tools/nodes/pathflash_enabled")) {
if (over_item == this->flashed_item) {
- break;
+ break;
}
if (!prefs->getBool("/tools/nodes/pathflash_selected") && selection->includes(over_item)) {
- break;
+ break;
}
if (this->flash_tempitem) {
@@ -506,14 +526,14 @@ bool NodeTool::root_handler(GdkEvent* event) {
}
if (!SP_IS_SHAPE(over_item)) {
- break; // for now, handle only shapes
+ break; // for now, handle only shapes
}
this->flashed_item = over_item;
SPCurve *c = SP_SHAPE(over_item)->getCurveBeforeLPE();
if (!c) {
- break; // break out when curve doesn't exist
+ break; // break out when curve doesn't exist
}
c->transform(over_item->i2dt_affine());
@@ -576,11 +596,42 @@ bool NodeTool::root_handler(GdkEvent* event) {
case GDK_KEY_RELEASE:
//ink_node_tool_update_tip(nt, event);
- this->update_tip(event);
+ this->update_tip(event);
+ break;
+
+ case GDK_BUTTON_RELEASE:
+ if (this->_selector->doubleClicked()) {
+ // If the selector received the doubleclick event, then we're at some distance from
+ // the path; otherwise, the doubleclick event would have been received by
+ // CurveDragPoint; we will insert nodes into the path anyway but only if we can snap
+ // to the path. Otherwise the position would not be very well defined.
+ if (!(event->motion.state & GDK_SHIFT_MASK)) {
+ Geom::Point const motion_w(event->motion.x, event->motion.y);
+ Geom::Point const motion_dt(this->desktop->w2d(motion_w));
+
+ SnapManager &m = this->desktop->namedview->snap_manager;
+ m.setup(this->desktop);
+ Inkscape::SnapCandidatePoint scp(motion_dt, Inkscape::SNAPSOURCE_OTHER_HANDLE);
+ Inkscape::SnappedPoint sp = m.freeSnap(scp, Geom::OptRect(), true);
+ m.unSetup();
+
+ if (sp.getSnapped()) {
+ // The first click of the double click will have cleared the path selection, because
+ // we clicked aside of the path. We need to undo this on double click
+ Inkscape::Selection *selection = desktop->getSelection();
+ selection->addList(_previous_selection);
+
+ // The selection has been restored, and the signal selection_changed has been emitted,
+ // which has again forced a restore of the _mmap variable of the MultiPathManipulator (this->_multipath)
+ // Now we can insert the new nodes as if nothing has happened!
+ this->_multipath->insertNode(this->desktop->d2w(sp.getPoint()));
+ }
+ }
+ }
break;
default:
- break;
+ break;
}
return ToolBase::root_handler(event);
@@ -593,7 +644,7 @@ void NodeTool::update_tip(GdkEvent *event) {
unsigned new_state = state_after_event(event);
if (new_state == event->key.state) {
- return;
+ return;
}
if (state_held_shift(new_state)) {
@@ -614,9 +665,27 @@ void NodeTool::update_tip(GdkEvent *event) {
unsigned total = this->_selected_nodes->allPoints().size();
if (sz != 0) {
- char *nodestring = g_strdup_printf(
- ngettext("<b>%u of %u</b> node selected.", "<b>%u of %u</b> nodes selected.", total),
- sz, total);
+ char *nodestring;
+ if (sz == 2) {
+ // if there are only two nodes selected, display the angle
+ // of a line going through them relative to the X axis.
+ Inkscape::UI::ControlPointSelection::Set &selection_nodes = this->_selected_nodes->allPoints();
+ std::vector<Geom::Point> positions;
+ for (Inkscape::UI::ControlPointSelection::Set::iterator i = selection_nodes.begin(); i != selection_nodes.end(); ++i) {
+ if ((*i)->selected()) {
+ Inkscape::UI::Node *n = dynamic_cast<Inkscape::UI::Node *>(*i);
+ positions.push_back(n->position());
+ }
+ }
+ g_assert(positions.size() == 2);
+ const double angle = Geom::rad_to_deg(Geom::Line(positions[0], positions[1]).angle());
+ nodestring = g_strdup_printf("<b>%u of %u</b> nodes selected, angle: %.2f°.", sz, total, angle);
+ }
+ else {
+ nodestring = g_strdup_printf(
+ ngettext("<b>%u of %u</b> node selected.", "<b>%u of %u</b> nodes selected.", total),
+ sz, total);
+ }
if (this->_last_over) {
// TRANSLATORS: The %s below is where the "%u of %u nodes selected" sentence gets put
@@ -658,12 +727,11 @@ void NodeTool::select_area(Geom::Rect const &sel, GdkEventButton *event) {
if (this->_multipath->empty()) {
// if multipath is empty, select rubberbanded items rather than nodes
Inkscape::Selection *selection = this->desktop->selection;
- GSList *items = this->desktop->getDocument()->getItemsInBox(this->desktop->dkey, sel);
+ std::vector<SPItem*> items = this->desktop->getDocument()->getItemsInBox(this->desktop->dkey, sel);
selection->setList(items);
- g_slist_free(items);
} else {
if (!held_shift(*event)) {
- this->_selected_nodes->clear();
+ this->_selected_nodes->clear();
}
this->_selected_nodes->selectArea(sel);
@@ -674,11 +742,11 @@ void NodeTool::select_point(Geom::Point const &/*sel*/, GdkEventButton *event) {
using namespace Inkscape::UI; // pull in event helpers
if (!event) {
- return;
+ return;
}
if (event->button != 1) {
- return;
+ return;
}
Inkscape::Selection *selection = this->desktop->selection;
diff --git a/src/ui/tools/node-tool.h b/src/ui/tools/node-tool.h
index 20375e869..8342d66a6 100644
--- a/src/ui/tools/node-tool.h
+++ b/src/ui/tools/node-tool.h
@@ -19,18 +19,18 @@
#include "selection.h"
namespace Inkscape {
- namespace Display {
- class TemporaryItem;
- }
-
- namespace UI {
- class MultiPathManipulator;
- class ControlPointSelection;
- class Selector;
- class ControlPoint;
-
- struct PathSharedData;
- }
+ namespace Display {
+ class TemporaryItem;
+ }
+
+ namespace UI {
+ class MultiPathManipulator;
+ class ControlPointSelection;
+ class Selector;
+ class ControlPoint;
+
+ struct PathSharedData;
+ }
}
struct SPCanvasGroup;
@@ -44,26 +44,26 @@ namespace Tools {
class NodeTool : public ToolBase {
public:
- NodeTool();
- virtual ~NodeTool();
+ NodeTool();
+ virtual ~NodeTool();
- Inkscape::UI::ControlPointSelection* _selected_nodes;
+ Inkscape::UI::ControlPointSelection* _selected_nodes;
Inkscape::UI::MultiPathManipulator* _multipath;
bool edit_clipping_paths;
bool edit_masks;
- static const std::string prefsPath;
+ static const std::string prefsPath;
- virtual void setup();
- virtual void update_helperpath();
- virtual void set(const Inkscape::Preferences::Entry& val);
- virtual bool root_handler(GdkEvent* event);
+ virtual void setup();
+ virtual void update_helperpath();
+ virtual void set(const Inkscape::Preferences::Entry& val);
+ virtual bool root_handler(GdkEvent* event);
- virtual const std::string& getPrefsPath();
+ virtual const std::string& getPrefsPath();
private:
- sigc::connection _selection_changed_connection;
+ sigc::connection _selection_changed_connection;
sigc::connection _mouseover_changed_connection;
sigc::connection _sizeUpdatedConn;
@@ -85,13 +85,16 @@ private:
bool show_transform_handles;
bool single_node_transform_handles;
- void selection_changed(Inkscape::Selection *sel);
+ std::vector<SPItem*> _current_selection;
+ std::vector<SPItem*> _previous_selection;
- void select_area(Geom::Rect const &sel, GdkEventButton *event);
- void select_point(Geom::Point const &sel, GdkEventButton *event);
- void mouseover_changed(Inkscape::UI::ControlPoint *p);
- void update_tip(GdkEvent *event);
- void handleControlUiStyleChange();
+ void selection_changed(Inkscape::Selection *sel);
+
+ void select_area(Geom::Rect const &sel, GdkEventButton *event);
+ void select_point(Geom::Point const &sel, GdkEventButton *event);
+ void mouseover_changed(Inkscape::UI::ControlPoint *p);
+ void update_tip(GdkEvent *event);
+ void handleControlUiStyleChange();
};
}
diff --git a/src/ui/tools/pen-tool.cpp b/src/ui/tools/pen-tool.cpp
index daffc7032..827dbf5c3 100644
--- a/src/ui/tools/pen-tool.cpp
+++ b/src/ui/tools/pen-tool.cpp
@@ -57,8 +57,7 @@
#include <typeinfo>
#include <2geom/pathvector.h>
#include <2geom/affine.h>
-#include <2geom/bezier-curve.h>
-#include <2geom/hvlinesegment.h>
+#include <2geom/curves.h>
#include "helper/geom-nodetype.h"
#include "helper/geom-curves.h"
@@ -71,7 +70,7 @@
#define INKSCAPE_LPE_BSPLINE_C
#include "live_effects/lpe-bspline.h"
-#include <2geom/nearest-point.h>
+#include <2geom/nearest-time.h>
#include "live_effects/effect.h"
@@ -762,14 +761,12 @@ bool PenTool::_handleButtonRelease(GdkEventButton const &revent) {
}
}
this->state = PenTool::CONTROL;
- ret = true;
break;
case PenTool::CONTROL:
// End current segment
this->_endpointSnap(p, revent.state);
this->_finishSegment(p, revent.state);
this->state = PenTool::POINT;
- ret = true;
break;
case PenTool::CLOSE:
// End current segment
@@ -783,12 +780,10 @@ bool PenTool::_handleButtonRelease(GdkEventButton const &revent) {
}
this->_finish(true);
this->state = PenTool::POINT;
- ret = true;
break;
case PenTool::STOP:
// This is allowed, if we just canceled curve
this->state = PenTool::POINT;
- ret = true;
break;
default:
break;
@@ -823,7 +818,6 @@ bool PenTool::_handleButtonRelease(GdkEventButton const &revent) {
break;
}
this->state = PenTool::POINT;
- ret = true;
break;
default:
break;
@@ -1357,8 +1351,9 @@ void PenTool::_bsplineSpiroColor()
void PenTool::_bsplineSpiro(bool shift)
{
- if(!this->spiro && !this->bspline)
+ if(!this->spiro && !this->bspline){
return;
+ }
shift?this->_bsplineSpiroOff():this->_bsplineSpiroOn();
this->_bsplineSpiroBuild();
@@ -1419,21 +1414,26 @@ void PenTool::_bsplineSpiroStartAnchor(bool shift)
}else{
this->spiro = false;
}
- if(!this->spiro && !this->bspline)
+ if(!this->spiro && !this->bspline){
+ SPCurve *tmp_curve = this->sa->curve->copy();
+ if (this->sa->start) {
+ tmp_curve = tmp_curve ->create_reverse();
+ }
+ this->overwrite_curve = tmp_curve ;
return;
-
- if(shift)
+ }
+ if(shift){
this->_bsplineSpiroStartAnchorOff();
- else
+ } else {
this->_bsplineSpiroStartAnchorOn();
+ }
}
void PenTool::_bsplineSpiroStartAnchorOn()
{
using Geom::X;
using Geom::Y;
- SPCurve *tmp_curve = new SPCurve();
- tmp_curve = this->sa->curve->copy();
+ SPCurve *tmp_curve = this->sa->curve->copy();
if(this->sa->start)
tmp_curve = tmp_curve ->create_reverse();
Geom::CubicBezier const * cubic = dynamic_cast<Geom::CubicBezier const*>(&*tmp_curve ->last_segment());
@@ -1465,8 +1465,7 @@ void PenTool::_bsplineSpiroStartAnchorOn()
void PenTool::_bsplineSpiroStartAnchorOff()
{
- SPCurve *tmp_curve = new SPCurve();
- tmp_curve = this->sa->curve->copy();
+ SPCurve *tmp_curve = this->sa->curve->copy();
if(this->sa->start)
tmp_curve = tmp_curve ->create_reverse();
Geom::CubicBezier const * cubic = dynamic_cast<Geom::CubicBezier const*>(&*tmp_curve ->last_segment());
@@ -1490,9 +1489,9 @@ void PenTool::_bsplineSpiroStartAnchorOff()
}
void PenTool::_bsplineSpiroMotion(bool shift){
- if(!this->spiro && !this->bspline)
+ if(!this->spiro && !this->bspline){
return;
-
+ }
using Geom::X;
using Geom::Y;
if(this->red_curve->is_empty()) return;
@@ -1522,7 +1521,7 @@ void PenTool::_bsplineSpiroMotion(bool shift){
Geom::D2< Geom::SBasis > SBasisweight_power;
weight_power->moveto(tmp_curve ->last_segment()->finalPoint());
weight_power->lineto(tmp_curve ->last_segment()->initialPoint());
- float WP = Geom::nearest_point((*cubic)[2],*weight_power->first_segment());
+ float WP = Geom::nearest_time((*cubic)[2],*weight_power->first_segment());
weight_power->reset();
weight_power->moveto(this->red_curve->last_segment()->initialPoint());
weight_power->lineto(this->red_curve->last_segment()->finalPoint());
@@ -1564,7 +1563,7 @@ void PenTool::_bsplineSpiroEndAnchorOn()
using Geom::Y;
this->p[2] = this->p[3] + (1./3)*(this->p[0] - this->p[3]);
this->p[2] = Geom::Point(this->p[2][X] + HANDLE_CUBIC_GAP,this->p[2][Y] + HANDLE_CUBIC_GAP);
- SPCurve *tmp_curve = new SPCurve();
+ SPCurve *tmp_curve;
SPCurve *last_segment = new SPCurve();
Geom::Point point_c(0,0);
bool reverse = false;
@@ -1621,7 +1620,7 @@ void PenTool::_bsplineSpiroEndAnchorOn()
void PenTool::_bsplineSpiroEndAnchorOff()
{
- SPCurve *tmp_curve = new SPCurve();
+ SPCurve *tmp_curve;
SPCurve *last_segment = new SPCurve();
bool reverse = false;
this->p[2] = this->p[3];
@@ -1744,7 +1743,7 @@ void PenTool::_bsplineSpiroBuild()
//from LPE BSPLINE:
void PenTool::_bsplineDoEffect(SPCurve * curve)
{
- const double NO_POWER = 0.0;
+ //const double NO_POWER = 0.0;
const double DEFAULT_START_POWER = 0.3334;
const double DEFAULT_END_POWER = 0.6667;
if (curve->get_segment_count() < 1) {
@@ -1798,12 +1797,12 @@ void PenTool::_bsplineDoEffect(SPCurve * curve)
if(are_near((*cubic)[1],(*cubic)[0]) && !are_near((*cubic)[2],(*cubic)[3])) {
point_at1 = sbasis_in.valueAt(DEFAULT_START_POWER);
} else {
- point_at1 = sbasis_in.valueAt(Geom::nearest_point((*cubic)[1], *in->first_segment()));
+ point_at1 = sbasis_in.valueAt(Geom::nearest_time((*cubic)[1], *in->first_segment()));
}
if(are_near((*cubic)[2],(*cubic)[3]) && !are_near((*cubic)[1],(*cubic)[0])) {
point_at2 = sbasis_in.valueAt(DEFAULT_END_POWER);
} else {
- point_at2 = sbasis_in.valueAt(Geom::nearest_point((*cubic)[2], *in->first_segment()));
+ point_at2 = sbasis_in.valueAt(Geom::nearest_time((*cubic)[2], *in->first_segment()));
}
} else {
point_at1 = in->first_segment()->initialPoint();
@@ -1821,7 +1820,7 @@ void PenTool::_bsplineDoEffect(SPCurve * curve)
if(are_near((*cubic)[1],(*cubic)[0]) && !are_near((*cubic)[2],(*cubic)[3])) {
next_point_at1 = sbasis_in.valueAt(DEFAULT_START_POWER);
} else {
- next_point_at1 = sbasis_out.valueAt(Geom::nearest_point((*cubic)[1], *out->first_segment()));
+ next_point_at1 = sbasis_out.valueAt(Geom::nearest_time((*cubic)[1], *out->first_segment()));
}
} else {
next_point_at1 = out->first_segment()->initialPoint();
@@ -1838,7 +1837,7 @@ void PenTool::_bsplineDoEffect(SPCurve * curve)
cubic = dynamic_cast<Geom::CubicBezier const *>(&*path_it->begin());
if (cubic) {
line_helper->moveto(sbasis_start.valueAt(
- Geom::nearest_point((*cubic)[1], *start->first_segment())));
+ Geom::nearest_time((*cubic)[1], *start->first_segment())));
} else {
line_helper->moveto(start->first_segment()->initialPoint());
}
@@ -1852,7 +1851,7 @@ void PenTool::_bsplineDoEffect(SPCurve * curve)
cubic = dynamic_cast<Geom::CubicBezier const *>(&*curve_it1);
if (cubic) {
line_helper->lineto(sbasis_end.valueAt(
- Geom::nearest_point((*cubic)[2], *end->first_segment())));
+ Geom::nearest_time((*cubic)[2], *end->first_segment())));
} else {
line_helper->lineto(end->first_segment()->finalPoint());
}
diff --git a/src/ui/tools/pencil-tool.cpp b/src/ui/tools/pencil-tool.cpp
index 008804162..16c26546f 100644
--- a/src/ui/tools/pencil-tool.cpp
+++ b/src/ui/tools/pencil-tool.cpp
@@ -53,6 +53,7 @@ static Geom::Point pencil_drag_origin_w(0, 0);
static bool pencil_within_tolerance = false;
static bool in_svg_plane(Geom::Point const &p) { return Geom::LInfty(p) < 1e18; }
+const double HANDLE_CUBIC_GAP = 0.01;
const std::string& PencilTool::getPrefsPath() {
return PencilTool::prefsPath;
@@ -357,7 +358,6 @@ bool PencilTool::_handleButtonRelease(GdkEventButton const &revent) {
// Ctrl+click creates a single point so only set context in ADDLINE mode when Ctrl isn't pressed
this->state = SP_PENCIL_CONTEXT_ADDLINE;
}
- ret = true;
break;
case SP_PENCIL_CONTEXT_ADDLINE:
/* Finish segment now */
@@ -371,7 +371,6 @@ bool PencilTool::_handleButtonRelease(GdkEventButton const &revent) {
this->_finishEndpoint();
this->state = SP_PENCIL_CONTEXT_IDLE;
sp_event_context_discard_delayed_snap_event(this);
- ret = true;
break;
case SP_PENCIL_CONTEXT_FREEHAND:
if (revent.state & GDK_MOD1_MASK) {
@@ -413,7 +412,6 @@ bool PencilTool::_handleButtonRelease(GdkEventButton const &revent) {
// reset sketch mode too
this->sketch_n = 0;
}
- ret = true;
break;
case SP_PENCIL_CONTEXT_SKETCH:
default:
@@ -663,10 +661,10 @@ void PencilTool::_interpolate() {
for (int c = 0; c < n_segs; c++) {
// if we are in BSpline we modify the trace to create adhoc nodes
if(mode == 2){
- Geom::Point point_at1 = b[4*c+0] + (1./3)*(b[4*c+3] - b[4*c+0]);
- point_at1 = Geom::Point(point_at1[X] + 0.0001,point_at1[Y] + 0.0001);
- Geom::Point point_at2 = b[4*c+3] + (1./3)*(b[4*c+0] - b[4*c+3]);
- point_at2 = Geom::Point(point_at2[X] + 0.0001,point_at2[Y] + 0.0001);
+ Geom::Point point_at1 = b[4 * c + 0] + (1./3) * (b[4 * c + 3] - b[4 * c + 0]);
+ point_at1 = Geom::Point(point_at1[X] + HANDLE_CUBIC_GAP, point_at1[Y] + HANDLE_CUBIC_GAP);
+ Geom::Point point_at2 = b[4 * c + 3] + (1./3) * (b[4 * c + 0] - b[4 * c + 3]);
+ point_at2 = Geom::Point(point_at2[X] + HANDLE_CUBIC_GAP, point_at2[Y] + HANDLE_CUBIC_GAP);
this->green_curve->curveto(point_at1,point_at2,b[4*c+3]);
}else{
this->green_curve->curveto(b[4 * c + 1], b[4 * c + 2], b[4 * c + 3]);
@@ -811,9 +809,9 @@ void PencilTool::_fitAndSplit() {
guint mode = prefs->getInt("/tools/freehand/pencil/freehand-mode", 0);
if(mode == 2){
Geom::Point point_at1 = b[0] + (1./3)*(b[3] - b[0]);
- point_at1 = Geom::Point(point_at1[X] + 0.0001,point_at1[Y] + 0.0001);
+ point_at1 = Geom::Point(point_at1[X] + HANDLE_CUBIC_GAP, point_at1[Y] + HANDLE_CUBIC_GAP);
Geom::Point point_at2 = b[3] + (1./3)*(b[0] - b[3]);
- point_at2 = Geom::Point(point_at2[X] + 0.0001,point_at2[Y] + 0.0001);
+ point_at2 = Geom::Point(point_at2[X] + HANDLE_CUBIC_GAP, point_at2[Y] + HANDLE_CUBIC_GAP);
this->red_curve->curveto(point_at1,point_at2,b[3]);
}else{
this->red_curve->curveto(b[1], b[2], b[3]);
diff --git a/src/ui/tools/rect-tool.cpp b/src/ui/tools/rect-tool.cpp
index 62a9006ea..844965c4d 100644
--- a/src/ui/tools/rect-tool.cpp
+++ b/src/ui/tools/rect-tool.cpp
@@ -143,7 +143,6 @@ bool RectTool::item_handler(SPItem* item, GdkEvent* event) {
case GDK_BUTTON_PRESS:
if ( event->button.button == 1 && !this->space_panning) {
Inkscape::setup_for_drag_start(desktop, this, event);
- ret = TRUE;
}
break;
// motion and release are always on root (why?)
diff --git a/src/ui/tools/select-tool.cpp b/src/ui/tools/select-tool.cpp
index 40b994968..f06b03d91 100644
--- a/src/ui/tools/select-tool.cpp
+++ b/src/ui/tools/select-tool.cpp
@@ -472,7 +472,7 @@ bool SelectTool::root_handler(GdkEvent* event) {
case GDK_2BUTTON_PRESS:
if (event->button.button == 1) {
if (!selection->isEmpty()) {
- SPItem *clicked_item = static_cast<SPItem *>(selection->itemList()->data);
+ SPItem *clicked_item = selection->itemList()[0];
if (dynamic_cast<SPGroup *>(clicked_item) && !dynamic_cast<SPBox3D *>(clicked_item)) { // enter group if it's not a 3D box
desktop->setCurrentLayer(clicked_item);
@@ -709,7 +709,7 @@ bool SelectTool::root_handler(GdkEvent* event) {
if (r->is_started() && !within_tolerance) {
// this was a rubberband drag
- GSList *items = NULL;
+ std::vector<SPItem*> items;
if (r->getMode() == RUBBERBAND_MODE_RECT) {
Geom::OptRect const b = r->getRectangle();
@@ -730,7 +730,6 @@ bool SelectTool::root_handler(GdkEvent* event) {
selection->setList (items);
}
- g_slist_free (items);
} else { // it was just a click, or a too small rubberband
r->stop();
@@ -778,7 +777,6 @@ bool SelectTool::root_handler(GdkEvent* event) {
}
rb_escaped = 0;
- ret = TRUE;
}
}
}
diff --git a/src/ui/tools/spray-tool.cpp b/src/ui/tools/spray-tool.cpp
index 0399b1e55..e2be5ca4b 100644
--- a/src/ui/tools/spray-tool.cpp
+++ b/src/ui/tools/spray-tool.cpp
@@ -133,14 +133,13 @@ SprayTool::SprayTool()
: ToolBase(cursor_spray_xpm, 4, 4, false)
, pressure(TC_DEFAULT_PRESSURE)
, dragging(false)
- , usepressure(0)
- , usetilt(0)
+ , usepressure(false)
+ , usetilt(false)
, usetext(false)
, width(0.2)
, ratio(0)
, tilt(0)
, rotation_variation(0)
- , force(0.2)
, population(0)
, scale_variation(1)
, scale(1)
@@ -165,20 +164,12 @@ SprayTool::~SprayTool() {
}
}
-static bool is_transform_modes(gint mode)
-{
- return (mode == SPRAY_MODE_COPY ||
- mode == SPRAY_MODE_CLONE ||
- mode == SPRAY_MODE_SINGLE_PATH ||
- mode == SPRAY_OPTION);
-}
-
void SprayTool::update_cursor(bool /*with_shift*/) {
guint num = 0;
gchar *sel_message = NULL;
if (!desktop->selection->isEmpty()) {
- num = g_slist_length(const_cast<GSList *>(desktop->selection->itemList()));
+ num = desktop->selection->itemList().size();
sel_message = g_strdup_printf(ngettext("<b>%i</b> object selected","<b>%i</b> objects selected",num), num);
} else {
sel_message = g_strdup_printf("%s", _("<b>Nothing</b> selected"));
@@ -207,8 +198,7 @@ void SprayTool::setup() {
{
/* TODO: have a look at sp_dyna_draw_context_setup where the same is done.. generalize? at least make it an arcto! */
- Geom::PathVector path;
- Geom::Circle(0, 0, 1).getPath(path);
+ Geom::PathVector path = Geom::Path(Geom::Circle(0,0,1));
SPCurve *c = new SPCurve(path);
@@ -229,7 +219,6 @@ void SprayTool::setup() {
sp_event_context_read(this, "scale_variation");
sp_event_context_read(this, "mode");
sp_event_context_read(this, "population");
- sp_event_context_read(this, "force");
sp_event_context_read(this, "mean");
sp_event_context_read(this, "standard_deviation");
sp_event_context_read(this, "usepressure");
@@ -271,9 +260,7 @@ void SprayTool::set(const Inkscape::Preferences::Entry& val) {
this->tilt = CLAMP(val.getDouble(0.1), 0, 1000.0);
} else if (path == "ratio") {
this->ratio = CLAMP(val.getDouble(), 0.0, 0.9);
- } else if (path == "force") {
- this->force = CLAMP(val.getDouble(1.0), 0, 1.0);
- }
+ }
}
static void sp_spray_extinput(SprayTool *tc, GdkEvent *event)
@@ -290,16 +277,6 @@ static double get_dilate_radius(SprayTool *tc)
return 250 * tc->width/SP_EVENT_CONTEXT(tc)->desktop->current_zoom();
}
-static double get_path_force(SprayTool *tc)
-{
- double force = 8 * (tc->usepressure? tc->pressure : TC_DEFAULT_PRESSURE)
- /sqrt(SP_EVENT_CONTEXT(tc)->desktop->current_zoom());
- if (force > 3) {
- force += 4 * (force - 3);
- }
- return force * tc->force;
-}
-
static double get_path_mean(SprayTool *tc)
{
return tc->mean;
@@ -310,10 +287,11 @@ static double get_path_standard_deviation(SprayTool *tc)
return tc->standard_deviation;
}
-static double get_move_force(SprayTool *tc)
+static double get_population(SprayTool *tc)
{
- double force = (tc->usepressure? tc->pressure : TC_DEFAULT_PRESSURE);
- return force * tc->force;
+ double pressure = (tc->usepressure? tc->pressure / TC_DEFAULT_PRESSURE : 1);
+ //g_warning("Pressure, population: %f, %f", pressure, pressure * tc->population);
+ return pressure * tc->population;
}
static double get_move_mean(SprayTool *tc)
@@ -361,7 +339,6 @@ static bool sp_spray_recursive(SPDesktop *desktop,
Geom::Point /*vector*/,
gint mode,
double radius,
- double /*force*/,
double population,
double &scale,
double scale_variation,
@@ -426,11 +403,9 @@ static bool sp_spray_recursive(SPDesktop *desktop,
SPItem *unionResult = NULL; // Previous union
int i=1;
- for (GSList *items = g_slist_copy(const_cast<GSList *>(selection->itemList()));
- items != NULL;
- items = items->next) {
-
- SPItem *item1 = dynamic_cast<SPItem *>(static_cast<SPObject *>(items->data));
+ std::vector<SPItem*> items=selection->itemList();
+ for(std::vector<SPItem*>::const_iterator it=items.begin();it!=items.end();it++){
+ SPItem *item1 = *it;
if (i == 1) {
parent_item = item1;
}
@@ -527,8 +502,8 @@ static bool sp_spray_dilate(SprayTool *tc, Geom::Point /*event_p*/, Geom::Point
bool did = false;
double radius = get_dilate_radius(tc);
- double path_force = get_path_force(tc);
- if (radius == 0 || path_force == 0) {
+ double population = get_population(tc);
+ if (radius == 0 || population == 0) {
return false;
}
double path_mean = get_path_mean(tc);
@@ -539,42 +514,29 @@ static bool sp_spray_dilate(SprayTool *tc, Geom::Point /*event_p*/, Geom::Point
if (radius == 0 || path_standard_deviation == 0) {
return false;
}
- double move_force = get_move_force(tc);
double move_mean = get_move_mean(tc);
double move_standard_deviation = get_move_standard_deviation(tc);
{
- GSList *const original_selection = g_slist_copy(const_cast<GSList *>(selection->itemList()));
+ std::vector<SPItem*> const items(selection->itemList());
- for (GSList *items = original_selection;
- items != NULL;
- items = items->next) {
- SPItem *item = dynamic_cast<SPItem *>(static_cast<SPObject *>(items->data));
+ for(std::vector<SPItem*>::const_iterator i=items.begin();i!=items.end();i++){
+ SPItem *item = *i;
g_assert(item != NULL);
sp_object_ref(item);
}
- for (GSList *items = original_selection;
- items != NULL;
- items = items->next) {
- SPItem *item = dynamic_cast<SPItem *>(static_cast<SPObject *>(items->data));
+ for(std::vector<SPItem*>::const_iterator i=items.begin();i!=items.end();i++){
+ SPItem *item = *i;
g_assert(item != NULL);
- if (is_transform_modes(tc->mode)) {
- if (sp_spray_recursive(desktop, selection, item, p, vector, tc->mode, radius, move_force, tc->population, tc->scale, tc->scale_variation, reverse, move_mean, move_standard_deviation, tc->ratio, tc->tilt, tc->rotation_variation, tc->distrib)) {
- did = true;
- }
- } else {
- if (sp_spray_recursive(desktop, selection, item, p, vector, tc->mode, radius, path_force, tc->population, tc->scale, tc->scale_variation, reverse, path_mean, path_standard_deviation, tc->ratio, tc->tilt, tc->rotation_variation, tc->distrib)) {
- did = true;
- }
+ if (sp_spray_recursive(desktop, selection, item, p, vector, tc->mode, radius, population, tc->scale, tc->scale_variation, reverse, move_mean, move_standard_deviation, tc->ratio, tc->tilt, tc->rotation_variation, tc->distrib)) {
+ did = true;
}
}
- for (GSList *items = original_selection;
- items != NULL;
- items = items->next) {
- SPItem *item = dynamic_cast<SPItem *>(static_cast<SPObject *>(items->data));
+ for(std::vector<SPItem*>::const_iterator i=items.begin();i!=items.end();i++){
+ SPItem *item = *i;
g_assert(item != NULL);
sp_object_unref(item);
}
@@ -650,7 +612,7 @@ bool SprayTool::root_handler(GdkEvent* event) {
guint num = 0;
if (!desktop->selection->isEmpty()) {
- num = g_slist_length(const_cast<GSList *>(desktop->selection->itemList()));
+ num = desktop->selection->itemList().size();
}
if (num == 0) {
this->message_context->flash(Inkscape::ERROR_MESSAGE, _("<b>Nothing selected!</b> Select objects to spray."));
diff --git a/src/ui/tools/spray-tool.h b/src/ui/tools/spray-tool.h
index 1a8f98006..8df730201 100644
--- a/src/ui/tools/spray-tool.h
+++ b/src/ui/tools/spray-tool.h
@@ -52,8 +52,8 @@ enum {
class SprayTool : public ToolBase {
public:
- SprayTool();
- virtual ~SprayTool();
+ SprayTool();
+ virtual ~SprayTool();
//ToolBase event_context;
//Inkscape::UI::Dialog::Dialog *dialog_option;//Attribut de type SprayOptionClass, localisé dans scr/ui/dialog
@@ -70,7 +70,6 @@ public:
double ratio;
double tilt;
double rotation_variation;
- double force;
double population;
double scale_variation;
double scale;
@@ -90,16 +89,16 @@ public:
sigc::connection style_set_connection;
- static const std::string prefsPath;
+ static const std::string prefsPath;
- virtual void setup();
- virtual void set(const Inkscape::Preferences::Entry& val);
- virtual bool root_handler(GdkEvent* event);
+ virtual void setup();
+ virtual void set(const Inkscape::Preferences::Entry& val);
+ virtual bool root_handler(GdkEvent* event);
- virtual const std::string& getPrefsPath();
+ virtual const std::string& getPrefsPath();
- void update_cursor(bool /*with_shift*/);
+ void update_cursor(bool /*with_shift*/);
};
}
diff --git a/src/ui/tools/text-tool.cpp b/src/ui/tools/text-tool.cpp
index a2c0c81ae..1888551cf 100644
--- a/src/ui/tools/text-tool.cpp
+++ b/src/ui/tools/text-tool.cpp
@@ -1461,7 +1461,7 @@ int TextTool::_styleQueried(SPStyle *style, int property)
}
sp_text_context_validate_cursor_iterators(this);
- GSList *styles_list = NULL;
+ std::vector<SPItem*> styles_list;
Inkscape::Text::Layout::iterator begin_it, end_it;
if (this->text_sel_start < this->text_sel_end) {
@@ -1477,7 +1477,7 @@ int TextTool::_styleQueried(SPStyle *style, int property)
}
}
for (Inkscape::Text::Layout::iterator it = begin_it ; it < end_it ; it.nextStartOfSpan()) {
- SPObject const *pos_obj = 0;
+ SPObject *pos_obj = 0;
void *rawptr = 0;
layout->getSourceOfCharacter(it, &rawptr);
if (!rawptr || !SP_IS_OBJECT(rawptr)) {
@@ -1487,12 +1487,11 @@ int TextTool::_styleQueried(SPStyle *style, int property)
while (SP_IS_STRING(pos_obj) && pos_obj->parent) {
pos_obj = pos_obj->parent; // SPStrings don't have style
}
- styles_list = g_slist_prepend(styles_list, (gpointer)pos_obj);
+ styles_list.insert(styles_list.begin(),(SPItem*)pos_obj);
}
int result = sp_desktop_query_style_from_list (styles_list, style, property);
- g_slist_free(styles_list);
return result;
}
diff --git a/src/ui/tools/tool-base.cpp b/src/ui/tools/tool-base.cpp
index 2eb6d24d9..0f9b3ee7a 100644
--- a/src/ui/tools/tool-base.cpp
+++ b/src/ui/tools/tool-base.cpp
@@ -1174,11 +1174,9 @@ SPItem *sp_event_context_find_item(SPDesktop *desktop, Geom::Point const &p,
SPItem *
sp_event_context_over_item(SPDesktop *desktop, SPItem *item,
Geom::Point const &p) {
- GSList *temp = NULL;
- temp = g_slist_prepend(temp, item);
+ std::vector<SPItem*> temp;
+ temp.push_back(item);
SPItem *item_at_point = desktop->getItemFromListAtPointBottom(temp, p);
- g_slist_free(temp);
-
return item_at_point;
}
diff --git a/src/ui/tools/tool-base.h b/src/ui/tools/tool-base.h
index 7a6ab83e7..58eb6f88e 100644
--- a/src/ui/tools/tool-base.h
+++ b/src/ui/tools/tool-base.h
@@ -75,7 +75,12 @@ public:
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
double value = prefs->getDoubleLimited("/options/snapdelay/value", 0, 0, 1000);
- _timer_id = g_timeout_add(value, &sp_event_context_snap_watchdog_callback, this);
+ // We used to have this specified in milliseconds; this has changed to seconds now for consistency's sake
+ if (value > 1) { // Apparently we have an old preference file, this value must have been in milliseconds;
+ value = value / 1000.0; // now convert this value to seconds
+ }
+
+ _timer_id = g_timeout_add(value*1000.0, &sp_event_context_snap_watchdog_callback, this);
_event = gdk_event_copy((GdkEvent*) event);
((GdkEventMotion *)_event)->time = GDK_CURRENT_TIME;
diff --git a/src/ui/tools/tweak-tool.cpp b/src/ui/tools/tweak-tool.cpp
index 80b52fba6..94f7aa135 100644
--- a/src/ui/tools/tweak-tool.cpp
+++ b/src/ui/tools/tweak-tool.cpp
@@ -153,7 +153,7 @@ void TweakTool::update_cursor (bool with_shift) {
gchar *sel_message = NULL;
if (!desktop->selection->isEmpty()) {
- num = g_slist_length(const_cast<GSList *>(desktop->selection->itemList()));
+ num = desktop->selection->itemList().size();
sel_message = g_strdup_printf(ngettext("<b>%i</b> object selected","<b>%i</b> objects selected",num), num);
} else {
sel_message = g_strdup_printf("%s", _("<b>Nothing</b> selected"));
@@ -259,8 +259,7 @@ void TweakTool::setup() {
{
/* TODO: have a look at sp_dyna_draw_context_setup where the same is done.. generalize? at least make it an arcto! */
- Geom::PathVector path;
- Geom::Circle(0, 0, 1).getPath(path);
+ Geom::PathVector path = Geom::Path(Geom::Circle(0,0,1));
SPCurve *c = new SPCurve(path);
@@ -372,14 +371,13 @@ sp_tweak_dilate_recursive (Inkscape::Selection *selection, SPItem *item, Geom::P
}
if (dynamic_cast<SPText *>(item) || dynamic_cast<SPFlowtext *>(item)) {
- GSList *items = g_slist_prepend (NULL, item);
- GSList *selected = NULL;
- GSList *to_select = NULL;
+ std::vector<SPItem*> items;
+ items.push_back(item);
+ std::vector<SPItem*> selected;
+ std::vector<Inkscape::XML::Node*> to_select;
SPDocument *doc = item->document;
- sp_item_list_to_curves (items, &selected, &to_select);
- g_slist_free (items);
- SPObject* newObj = doc->getObjectByRepr(static_cast<Inkscape::XML::Node *>(to_select->data));
- g_slist_free (to_select);
+ sp_item_list_to_curves (items, selected, to_select);
+ SPObject* newObj = doc->getObjectByRepr(to_select[0]);
item = dynamic_cast<SPItem *>(newObj);
g_assert(item != NULL);
selection->add(item);
@@ -1078,11 +1076,9 @@ sp_tweak_dilate (TweakTool *tc, Geom::Point event_p, Geom::Point p, Geom::Point
double move_force = get_move_force(tc);
double color_force = MIN(sqrt(path_force)/20.0, 1);
- for (GSList *items = g_slist_copy(const_cast<GSList *>(selection->itemList()));
- items != NULL;
- items = items->next) {
-
- SPItem *item = dynamic_cast<SPItem *>(static_cast<SPObject *>(items->data));
+ std::vector<SPItem*> items=selection->itemList();
+ for(std::vector<SPItem*>::const_iterator i=items.begin();i!=items.end();i++){
+ SPItem *item = *i;
if (is_color_mode (tc->mode)) {
if (do_fill || do_stroke || do_opacity) {
@@ -1189,7 +1185,7 @@ bool TweakTool::root_handler(GdkEvent* event) {
guint num = 0;
if (!desktop->selection->isEmpty()) {
- num = g_slist_length(const_cast<GSList *>(desktop->selection->itemList()));
+ num = desktop->selection->itemList().size();
}
if (num == 0) {
this->message_context->flash(Inkscape::ERROR_MESSAGE, _("<b>Nothing selected!</b> Select objects to tweak."));
diff --git a/src/ui/widget/Makefile_insert b/src/ui/widget/Makefile_insert
index e18b790bd..eb98e6872 100644
--- a/src/ui/widget/Makefile_insert
+++ b/src/ui/widget/Makefile_insert
@@ -6,10 +6,22 @@ ink_common_sources += \
ui/widget/attr-widget.h \
ui/widget/button.h \
ui/widget/button.cpp \
+ ui/widget/color-entry.cpp \
+ ui/widget/color-entry.h \
+ ui/widget/color-icc-selector.cpp \
+ ui/widget/color-icc-selector.h \
+ ui/widget/color-notebook.cpp \
+ ui/widget/color-notebook.h \
+ ui/widget/color-wheel-selector.cpp \
+ ui/widget/color-wheel-selector.h \
ui/widget/color-picker.cpp \
ui/widget/color-picker.h \
ui/widget/color-preview.cpp \
ui/widget/color-preview.h \
+ ui/widget/color-slider.cpp \
+ ui/widget/color-slider.h \
+ ui/widget/color-scales.cpp \
+ ui/widget/color-scales.h \
ui/widget/combo-enums.h \
ui/widget/dock.h \
ui/widget/dock.cpp \
@@ -21,8 +33,10 @@ ink_common_sources += \
ui/widget/entry.h \
ui/widget/filter-effect-chooser.h \
ui/widget/filter-effect-chooser.cpp \
- ui/widget/gimpspinscale.c \
- ui/widget/gimpspinscale.h \
+ ui/widget/font-variants.h \
+ ui/widget/font-variants.cpp \
+ ui/widget/gimpspinscale.c \
+ ui/widget/gimpspinscale.h \
ui/widget/gimpcolorwheel.c \
ui/widget/gimpcolorwheel.h \
ui/widget/frame.cpp \
diff --git a/src/ui/widget/color-entry.cpp b/src/ui/widget/color-entry.cpp
new file mode 100644
index 000000000..f5658c3a6
--- /dev/null
+++ b/src/ui/widget/color-entry.cpp
@@ -0,0 +1,114 @@
+/** @file
+ * Entry widget for typing color value in css form
+ *//*
+ * Authors:
+ * Tomasz Boczkowski <penginsbacon@gmail.com>
+ *
+ * Copyright (C) 2014 Authors
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+#include <glibmm.h>
+#include <glibmm/i18n.h>
+#include <iomanip>
+
+#include "color-entry.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+ColorEntry::ColorEntry(SelectedColor &color)
+ : _color(color)
+ , _updating(false)
+ , _updatingrgba(false)
+{
+ _color_changed_connection = color.signal_changed.connect(sigc::mem_fun(this, &ColorEntry::_onColorChanged));
+ _color_dragged_connection = color.signal_dragged.connect(sigc::mem_fun(this, &ColorEntry::_onColorChanged));
+ _onColorChanged();
+
+ set_max_length(8);
+ set_width_chars(8);
+ set_tooltip_text(_("Hexadecimal RGBA value of the color"));
+}
+
+ColorEntry::~ColorEntry()
+{
+ _color_changed_connection.disconnect();
+ _color_dragged_connection.disconnect();
+}
+
+void ColorEntry::on_changed()
+{
+ if (_updating) {
+ return;
+ }
+ if (_updatingrgba) {
+ return; // Typing text into entry box
+ }
+
+ Glib::ustring text = get_text();
+ bool changed = false;
+
+ // Coerce the value format to eight hex digits
+ if (!text.empty() && text[0] == '#') {
+ changed = true;
+ text.erase(0, 1);
+ if (text.size() == 6) {
+ // it was a standard RGB hex
+ unsigned int alpha = SP_COLOR_F_TO_U(_color.alpha());
+ text += Glib::ustring::format(std::hex, std::setw(2), std::setfill(L'0'), alpha);
+ }
+ }
+
+ gchar *str = g_strdup(text.c_str());
+ gchar *end = 0;
+ guint64 rgba = g_ascii_strtoull(str, &end, 16);
+ if (end != str) {
+ ptrdiff_t len = end - str;
+ if (len < 8) {
+ rgba = rgba << (4 * (8 - len));
+ }
+ _updatingrgba = true;
+ if (changed) {
+ set_text(str);
+ }
+ SPColor color(rgba);
+ _color.setColorAlpha(color, SP_RGBA32_A_F(rgba));
+ _updatingrgba = false;
+ }
+ g_free(str);
+}
+
+
+void ColorEntry::_onColorChanged()
+{
+ if (_updatingrgba) {
+ return;
+ }
+
+ SPColor color = _color.color();
+ gdouble alpha = _color.alpha();
+
+ guint32 rgba = color.toRGBA32(alpha);
+ Glib::ustring text = Glib::ustring::format(std::hex, std::setw(8), std::setfill(L'0'), rgba);
+
+ Glib::ustring old_text = get_text();
+ if (old_text != text) {
+ _updating = true;
+ set_text(text);
+ _updating = false;
+ }
+}
+}
+}
+}
+/*
+ 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/color-entry.h b/src/ui/widget/color-entry.h
new file mode 100644
index 000000000..edabe1980
--- /dev/null
+++ b/src/ui/widget/color-entry.h
@@ -0,0 +1,54 @@
+/** @file
+ * Entry widget for typing color value in css form
+ *//*
+ * Authors:
+ * Tomasz Boczkowski <penginsbacon@gmail.com>
+ *
+ * Copyright (C) 2014 Authors
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifndef SEEN_COLOR_ENTRY_H
+#define SEEN_COLOR_ENTRY_H_
+
+#include <gtkmm/entry.h>
+#include "ui/selected-color.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+class ColorEntry : public Gtk::Entry
+{
+public:
+ ColorEntry(SelectedColor &color);
+ virtual ~ColorEntry();
+
+protected:
+ void on_changed();
+
+private:
+ void _onColorChanged();
+
+ SelectedColor &_color;
+ sigc::connection _color_changed_connection;
+ sigc::connection _color_dragged_connection;
+ bool _updating;
+ bool _updatingrgba;
+};
+
+}
+}
+}
+
+#endif
+/*
+ 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/color-icc-selector.cpp b/src/ui/widget/color-icc-selector.cpp
new file mode 100644
index 000000000..1c31ae33a
--- /dev/null
+++ b/src/ui/widget/color-icc-selector.cpp
@@ -0,0 +1,1079 @@
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <math.h>
+#include <gtkmm/adjustment.h>
+#include <glibmm/i18n.h>
+
+#include <gtk/gtk.h>
+#include <map>
+#include <set>
+#include <vector>
+
+#include "ui/dialog-events.h"
+#include "ui/widget/color-icc-selector.h"
+#include "ui/widget/color-scales.h"
+#include "ui/widget/color-slider.h"
+#include "svg/svg-icc-color.h"
+#include "colorspace.h"
+#include "document.h"
+#include "inkscape.h"
+#include "profile-manager.h"
+#include "widgets/gradient-vector.h"
+
+#define noDEBUG_LCMS
+
+#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
+#include "color-profile.h"
+#include "cms-system.h"
+#include "color-profile-cms-fns.h"
+
+#ifdef DEBUG_LCMS
+#include "preferences.h"
+#endif // DEBUG_LCMS
+#endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
+
+#ifdef DEBUG_LCMS
+extern guint update_in_progress;
+#define DEBUG_MESSAGE(key, ...) \
+ { \
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get(); \
+ bool dump = prefs->getBool("/options/scislac/" #key); \
+ bool dumpD = prefs->getBool("/options/scislac/" #key "D"); \
+ bool dumpD2 = prefs->getBool("/options/scislac/" #key "D2"); \
+ dumpD && = ((update_in_progress == 0) || dumpD2); \
+ if (dump) { \
+ g_message(__VA_ARGS__); \
+ } \
+ if (dumpD) { \
+ GtkWidget *dialog = gtk_message_dialog_new(NULL, GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_INFO, \
+ GTK_BUTTONS_OK, __VA_ARGS__); \
+ g_signal_connect_swapped(dialog, "response", G_CALLBACK(gtk_widget_destroy), dialog); \
+ gtk_widget_show_all(dialog); \
+ } \
+ }
+#endif // DEBUG_LCMS
+
+
+#define XPAD 4
+#define YPAD 1
+
+namespace {
+
+size_t maxColorspaceComponentCount = 0;
+
+#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
+
+/**
+ * Internal variable to track all known colorspaces.
+ */
+std::set<cmsUInt32Number> knownColorspaces;
+
+#endif
+
+
+/**
+ * Simple helper to allow bitwise or on GtkAttachOptions.
+ */
+GtkAttachOptions operator|(GtkAttachOptions lhs, GtkAttachOptions rhs)
+{
+ return static_cast<GtkAttachOptions>(static_cast<int>(lhs) | static_cast<int>(rhs));
+}
+
+/**
+ * Helper function to handle GTK2/GTK3 attachment #ifdef code.
+ */
+void attachToGridOrTable(GtkWidget *parent, GtkWidget *child, guint left, guint top, guint width, guint height,
+ bool hexpand = false, bool centered = false, guint xpadding = XPAD, guint ypadding = YPAD)
+{
+#if GTK_CHECK_VERSION(3, 0, 0)
+ #if GTK_CHECK_VERSION(3, 12, 0)
+ gtk_widget_set_margin_start(child, xpadding);
+ gtk_widget_set_margin_end(child, xpadding);
+ #else
+ gtk_widget_set_margin_left(child, xpadding);
+ gtk_widget_set_margin_right(child, xpadding);
+ #endif
+
+ gtk_widget_set_margin_top(child, ypadding);
+ gtk_widget_set_margin_bottom(child, ypadding);
+ if (hexpand) {
+ gtk_widget_set_hexpand(child, TRUE);
+ }
+ if (centered) {
+ gtk_widget_set_halign(child, GTK_ALIGN_CENTER);
+ gtk_widget_set_valign(child, GTK_ALIGN_CENTER);
+ }
+ gtk_grid_attach(GTK_GRID(parent), child, left, top, width, height);
+#else
+ GtkAttachOptions xoptions =
+ centered ? static_cast<GtkAttachOptions>(0) : hexpand ? (GTK_EXPAND | GTK_FILL) : GTK_FILL;
+ GtkAttachOptions yoptions = centered ? static_cast<GtkAttachOptions>(0) : GTK_FILL;
+
+ gtk_table_attach(GTK_TABLE(parent), child, left, left + width, top, top + height, xoptions, yoptions, xpadding,
+ ypadding);
+#endif
+}
+
+} // namespace
+
+/*
+icSigRgbData
+icSigCmykData
+icSigCmyData
+*/
+#define SPACE_ID_RGB 0
+#define SPACE_ID_CMY 1
+#define SPACE_ID_CMYK 2
+
+
+#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
+static cmsUInt16Number *getScratch()
+{
+ // bytes per pixel * input channels * width
+ static cmsUInt16Number *scritch = static_cast<cmsUInt16Number *>(g_new(cmsUInt16Number, 4 * 1024));
+
+ return scritch;
+}
+
+colorspace::Component::Component()
+ : name()
+ , tip()
+ , scale(1)
+{
+}
+
+colorspace::Component::Component(std::string const &name, std::string const &tip, guint scale)
+ : name(name)
+ , tip(tip)
+ , scale(scale)
+{
+}
+
+std::vector<colorspace::Component> colorspace::getColorSpaceInfo(uint32_t space)
+{
+ static std::map<cmsUInt32Number, std::vector<Component> > sets;
+ if (sets.empty()) {
+ sets[cmsSigXYZData].push_back(Component("_X", "X", 2)); // TYPE_XYZ_16
+ sets[cmsSigXYZData].push_back(Component("_Y", "Y", 1));
+ sets[cmsSigXYZData].push_back(Component("_Z", "Z", 2));
+
+ sets[cmsSigLabData].push_back(Component("_L", "L", 100)); // TYPE_Lab_16
+ sets[cmsSigLabData].push_back(Component("_a", "a", 256));
+ sets[cmsSigLabData].push_back(Component("_b", "b", 256));
+
+ // cmsSigLuvData
+
+ sets[cmsSigYCbCrData].push_back(Component("_Y", "Y", 1)); // TYPE_YCbCr_16
+ sets[cmsSigYCbCrData].push_back(Component("C_b", "Cb", 1));
+ sets[cmsSigYCbCrData].push_back(Component("C_r", "Cr", 1));
+
+ sets[cmsSigYxyData].push_back(Component("_Y", "Y", 1)); // TYPE_Yxy_16
+ sets[cmsSigYxyData].push_back(Component("_x", "x", 1));
+ sets[cmsSigYxyData].push_back(Component("y", "y", 1));
+
+ sets[cmsSigRgbData].push_back(Component(_("_R:"), _("Red"), 1)); // TYPE_RGB_16
+ sets[cmsSigRgbData].push_back(Component(_("_G:"), _("Green"), 1));
+ sets[cmsSigRgbData].push_back(Component(_("_B:"), _("Blue"), 1));
+
+ sets[cmsSigGrayData].push_back(Component(_("G:"), _("Gray"), 1)); // TYPE_GRAY_16
+
+ sets[cmsSigHsvData].push_back(Component(_("_H:"), _("Hue"), 360)); // TYPE_HSV_16
+ sets[cmsSigHsvData].push_back(Component(_("_S:"), _("Saturation"), 1));
+ sets[cmsSigHsvData].push_back(Component("_V:", "Value", 1));
+
+ sets[cmsSigHlsData].push_back(Component(_("_H:"), _("Hue"), 360)); // TYPE_HLS_16
+ sets[cmsSigHlsData].push_back(Component(_("_L:"), _("Lightness"), 1));
+ sets[cmsSigHlsData].push_back(Component(_("_S:"), _("Saturation"), 1));
+
+ sets[cmsSigCmykData].push_back(Component(_("_C:"), _("Cyan"), 1)); // TYPE_CMYK_16
+ sets[cmsSigCmykData].push_back(Component(_("_M:"), _("Magenta"), 1));
+ sets[cmsSigCmykData].push_back(Component(_("_Y:"), _("Yellow"), 1));
+ sets[cmsSigCmykData].push_back(Component(_("_K:"), _("Black"), 1));
+
+ sets[cmsSigCmyData].push_back(Component(_("_C:"), _("Cyan"), 1)); // TYPE_CMY_16
+ sets[cmsSigCmyData].push_back(Component(_("_M:"), _("Magenta"), 1));
+ sets[cmsSigCmyData].push_back(Component(_("_Y:"), _("Yellow"), 1));
+
+ for (std::map<cmsUInt32Number, std::vector<Component> >::iterator it = sets.begin(); it != sets.end(); ++it) {
+ knownColorspaces.insert(it->first);
+ maxColorspaceComponentCount = std::max(maxColorspaceComponentCount, it->second.size());
+ }
+ }
+
+ std::vector<Component> target;
+
+ if (sets.find(space) != sets.end()) {
+ target = sets[space];
+ }
+ return target;
+}
+
+
+std::vector<colorspace::Component> colorspace::getColorSpaceInfo(Inkscape::ColorProfile *prof)
+{
+ return getColorSpaceInfo(asICColorSpaceSig(prof->getColorSpace()));
+}
+
+#endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+/**
+ * Class containing the parts for a single color component's UI presence.
+ */
+class ComponentUI {
+ public:
+ ComponentUI()
+ : _component()
+ , _adj(0)
+ , _slider(0)
+ , _btn(0)
+ , _label(0)
+ , _map(0)
+ {
+ }
+
+ ComponentUI(colorspace::Component const &component)
+ : _component(component)
+ , _adj(0)
+ , _slider(0)
+ , _btn(0)
+ , _label(0)
+ , _map(0)
+ {
+ }
+
+ colorspace::Component _component;
+ GtkAdjustment *_adj; // Component adjustment
+ Inkscape::UI::Widget::ColorSlider *_slider;
+ GtkWidget *_btn; // spinbutton
+ GtkWidget *_label; // Label
+ guchar *_map;
+};
+
+/**
+ * Class that implements the internals of the selector.
+ */
+class ColorICCSelectorImpl {
+ public:
+ ColorICCSelectorImpl(ColorICCSelector *owner, SelectedColor &color);
+
+ ~ColorICCSelectorImpl();
+
+ static void _adjustmentChanged(GtkAdjustment *adjustment, ColorICCSelectorImpl *cs);
+
+ void _sliderGrabbed();
+ void _sliderReleased();
+ void _sliderChanged();
+
+ static void _profileSelected(GtkWidget *src, gpointer data);
+ static void _fixupHit(GtkWidget *src, gpointer data);
+
+#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
+ void _setProfile(SVGICCColor *profile);
+ void _switchToProfile(gchar const *name);
+#endif
+ void _updateSliders(gint ignore);
+ void _profilesChanged(std::string const &name);
+
+ ColorICCSelector *_owner;
+ SelectedColor &_color;
+
+ gboolean _updating : 1;
+ gboolean _dragging : 1;
+
+ guint32 _fixupNeeded;
+ GtkWidget *_fixupBtn;
+ GtkWidget *_profileSel;
+
+ std::vector<ComponentUI> _compUI;
+
+ GtkAdjustment *_adj; // Channel adjustment
+ Inkscape::UI::Widget::ColorSlider *_slider;
+ GtkWidget *_sbtn; // Spinbutton
+ GtkWidget *_label; // Label
+
+#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
+ std::string _profileName;
+ Inkscape::ColorProfile *_prof;
+ guint _profChannelCount;
+ gulong _profChangedID;
+#endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
+};
+
+
+
+const gchar *ColorICCSelector::MODE_NAME = N_("CMS");
+
+ColorICCSelector::ColorICCSelector(SelectedColor &color)
+ : _impl(NULL)
+{
+ _impl = new ColorICCSelectorImpl(this, color);
+ init();
+ color.signal_changed.connect(sigc::mem_fun(this, &ColorICCSelector::_colorChanged));
+ // color.signal_dragged.connect(sigc::mem_fun(this, &ColorICCSelector::_colorChanged));
+}
+
+ColorICCSelector::~ColorICCSelector()
+{
+ if (_impl) {
+ delete _impl;
+ _impl = 0;
+ }
+}
+
+
+
+ColorICCSelectorImpl::ColorICCSelectorImpl(ColorICCSelector *owner, SelectedColor &color)
+ : _owner(owner)
+ , _color(color)
+ , _updating(FALSE)
+ , _dragging(FALSE)
+ , _fixupNeeded(0)
+ , _fixupBtn(0)
+ , _profileSel(0)
+ , _compUI()
+ , _adj(0)
+ , _slider(0)
+ , _sbtn(0)
+ , _label(0)
+#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
+ , _profileName()
+ , _prof(0)
+ , _profChannelCount(0)
+ , _profChangedID(0)
+#endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
+{
+}
+
+ColorICCSelectorImpl::~ColorICCSelectorImpl()
+{
+ _adj = 0;
+ _sbtn = 0;
+ _label = 0;
+}
+
+void ColorICCSelector::init()
+{
+ gint row = 0;
+
+ _impl->_updating = FALSE;
+ _impl->_dragging = FALSE;
+
+ GtkWidget *t = GTK_WIDGET(gobj());
+
+ _impl->_compUI.clear();
+
+ // Create components
+ row = 0;
+
+
+ _impl->_fixupBtn = gtk_button_new_with_label(_("Fix"));
+ g_signal_connect(G_OBJECT(_impl->_fixupBtn), "clicked", G_CALLBACK(ColorICCSelectorImpl::_fixupHit),
+ (gpointer)_impl);
+ gtk_widget_set_sensitive(_impl->_fixupBtn, FALSE);
+ gtk_widget_set_tooltip_text(_impl->_fixupBtn, _("Fix RGB fallback to match icc-color() value."));
+ // gtk_misc_set_alignment( GTK_MISC (_impl->_fixupBtn), 1.0, 0.5 );
+ gtk_widget_show(_impl->_fixupBtn);
+
+ attachToGridOrTable(t, _impl->_fixupBtn, 0, row, 1, 1);
+
+ // Combobox and store with 2 columns : label (0) and full name (1)
+ GtkListStore *store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_STRING);
+ _impl->_profileSel = gtk_combo_box_new_with_model(GTK_TREE_MODEL(store));
+
+ GtkCellRenderer *renderer = gtk_cell_renderer_text_new();
+ gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(_impl->_profileSel), renderer, TRUE);
+ gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(_impl->_profileSel), renderer, "text", 0, NULL);
+
+ GtkTreeIter iter;
+ gtk_list_store_append(store, &iter);
+ gtk_list_store_set(store, &iter, 0, _("<none>"), 1, _("<none>"), -1);
+
+ gtk_widget_show(_impl->_profileSel);
+ gtk_combo_box_set_active(GTK_COMBO_BOX(_impl->_profileSel), 0);
+
+ attachToGridOrTable(t, _impl->_profileSel, 1, row, 1, 1);
+
+#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
+ _impl->_profChangedID = g_signal_connect(G_OBJECT(_impl->_profileSel), "changed",
+ G_CALLBACK(ColorICCSelectorImpl::_profileSelected), (gpointer)_impl);
+#else
+ gtk_widget_set_sensitive(_impl->_profileSel, false);
+#endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
+
+
+ row++;
+
+// populate the data for colorspaces and channels:
+#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
+ std::vector<colorspace::Component> things = colorspace::getColorSpaceInfo(cmsSigRgbData);
+#endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
+
+ for (size_t i = 0; i < maxColorspaceComponentCount; i++) {
+#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
+ if (i < things.size()) {
+ _impl->_compUI.push_back(ComponentUI(things[i]));
+ }
+ else {
+ _impl->_compUI.push_back(ComponentUI());
+ }
+
+ std::string labelStr = (i < things.size()) ? things[i].name.c_str() : "";
+#else
+ _impl->_compUI.push_back(ComponentUI());
+
+ std::string labelStr = ".";
+#endif
+
+ _impl->_compUI[i]._label = gtk_label_new_with_mnemonic(labelStr.c_str());
+ gtk_misc_set_alignment(GTK_MISC(_impl->_compUI[i]._label), 1.0, 0.5);
+ gtk_widget_show(_impl->_compUI[i]._label);
+ gtk_widget_set_no_show_all(_impl->_compUI[i]._label, TRUE);
+
+ attachToGridOrTable(t, _impl->_compUI[i]._label, 0, row, 1, 1);
+
+ // Adjustment
+ guint scaleValue = _impl->_compUI[i]._component.scale;
+ gdouble step = static_cast<gdouble>(scaleValue) / 100.0;
+ gdouble page = static_cast<gdouble>(scaleValue) / 10.0;
+ gint digits = (step > 0.9) ? 0 : 2;
+ _impl->_compUI[i]._adj = GTK_ADJUSTMENT(gtk_adjustment_new(0.0, 0.0, scaleValue, step, page, page));
+
+ // Slider
+ _impl->_compUI[i]._slider =
+ Gtk::manage(new Inkscape::UI::Widget::ColorSlider(Glib::wrap(_impl->_compUI[i]._adj, true)));
+#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
+ _impl->_compUI[i]._slider->set_tooltip_text((i < things.size()) ? things[i].tip.c_str() : "");
+#else
+ _impl->_compUI[i]._slider->set_tooltip_text(".");
+#endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
+ _impl->_compUI[i]._slider->show();
+ _impl->_compUI[i]._slider->set_no_show_all();
+
+ attachToGridOrTable(t, _impl->_compUI[i]._slider->gobj(), 1, row, 1, 1, true);
+
+ _impl->_compUI[i]._btn = gtk_spin_button_new(_impl->_compUI[i]._adj, step, digits);
+#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
+ gtk_widget_set_tooltip_text(_impl->_compUI[i]._btn, (i < things.size()) ? things[i].tip.c_str() : "");
+#else
+ gtk_widget_set_tooltip_text(_impl->_compUI[i]._btn, ".");
+#endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
+ sp_dialog_defocus_on_enter(_impl->_compUI[i]._btn);
+ gtk_label_set_mnemonic_widget(GTK_LABEL(_impl->_compUI[i]._label), _impl->_compUI[i]._btn);
+ gtk_widget_show(_impl->_compUI[i]._btn);
+ gtk_widget_set_no_show_all(_impl->_compUI[i]._btn, TRUE);
+
+ attachToGridOrTable(t, _impl->_compUI[i]._btn, 2, row, 1, 1, false, true);
+
+ _impl->_compUI[i]._map = g_new(guchar, 4 * 1024);
+ memset(_impl->_compUI[i]._map, 0x0ff, 1024 * 4);
+
+
+ // Signals
+ g_signal_connect(G_OBJECT(_impl->_compUI[i]._adj), "value_changed",
+ G_CALLBACK(ColorICCSelectorImpl::_adjustmentChanged), _impl);
+
+ _impl->_compUI[i]._slider->signal_grabbed.connect(sigc::mem_fun(_impl, &ColorICCSelectorImpl::_sliderGrabbed));
+ _impl->_compUI[i]._slider->signal_released.connect(
+ sigc::mem_fun(_impl, &ColorICCSelectorImpl::_sliderReleased));
+ _impl->_compUI[i]._slider->signal_value_changed.connect(
+ sigc::mem_fun(_impl, &ColorICCSelectorImpl::_sliderChanged));
+
+ row++;
+ }
+
+ // Label
+ _impl->_label = gtk_label_new_with_mnemonic(_("_A:"));
+ gtk_misc_set_alignment(GTK_MISC(_impl->_label), 1.0, 0.5);
+ gtk_widget_show(_impl->_label);
+
+ attachToGridOrTable(t, _impl->_label, 0, row, 1, 1);
+
+ // Adjustment
+ _impl->_adj = GTK_ADJUSTMENT(gtk_adjustment_new(0.0, 0.0, 255.0, 1.0, 10.0, 10.0));
+
+ // Slider
+ _impl->_slider = Gtk::manage(new Inkscape::UI::Widget::ColorSlider(Glib::wrap(_impl->_adj, true)));
+ _impl->_slider->set_tooltip_text(_("Alpha (opacity)"));
+ _impl->_slider->show();
+
+ attachToGridOrTable(t, _impl->_slider->gobj(), 1, row, 1, 1, true);
+
+ _impl->_slider->setColors(SP_RGBA32_F_COMPOSE(1.0, 1.0, 1.0, 0.0), SP_RGBA32_F_COMPOSE(1.0, 1.0, 1.0, 0.5),
+ SP_RGBA32_F_COMPOSE(1.0, 1.0, 1.0, 1.0));
+
+
+ // Spinbutton
+ _impl->_sbtn = gtk_spin_button_new(GTK_ADJUSTMENT(_impl->_adj), 1.0, 0);
+ gtk_widget_set_tooltip_text(_impl->_sbtn, _("Alpha (opacity)"));
+ sp_dialog_defocus_on_enter(_impl->_sbtn);
+ gtk_label_set_mnemonic_widget(GTK_LABEL(_impl->_label), _impl->_sbtn);
+ gtk_widget_show(_impl->_sbtn);
+
+ attachToGridOrTable(t, _impl->_sbtn, 2, row, 1, 1, false, true);
+
+ // Signals
+ g_signal_connect(G_OBJECT(_impl->_adj), "value_changed", G_CALLBACK(ColorICCSelectorImpl::_adjustmentChanged),
+ _impl);
+
+ _impl->_slider->signal_grabbed.connect(sigc::mem_fun(_impl, &ColorICCSelectorImpl::_sliderGrabbed));
+ _impl->_slider->signal_released.connect(sigc::mem_fun(_impl, &ColorICCSelectorImpl::_sliderReleased));
+ _impl->_slider->signal_value_changed.connect(sigc::mem_fun(_impl, &ColorICCSelectorImpl::_sliderChanged));
+
+ gtk_widget_show(t);
+}
+
+void ColorICCSelectorImpl::_fixupHit(GtkWidget * /*src*/, gpointer data)
+{
+ ColorICCSelectorImpl *self = reinterpret_cast<ColorICCSelectorImpl *>(data);
+ gtk_widget_set_sensitive(self->_fixupBtn, FALSE);
+ self->_adjustmentChanged(self->_compUI[0]._adj, self);
+}
+
+#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
+void ColorICCSelectorImpl::_profileSelected(GtkWidget * /*src*/, gpointer data)
+{
+ ColorICCSelectorImpl *self = reinterpret_cast<ColorICCSelectorImpl *>(data);
+
+ GtkTreeIter iter;
+ if (gtk_combo_box_get_active_iter(GTK_COMBO_BOX(self->_profileSel), &iter)) {
+ GtkTreeModel *store = gtk_combo_box_get_model(GTK_COMBO_BOX(self->_profileSel));
+ gchar *name = 0;
+
+ gtk_tree_model_get(store, &iter, 1, &name, -1);
+ self->_switchToProfile(name);
+ gtk_widget_set_tooltip_text(self->_profileSel, name);
+
+ if (name) {
+ g_free(name);
+ }
+ }
+}
+#endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
+
+#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
+void ColorICCSelectorImpl::_switchToProfile(gchar const *name)
+{
+ bool dirty = false;
+ SPColor tmp(_color.color());
+
+ if (name) {
+ if (tmp.icc && tmp.icc->colorProfile == name) {
+#ifdef DEBUG_LCMS
+ g_message("Already at name [%s]", name);
+#endif // DEBUG_LCMS
+ }
+ else {
+#ifdef DEBUG_LCMS
+ g_message("Need to switch to profile [%s]", name);
+#endif // DEBUG_LCMS
+ if (tmp.icc) {
+ tmp.icc->colors.clear();
+ }
+ else {
+ tmp.icc = new SVGICCColor();
+ }
+ tmp.icc->colorProfile = name;
+ Inkscape::ColorProfile *newProf = SP_ACTIVE_DOCUMENT->profileManager->find(name);
+ if (newProf) {
+ cmsHTRANSFORM trans = newProf->getTransfFromSRGB8();
+ if (trans) {
+ guint32 val = _color.color().toRGBA32(0);
+ guchar pre[4] = {
+ static_cast<guchar>(SP_RGBA32_R_U(val)),
+ static_cast<guchar>(SP_RGBA32_G_U(val)),
+ static_cast<guchar>(SP_RGBA32_B_U(val)),
+ 255};
+#ifdef DEBUG_LCMS
+ g_message("Shoving in [%02x] [%02x] [%02x]", pre[0], pre[1], pre[2]);
+#endif // DEBUG_LCMS
+ cmsUInt16Number post[4] = { 0, 0, 0, 0 };
+ cmsDoTransform(trans, pre, post, 1);
+#ifdef DEBUG_LCMS
+ g_message("got on out [%04x] [%04x] [%04x] [%04x]", post[0], post[1], post[2], post[3]);
+#endif // DEBUG_LCMS
+#if HAVE_LIBLCMS1
+ guint count = _cmsChannelsOf(asICColorSpaceSig(newProf->getColorSpace()));
+#elif HAVE_LIBLCMS2
+ guint count = cmsChannelsOf(asICColorSpaceSig(newProf->getColorSpace()));
+#endif
+
+ std::vector<colorspace::Component> things =
+ colorspace::getColorSpaceInfo(asICColorSpaceSig(newProf->getColorSpace()));
+
+ for (guint i = 0; i < count; i++) {
+ gdouble val =
+ (((gdouble)post[i]) / 65535.0) * (gdouble)((i < things.size()) ? things[i].scale : 1);
+#ifdef DEBUG_LCMS
+ g_message(" scaled %d by %d to be %f", i, ((i < things.size()) ? things[i].scale : 1), val);
+#endif // DEBUG_LCMS
+ tmp.icc->colors.push_back(val);
+ }
+ cmsHTRANSFORM retrans = newProf->getTransfToSRGB8();
+ if (retrans) {
+ cmsDoTransform(retrans, post, pre, 1);
+#ifdef DEBUG_LCMS
+ g_message(" back out [%02x] [%02x] [%02x]", pre[0], pre[1], pre[2]);
+#endif // DEBUG_LCMS
+ tmp.set(SP_RGBA32_U_COMPOSE(pre[0], pre[1], pre[2], 0xff));
+ }
+ }
+ }
+ dirty = true;
+ }
+ }
+ else {
+#ifdef DEBUG_LCMS
+ g_message("NUKE THE ICC");
+#endif // DEBUG_LCMS
+ if (tmp.icc) {
+ delete tmp.icc;
+ tmp.icc = 0;
+ dirty = true;
+ _fixupHit(0, this);
+ }
+ else {
+#ifdef DEBUG_LCMS
+ g_message("No icc to nuke");
+#endif // DEBUG_LCMS
+ }
+ }
+
+ if (dirty) {
+#ifdef DEBUG_LCMS
+ g_message("+----------------");
+ g_message("+ new color is [%s]", tmp.toString().c_str());
+#endif // DEBUG_LCMS
+ _setProfile(tmp.icc);
+ //_adjustmentChanged( _compUI[0]._adj, SP_COLOR_ICC_SELECTOR(_csel) );
+ _color.setColor(tmp);
+#ifdef DEBUG_LCMS
+ g_message("+_________________");
+#endif // DEBUG_LCMS
+ }
+}
+#endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
+
+#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
+void ColorICCSelectorImpl::_profilesChanged(std::string const &name)
+{
+ GtkComboBox *combo = GTK_COMBO_BOX(_profileSel);
+
+ g_signal_handler_block(G_OBJECT(_profileSel), _profChangedID);
+
+ GtkListStore *store = GTK_LIST_STORE(gtk_combo_box_get_model(combo));
+ gtk_list_store_clear(store);
+
+ GtkTreeIter iter;
+ gtk_list_store_append(store, &iter);
+ gtk_list_store_set(store, &iter, 0, _("<none>"), 1, _("<none>"), -1);
+
+ gtk_combo_box_set_active(combo, 0);
+
+ int index = 1;
+ const GSList *current = SP_ACTIVE_DOCUMENT->getResourceList("iccprofile");
+ while (current) {
+ SPObject *obj = SP_OBJECT(current->data);
+ Inkscape::ColorProfile *prof = reinterpret_cast<Inkscape::ColorProfile *>(obj);
+
+ gtk_list_store_append(store, &iter);
+ gtk_list_store_set(store, &iter, 0, gr_ellipsize_text(prof->name, 25).c_str(), 1, prof->name, -1);
+
+ if (name == prof->name) {
+ gtk_combo_box_set_active(combo, index);
+ gtk_widget_set_tooltip_text(_profileSel, prof->name);
+ }
+
+ index++;
+ current = g_slist_next(current);
+ }
+
+ g_signal_handler_unblock(G_OBJECT(_profileSel), _profChangedID);
+}
+#else
+void ColorICCSelectorImpl::_profilesChanged(std::string const & /*name*/) {}
+#endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
+
+void ColorICCSelector::on_show()
+{
+#if GTK_CHECK_VERSION(3, 0, 0)
+ Gtk::Grid::on_show();
+#else
+ Gtk::Table::on_show();
+#endif
+ _colorChanged();
+}
+
+// Helpers for setting color value
+
+void ColorICCSelector::_colorChanged()
+{
+ _impl->_updating = TRUE;
+// sp_color_icc_set_color( SP_COLOR_ICC( _icc ), &color );
+
+#ifdef DEBUG_LCMS
+ g_message("/^^^^^^^^^ %p::_colorChanged(%08x:%s)", this, _impl->_color.color().toRGBA32(_impl->_color.alpha()),
+ ((_impl->_color.color().icc) ? _impl->_color.color().icc->colorProfile.c_str() : "<null>"));
+#endif // DEBUG_LCMS
+
+#ifdef DEBUG_LCMS
+ g_message("FLIPPIES!!!! %p '%s'", _impl->_color.color().icc,
+ (_impl->_color.color().icc ? _impl->_color.color().icc->colorProfile.c_str() : "<null>"));
+#endif // DEBUG_LCMS
+
+ _impl->_profilesChanged((_impl->_color.color().icc) ? _impl->_color.color().icc->colorProfile : std::string(""));
+ ColorScales::setScaled(_impl->_adj, _impl->_color.alpha());
+
+#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
+ _impl->_setProfile(_impl->_color.color().icc);
+ _impl->_fixupNeeded = 0;
+ gtk_widget_set_sensitive(_impl->_fixupBtn, FALSE);
+
+ if (_impl->_prof) {
+ if (_impl->_prof->getTransfToSRGB8()) {
+ cmsUInt16Number tmp[4];
+ for (guint i = 0; i < _impl->_profChannelCount; i++) {
+ gdouble val = 0.0;
+ if (_impl->_color.color().icc->colors.size() > i) {
+ if (_impl->_compUI[i]._component.scale == 256) {
+ val = (_impl->_color.color().icc->colors[i] + 128.0) /
+ static_cast<gdouble>(_impl->_compUI[i]._component.scale);
+ }
+ else {
+ val = _impl->_color.color().icc->colors[i] /
+ static_cast<gdouble>(_impl->_compUI[i]._component.scale);
+ }
+ }
+ tmp[i] = val * 0x0ffff;
+ }
+ guchar post[4] = { 0, 0, 0, 0 };
+ cmsHTRANSFORM trans = _impl->_prof->getTransfToSRGB8();
+ if (trans) {
+ cmsDoTransform(trans, tmp, post, 1);
+ guint32 other = SP_RGBA32_U_COMPOSE(post[0], post[1], post[2], 255);
+ if (other != _impl->_color.color().toRGBA32(255)) {
+ _impl->_fixupNeeded = other;
+ gtk_widget_set_sensitive(_impl->_fixupBtn, TRUE);
+#ifdef DEBUG_LCMS
+ g_message("Color needs to change 0x%06x to 0x%06x", _color.toRGBA32(255) >> 8, other >> 8);
+#endif // DEBUG_LCMS
+ }
+ }
+ }
+ }
+#else
+//(void)color;
+#endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
+ _impl->_updateSliders(-1);
+
+
+ _impl->_updating = FALSE;
+#ifdef DEBUG_LCMS
+ g_message("\\_________ %p::_colorChanged()", this);
+#endif // DEBUG_LCMS
+}
+
+#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
+void ColorICCSelectorImpl::_setProfile(SVGICCColor *profile)
+{
+#ifdef DEBUG_LCMS
+ g_message("/^^^^^^^^^ %p::_setProfile(%s)", this, ((profile) ? profile->colorProfile.c_str() : "<null>"));
+#endif // DEBUG_LCMS
+ bool profChanged = false;
+ if (_prof && (!profile || (_profileName != profile->colorProfile))) {
+ // Need to clear out the prior one
+ profChanged = true;
+ _profileName.clear();
+ _prof = 0;
+ _profChannelCount = 0;
+ }
+ else if (profile && !_prof) {
+ profChanged = true;
+ }
+
+ for (size_t i = 0; i < _compUI.size(); i++) {
+ gtk_widget_hide(_compUI[i]._label);
+ _compUI[i]._slider->hide();
+ gtk_widget_hide(_compUI[i]._btn);
+ }
+
+ if (profile) {
+ _prof = SP_ACTIVE_DOCUMENT->profileManager->find(profile->colorProfile.c_str());
+ if (_prof && (asICColorProfileClassSig(_prof->getProfileClass()) != cmsSigNamedColorClass)) {
+#if HAVE_LIBLCMS1
+ _profChannelCount = _cmsChannelsOf(asICColorSpaceSig(_prof->getColorSpace()));
+#elif HAVE_LIBLCMS2
+ _profChannelCount = cmsChannelsOf(asICColorSpaceSig(_prof->getColorSpace()));
+#endif
+
+ if (profChanged) {
+ std::vector<colorspace::Component> things =
+ colorspace::getColorSpaceInfo(asICColorSpaceSig(_prof->getColorSpace()));
+ for (size_t i = 0; (i < things.size()) && (i < _profChannelCount); ++i) {
+ _compUI[i]._component = things[i];
+ }
+
+ for (guint i = 0; i < _profChannelCount; i++) {
+ gtk_label_set_text_with_mnemonic(GTK_LABEL(_compUI[i]._label),
+ (i < things.size()) ? things[i].name.c_str() : "");
+
+ _compUI[i]._slider->set_tooltip_text((i < things.size()) ? things[i].tip.c_str() : "");
+ gtk_widget_set_tooltip_text(_compUI[i]._btn, (i < things.size()) ? things[i].tip.c_str() : "");
+
+ _compUI[i]._slider->setColors(SPColor(0.0, 0.0, 0.0).toRGBA32(0xff),
+ SPColor(0.5, 0.5, 0.5).toRGBA32(0xff),
+ SPColor(1.0, 1.0, 1.0).toRGBA32(0xff));
+ /*
+ _compUI[i]._adj = GTK_ADJUSTMENT( gtk_adjustment_new( val, 0.0, _fooScales[i],
+ step, page, page ) );
+ g_signal_connect( G_OBJECT( _compUI[i]._adj ), "value_changed", G_CALLBACK(
+ _adjustmentChanged ), _csel );
+
+ sp_color_slider_set_adjustment( SP_COLOR_SLIDER(_compUI[i]._slider),
+ _compUI[i]._adj );
+ gtk_spin_button_set_adjustment( GTK_SPIN_BUTTON(_compUI[i]._btn),
+ _compUI[i]._adj );
+ gtk_spin_button_set_digits( GTK_SPIN_BUTTON(_compUI[i]._btn), digits );
+ */
+ gtk_widget_show(_compUI[i]._label);
+ _compUI[i]._slider->show();
+ gtk_widget_show(_compUI[i]._btn);
+ // gtk_adjustment_set_value( _compUI[i]._adj, 0.0 );
+ // gtk_adjustment_set_value( _compUI[i]._adj, val );
+ }
+ for (size_t i = _profChannelCount; i < _compUI.size(); i++) {
+ gtk_widget_hide(_compUI[i]._label);
+ _compUI[i]._slider->hide();
+ gtk_widget_hide(_compUI[i]._btn);
+ }
+ }
+ }
+ else {
+ // Give up for now on named colors
+ _prof = 0;
+ }
+ }
+
+#ifdef DEBUG_LCMS
+ g_message("\\_________ %p::_setProfile()", this);
+#endif // DEBUG_LCMS
+}
+#endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
+
+void ColorICCSelectorImpl::_updateSliders(gint ignore)
+{
+#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
+ if (_color.color().icc) {
+ for (guint i = 0; i < _profChannelCount; i++) {
+ gdouble val = 0.0;
+ if (_color.color().icc->colors.size() > i) {
+ if (_compUI[i]._component.scale == 256) {
+ val = (_color.color().icc->colors[i] + 128.0) / static_cast<gdouble>(_compUI[i]._component.scale);
+ }
+ else {
+ val = _color.color().icc->colors[i] / static_cast<gdouble>(_compUI[i]._component.scale);
+ }
+ }
+ gtk_adjustment_set_value(_compUI[i]._adj, val);
+ }
+
+ if (_prof) {
+ if (_prof->getTransfToSRGB8()) {
+ for (guint i = 0; i < _profChannelCount; i++) {
+ if (static_cast<gint>(i) != ignore) {
+ cmsUInt16Number *scratch = getScratch();
+ cmsUInt16Number filler[4] = { 0, 0, 0, 0 };
+ for (guint j = 0; j < _profChannelCount; j++) {
+ filler[j] = 0x0ffff * ColorScales::getScaled(_compUI[j]._adj);
+ }
+
+ cmsUInt16Number *p = scratch;
+ for (guint x = 0; x < 1024; x++) {
+ for (guint j = 0; j < _profChannelCount; j++) {
+ if (j == i) {
+ *p++ = x * 0x0ffff / 1024;
+ }
+ else {
+ *p++ = filler[j];
+ }
+ }
+ }
+
+ cmsHTRANSFORM trans = _prof->getTransfToSRGB8();
+ if (trans) {
+ cmsDoTransform(trans, scratch, _compUI[i]._map, 1024);
+ if (_compUI[i]._slider)
+ {
+ _compUI[i]._slider->setMap(_compUI[i]._map);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+#else
+ (void)ignore;
+#endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
+
+ guint32 start = _color.color().toRGBA32(0x00);
+ guint32 mid = _color.color().toRGBA32(0x7f);
+ guint32 end = _color.color().toRGBA32(0xff);
+
+ _slider->setColors(start, mid, end);
+}
+
+
+void ColorICCSelectorImpl::_adjustmentChanged(GtkAdjustment *adjustment, ColorICCSelectorImpl *cs)
+{
+// // TODO check this. It looks questionable:
+// // if a value is entered between 0 and 1 exclusive, normalize it to (int) 0..255 or 0..100
+// if (adjustment->value > 0.0 && adjustment->value < 1.0) {
+// gtk_adjustment_set_value( adjustment, floor ((adjustment->value) * adjustment->upper + 0.5) );
+// }
+
+#ifdef DEBUG_LCMS
+ g_message("/^^^^^^^^^ %p::_adjustmentChanged()", cs);
+#endif // DEBUG_LCMS
+
+ ColorICCSelector *iccSelector = cs->_owner;
+ if (iccSelector->_impl->_updating) {
+ return;
+ }
+
+ iccSelector->_impl->_updating = TRUE;
+
+ gint match = -1;
+
+ SPColor newColor(iccSelector->_impl->_color.color());
+ gfloat scaled = ColorScales::getScaled(iccSelector->_impl->_adj);
+ if (iccSelector->_impl->_adj == adjustment) {
+#ifdef DEBUG_LCMS
+ g_message("ALPHA");
+#endif // DEBUG_LCMS
+ }
+ else {
+#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
+ for (size_t i = 0; i < iccSelector->_impl->_compUI.size(); i++) {
+ if (iccSelector->_impl->_compUI[i]._adj == adjustment) {
+ match = i;
+ break;
+ }
+ }
+ if (match >= 0) {
+#ifdef DEBUG_LCMS
+ g_message(" channel %d", match);
+#endif // DEBUG_LCMS
+ }
+
+
+ cmsUInt16Number tmp[4];
+ for (guint i = 0; i < 4; i++) {
+ tmp[i] = ColorScales::getScaled(iccSelector->_impl->_compUI[i]._adj) * 0x0ffff;
+ }
+ guchar post[4] = { 0, 0, 0, 0 };
+
+ cmsHTRANSFORM trans = iccSelector->_impl->_prof->getTransfToSRGB8();
+ if (trans) {
+ cmsDoTransform(trans, tmp, post, 1);
+ }
+
+ SPColor other(SP_RGBA32_U_COMPOSE(post[0], post[1], post[2], 255));
+ other.icc = new SVGICCColor();
+ if (iccSelector->_impl->_color.color().icc) {
+ other.icc->colorProfile = iccSelector->_impl->_color.color().icc->colorProfile;
+ }
+
+ guint32 prior = iccSelector->_impl->_color.color().toRGBA32(255);
+ guint32 newer = other.toRGBA32(255);
+
+ if (prior != newer) {
+#ifdef DEBUG_LCMS
+ g_message("Transformed color from 0x%08x to 0x%08x", prior, newer);
+ g_message(" ~~~~ FLIP");
+#endif // DEBUG_LCMS
+ newColor = other;
+ newColor.icc->colors.clear();
+ for (guint i = 0; i < iccSelector->_impl->_profChannelCount; i++) {
+ gdouble val = ColorScales::getScaled(iccSelector->_impl->_compUI[i]._adj);
+ val *= iccSelector->_impl->_compUI[i]._component.scale;
+ if (iccSelector->_impl->_compUI[i]._component.scale == 256) {
+ val -= 128;
+ }
+ newColor.icc->colors.push_back(val);
+ }
+ }
+#endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
+ }
+ iccSelector->_impl->_color.setColorAlpha(newColor, scaled);
+ // iccSelector->_updateInternals( newColor, scaled, iccSelector->_impl->_dragging );
+ iccSelector->_impl->_updateSliders(match);
+
+ iccSelector->_impl->_updating = FALSE;
+#ifdef DEBUG_LCMS
+ g_message("\\_________ %p::_adjustmentChanged()", cs);
+#endif // DEBUG_LCMS
+}
+
+void ColorICCSelectorImpl::_sliderGrabbed()
+{
+ // ColorICCSelector* iccSelector = dynamic_cast<ColorICCSelector*>(SP_COLOR_SELECTOR(cs)->base);
+ // if (!iccSelector->_dragging) {
+ // iccSelector->_dragging = TRUE;
+ // iccSelector->_grabbed();
+ // iccSelector->_updateInternals( iccSelector->_color, ColorScales::getScaled( iccSelector->_impl->_adj ),
+ // iccSelector->_dragging );
+ // }
+}
+
+void ColorICCSelectorImpl::_sliderReleased()
+{
+ // ColorICCSelector* iccSelector = dynamic_cast<ColorICCSelector*>(SP_COLOR_SELECTOR(cs)->base);
+ // if (iccSelector->_dragging) {
+ // iccSelector->_dragging = FALSE;
+ // iccSelector->_released();
+ // iccSelector->_updateInternals( iccSelector->_color, ColorScales::getScaled( iccSelector->_adj ),
+ // iccSelector->_dragging );
+ // }
+}
+
+#ifdef DEBUG_LCMS
+void ColorICCSelectorImpl::_sliderChanged(SPColorSlider *slider, SPColorICCSelector *cs)
+#else
+void ColorICCSelectorImpl::_sliderChanged()
+#endif // DEBUG_LCMS
+{
+#ifdef DEBUG_LCMS
+ g_message("Changed %p and %p", slider, cs);
+#endif // DEBUG_LCMS
+ // ColorICCSelector* iccSelector = dynamic_cast<ColorICCSelector*>(SP_COLOR_SELECTOR(cs)->base);
+
+ // iccSelector->_updateInternals( iccSelector->_color, ColorScales::getScaled( iccSelector->_adj ),
+ // iccSelector->_dragging );
+}
+
+Gtk::Widget *ColorICCSelectorFactory::createWidget(Inkscape::UI::SelectedColor &color) const
+{
+ Gtk::Widget *w = Gtk::manage(new ColorICCSelector(color));
+ return w;
+}
+
+Glib::ustring ColorICCSelectorFactory::modeName() const { return gettext(ColorICCSelector::MODE_NAME); }
+}
+}
+}
+/*
+ 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/color-icc-selector.h b/src/ui/widget/color-icc-selector.h
new file mode 100644
index 000000000..1bcb0a540
--- /dev/null
+++ b/src/ui/widget/color-icc-selector.h
@@ -0,0 +1,78 @@
+#ifndef SEEN_SP_COLOR_ICC_SELECTOR_H
+#define SEEN_SP_COLOR_ICC_SELECTOR_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <gtkmm/widget.h>
+#if WITH_GTKMM_3_0
+#include <gtkmm/grid.h>
+#else
+#include <gtkmm/table.h>
+#endif
+
+#include "ui/selected-color.h"
+
+namespace Inkscape {
+
+class ColorProfile;
+
+namespace UI {
+namespace Widget {
+
+class ColorICCSelectorImpl;
+
+class ColorICCSelector
+#if GTK_CHECK_VERSION(3, 0, 0)
+ : public Gtk::Grid
+#else
+ : public Gtk::Table
+#endif
+ {
+ public:
+ static const gchar *MODE_NAME;
+
+ ColorICCSelector(SelectedColor &color);
+ virtual ~ColorICCSelector();
+
+ virtual void init();
+
+ protected:
+ void on_show();
+
+ virtual void _colorChanged();
+
+ void _recalcColor(gboolean changing);
+
+ private:
+ friend class ColorICCSelectorImpl;
+
+ // By default, disallow copy constructor and assignment operator
+ ColorICCSelector(const ColorICCSelector &obj);
+ ColorICCSelector &operator=(const ColorICCSelector &obj);
+
+ ColorICCSelectorImpl *_impl;
+};
+
+
+class ColorICCSelectorFactory : public ColorSelectorFactory {
+ public:
+ Gtk::Widget *createWidget(SelectedColor &color) const;
+ Glib::ustring modeName() const;
+};
+}
+}
+}
+#endif // SEEN_SP_COLOR_ICC_SELECTOR_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/color-notebook.cpp b/src/ui/widget/color-notebook.cpp
new file mode 100644
index 000000000..60abf43bf
--- /dev/null
+++ b/src/ui/widget/color-notebook.cpp
@@ -0,0 +1,379 @@
+/**
+ * @file
+ * A notebook with RGB, CMYK, CMS, HSL, and Wheel pages - implementation
+ */
+/* Authors:
+ * Lauris Kaplinski <lauris@kaplinski.com>
+ * bulia byak <buliabyak@users.sf.net>
+ * Tomasz Boczkowski <penginsbacon@gmail.com> (c++-sification)
+ *
+ * Copyright (C) 2001-2014 Authors
+ *
+ * This code is in public domain
+ */
+
+#undef SPCS_PREVIEW
+#define noDUMP_CHANGE_INFO
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "widgets/icon.h"
+#include <cstring>
+#include <string>
+#include <cstdlib>
+#include <cstddef>
+#include <glibmm/i18n.h>
+#include <gtkmm/label.h>
+#include <gtkmm/notebook.h>
+
+#include "preferences.h"
+#include "widgets/spw-utilities.h"
+#include "svg/svg-icc-color.h"
+#include "inkscape.h"
+#include "document.h"
+#include "profile-manager.h"
+#include "color-profile.h"
+#include "cms-system.h"
+#include "ui/dialog-events.h"
+#include "ui/tools-switch.h"
+#include "ui/tools/tool-base.h"
+#include "ui/widget/color-entry.h"
+#include "ui/widget/color-icc-selector.h"
+#include "ui/widget/color-notebook.h"
+#include "ui/widget/color-scales.h"
+#include "ui/widget/color-wheel-selector.h"
+
+using Inkscape::CMSSystem;
+
+#define XPAD 4
+#define YPAD 1
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+
+ColorNotebook::ColorNotebook(SelectedColor &color)
+#if GTK_CHECK_VERSION(3, 0, 0)
+ : Gtk::Grid()
+#else
+ : Gtk::Table(2, 3, false)
+#endif
+ , _selected_color(color)
+
+{
+ Page *page;
+
+ page = new Page(new ColorScalesFactory(SP_COLOR_SCALES_MODE_RGB), true);
+ _available_pages.push_back(page);
+ page = new Page(new ColorScalesFactory(SP_COLOR_SCALES_MODE_HSV), true);
+ _available_pages.push_back(page);
+ page = new Page(new ColorScalesFactory(SP_COLOR_SCALES_MODE_CMYK), true);
+ _available_pages.push_back(page);
+ page = new Page(new ColorWheelSelectorFactory, true);
+ _available_pages.push_back(page);
+#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
+ page = new Page(new ColorICCSelectorFactory, true);
+ _available_pages.push_back(page);
+#endif
+
+ _initUI();
+
+ _selected_color.signal_changed.connect(sigc::mem_fun(this, &ColorNotebook::_onSelectedColorChanged));
+ _selected_color.signal_dragged.connect(sigc::mem_fun(this, &ColorNotebook::_onSelectedColorChanged));
+}
+
+ColorNotebook::~ColorNotebook()
+{
+ if (_buttons) {
+ delete[] _buttons;
+ _buttons = 0;
+ }
+}
+
+ColorNotebook::Page::Page(Inkscape::UI::ColorSelectorFactory *selector_factory, bool enabled_full)
+ : selector_factory(selector_factory)
+ , enabled_full(enabled_full)
+{
+}
+
+
+void ColorNotebook::_initUI()
+{
+ guint row = 0;
+
+ Gtk::Notebook *notebook = Gtk::manage(new Gtk::Notebook);
+ notebook->show();
+ notebook->set_show_border(false);
+ notebook->set_show_tabs(false);
+ _book = GTK_WIDGET(notebook->gobj());
+
+#if GTK_CHECK_VERSION(3, 0, 0)
+ _buttonbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 2);
+ gtk_box_set_homogeneous(GTK_BOX(_buttonbox), TRUE);
+#else
+ _buttonbox = gtk_hbox_new(TRUE, 2);
+#endif
+
+ gtk_widget_show(_buttonbox);
+ _buttons = new GtkWidget *[_available_pages.size()];
+
+ for (int i = 0; static_cast<size_t>(i) < _available_pages.size(); i++) {
+ _addPage(_available_pages[i]);
+ }
+
+ sp_set_font_size_smaller(_buttonbox);
+
+#if GTK_CHECK_VERSION(3, 0, 0)
+ #if GTK_CHECK_VERSION(3, 12, 0)
+ gtk_widget_set_margin_start(_buttonbox, XPAD);
+ gtk_widget_set_margin_end(_buttonbox, XPAD);
+ #else
+ gtk_widget_set_margin_left(_buttonbox, XPAD);
+ gtk_widget_set_margin_right(_buttonbox, XPAD);
+ #endif
+ gtk_widget_set_margin_top(_buttonbox, YPAD);
+ gtk_widget_set_margin_bottom(_buttonbox, YPAD);
+ gtk_widget_set_hexpand(_buttonbox, TRUE);
+ gtk_widget_set_valign(_buttonbox, GTK_ALIGN_CENTER);
+ attach(*Glib::wrap(_buttonbox), 0, row, 2, 1);
+#else
+ attach(*Glib::wrap(_buttonbox), 0, 2, row, row + 1, Gtk::EXPAND | Gtk::FILL, static_cast<Gtk::AttachOptions>(0),
+ XPAD, YPAD);
+#endif
+
+ row++;
+
+#if GTK_CHECK_VERSION(3, 0, 0)
+#if GTK_CHECK_VERSION(3, 12, 0)
+ gtk_widget_set_margin_start(_book, XPAD * 2);
+ gtk_widget_set_margin_end(_book, XPAD * 2);
+#else
+ gtk_widget_set_margin_left(_book, XPAD * 2);
+ gtk_widget_set_margin_right(_book, XPAD * 2);
+#endif
+ gtk_widget_set_margin_top(_book, YPAD);
+ gtk_widget_set_margin_bottom(_book, YPAD);
+ gtk_widget_set_hexpand(_book, TRUE);
+ gtk_widget_set_vexpand(_book, TRUE);
+ attach(*notebook, 0, row, 2, 1);
+#else
+ attach(*notebook, 0, 2, row, row + 1, Gtk::EXPAND | Gtk::FILL, Gtk::EXPAND | Gtk::FILL, XPAD * 2, YPAD);
+#endif
+
+ // restore the last active page
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ _setCurrentPage(prefs->getInt("/colorselector/page", 0));
+ row++;
+
+#if GTK_CHECK_VERSION(3, 0, 0)
+ GtkWidget *rgbabox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
+#else
+ GtkWidget *rgbabox = gtk_hbox_new(FALSE, 0);
+#endif
+
+#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
+ /* Create color management icons */
+ _box_colormanaged = gtk_event_box_new();
+ GtkWidget *colormanaged = gtk_image_new_from_icon_name("color-management-icon", GTK_ICON_SIZE_SMALL_TOOLBAR);
+ gtk_container_add(GTK_CONTAINER(_box_colormanaged), colormanaged);
+ gtk_widget_set_tooltip_text(_box_colormanaged, _("Color Managed"));
+ gtk_widget_set_sensitive(_box_colormanaged, false);
+ gtk_box_pack_start(GTK_BOX(rgbabox), _box_colormanaged, FALSE, FALSE, 2);
+
+ _box_outofgamut = gtk_event_box_new();
+ GtkWidget *outofgamut = gtk_image_new_from_icon_name("out-of-gamut-icon", GTK_ICON_SIZE_SMALL_TOOLBAR);
+ gtk_container_add(GTK_CONTAINER(_box_outofgamut), outofgamut);
+ gtk_widget_set_tooltip_text(_box_outofgamut, _("Out of gamut!"));
+ gtk_widget_set_sensitive(_box_outofgamut, false);
+ gtk_box_pack_start(GTK_BOX(rgbabox), _box_outofgamut, FALSE, FALSE, 2);
+
+ _box_toomuchink = gtk_event_box_new();
+ GtkWidget *toomuchink = gtk_image_new_from_icon_name("too-much-ink-icon", GTK_ICON_SIZE_SMALL_TOOLBAR);
+ gtk_container_add(GTK_CONTAINER(_box_toomuchink), toomuchink);
+ gtk_widget_set_tooltip_text(_box_toomuchink, _("Too much ink!"));
+ gtk_widget_set_sensitive(_box_toomuchink, false);
+ gtk_box_pack_start(GTK_BOX(rgbabox), _box_toomuchink, FALSE, FALSE, 2);
+#endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
+
+
+ /* Color picker */
+ GtkWidget *picker = gtk_image_new_from_icon_name("color-picker", GTK_ICON_SIZE_SMALL_TOOLBAR);
+ _btn_picker = gtk_button_new();
+ gtk_button_set_relief(GTK_BUTTON(_btn_picker), GTK_RELIEF_NONE);
+ gtk_container_add(GTK_CONTAINER(_btn_picker), picker);
+ gtk_widget_set_tooltip_text(_btn_picker, _("Pick colors from image"));
+ gtk_box_pack_start(GTK_BOX(rgbabox), _btn_picker, FALSE, FALSE, 2);
+ g_signal_connect(G_OBJECT(_btn_picker), "clicked", G_CALLBACK(ColorNotebook::_onPickerClicked), this);
+
+ /* Create RGBA entry and color preview */
+ _rgbal = gtk_label_new_with_mnemonic(_("RGBA_:"));
+ gtk_misc_set_alignment(GTK_MISC(_rgbal), 1.0, 0.5);
+ gtk_box_pack_start(GTK_BOX(rgbabox), _rgbal, TRUE, TRUE, 2);
+
+ ColorEntry *rgba_entry = Gtk::manage(new ColorEntry(_selected_color));
+ sp_dialog_defocus_on_enter(GTK_WIDGET(rgba_entry->gobj()));
+ gtk_box_pack_start(GTK_BOX(rgbabox), GTK_WIDGET(rgba_entry->gobj()), FALSE, FALSE, 0);
+ gtk_label_set_mnemonic_widget(GTK_LABEL(_rgbal), GTK_WIDGET(rgba_entry->gobj()));
+
+ sp_set_font_size_smaller(rgbabox);
+ gtk_widget_show_all(rgbabox);
+
+#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
+ // the "too much ink" icon is initially hidden
+ gtk_widget_hide(GTK_WIDGET(_box_toomuchink));
+#endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
+
+#if GTK_CHECK_VERSION(3, 0, 0)
+ #if GTK_CHECK_VERSION(3, 12, 0)
+ gtk_widget_set_margin_start(rgbabox, XPAD);
+ gtk_widget_set_margin_end(rgbabox, XPAD);
+ #else
+ gtk_widget_set_margin_left(rgbabox, XPAD);
+ gtk_widget_set_margin_right(rgbabox, XPAD);
+ #endif
+ gtk_widget_set_margin_top(rgbabox, YPAD);
+ gtk_widget_set_margin_bottom(rgbabox, YPAD);
+ attach(*Glib::wrap(rgbabox), 0, row, 2, 1);
+#else
+ attach(*Glib::wrap(rgbabox), 0, 2, row, row + 1, Gtk::FILL, Gtk::SHRINK, XPAD, YPAD);
+#endif
+
+#ifdef SPCS_PREVIEW
+ _p = sp_color_preview_new(0xffffffff);
+ gtk_widget_show(_p);
+ attach(*Glib::wrap(_p), 2, 3, row, row + 1, Gtk::FILL, Gtk::FILL, XPAD, YPAD);
+#endif
+
+ g_signal_connect(G_OBJECT(_book), "switch-page", G_CALLBACK(ColorNotebook::_onPageSwitched), this);
+}
+
+void ColorNotebook::_onPickerClicked(GtkWidget * /*widget*/, ColorNotebook * /*colorbook*/)
+{
+ // Set the dropper into a "one click" mode, so it reverts to the previous tool after a click
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ prefs->setBool("/tools/dropper/onetimepick", true);
+ Inkscape::UI::Tools::sp_toggle_dropper(SP_ACTIVE_DESKTOP);
+}
+
+void ColorNotebook::_onButtonClicked(GtkWidget *widget, ColorNotebook *nb)
+{
+ if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) {
+ return;
+ }
+
+ for (gint i = 0; i < gtk_notebook_get_n_pages(GTK_NOTEBOOK(nb->_book)); i++) {
+ if (nb->_buttons[i] == widget) {
+ gtk_notebook_set_current_page(GTK_NOTEBOOK(nb->_book), i);
+ }
+ }
+}
+
+void ColorNotebook::_onSelectedColorChanged() { _updateICCButtons(); }
+
+void ColorNotebook::_onPageSwitched(GtkNotebook *notebook, GtkWidget *page, guint page_num, ColorNotebook *colorbook)
+{
+ if (colorbook->get_visible()) {
+ // remember the page we switched to
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ prefs->setInt("/colorselector/page", page_num);
+ }
+}
+
+
+// TODO pass in param so as to avoid the need for SP_ACTIVE_DOCUMENT
+void ColorNotebook::_updateICCButtons()
+{
+ SPColor color = _selected_color.color();
+ gfloat alpha = _selected_color.alpha();
+
+ g_return_if_fail((0.0 <= alpha) && (alpha <= 1.0));
+
+#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
+ /* update color management icon*/
+ gtk_widget_set_sensitive(_box_colormanaged, color.icc != NULL);
+
+ /* update out-of-gamut icon */
+ gtk_widget_set_sensitive(_box_outofgamut, false);
+ if (color.icc) {
+ Inkscape::ColorProfile *target_profile =
+ SP_ACTIVE_DOCUMENT->profileManager->find(color.icc->colorProfile.c_str());
+ if (target_profile)
+ gtk_widget_set_sensitive(_box_outofgamut, target_profile->GamutCheck(color));
+ }
+
+ /* update too-much-ink icon */
+ gtk_widget_set_sensitive(_box_toomuchink, false);
+ if (color.icc) {
+ Inkscape::ColorProfile *prof = SP_ACTIVE_DOCUMENT->profileManager->find(color.icc->colorProfile.c_str());
+ if (prof && CMSSystem::isPrintColorSpace(prof)) {
+ gtk_widget_show(GTK_WIDGET(_box_toomuchink));
+ double ink_sum = 0;
+ for (unsigned int i = 0; i < color.icc->colors.size(); i++) {
+ ink_sum += color.icc->colors[i];
+ }
+
+ /* Some literature states that when the sum of paint values exceed 320%, it is considered to be a satured
+ color,
+ which means the paper can get too wet due to an excessive ammount of ink. This may lead to several
+ issues
+ such as misalignment and poor quality of printing in general.*/
+ if (ink_sum > 3.2)
+ gtk_widget_set_sensitive(_box_toomuchink, true);
+ }
+ else {
+ gtk_widget_hide(GTK_WIDGET(_box_toomuchink));
+ }
+ }
+#endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
+}
+
+void ColorNotebook::_setCurrentPage(int i)
+{
+ gtk_notebook_set_current_page(GTK_NOTEBOOK(_book), i);
+
+ if (_buttons && (static_cast<size_t>(i) < _available_pages.size())) {
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(_buttons[i]), TRUE);
+ }
+}
+
+void ColorNotebook::_addPage(Page &page)
+{
+ Gtk::Widget *selector_widget;
+
+ selector_widget = page.selector_factory->createWidget(_selected_color);
+ if (selector_widget) {
+ selector_widget->show();
+
+ Glib::ustring mode_name = page.selector_factory->modeName();
+ Gtk::Widget *tab_label = Gtk::manage(new Gtk::Label(mode_name));
+ gint page_num = gtk_notebook_append_page(GTK_NOTEBOOK(_book), selector_widget->gobj(), tab_label->gobj());
+
+ _buttons[page_num] = gtk_radio_button_new_with_label(NULL, mode_name.c_str());
+ gtk_toggle_button_set_mode(GTK_TOGGLE_BUTTON(_buttons[page_num]), FALSE);
+ if (page_num > 0) {
+ GSList *group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(_buttons[0]));
+ gtk_radio_button_set_group(GTK_RADIO_BUTTON(_buttons[page_num]), group);
+ }
+ gtk_widget_show(_buttons[page_num]);
+ gtk_box_pack_start(GTK_BOX(_buttonbox), _buttons[page_num], TRUE, TRUE, 0);
+
+ g_signal_connect(G_OBJECT(_buttons[page_num]), "clicked", G_CALLBACK(_onButtonClicked), this);
+ }
+}
+}
+}
+}
+
+/*
+ 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/color-notebook.h b/src/ui/widget/color-notebook.h
new file mode 100644
index 000000000..d28028c72
--- /dev/null
+++ b/src/ui/widget/color-notebook.h
@@ -0,0 +1,99 @@
+/**
+ * @file
+ * A notebook with RGB, CMYK, CMS, HSL, and Wheel pages
+ */
+/* Authors:
+ * Lauris Kaplinski <lauris@kaplinski.com>
+ * bulia byak <buliabyak@users.sf.net>
+ * Tomasz Boczkowski <penginsbacon@gmail.com> (c++-sification)
+ *
+ * Copyright (C) 2001-2014 Authors
+ *
+ * This code is in public domain
+ */
+#ifndef SEEN_SP_COLOR_NOTEBOOK_H
+#define SEEN_SP_COLOR_NOTEBOOK_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <boost/ptr_container/ptr_vector.hpp>
+#if WITH_GTKMM_3_0
+#include <gtkmm/grid.h>
+#else
+#include <gtkmm/table.h>
+#endif
+#include <gtk/gtk.h>
+#include <glib.h>
+
+#include "color.h"
+#include "ui/selected-color.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+class ColorNotebook
+#if GTK_CHECK_VERSION(3, 0, 0)
+ : public Gtk::Grid
+#else
+ : public Gtk::Table
+#endif
+{
+public:
+ ColorNotebook(SelectedColor &color);
+ virtual ~ColorNotebook();
+
+protected:
+ struct Page {
+ Page(Inkscape::UI::ColorSelectorFactory *selector_factory, bool enabled_full);
+
+ Inkscape::UI::ColorSelectorFactory *selector_factory;
+ bool enabled_full;
+ };
+
+ virtual void _initUI();
+ void _addPage(Page &page);
+
+ static void _onButtonClicked(GtkWidget *widget, ColorNotebook *colorbook);
+ static void _onPickerClicked(GtkWidget *widget, ColorNotebook *colorbook);
+ static void _onPageSwitched(GtkNotebook *notebook, GtkWidget *page, guint page_num, ColorNotebook *colorbook);
+ virtual void _onSelectedColorChanged();
+
+ void _updateICCButtons();
+ void _setCurrentPage(int i);
+
+ Inkscape::UI::SelectedColor &_selected_color;
+ gulong _entryId;
+ GtkWidget *_book;
+ GtkWidget *_buttonbox;
+ GtkWidget **_buttons;
+ GtkWidget *_rgbal; /* RGBA entry */
+#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
+ GtkWidget *_box_outofgamut, *_box_colormanaged, *_box_toomuchink;
+#endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
+ GtkWidget *_btn_picker;
+ GtkWidget *_p; /* Color preview */
+ boost::ptr_vector<Page> _available_pages;
+
+private:
+ // By default, disallow copy constructor and assignment operator
+ ColorNotebook(const ColorNotebook &obj);
+ ColorNotebook &operator=(const ColorNotebook &obj);
+};
+}
+}
+}
+#endif // SEEN_SP_COLOR_NOTEBOOK_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/color-picker.cpp b/src/ui/widget/color-picker.cpp
index d4c4d394e..a66fbfc9c 100644
--- a/src/ui/widget/color-picker.cpp
+++ b/src/ui/widget/color-picker.cpp
@@ -17,7 +17,7 @@
#include "document-undo.h"
#include "ui/dialog-events.h"
-#include "widgets/sp-color-notebook.h"
+#include "ui/widget/color-notebook.h"
#include "verbs.h"
@@ -27,8 +27,6 @@ namespace Inkscape {
namespace UI {
namespace Widget {
-void sp_color_picker_color_mod(SPColorSelector *csel, GObject *cp);
-
ColorPicker::ColorPicker (const Glib::ustring& title, const Glib::ustring& tip,
guint32 rgba, bool undo)
: _preview(rgba), _title(title), _rgba(rgba), _undo(undo),
@@ -39,12 +37,15 @@ ColorPicker::ColorPicker (const Glib::ustring& title, const Glib::ustring& tip,
_preview.show();
add (_preview);
set_tooltip_text (tip);
+
+ _selected_color.signal_changed.connect(sigc::mem_fun(this, &ColorPicker::_onSelectedColorChanged));
+ _selected_color.signal_dragged.connect(sigc::mem_fun(this, &ColorPicker::_onSelectedColorChanged));
+ _selected_color.signal_released.connect(sigc::mem_fun(this, &ColorPicker::_onSelectedColorChanged));
}
ColorPicker::~ColorPicker()
{
closeWindow();
- _colorSelector = NULL;
}
void ColorPicker::setupDialog(const Glib::ustring &title)
@@ -55,25 +56,17 @@ void ColorPicker::setupDialog(const Glib::ustring &title)
_colorSelectorDialog.hide();
_colorSelectorDialog.set_title (title);
_colorSelectorDialog.set_border_width (4);
- _colorSelector = SP_COLOR_SELECTOR(sp_color_selector_new(SP_TYPE_COLOR_NOTEBOOK));
+
+ _color_selector = Gtk::manage(new ColorNotebook(_selected_color));
#if WITH_GTKMM_3_0
_colorSelectorDialog.get_content_area()->pack_start (
- *Glib::wrap(&_colorSelector->vbox), true, true, 0);
+ *_color_selector, true, true, 0);
#else
_colorSelectorDialog.get_vbox()->pack_start (
- *Glib::wrap(&_colorSelector->vbox), true, true, 0);
+ *_color_selector, true, true, 0);
#endif
-
- g_signal_connect(G_OBJECT(_colorSelector), "dragged",
- G_CALLBACK(sp_color_picker_color_mod), (void *)this);
- g_signal_connect(G_OBJECT(_colorSelector), "released",
- G_CALLBACK(sp_color_picker_color_mod), (void *)this);
- g_signal_connect(G_OBJECT(_colorSelector), "changed",
- G_CALLBACK(sp_color_picker_color_mod), (void *)this);
-
- gtk_widget_show(GTK_WIDGET(_colorSelector));
-
+ _color_selector->show();
}
void ColorPicker::setRgba32 (guint32 rgba)
@@ -82,11 +75,11 @@ void ColorPicker::setRgba32 (guint32 rgba)
_preview.setRgba32 (rgba);
_rgba = rgba;
- if (_colorSelector)
+ if (_color_selector)
{
- SPColor color;
- color.set( rgba );
- _colorSelector->base->setColorAlpha(color, SP_RGBA32_A_F(rgba));
+ _updating = true;
+ _selected_color.setValue(rgba);
+ _updating = false;
}
}
@@ -97,11 +90,11 @@ void ColorPicker::closeWindow()
void ColorPicker::on_clicked()
{
- if (_colorSelector)
+ if (_color_selector)
{
- SPColor color;
- color.set( _rgba );
- _colorSelector->base->setColorAlpha(color, SP_RGBA32_A_F(_rgba));
+ _updating = true;
+ _selected_color.setValue(_rgba);
+ _updating = false;
}
_colorSelectorDialog.show();
}
@@ -110,34 +103,31 @@ void ColorPicker::on_changed (guint32)
{
}
-void sp_color_picker_color_mod(SPColorSelector *csel, GObject *cp)
-{
+void ColorPicker::_onSelectedColorChanged() {
+ if (_updating) {
+ return;
+ }
+
if (_in_use) {
return;
} else {
_in_use = true;
}
- SPColor color;
- float alpha = 0;
- csel->base->getColorAlpha(color, alpha);
- guint32 rgba = color.toRGBA32( alpha );
-
- ColorPicker *ptr = reinterpret_cast<ColorPicker *>(cp);
-
- (ptr->_preview).setRgba32 (rgba);
+ guint32 rgba = _selected_color.value();
+ _preview.setRgba32(rgba);
- if (ptr->_undo && SP_ACTIVE_DESKTOP)
+ if (_undo && SP_ACTIVE_DESKTOP) {
DocumentUndo::done(SP_ACTIVE_DESKTOP->getDocument(), SP_VERB_NONE,
/* TODO: annotate */ "color-picker.cpp:130");
+ }
- ptr->on_changed (rgba);
+ on_changed(rgba);
_in_use = false;
- ptr->_changed_signal.emit (rgba);
- ptr->_rgba = rgba;
+ _changed_signal.emit(rgba);
+ _rgba = rgba;
}
-
}//namespace Widget
}//namespace UI
}//namespace Inkscape
diff --git a/src/ui/widget/color-picker.h b/src/ui/widget/color-picker.h
index 99904b081..e8a738b5b 100644
--- a/src/ui/widget/color-picker.h
+++ b/src/ui/widget/color-picker.h
@@ -18,6 +18,7 @@
#include <gtkmm/dialog.h>
#include <gtkmm/button.h>
#include <sigc++/sigc++.h>
+#include "ui/selected-color.h"
#include "ui/widget/color-preview.h"
struct SPColorSelector;
@@ -49,7 +50,7 @@ public:
protected:
- friend void sp_color_picker_color_mod(SPColorSelector *csel, GObject *cp);
+ void _onSelectedColorChanged();
virtual void on_clicked();
virtual void on_changed (guint32);
@@ -59,13 +60,14 @@ protected:
sigc::signal<void,guint32> _changed_signal;
guint32 _rgba;
bool _undo;
-
+ bool _updating;
//Dialog
void setupDialog(const Glib::ustring &title);
//Inkscape::UI::Dialog::Dialog _colorSelectorDialog;
Gtk::Dialog _colorSelectorDialog;
- SPColorSelector *_colorSelector;
+ SelectedColor _selected_color;
+ Gtk::Widget *_color_selector;
};
}//namespace Widget
diff --git a/src/ui/widget/color-scales.cpp b/src/ui/widget/color-scales.cpp
new file mode 100644
index 000000000..170f83887
--- /dev/null
+++ b/src/ui/widget/color-scales.cpp
@@ -0,0 +1,677 @@
+/*
+ * bulia byak <buliabyak@users.sf.net>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <math.h>
+#include <gtkmm/adjustment.h>
+#include <glibmm/i18n.h>
+#include <gtk/gtk.h>
+
+#include "svg/svg-icc-color.h"
+#include "ui/dialog-events.h"
+#include "ui/widget/color-scales.h"
+#include "ui/widget/color-slider.h"
+
+#define CSC_CHANNEL_R (1 << 0)
+#define CSC_CHANNEL_G (1 << 1)
+#define CSC_CHANNEL_B (1 << 2)
+#define CSC_CHANNEL_A (1 << 3)
+#define CSC_CHANNEL_H (1 << 0)
+#define CSC_CHANNEL_S (1 << 1)
+#define CSC_CHANNEL_V (1 << 2)
+#define CSC_CHANNEL_C (1 << 0)
+#define CSC_CHANNEL_M (1 << 1)
+#define CSC_CHANNEL_Y (1 << 2)
+#define CSC_CHANNEL_K (1 << 3)
+#define CSC_CHANNEL_CMYKA (1 << 4)
+
+#define CSC_CHANNELS_ALL 0
+
+#define XPAD 4
+#define YPAD 1
+
+#define noDUMP_CHANGE_INFO 1
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+
+static const gchar *sp_color_scales_hue_map();
+
+const gchar *ColorScales::SUBMODE_NAMES[] = { N_("None"), N_("RGB"), N_("HSL"), N_("CMYK") };
+
+ColorScales::ColorScales(SelectedColor &color, SPColorScalesMode mode)
+#if GTK_CHECK_VERSION(3, 0, 0)
+ : Gtk::Grid()
+#else
+ : Gtk::Table(5, 3, false)
+#endif
+ , _color(color)
+ , _rangeLimit(255.0)
+ , _updating(FALSE)
+ , _dragging(FALSE)
+{
+ for (gint i = 0; i < 5; i++) {
+ _l[i] = 0;
+ _a[i] = 0;
+ _s[i] = 0;
+ _b[i] = 0;
+ }
+
+ _initUI(mode);
+
+ _color.signal_changed.connect(sigc::mem_fun(this, &ColorScales::_onColorChanged));
+ _color.signal_dragged.connect(sigc::mem_fun(this, &ColorScales::_onColorChanged));
+}
+
+ColorScales::~ColorScales()
+{
+ for (gint i = 0; i < 5; i++) {
+ _l[i] = 0;
+ _a[i] = 0;
+ _s[i] = 0;
+ _b[i] = 0;
+ }
+}
+
+void ColorScales::_initUI(SPColorScalesMode mode)
+{
+ gint i;
+
+ _updating = FALSE;
+ _dragging = FALSE;
+
+ GtkWidget *t = GTK_WIDGET(gobj());
+
+ /* Create components */
+ for (i = 0; i < static_cast<gint>(G_N_ELEMENTS(_a)); i++) {
+ /* Label */
+ _l[i] = gtk_label_new("");
+ gtk_misc_set_alignment(GTK_MISC(_l[i]), 1.0, 0.5);
+ gtk_widget_show(_l[i]);
+
+#if GTK_CHECK_VERSION(3, 0, 0)
+ #if GTK_CHECK_VERSION(3, 12, 0)
+ gtk_widget_set_margin_start(_l[i], XPAD);
+ gtk_widget_set_margin_end(_l[i], XPAD);
+ #else
+ gtk_widget_set_margin_left(_l[i], XPAD);
+ gtk_widget_set_margin_right(_l[i], XPAD);
+ #endif
+ gtk_widget_set_margin_top(_l[i], YPAD);
+ gtk_widget_set_margin_bottom(_l[i], YPAD);
+ gtk_grid_attach(GTK_GRID(t), _l[i], 0, i, 1, 1);
+#else
+ gtk_table_attach(GTK_TABLE(t), _l[i], 0, 1, i, i + 1, GTK_FILL, GTK_FILL, XPAD, YPAD);
+#endif
+
+ /* Adjustment */
+ _a[i] = GTK_ADJUSTMENT(gtk_adjustment_new(0.0, 0.0, _rangeLimit, 1.0, 10.0, 10.0));
+ /* Slider */
+ _s[i] = Gtk::manage(new Inkscape::UI::Widget::ColorSlider(Glib::wrap(_a[i], true)));
+ _s[i]->show();
+
+#if GTK_CHECK_VERSION(3, 0, 0)
+ #if GTK_CHECK_VERSION(3, 12, 0)
+ _s[i]->set_margin_start(XPAD);
+ _s[i]->set_margin_end(XPAD);
+ #else
+ _s[i]->set_margin_left(XPAD);
+ _s[i]->set_margin_right(XPAD);
+ #endif
+ _s[i]->set_margin_top(YPAD);
+ _s[i]->set_margin_bottom(YPAD);
+ _s[i]->set_hexpand(true);
+ gtk_grid_attach(GTK_GRID(t), _s[i]->gobj(), 1, i, 1, 1);
+#else
+ gtk_table_attach(GTK_TABLE(t), _s[i]->gobj(), 1, 2, i, i + 1, (GtkAttachOptions)(GTK_EXPAND | GTK_FILL),
+ GTK_FILL, XPAD, YPAD);
+#endif
+
+ /* Spinbutton */
+ _b[i] = gtk_spin_button_new(GTK_ADJUSTMENT(_a[i]), 1.0, 0);
+ sp_dialog_defocus_on_enter(_b[i]);
+ gtk_label_set_mnemonic_widget(GTK_LABEL(_l[i]), _b[i]);
+ gtk_widget_show(_b[i]);
+
+#if GTK_CHECK_VERSION(3, 0, 0)
+ #if GTK_CHECK_VERSION(3, 12, 0)
+ gtk_widget_set_margin_start(_b[i], XPAD);
+ gtk_widget_set_margin_end(_b[i], XPAD);
+ #else
+ gtk_widget_set_margin_left(_b[i], XPAD);
+ gtk_widget_set_margin_right(_b[i], XPAD);
+ #endif
+ gtk_widget_set_margin_top(_b[i], YPAD);
+ gtk_widget_set_margin_bottom(_b[i], YPAD);
+ gtk_widget_set_halign(_b[i], GTK_ALIGN_CENTER);
+ gtk_widget_set_valign(_b[i], GTK_ALIGN_CENTER);
+ gtk_grid_attach(GTK_GRID(t), _b[i], 2, i, 1, 1);
+#else
+ gtk_table_attach(GTK_TABLE(t), _b[i], 2, 3, i, i + 1, (GtkAttachOptions)0, (GtkAttachOptions)0, XPAD, YPAD);
+#endif
+
+ /* Attach channel value to adjustment */
+ g_object_set_data(G_OBJECT(_a[i]), "channel", GINT_TO_POINTER(i));
+ /* Signals */
+ g_signal_connect(G_OBJECT(_a[i]), "value_changed", G_CALLBACK(_adjustmentAnyChanged), this);
+ _s[i]->signal_grabbed.connect(sigc::mem_fun(this, &ColorScales::_sliderAnyGrabbed));
+ _s[i]->signal_released.connect(sigc::mem_fun(this, &ColorScales::_sliderAnyReleased));
+ _s[i]->signal_value_changed.connect(sigc::mem_fun(this, &ColorScales::_sliderAnyChanged));
+ }
+
+ //Prevent 5th bar from being shown by PanelDialog::show_all_children
+ gtk_widget_set_no_show_all(_l[4], TRUE);
+ _s[4]->set_no_show_all(true);
+ gtk_widget_set_no_show_all(_b[4], TRUE);
+
+ /* Initial mode is none, so it works */
+ setMode(mode);
+}
+
+void ColorScales::_recalcColor()
+{
+ SPColor color;
+ gfloat alpha = 1.0;
+ gfloat c[5];
+
+ switch (_mode) {
+ case SP_COLOR_SCALES_MODE_RGB:
+ case SP_COLOR_SCALES_MODE_HSV:
+ _getRgbaFloatv(c);
+ color.set(c[0], c[1], c[2]);
+ alpha = c[3];
+ break;
+ case SP_COLOR_SCALES_MODE_CMYK: {
+ _getCmykaFloatv(c);
+
+ float rgb[3];
+ sp_color_cmyk_to_rgb_floatv(rgb, c[0], c[1], c[2], c[3]);
+ color.set(rgb[0], rgb[1], rgb[2]);
+ alpha = c[4];
+ break;
+ }
+ default:
+ g_warning("file %s: line %d: Illegal color selector mode %d", __FILE__, __LINE__, _mode);
+ break;
+ }
+
+ _color.preserveICC();
+ _color.setColorAlpha(color, alpha);
+}
+
+void ColorScales::_updateDisplay()
+{
+#ifdef DUMP_CHANGE_INFO
+ g_message("ColorScales::_onColorChanged( this=%p, %f, %f, %f, %f)", this, _color.color().v.c[0],
+ _color.color().v.c[1], _color.color().v.c[2], _color.alpha());
+#endif
+ gfloat tmp[3];
+ gfloat c[5] = { 0.0, 0.0, 0.0, 0.0 };
+
+ SPColor color = _color.color();
+
+ switch (_mode) {
+ case SP_COLOR_SCALES_MODE_RGB:
+ sp_color_get_rgb_floatv(&color, c);
+ c[3] = _color.alpha();
+ c[4] = 0.0;
+ break;
+ case SP_COLOR_SCALES_MODE_HSV:
+ sp_color_get_rgb_floatv(&color, tmp);
+ sp_color_rgb_to_hsl_floatv(c, tmp[0], tmp[1], tmp[2]);
+ c[3] = _color.alpha();
+ c[4] = 0.0;
+ break;
+ case SP_COLOR_SCALES_MODE_CMYK:
+ sp_color_get_cmyk_floatv(&color, c);
+ c[4] = _color.alpha();
+ break;
+ default:
+ g_warning("file %s: line %d: Illegal color selector mode %d", __FILE__, __LINE__, _mode);
+ break;
+ }
+
+ _updating = TRUE;
+ setScaled(_a[0], c[0]);
+ setScaled(_a[1], c[1]);
+ setScaled(_a[2], c[2]);
+ setScaled(_a[3], c[3]);
+ setScaled(_a[4], c[4]);
+ _updateSliders(CSC_CHANNELS_ALL);
+ _updating = FALSE;
+}
+
+/* Helpers for setting color value */
+gfloat ColorScales::getScaled(const GtkAdjustment *a)
+{
+ gfloat val = gtk_adjustment_get_value(const_cast<GtkAdjustment *>(a)) /
+ gtk_adjustment_get_upper(const_cast<GtkAdjustment *>(a));
+ return val;
+}
+
+void ColorScales::setScaled(GtkAdjustment *a, gfloat v)
+{
+ gfloat val = v * gtk_adjustment_get_upper(a);
+ gtk_adjustment_set_value(a, val);
+}
+
+void ColorScales::_setRangeLimit(gdouble upper)
+{
+ _rangeLimit = upper;
+ for (gint i = 0; i < static_cast<gint>(G_N_ELEMENTS(_a)); i++) {
+ gtk_adjustment_set_upper(_a[i], upper);
+ gtk_adjustment_changed(_a[i]);
+ }
+}
+
+void ColorScales::_onColorChanged()
+{
+ if (!get_visible()) {
+ return;
+ }
+ _updateDisplay();
+}
+
+void ColorScales::on_show()
+{
+#if GTK_CHECK_VERSION(3, 0, 0)
+ Gtk::Grid::on_show();
+#else
+ Gtk::Table::on_show();
+#endif
+ _updateDisplay();
+}
+
+void ColorScales::_getRgbaFloatv(gfloat *rgba)
+{
+ g_return_if_fail(rgba != NULL);
+
+ switch (_mode) {
+ case SP_COLOR_SCALES_MODE_RGB:
+ rgba[0] = getScaled(_a[0]);
+ rgba[1] = getScaled(_a[1]);
+ rgba[2] = getScaled(_a[2]);
+ rgba[3] = getScaled(_a[3]);
+ break;
+ case SP_COLOR_SCALES_MODE_HSV:
+ sp_color_hsl_to_rgb_floatv(rgba, getScaled(_a[0]), getScaled(_a[1]), getScaled(_a[2]));
+ rgba[3] = getScaled(_a[3]);
+ break;
+ case SP_COLOR_SCALES_MODE_CMYK:
+ sp_color_cmyk_to_rgb_floatv(rgba, getScaled(_a[0]), getScaled(_a[1]), getScaled(_a[2]), getScaled(_a[3]));
+ rgba[3] = getScaled(_a[4]);
+ break;
+ default:
+ g_warning("file %s: line %d: Illegal color selector mode", __FILE__, __LINE__);
+ break;
+ }
+}
+
+void ColorScales::_getCmykaFloatv(gfloat *cmyka)
+{
+ gfloat rgb[3];
+
+ g_return_if_fail(cmyka != NULL);
+
+ switch (_mode) {
+ case SP_COLOR_SCALES_MODE_RGB:
+ sp_color_rgb_to_cmyk_floatv(cmyka, getScaled(_a[0]), getScaled(_a[1]), getScaled(_a[2]));
+ cmyka[4] = getScaled(_a[3]);
+ break;
+ case SP_COLOR_SCALES_MODE_HSV:
+ sp_color_hsl_to_rgb_floatv(rgb, getScaled(_a[0]), getScaled(_a[1]), getScaled(_a[2]));
+ sp_color_rgb_to_cmyk_floatv(cmyka, rgb[0], rgb[1], rgb[2]);
+ cmyka[4] = getScaled(_a[3]);
+ break;
+ case SP_COLOR_SCALES_MODE_CMYK:
+ cmyka[0] = getScaled(_a[0]);
+ cmyka[1] = getScaled(_a[1]);
+ cmyka[2] = getScaled(_a[2]);
+ cmyka[3] = getScaled(_a[3]);
+ cmyka[4] = getScaled(_a[4]);
+ break;
+ default:
+ g_warning("file %s: line %d: Illegal color selector mode", __FILE__, __LINE__);
+ break;
+ }
+}
+
+guint32 ColorScales::_getRgba32()
+{
+ gfloat c[4];
+ guint32 rgba;
+
+ _getRgbaFloatv(c);
+
+ rgba = SP_RGBA32_F_COMPOSE(c[0], c[1], c[2], c[3]);
+
+ return rgba;
+}
+
+void ColorScales::setMode(SPColorScalesMode mode)
+{
+ gfloat rgba[4];
+ gfloat c[4];
+
+ if (_mode == mode)
+ return;
+
+ if ((_mode == SP_COLOR_SCALES_MODE_RGB) || (_mode == SP_COLOR_SCALES_MODE_HSV) ||
+ (_mode == SP_COLOR_SCALES_MODE_CMYK)) {
+ _getRgbaFloatv(rgba);
+ }
+ else {
+ rgba[0] = rgba[1] = rgba[2] = rgba[3] = 1.0;
+ }
+
+ _mode = mode;
+
+ switch (mode) {
+ case SP_COLOR_SCALES_MODE_RGB:
+ _setRangeLimit(255.0);
+ gtk_label_set_markup_with_mnemonic(GTK_LABEL(_l[0]), _("_R:"));
+ _s[0]->set_tooltip_text(_("Red"));
+ gtk_widget_set_tooltip_text(_b[0], _("Red"));
+ gtk_label_set_markup_with_mnemonic(GTK_LABEL(_l[1]), _("_G:"));
+ _s[1]->set_tooltip_text(_("Green"));
+ gtk_widget_set_tooltip_text(_b[1], _("Green"));
+ gtk_label_set_markup_with_mnemonic(GTK_LABEL(_l[2]), _("_B:"));
+ _s[2]->set_tooltip_text(_("Blue"));
+ gtk_widget_set_tooltip_text(_b[2], _("Blue"));
+ gtk_label_set_markup_with_mnemonic(GTK_LABEL(_l[3]), _("_A:"));
+ _s[3]->set_tooltip_text(_("Alpha (opacity)"));
+ gtk_widget_set_tooltip_text(_b[3], _("Alpha (opacity)"));
+ _s[0]->setMap(NULL);
+ gtk_widget_hide(_l[4]);
+ _s[4]->hide();
+ gtk_widget_hide(_b[4]);
+ _updating = TRUE;
+ setScaled(_a[0], rgba[0]);
+ setScaled(_a[1], rgba[1]);
+ setScaled(_a[2], rgba[2]);
+ setScaled(_a[3], rgba[3]);
+ _updateSliders(CSC_CHANNELS_ALL);
+ _updating = FALSE;
+ break;
+ case SP_COLOR_SCALES_MODE_HSV:
+ _setRangeLimit(255.0);
+ gtk_label_set_markup_with_mnemonic(GTK_LABEL(_l[0]), _("_H:"));
+ _s[0]->set_tooltip_text(_("Hue"));
+ gtk_widget_set_tooltip_text(_b[0], _("Hue"));
+ gtk_label_set_markup_with_mnemonic(GTK_LABEL(_l[1]), _("_S:"));
+ _s[1]->set_tooltip_text(_("Saturation"));
+ gtk_widget_set_tooltip_text(_b[1], _("Saturation"));
+ gtk_label_set_markup_with_mnemonic(GTK_LABEL(_l[2]), _("_L:"));
+ _s[2]->set_tooltip_text(_("Lightness"));
+ gtk_widget_set_tooltip_text(_b[2], _("Lightness"));
+ gtk_label_set_markup_with_mnemonic(GTK_LABEL(_l[3]), _("_A:"));
+ _s[3]->set_tooltip_text(_("Alpha (opacity)"));
+ gtk_widget_set_tooltip_text(_b[3], _("Alpha (opacity)"));
+ _s[0]->setMap((guchar *)(sp_color_scales_hue_map()));
+ gtk_widget_hide(_l[4]);
+ _s[4]->hide();
+ gtk_widget_hide(_b[4]);
+ _updating = TRUE;
+ c[0] = 0.0;
+ sp_color_rgb_to_hsl_floatv(c, rgba[0], rgba[1], rgba[2]);
+ setScaled(_a[0], c[0]);
+ setScaled(_a[1], c[1]);
+ setScaled(_a[2], c[2]);
+ setScaled(_a[3], rgba[3]);
+ _updateSliders(CSC_CHANNELS_ALL);
+ _updating = FALSE;
+ break;
+ case SP_COLOR_SCALES_MODE_CMYK:
+ _setRangeLimit(100.0);
+ gtk_label_set_markup_with_mnemonic(GTK_LABEL(_l[0]), _("_C:"));
+ _s[0]->set_tooltip_text(_("Cyan"));
+ gtk_widget_set_tooltip_text(_b[0], _("Cyan"));
+ gtk_label_set_markup_with_mnemonic(GTK_LABEL(_l[1]), _("_M:"));
+ _s[1]->set_tooltip_text(_("Magenta"));
+ gtk_widget_set_tooltip_text(_b[1], _("Magenta"));
+ gtk_label_set_markup_with_mnemonic(GTK_LABEL(_l[2]), _("_Y:"));
+ _s[2]->set_tooltip_text(_("Yellow"));
+ gtk_widget_set_tooltip_text(_b[2], _("Yellow"));
+ gtk_label_set_markup_with_mnemonic(GTK_LABEL(_l[3]), _("_K:"));
+ _s[3]->set_tooltip_text(_("Black"));
+ gtk_widget_set_tooltip_text(_b[3], _("Black"));
+ gtk_label_set_markup_with_mnemonic(GTK_LABEL(_l[4]), _("_A:"));
+ _s[4]->set_tooltip_text(_("Alpha (opacity)"));
+ gtk_widget_set_tooltip_text(_b[4], _("Alpha (opacity)"));
+ _s[0]->setMap(NULL);
+ gtk_widget_show(_l[4]);
+ _s[4]->show();
+ gtk_widget_show(_b[4]);
+ _updating = TRUE;
+
+ sp_color_rgb_to_cmyk_floatv(c, rgba[0], rgba[1], rgba[2]);
+ setScaled(_a[0], c[0]);
+ setScaled(_a[1], c[1]);
+ setScaled(_a[2], c[2]);
+ setScaled(_a[3], c[3]);
+
+ setScaled(_a[4], rgba[3]);
+ _updateSliders(CSC_CHANNELS_ALL);
+ _updating = FALSE;
+ break;
+ default:
+ g_warning("file %s: line %d: Illegal color selector mode", __FILE__, __LINE__);
+ break;
+ }
+}
+
+SPColorScalesMode ColorScales::getMode() const { return _mode; }
+
+void ColorScales::_adjustmentAnyChanged(GtkAdjustment *adjustment, ColorScales *cs)
+{
+ gint channel = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(adjustment), "channel"));
+
+ _adjustmentChanged(cs, channel);
+}
+
+void ColorScales::_sliderAnyGrabbed()
+{
+ if (_updating) {
+ return;
+ }
+ if (!_dragging) {
+ _dragging = TRUE;
+ _color.setHeld(true);
+ }
+}
+
+void ColorScales::_sliderAnyReleased()
+{
+ if (_updating) {
+ return;
+ }
+ if (_dragging) {
+ _dragging = FALSE;
+ _color.setHeld(false);
+ }
+}
+
+void ColorScales::_sliderAnyChanged()
+{
+ if (_updating) {
+ return;
+ }
+ _recalcColor();
+}
+
+void ColorScales::_adjustmentChanged(ColorScales *scales, guint channel)
+{
+ if (scales->_updating) {
+ return;
+ }
+
+ scales->_updateSliders((1 << channel));
+ scales->_recalcColor();
+}
+
+void ColorScales::_updateSliders(guint channels)
+{
+ gfloat rgb0[3], rgbm[3], rgb1[3];
+#ifdef SPCS_PREVIEW
+ guint32 rgba;
+#endif
+ switch (_mode) {
+ case SP_COLOR_SCALES_MODE_RGB:
+ if ((channels != CSC_CHANNEL_R) && (channels != CSC_CHANNEL_A)) {
+ /* Update red */
+ _s[0]->setColors(SP_RGBA32_F_COMPOSE(0.0, getScaled(_a[1]), getScaled(_a[2]), 1.0),
+ SP_RGBA32_F_COMPOSE(0.5, getScaled(_a[1]), getScaled(_a[2]), 1.0),
+ SP_RGBA32_F_COMPOSE(1.0, getScaled(_a[1]), getScaled(_a[2]), 1.0));
+ }
+ if ((channels != CSC_CHANNEL_G) && (channels != CSC_CHANNEL_A)) {
+ /* Update green */
+ _s[1]->setColors(SP_RGBA32_F_COMPOSE(getScaled(_a[0]), 0.0, getScaled(_a[2]), 1.0),
+ SP_RGBA32_F_COMPOSE(getScaled(_a[0]), 0.5, getScaled(_a[2]), 1.0),
+ SP_RGBA32_F_COMPOSE(getScaled(_a[0]), 1.0, getScaled(_a[2]), 1.0));
+ }
+ if ((channels != CSC_CHANNEL_B) && (channels != CSC_CHANNEL_A)) {
+ /* Update blue */
+ _s[2]->setColors(SP_RGBA32_F_COMPOSE(getScaled(_a[0]), getScaled(_a[1]), 0.0, 1.0),
+ SP_RGBA32_F_COMPOSE(getScaled(_a[0]), getScaled(_a[1]), 0.5, 1.0),
+ SP_RGBA32_F_COMPOSE(getScaled(_a[0]), getScaled(_a[1]), 1.0, 1.0));
+ }
+ if (channels != CSC_CHANNEL_A) {
+ /* Update alpha */
+ _s[3]->setColors(SP_RGBA32_F_COMPOSE(getScaled(_a[0]), getScaled(_a[1]), getScaled(_a[2]), 0.0),
+ SP_RGBA32_F_COMPOSE(getScaled(_a[0]), getScaled(_a[1]), getScaled(_a[2]), 0.5),
+ SP_RGBA32_F_COMPOSE(getScaled(_a[0]), getScaled(_a[1]), getScaled(_a[2]), 1.0));
+ }
+ break;
+ case SP_COLOR_SCALES_MODE_HSV:
+ /* Hue is never updated */
+ if ((channels != CSC_CHANNEL_S) && (channels != CSC_CHANNEL_A)) {
+ /* Update saturation */
+ sp_color_hsl_to_rgb_floatv(rgb0, getScaled(_a[0]), 0.0, getScaled(_a[2]));
+ sp_color_hsl_to_rgb_floatv(rgbm, getScaled(_a[0]), 0.5, getScaled(_a[2]));
+ sp_color_hsl_to_rgb_floatv(rgb1, getScaled(_a[0]), 1.0, getScaled(_a[2]));
+ _s[1]->setColors(SP_RGBA32_F_COMPOSE(rgb0[0], rgb0[1], rgb0[2], 1.0),
+ SP_RGBA32_F_COMPOSE(rgbm[0], rgbm[1], rgbm[2], 1.0),
+ SP_RGBA32_F_COMPOSE(rgb1[0], rgb1[1], rgb1[2], 1.0));
+ }
+ if ((channels != CSC_CHANNEL_V) && (channels != CSC_CHANNEL_A)) {
+ /* Update value */
+ sp_color_hsl_to_rgb_floatv(rgb0, getScaled(_a[0]), getScaled(_a[1]), 0.0);
+ sp_color_hsl_to_rgb_floatv(rgbm, getScaled(_a[0]), getScaled(_a[1]), 0.5);
+ sp_color_hsl_to_rgb_floatv(rgb1, getScaled(_a[0]), getScaled(_a[1]), 1.0);
+ _s[2]->setColors(SP_RGBA32_F_COMPOSE(rgb0[0], rgb0[1], rgb0[2], 1.0),
+ SP_RGBA32_F_COMPOSE(rgbm[0], rgbm[1], rgbm[2], 1.0),
+ SP_RGBA32_F_COMPOSE(rgb1[0], rgb1[1], rgb1[2], 1.0));
+ }
+ if (channels != CSC_CHANNEL_A) {
+ /* Update alpha */
+ sp_color_hsl_to_rgb_floatv(rgb0, getScaled(_a[0]), getScaled(_a[1]), getScaled(_a[2]));
+ _s[3]->setColors(SP_RGBA32_F_COMPOSE(rgb0[0], rgb0[1], rgb0[2], 0.0),
+ SP_RGBA32_F_COMPOSE(rgb0[0], rgb0[1], rgb0[2], 0.5),
+ SP_RGBA32_F_COMPOSE(rgb0[0], rgb0[1], rgb0[2], 1.0));
+ }
+ break;
+ case SP_COLOR_SCALES_MODE_CMYK:
+ if ((channels != CSC_CHANNEL_C) && (channels != CSC_CHANNEL_CMYKA)) {
+ /* Update C */
+ sp_color_cmyk_to_rgb_floatv(rgb0, 0.0, getScaled(_a[1]), getScaled(_a[2]), getScaled(_a[3]));
+ sp_color_cmyk_to_rgb_floatv(rgbm, 0.5, getScaled(_a[1]), getScaled(_a[2]), getScaled(_a[3]));
+ sp_color_cmyk_to_rgb_floatv(rgb1, 1.0, getScaled(_a[1]), getScaled(_a[2]), getScaled(_a[3]));
+ _s[0]->setColors(SP_RGBA32_F_COMPOSE(rgb0[0], rgb0[1], rgb0[2], 1.0),
+ SP_RGBA32_F_COMPOSE(rgbm[0], rgbm[1], rgbm[2], 1.0),
+ SP_RGBA32_F_COMPOSE(rgb1[0], rgb1[1], rgb1[2], 1.0));
+ }
+ if ((channels != CSC_CHANNEL_M) && (channels != CSC_CHANNEL_CMYKA)) {
+ /* Update M */
+ sp_color_cmyk_to_rgb_floatv(rgb0, getScaled(_a[0]), 0.0, getScaled(_a[2]), getScaled(_a[3]));
+ sp_color_cmyk_to_rgb_floatv(rgbm, getScaled(_a[0]), 0.5, getScaled(_a[2]), getScaled(_a[3]));
+ sp_color_cmyk_to_rgb_floatv(rgb1, getScaled(_a[0]), 1.0, getScaled(_a[2]), getScaled(_a[3]));
+ _s[1]->setColors(SP_RGBA32_F_COMPOSE(rgb0[0], rgb0[1], rgb0[2], 1.0),
+ SP_RGBA32_F_COMPOSE(rgbm[0], rgbm[1], rgbm[2], 1.0),
+ SP_RGBA32_F_COMPOSE(rgb1[0], rgb1[1], rgb1[2], 1.0));
+ }
+ if ((channels != CSC_CHANNEL_Y) && (channels != CSC_CHANNEL_CMYKA)) {
+ /* Update Y */
+ sp_color_cmyk_to_rgb_floatv(rgb0, getScaled(_a[0]), getScaled(_a[1]), 0.0, getScaled(_a[3]));
+ sp_color_cmyk_to_rgb_floatv(rgbm, getScaled(_a[0]), getScaled(_a[1]), 0.5, getScaled(_a[3]));
+ sp_color_cmyk_to_rgb_floatv(rgb1, getScaled(_a[0]), getScaled(_a[1]), 1.0, getScaled(_a[3]));
+ _s[2]->setColors(SP_RGBA32_F_COMPOSE(rgb0[0], rgb0[1], rgb0[2], 1.0),
+ SP_RGBA32_F_COMPOSE(rgbm[0], rgbm[1], rgbm[2], 1.0),
+ SP_RGBA32_F_COMPOSE(rgb1[0], rgb1[1], rgb1[2], 1.0));
+ }
+ if ((channels != CSC_CHANNEL_K) && (channels != CSC_CHANNEL_CMYKA)) {
+ /* Update K */
+ sp_color_cmyk_to_rgb_floatv(rgb0, getScaled(_a[0]), getScaled(_a[1]), getScaled(_a[2]), 0.0);
+ sp_color_cmyk_to_rgb_floatv(rgbm, getScaled(_a[0]), getScaled(_a[1]), getScaled(_a[2]), 0.5);
+ sp_color_cmyk_to_rgb_floatv(rgb1, getScaled(_a[0]), getScaled(_a[1]), getScaled(_a[2]), 1.0);
+ _s[3]->setColors(SP_RGBA32_F_COMPOSE(rgb0[0], rgb0[1], rgb0[2], 1.0),
+ SP_RGBA32_F_COMPOSE(rgbm[0], rgbm[1], rgbm[2], 1.0),
+ SP_RGBA32_F_COMPOSE(rgb1[0], rgb1[1], rgb1[2], 1.0));
+ }
+ if (channels != CSC_CHANNEL_CMYKA) {
+ /* Update alpha */
+ sp_color_cmyk_to_rgb_floatv(rgb0, getScaled(_a[0]), getScaled(_a[1]), getScaled(_a[2]),
+ getScaled(_a[3]));
+ _s[4]->setColors(SP_RGBA32_F_COMPOSE(rgb0[0], rgb0[1], rgb0[2], 0.0),
+ SP_RGBA32_F_COMPOSE(rgb0[0], rgb0[1], rgb0[2], 0.5),
+ SP_RGBA32_F_COMPOSE(rgb0[0], rgb0[1], rgb0[2], 1.0));
+ }
+ break;
+ default:
+ g_warning("file %s: line %d: Illegal color selector mode", __FILE__, __LINE__);
+ break;
+ }
+
+#ifdef SPCS_PREVIEW
+ rgba = sp_color_scales_get_rgba32(cs);
+ sp_color_preview_set_rgba32(SP_COLOR_PREVIEW(_p), rgba);
+#endif
+}
+
+static const gchar *sp_color_scales_hue_map(void)
+{
+ static gchar *map = NULL;
+
+ if (!map) {
+ gchar *p;
+ gint h;
+ map = g_new(gchar, 4 * 1024);
+ p = map;
+ for (h = 0; h < 1024; h++) {
+ gfloat rgb[3];
+ sp_color_hsl_to_rgb_floatv(rgb, h / 1024.0, 1.0, 0.5);
+ *p++ = SP_COLOR_F_TO_U(rgb[0]);
+ *p++ = SP_COLOR_F_TO_U(rgb[1]);
+ *p++ = SP_COLOR_F_TO_U(rgb[2]);
+ *p++ = 255;
+ }
+ }
+
+ return map;
+}
+
+ColorScalesFactory::ColorScalesFactory(SPColorScalesMode submode)
+ : _submode(submode)
+{
+}
+
+ColorScalesFactory::~ColorScalesFactory() {}
+
+Gtk::Widget *ColorScalesFactory::createWidget(Inkscape::UI::SelectedColor &color) const
+{
+ Gtk::Widget *w = Gtk::manage(new ColorScales(color, _submode));
+ return w;
+}
+
+Glib::ustring ColorScalesFactory::modeName() const {
+ return gettext(ColorScales::SUBMODE_NAMES[_submode]);
+}
+
+}
+}
+}
diff --git a/src/ui/widget/color-scales.h b/src/ui/widget/color-scales.h
new file mode 100644
index 000000000..aeacfbcc1
--- /dev/null
+++ b/src/ui/widget/color-scales.h
@@ -0,0 +1,112 @@
+#ifndef SEEN_SP_COLOR_SCALES_H
+#define SEEN_SP_COLOR_SCALES_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#if WITH_GTKMM_3_0
+#include <gtkmm/grid.h>
+#else
+#include <gtkmm/table.h>
+#endif
+
+#include "ui/selected-color.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+class ColorSlider;
+
+typedef enum {
+ SP_COLOR_SCALES_MODE_NONE = 0,
+ SP_COLOR_SCALES_MODE_RGB = 1,
+ SP_COLOR_SCALES_MODE_HSV = 2,
+ SP_COLOR_SCALES_MODE_CMYK = 3
+} SPColorScalesMode;
+
+class ColorScales
+#if GTK_CHECK_VERSION(3, 0, 0)
+ : public Gtk::Grid
+#else
+ : public Gtk::Table
+#endif
+{
+public:
+ static const gchar *SUBMODE_NAMES[];
+
+ static gfloat getScaled(const GtkAdjustment *a);
+ static void setScaled(GtkAdjustment *a, gfloat v);
+
+ ColorScales(SelectedColor &color, SPColorScalesMode mode);
+ virtual ~ColorScales();
+
+ virtual void _initUI(SPColorScalesMode mode);
+
+ void setMode(SPColorScalesMode mode);
+ SPColorScalesMode getMode() const;
+
+protected:
+ void _onColorChanged();
+ void on_show();
+
+ static void _adjustmentAnyChanged(GtkAdjustment *adjustment, ColorScales *cs);
+ void _sliderAnyGrabbed();
+ void _sliderAnyReleased();
+ void _sliderAnyChanged();
+ static void _adjustmentChanged(ColorScales *cs, guint channel);
+
+ void _getRgbaFloatv(gfloat *rgba);
+ void _getCmykaFloatv(gfloat *cmyka);
+ guint32 _getRgba32();
+ void _updateSliders(guint channels);
+ void _recalcColor();
+ void _updateDisplay();
+
+ void _setRangeLimit(gdouble upper);
+
+ SelectedColor &_color;
+ SPColorScalesMode _mode;
+ gdouble _rangeLimit;
+ gboolean _updating : 1;
+ gboolean _dragging : 1;
+ GtkAdjustment *_a[5]; /* Channel adjustments */
+ Inkscape::UI::Widget::ColorSlider *_s[5]; /* Channel sliders */
+ GtkWidget *_b[5]; /* Spinbuttons */
+ GtkWidget *_l[5]; /* Labels */
+
+private:
+ // By default, disallow copy constructor and assignment operator
+ ColorScales(ColorScales const &obj);
+ ColorScales &operator=(ColorScales const &obj);
+};
+
+class ColorScalesFactory : public Inkscape::UI::ColorSelectorFactory
+{
+public:
+ ColorScalesFactory(SPColorScalesMode submode);
+ ~ColorScalesFactory();
+
+ Gtk::Widget *createWidget(Inkscape::UI::SelectedColor &color) const;
+ Glib::ustring modeName() const;
+
+private:
+ SPColorScalesMode _submode;
+};
+
+}
+}
+}
+
+#endif /* !SEEN_SP_COLOR_SCALES_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 :
diff --git a/src/ui/widget/color-slider.cpp b/src/ui/widget/color-slider.cpp
new file mode 100644
index 000000000..0c9586a67
--- /dev/null
+++ b/src/ui/widget/color-slider.cpp
@@ -0,0 +1,633 @@
+/**
+ * @file
+ * A slider with colored background - implementation.
+ */
+/* Author:
+ * Lauris Kaplinski <lauris@kaplinski.com>
+ * bulia byak <buliabyak@users.sf.net>
+ *
+ * Copyright (C) 2001-2002 Lauris Kaplinski
+ *
+ * This code is in public domain
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gdkmm/cursor.h>
+#include <gdkmm/screen.h>
+#include <gdkmm/general.h>
+#include <gtkmm/adjustment.h>
+#if WITH_GTKMM_3_0
+#include <gtkmm/stylecontext.h>
+#else
+#include <gtkmm/style.h>
+#endif
+#include <gtk/gtk.h>
+
+#include "ui/widget/color-scales.h"
+#include "ui/widget/color-slider.h"
+#include "preferences.h"
+
+static const gint SLIDER_WIDTH = 96;
+static const gint SLIDER_HEIGHT = 8;
+static const gint ARROW_SIZE = 7;
+
+static const guchar *sp_color_slider_render_gradient(gint x0, gint y0, gint width, gint height, gint c[], gint dc[],
+ guint b0, guint b1, guint mask);
+static const guchar *sp_color_slider_render_map(gint x0, gint y0, gint width, gint height, guchar *map, gint start,
+ gint step, guint b0, guint b1, guint mask);
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+#if GTK_CHECK_VERSION(3, 0, 0)
+ColorSlider::ColorSlider(Glib::RefPtr<Gtk::Adjustment> adjustment)
+ : _dragging(false)
+#else
+ColorSlider::ColorSlider(Gtk::Adjustment *adjustment)
+ : _dragging(false)
+ , _adjustment(NULL)
+#endif
+ , _value(0.0)
+ , _oldvalue(0.0)
+ , _mapsize(0)
+ , _map(NULL)
+{
+ _c0[0] = 0x00;
+ _c0[1] = 0x00;
+ _c0[2] = 0x00;
+ _c0[3] = 0xff;
+
+ _cm[0] = 0xff;
+ _cm[1] = 0x00;
+ _cm[2] = 0x00;
+ _cm[3] = 0xff;
+
+ _c0[0] = 0xff;
+ _c0[1] = 0xff;
+ _c0[2] = 0xff;
+ _c0[3] = 0xff;
+
+ _b0 = 0x5f;
+ _b1 = 0xa0;
+ _bmask = 0x08;
+
+ setAdjustment(adjustment);
+}
+
+ColorSlider::~ColorSlider()
+{
+ if (_adjustment) {
+ _adjustment_changed_connection.disconnect();
+ _adjustment_value_changed_connection.disconnect();
+#if GTK_CHECK_VERSION(3, 0, 0)
+ _adjustment.reset();
+#else
+ _adjustment->unreference();
+ _adjustment = NULL;
+#endif
+ }
+}
+
+void ColorSlider::on_realize()
+{
+ set_realized();
+
+ if (!_gdk_window) {
+ GdkWindowAttr attributes;
+ gint attributes_mask;
+ Gtk::Allocation allocation = get_allocation();
+
+ memset(&attributes, 0, sizeof(attributes));
+ attributes.x = allocation.get_x();
+ attributes.y = allocation.get_y();
+ attributes.width = allocation.get_width();
+ attributes.height = allocation.get_height();
+ attributes.window_type = GDK_WINDOW_CHILD;
+ attributes.wclass = GDK_INPUT_OUTPUT;
+ attributes.visual = gdk_screen_get_system_visual(gdk_screen_get_default());
+#if !GTK_CHECK_VERSION(3, 0, 0)
+ attributes.colormap = gdk_screen_get_system_colormap(gdk_screen_get_default());
+#endif
+ attributes.event_mask = get_events();
+ attributes.event_mask |= (Gdk::EXPOSURE_MASK | Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK |
+ Gdk::POINTER_MOTION_MASK | Gdk::ENTER_NOTIFY_MASK | Gdk::LEAVE_NOTIFY_MASK);
+
+#if GTK_CHECK_VERSION(3, 0, 0)
+ attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL;
+#else
+ attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
+#endif
+
+ _gdk_window = Gdk::Window::create(get_parent_window(), &attributes, attributes_mask);
+ set_window(_gdk_window);
+ _gdk_window->set_user_data(gobj());
+
+#if !GTK_CHECK_VERSION(3, 0, 0)
+ style_attach();
+#endif
+ }
+}
+
+void ColorSlider::on_unrealize()
+{
+ _gdk_window.reset();
+
+ Gtk::Widget::on_unrealize();
+}
+
+void ColorSlider::on_size_allocate(Gtk::Allocation &allocation)
+{
+ set_allocation(allocation);
+
+ if (get_realized()) {
+ _gdk_window->move_resize(allocation.get_x(), allocation.get_y(), allocation.get_width(),
+ allocation.get_height());
+ }
+}
+
+#if GTK_CHECK_VERSION(3, 0, 0)
+
+void ColorSlider::get_preferred_width_vfunc(int &minimum_width, int &natural_width) const
+{
+ Glib::RefPtr<Gtk::StyleContext> style_context = get_style_context();
+ Gtk::Border padding = style_context->get_padding(get_state_flags());
+ int width = SLIDER_WIDTH + padding.get_left() + padding.get_right();
+ minimum_width = natural_width = width;
+}
+
+void ColorSlider::get_preferred_width_for_height_vfunc(int /*height*/, int &minimum_width, int &natural_width) const
+{
+ get_preferred_width(minimum_width, natural_width);
+}
+
+void ColorSlider::get_preferred_height_vfunc(int &minimum_height, int &natural_height) const
+{
+ Glib::RefPtr<Gtk::StyleContext> style_context = get_style_context();
+ Gtk::Border padding = style_context->get_padding(get_state_flags());
+ int height = SLIDER_HEIGHT + padding.get_top() + padding.get_bottom();
+ minimum_height = natural_height = height;
+}
+
+void ColorSlider::get_preferred_height_for_width_vfunc(int /*width*/, int &minimum_height, int &natural_height) const
+{
+ get_preferred_height(minimum_height, natural_height);
+}
+
+#else
+
+void ColorSlider::on_size_request(Gtk::Requisition *requisition)
+{
+ GtkStyle *style = gtk_widget_get_style(gobj());
+ requisition->width = SLIDER_WIDTH + style->xthickness * 2;
+ requisition->height = SLIDER_HEIGHT + style->ythickness * 2;
+}
+
+bool ColorSlider::on_expose_event(GdkEventExpose *event)
+{
+ bool result = false;
+
+ if (get_is_drawable()) {
+ Cairo::RefPtr<Cairo::Context> cr = _gdk_window->create_cairo_context();
+ result = on_draw(cr);
+ }
+ return result;
+}
+
+#endif
+
+bool ColorSlider::on_button_press_event(GdkEventButton *event)
+{
+ if (event->button == 1) {
+ Gtk::Allocation allocation = get_allocation();
+ gint cx, cw;
+#if GTK_CHECK_VERSION(3, 0, 0)
+ cx = get_style_context()->get_padding(get_state_flags()).get_left();
+#else
+ cx = get_style()->get_xthickness();
+#endif
+ cw = allocation.get_width() - 2 * cx;
+ signal_grabbed.emit();
+ _dragging = true;
+ _oldvalue = _value;
+ ColorScales::setScaled(_adjustment->gobj(), CLAMP((gfloat)(event->x - cx) / cw, 0.0, 1.0));
+ signal_dragged.emit();
+
+#if GTK_CHECK_VERSION(3, 0, 0)
+ gdk_device_grab(
+ gdk_event_get_device(reinterpret_cast<GdkEvent *>(event)), _gdk_window->gobj(), GDK_OWNERSHIP_NONE, FALSE,
+ static_cast<GdkEventMask>(GDK_POINTER_MOTION_MASK | GDK_BUTTON_RELEASE_MASK), NULL, event->time);
+#else
+ gdk_pointer_grab(get_window()->gobj(), FALSE,
+ static_cast<GdkEventMask>(GDK_POINTER_MOTION_MASK | GDK_BUTTON_RELEASE_MASK), NULL, NULL,
+ event->time);
+#endif
+ }
+
+ return false;
+}
+
+bool ColorSlider::on_button_release_event(GdkEventButton *event)
+{
+ if (event->button == 1) {
+
+#if GTK_CHECK_VERSION(3, 0, 0)
+ gdk_device_ungrab(gdk_event_get_device(reinterpret_cast<GdkEvent *>(event)),
+ gdk_event_get_time(reinterpret_cast<GdkEvent *>(event)));
+#else
+ get_window()->pointer_ungrab(event->time);
+#endif
+
+ _dragging = false;
+ signal_released.emit();
+ if (_value != _oldvalue) {
+ signal_value_changed.emit();
+ }
+ }
+
+ return false;
+}
+
+bool ColorSlider::on_motion_notify_event(GdkEventMotion *event)
+{
+ if (_dragging) {
+ gint cx, cw;
+ Gtk::Allocation allocation = get_allocation();
+#if GTK_CHECK_VERSION(3, 0, 0)
+ cx = get_style_context()->get_padding(get_state_flags()).get_left();
+#else
+ cx = get_style()->get_xthickness();
+#endif
+ cw = allocation.get_width() - 2 * cx;
+ ColorScales::setScaled(_adjustment->gobj(), CLAMP((gfloat)(event->x - cx) / cw, 0.0, 1.0));
+ signal_dragged.emit();
+ }
+
+ return false;
+}
+
+#if GTK_CHECK_VERSION(3, 0, 0)
+void ColorSlider::setAdjustment(Glib::RefPtr<Gtk::Adjustment> adjustment)
+{
+#else
+void ColorSlider::setAdjustment(Gtk::Adjustment *adjustment)
+{
+#endif
+ if (!adjustment) {
+#if GTK_CHECK_VERSION(3, 0, 0)
+ _adjustment = Gtk::Adjustment::create(0.0, 0.0, 1.0, 0.01, 0.0, 0.0);
+#else
+ _adjustment = Gtk::manage(new Gtk::Adjustment(0.0, 0.0, 1.0, 0.01, 0.0, 0.0));
+#endif
+ }
+ else {
+ adjustment->set_page_increment(0.0);
+ adjustment->set_page_size(0.0);
+ }
+
+ if (_adjustment != adjustment) {
+ if (_adjustment) {
+ _adjustment_changed_connection.disconnect();
+ _adjustment_value_changed_connection.disconnect();
+#if !GTK_CHECK_VERSION(3, 0, 0)
+ _adjustment->unreference();
+#endif
+ }
+
+ _adjustment = adjustment;
+ _adjustment_changed_connection =
+ _adjustment->signal_changed().connect(sigc::mem_fun(this, &ColorSlider::_onAdjustmentChanged));
+ _adjustment_value_changed_connection =
+ _adjustment->signal_value_changed().connect(sigc::mem_fun(this, &ColorSlider::_onAdjustmentValueChanged));
+
+ _value = ColorScales::getScaled(_adjustment->gobj());
+
+ _onAdjustmentChanged();
+ }
+}
+
+void ColorSlider::_onAdjustmentChanged() { queue_draw(); }
+
+void ColorSlider::_onAdjustmentValueChanged()
+{
+ if (_value != ColorScales::getScaled(_adjustment->gobj())) {
+ gint cx, cy, cw, ch;
+#if GTK_CHECK_VERSION(3, 0, 0)
+ Glib::RefPtr<Gtk::StyleContext> style_context = get_style_context();
+ Gtk::Allocation allocation = get_allocation();
+ Gtk::Border padding = style_context->get_padding(get_state_flags());
+ cx = padding.get_left();
+ cy = padding.get_top();
+#else
+ Glib::RefPtr<Gtk::Style> style = get_style();
+ Gtk::Allocation allocation = get_allocation();
+ cx = style->get_xthickness();
+ cy = style->get_ythickness();
+#endif
+ cw = allocation.get_width() - 2 * cx;
+ ch = allocation.get_height() - 2 * cy;
+ if ((gint)(ColorScales::getScaled(_adjustment->gobj()) * cw) != (gint)(_value * cw)) {
+ gint ax, ay;
+ gfloat value;
+ value = _value;
+ _value = ColorScales::getScaled(_adjustment->gobj());
+ ax = (int)(cx + value * cw - ARROW_SIZE / 2 - 2);
+ ay = cy;
+ queue_draw_area(ax, ay, ARROW_SIZE + 4, ch);
+ ax = (int)(cx + _value * cw - ARROW_SIZE / 2 - 2);
+ ay = cy;
+ queue_draw_area(ax, ay, ARROW_SIZE + 4, ch);
+ }
+ else {
+ _value = ColorScales::getScaled(_adjustment->gobj());
+ }
+ }
+}
+
+void ColorSlider::setColors(guint32 start, guint32 mid, guint32 end)
+{
+ // Remove any map, if set
+ _map = 0;
+
+ _c0[0] = start >> 24;
+ _c0[1] = (start >> 16) & 0xff;
+ _c0[2] = (start >> 8) & 0xff;
+ _c0[3] = start & 0xff;
+
+ _cm[0] = mid >> 24;
+ _cm[1] = (mid >> 16) & 0xff;
+ _cm[2] = (mid >> 8) & 0xff;
+ _cm[3] = mid & 0xff;
+
+ _c1[0] = end >> 24;
+ _c1[1] = (end >> 16) & 0xff;
+ _c1[2] = (end >> 8) & 0xff;
+ _c1[3] = end & 0xff;
+
+ queue_draw();
+}
+
+void ColorSlider::setMap(const guchar *map)
+{
+ _map = const_cast<guchar *>(map);
+
+ queue_draw();
+}
+
+void ColorSlider::setBackground(guint dark, guint light, guint size)
+{
+ _b0 = dark;
+ _b1 = light;
+ _bmask = size;
+
+ queue_draw();
+}
+
+bool ColorSlider::on_draw(const Cairo::RefPtr<Cairo::Context> &cr)
+{
+ gboolean colorsOnTop = Inkscape::Preferences::get()->getBool("/options/workarounds/colorsontop", false);
+
+ Gtk::Allocation allocation = get_allocation();
+
+#if GTK_CHECK_VERSION(3, 0, 0)
+ Glib::RefPtr<Gtk::StyleContext> style_context = get_style_context();
+#else
+ Glib::RefPtr<Gdk::Window> window = get_window();
+ Glib::RefPtr<Gtk::Style> style = get_style();
+#endif
+
+ // Draw shadow
+ if (colorsOnTop) {
+#if GTK_CHECK_VERSION(3, 0, 0)
+ style_context->render_frame(cr, 0, 0, allocation.get_width(), allocation.get_height());
+#else
+ gtk_paint_shadow(style->gobj(), window->gobj(), gtk_widget_get_state(gobj()), GTK_SHADOW_IN, NULL, gobj(),
+ "colorslider", 0, 0, allocation.get_width(), allocation.get_height());
+#endif
+ }
+
+ /* Paintable part of color gradient area */
+ Gdk::Rectangle carea;
+
+#if GTK_CHECK_VERSION(3, 0, 0)
+ Gtk::Border padding;
+
+ padding = style_context->get_padding(get_state_flags());
+
+ carea.set_x(padding.get_left());
+ carea.set_y(padding.get_top());
+ ;
+#else
+ carea.set_x(style->get_xthickness());
+ carea.set_y(style->get_ythickness());
+#endif
+
+ carea.set_width(allocation.get_width() - 2 * carea.get_x());
+ carea.set_height(allocation.get_height() - 2 * carea.get_y());
+
+ if (_map) {
+ /* Render map pixelstore */
+ gint d = (1024 << 16) / carea.get_width();
+ gint s = 0;
+
+ const guchar *b =
+ sp_color_slider_render_map(0, 0, carea.get_width(), carea.get_height(), _map, s, d, _b0, _b1, _bmask);
+
+ if (b != NULL && carea.get_width() > 0) {
+ Glib::RefPtr<Gdk::Pixbuf> pb = Gdk::Pixbuf::create_from_data(
+ b, Gdk::COLORSPACE_RGB, false, 8, carea.get_width(), carea.get_height(), carea.get_width() * 3);
+
+ Gdk::Cairo::set_source_pixbuf(cr, pb, carea.get_x(), carea.get_y());
+ cr->paint();
+ }
+ }
+ else {
+ gint c[4], dc[4];
+
+ /* Render gradient */
+
+ // part 1: from c0 to cm
+ if (carea.get_width() > 0) {
+ for (gint i = 0; i < 4; i++) {
+ c[i] = _c0[i] << 16;
+ dc[i] = ((_cm[i] << 16) - c[i]) / (carea.get_width() / 2);
+ }
+ guint wi = carea.get_width() / 2;
+ const guchar *b = sp_color_slider_render_gradient(0, 0, wi, carea.get_height(), c, dc, _b0, _b1, _bmask);
+
+ /* Draw pixelstore 1 */
+ if (b != NULL && wi > 0) {
+ Glib::RefPtr<Gdk::Pixbuf> pb =
+ Gdk::Pixbuf::create_from_data(b, Gdk::COLORSPACE_RGB, false, 8, wi, carea.get_height(), wi * 3);
+
+ Gdk::Cairo::set_source_pixbuf(cr, pb, carea.get_x(), carea.get_y());
+ cr->paint();
+ }
+ }
+
+ // part 2: from cm to c1
+ if (carea.get_width() > 0) {
+ for (gint i = 0; i < 4; i++) {
+ c[i] = _cm[i] << 16;
+ dc[i] = ((_c1[i] << 16) - c[i]) / (carea.get_width() / 2);
+ }
+ guint wi = carea.get_width() / 2;
+ const guchar *b = sp_color_slider_render_gradient(carea.get_width() / 2, 0, wi, carea.get_height(), c, dc,
+ _b0, _b1, _bmask);
+
+ /* Draw pixelstore 2 */
+ if (b != NULL && wi > 0) {
+ Glib::RefPtr<Gdk::Pixbuf> pb =
+ Gdk::Pixbuf::create_from_data(b, Gdk::COLORSPACE_RGB, false, 8, wi, carea.get_height(), wi * 3);
+
+ Gdk::Cairo::set_source_pixbuf(cr, pb, carea.get_width() / 2 + carea.get_x(), carea.get_y());
+ cr->paint();
+ }
+ }
+ }
+
+ /* Draw shadow */
+ if (!colorsOnTop) {
+#if GTK_CHECK_VERSION(3, 0, 0)
+ style_context->render_frame(cr, 0, 0, allocation.get_width(), allocation.get_height());
+#else
+ gtk_paint_shadow(style->gobj(), window->gobj(), gtk_widget_get_state(gobj()), GTK_SHADOW_IN, NULL, gobj(),
+ "colorslider", 0, 0, allocation.get_width(), allocation.get_height());
+#endif
+ }
+
+ /* Draw arrow */
+ gint x = (int)(_value * (carea.get_width() - 1) - ARROW_SIZE / 2 + carea.get_x());
+ gint y1 = carea.get_y();
+ gint y2 = carea.get_y() + carea.get_height() - 1;
+ cr->set_line_width(1.0);
+
+ // Define top arrow
+ cr->move_to(x - 0.5, y1 + 0.5);
+ cr->line_to(x + ARROW_SIZE - 0.5, y1 + 0.5);
+ cr->line_to(x + (ARROW_SIZE - 1) / 2.0, y1 + ARROW_SIZE / 2.0 + 0.5);
+ cr->line_to(x - 0.5, y1 + 0.5);
+
+ // Define bottom arrow
+ cr->move_to(x - 0.5, y2 + 0.5);
+ cr->line_to(x + ARROW_SIZE - 0.5, y2 + 0.5);
+ cr->line_to(x + (ARROW_SIZE - 1) / 2.0, y2 - ARROW_SIZE / 2.0 + 0.5);
+ cr->line_to(x - 0.5, y2 + 0.5);
+
+ // Render both arrows
+ cr->set_source_rgb(1.0, 1.0, 1.0);
+ cr->stroke_preserve();
+ cr->set_source_rgb(0.0, 0.0, 0.0);
+ cr->fill();
+
+ return false;
+}
+
+} // namespace Widget
+} // namespace UI
+} // namespace Inkscape
+
+/* Colors are << 16 */
+
+static const guchar *sp_color_slider_render_gradient(gint x0, gint y0, gint width, gint height, gint c[], gint dc[],
+ guint b0, guint b1, guint mask)
+{
+ static guchar *buf = NULL;
+ static gint bs = 0;
+ guchar *dp;
+ gint x, y;
+ guint r, g, b, a;
+
+ if (buf && (bs < width * height)) {
+ g_free(buf);
+ buf = NULL;
+ }
+ if (!buf) {
+ buf = g_new(guchar, width * height * 3);
+ bs = width * height;
+ }
+
+ dp = buf;
+ r = c[0];
+ g = c[1];
+ b = c[2];
+ a = c[3];
+ for (x = x0; x < x0 + width; x++) {
+ gint cr, cg, cb, ca;
+ guchar *d;
+ cr = r >> 16;
+ cg = g >> 16;
+ cb = b >> 16;
+ ca = a >> 16;
+ d = dp;
+ for (y = y0; y < y0 + height; y++) {
+ guint bg, fc;
+ /* Background value */
+ bg = ((x & mask) ^ (y & mask)) ? b0 : b1;
+ fc = (cr - bg) * ca;
+ d[0] = bg + ((fc + (fc >> 8) + 0x80) >> 8);
+ fc = (cg - bg) * ca;
+ d[1] = bg + ((fc + (fc >> 8) + 0x80) >> 8);
+ fc = (cb - bg) * ca;
+ d[2] = bg + ((fc + (fc >> 8) + 0x80) >> 8);
+ d += 3 * width;
+ }
+ r += dc[0];
+ g += dc[1];
+ b += dc[2];
+ a += dc[3];
+ dp += 3;
+ }
+
+ return buf;
+}
+
+/* Positions are << 16 */
+
+static const guchar *sp_color_slider_render_map(gint x0, gint y0, gint width, gint height, guchar *map, gint start,
+ gint step, guint b0, guint b1, guint mask)
+{
+ static guchar *buf = NULL;
+ static gint bs = 0;
+ guchar *dp;
+ gint x, y;
+
+ if (buf && (bs < width * height)) {
+ g_free(buf);
+ buf = NULL;
+ }
+ if (!buf) {
+ buf = g_new(guchar, width * height * 3);
+ bs = width * height;
+ }
+
+ dp = buf;
+ for (x = x0; x < x0 + width; x++) {
+ gint cr, cg, cb, ca;
+ guchar *d = dp;
+ guchar *sp = map + 4 * (start >> 16);
+ cr = *sp++;
+ cg = *sp++;
+ cb = *sp++;
+ ca = *sp++;
+ for (y = y0; y < y0 + height; y++) {
+ guint bg, fc;
+ /* Background value */
+ bg = ((x & mask) ^ (y & mask)) ? b0 : b1;
+ fc = (cr - bg) * ca;
+ d[0] = bg + ((fc + (fc >> 8) + 0x80) >> 8);
+ fc = (cg - bg) * ca;
+ d[1] = bg + ((fc + (fc >> 8) + 0x80) >> 8);
+ fc = (cb - bg) * ca;
+ d[2] = bg + ((fc + (fc >> 8) + 0x80) >> 8);
+ d += 3 * width;
+ }
+ dp += 3;
+ start += step;
+ }
+
+ return buf;
+}
diff --git a/src/ui/widget/color-slider.h b/src/ui/widget/color-slider.h
new file mode 100644
index 000000000..253f3123c
--- /dev/null
+++ b/src/ui/widget/color-slider.h
@@ -0,0 +1,110 @@
+/*
+ * A slider with colored background
+ *
+ * Author:
+ * Lauris Kaplinski <lauris@kaplinski.com>
+ *
+ * Copyright (C) 2001-2002 Lauris Kaplinski
+ *
+ * This code is in public domain
+ */
+
+#ifndef SEEN_COLOR_SLIDER_H
+#define SEEN_COLOR_SLIDER_H
+
+#include <gtkmm/widget.h>
+#include <sigc++/signal.h>
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+/*
+ * A slider with colored background
+ */
+class ColorSlider : public Gtk::Widget {
+public:
+#if GTK_CHECK_VERSION(3, 0, 0)
+ ColorSlider(Glib::RefPtr<Gtk::Adjustment> adjustment);
+#else
+ ColorSlider(Gtk::Adjustment *adjustment);
+#endif
+ ~ColorSlider();
+
+#if GTK_CHECK_VERSION(3, 0, 0)
+ void setAdjustment(Glib::RefPtr<Gtk::Adjustment> adjustment);
+#else
+ void setAdjustment(Gtk::Adjustment *adjustment);
+#endif
+
+ void setColors(guint32 start, guint32 mid, guint32 end);
+
+ void setMap(const guchar *map);
+
+ void setBackground(guint dark, guint light, guint size);
+
+ sigc::signal<void> signal_grabbed;
+ sigc::signal<void> signal_dragged;
+ sigc::signal<void> signal_released;
+ sigc::signal<void> signal_value_changed;
+
+protected:
+ void on_size_allocate(Gtk::Allocation &allocation);
+ void on_realize();
+ void on_unrealize();
+ bool on_button_press_event(GdkEventButton *event);
+ bool on_button_release_event(GdkEventButton *event);
+ bool on_motion_notify_event(GdkEventMotion *event);
+ bool on_draw(const Cairo::RefPtr<Cairo::Context> &cr);
+
+#if GTK_CHECK_VERSION(3, 0, 0)
+ void get_preferred_width_vfunc(int &minimum_width, int &natural_width) const;
+ void get_preferred_width_for_height_vfunc(int height, int &minimum_width, int &natural_width) const;
+ void get_preferred_height_vfunc(int &minimum_height, int &natural_height) const;
+ void get_preferred_height_for_width_vfunc(int width, int &minimum_height, int &natural_height) const;
+#else
+ void on_size_request(Gtk::Requisition *requisition);
+ bool on_expose_event(GdkEventExpose *event);
+#endif
+
+private:
+ void _onAdjustmentChanged();
+ void _onAdjustmentValueChanged();
+
+ bool _dragging;
+
+#if GTK_CHECK_VERSION(3, 0, 0)
+ Glib::RefPtr<Gtk::Adjustment> _adjustment;
+#else
+ Gtk::Adjustment *_adjustment;
+#endif
+ sigc::connection _adjustment_changed_connection;
+ sigc::connection _adjustment_value_changed_connection;
+
+ gfloat _value;
+ gfloat _oldvalue;
+ guchar _c0[4], _cm[4], _c1[4];
+ guchar _b0, _b1;
+ guchar _bmask;
+
+ gint _mapsize;
+ guchar *_map;
+
+ Glib::RefPtr<Gdk::Window> _gdk_window;
+};
+
+} // namespace Widget
+} // namespace UI
+} // namespace Inkscape
+
+#endif
+/*
+ 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/color-wheel-selector.cpp b/src/ui/widget/color-wheel-selector.cpp
new file mode 100644
index 000000000..ed3400bb5
--- /dev/null
+++ b/src/ui/widget/color-wheel-selector.cpp
@@ -0,0 +1,302 @@
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "color-wheel-selector.h"
+
+#include <math.h>
+#include <gtk/gtk.h>
+#include <glibmm/i18n.h>
+#include <gtkmm/adjustment.h>
+#include <gtkmm/label.h>
+#include <gtkmm/spinbutton.h>
+#include "svg/svg-icc-color.h"
+#include "ui/dialog-events.h"
+#include "ui/selected-color.h"
+#include "ui/widget/color-scales.h"
+#include "ui/widget/color-slider.h"
+#include "ui/widget/gimpcolorwheel.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+
+#define XPAD 4
+#define YPAD 1
+
+
+const gchar *ColorWheelSelector::MODE_NAME = N_("Wheel");
+
+ColorWheelSelector::ColorWheelSelector(SelectedColor &color)
+#if GTK_CHECK_VERSION(3, 0, 0)
+ : Gtk::Grid()
+#else
+ : Gtk::Table(5, 3, false)
+#endif
+ , _color(color)
+ , _updating(false)
+#if !GTK_CHECK_VERSION(3, 0, 0)
+ , _alpha_adjustment(NULL)
+#endif
+ , _wheel(0)
+ , _slider(0)
+{
+ _initUI();
+ _color_changed_connection = color.signal_changed.connect(sigc::mem_fun(this, &ColorWheelSelector::_colorChanged));
+ _color_dragged_connection = color.signal_dragged.connect(sigc::mem_fun(this, &ColorWheelSelector::_colorChanged));
+}
+
+ColorWheelSelector::~ColorWheelSelector()
+{
+ _wheel = 0;
+#if !GTK_CHECK_VERSION(3, 0, 0)
+ delete _alpha_adjustment;
+#endif
+
+ _color_changed_connection.disconnect();
+ _color_dragged_connection.disconnect();
+}
+
+void ColorWheelSelector::_initUI()
+{
+ /* Create components */
+ gint row = 0;
+
+ _wheel = gimp_color_wheel_new();
+ gtk_widget_show(_wheel);
+
+#if GTK_CHECK_VERSION(3, 0, 0)
+ gtk_widget_set_halign(_wheel, GTK_ALIGN_FILL);
+ gtk_widget_set_valign(_wheel, GTK_ALIGN_FILL);
+ gtk_widget_set_hexpand(_wheel, TRUE);
+ gtk_widget_set_vexpand(_wheel, TRUE);
+ gtk_grid_attach(GTK_GRID(gobj()), _wheel, 0, row, 3, 1);
+#else
+ gtk_table_attach(GTK_TABLE(gobj()), _wheel, 0, 3, row, row + 1, (GtkAttachOptions)(GTK_EXPAND | GTK_FILL),
+ (GtkAttachOptions)(GTK_EXPAND | GTK_FILL), 0, 0);
+#endif
+
+ row++;
+
+ /* Label */
+ Gtk::Label *label = Gtk::manage(new Gtk::Label(_("_A:"), true));
+ label->set_alignment(1.0, 0.5);
+ label->show();
+
+#if GTK_CHECK_VERSION(3, 0, 0)
+ #if GTK_CHECK_VERSION(3, 12, 0)
+ label->set_margin_start(XPAD);
+ label->set_margin_end(XPAD);
+ #else
+ label->set_margin_left(XPAD);
+ label->set_margin_right(XPAD);
+ #endif
+ label->set_margin_top(YPAD);
+ label->set_margin_bottom(YPAD);
+ label->set_halign(Gtk::ALIGN_FILL);
+ label->set_valign(Gtk::ALIGN_FILL);
+ attach(*label, 0, row, 1, 1);
+#else
+ attach(*label, 0, 1, row, row + 1, Gtk::FILL, Gtk::FILL, XPAD, YPAD);
+#endif
+
+/* Adjustment */
+#if GTK_CHECK_VERSION(3, 0, 0)
+ _alpha_adjustment = Gtk::Adjustment::create(0.0, 0.0, 255.0, 1.0, 10.0, 10.0);
+#else
+ _alpha_adjustment = new Gtk::Adjustment(0.0, 0.0, 255.0, 1.0, 10.0, 10.0);
+#endif
+ /* Slider */
+ _slider = Gtk::manage(new Inkscape::UI::Widget::ColorSlider(_alpha_adjustment));
+ _slider->set_tooltip_text(_("Alpha (opacity)"));
+ _slider->show();
+
+#if GTK_CHECK_VERSION(3, 0, 0)
+ #if GTK_CHECK_VERSION(3, 12, 0)
+ _slider->set_margin_start(XPAD);
+ _slider->set_margin_end(XPAD);
+ #else
+ _slider->set_margin_left(XPAD);
+ _slider->set_margin_right(XPAD);
+ #endif
+ _slider->set_margin_top(YPAD);
+ _slider->set_margin_bottom(YPAD);
+ _slider->set_hexpand(true);
+ _slider->set_halign(Gtk::ALIGN_FILL);
+ _slider->set_valign(Gtk::ALIGN_FILL);
+ attach(*_slider, 1, row, 1, 1);
+#else
+ attach(*_slider, 1, 2, row, row + 1, Gtk::EXPAND | Gtk::FILL, Gtk::FILL, XPAD, YPAD);
+#endif
+
+ _slider->setColors(SP_RGBA32_F_COMPOSE(1.0, 1.0, 1.0, 0.0), SP_RGBA32_F_COMPOSE(1.0, 1.0, 1.0, 0.5),
+ SP_RGBA32_F_COMPOSE(1.0, 1.0, 1.0, 1.0));
+
+/* Spinbutton */
+#if GTK_CHECK_VERSION(3, 0, 0)
+ Gtk::SpinButton *spin_button = Gtk::manage(new Gtk::SpinButton(_alpha_adjustment, 1.0, 0));
+#else
+ Gtk::SpinButton *spin_button = Gtk::manage(new Gtk::SpinButton(*_alpha_adjustment, 1.0, 0));
+#endif
+ spin_button->set_tooltip_text(_("Alpha (opacity)"));
+ sp_dialog_defocus_on_enter(GTK_WIDGET(spin_button->gobj()));
+ label->set_mnemonic_widget(*spin_button);
+ spin_button->show();
+
+#if GTK_CHECK_VERSION(3, 0, 0)
+ #if GTK_CHECK_VERSION(3, 12, 0)
+ spin_button->set_margin_start(XPAD);
+ spin_button->set_margin_end(XPAD);
+ #else
+ spin_button->set_margin_left(XPAD);
+ spin_button->set_margin_right(XPAD);
+ #endif
+ spin_button->set_margin_top(YPAD);
+ spin_button->set_margin_bottom(YPAD);
+ spin_button->set_halign(Gtk::ALIGN_CENTER);
+ spin_button->set_valign(Gtk::ALIGN_CENTER);
+ attach(*spin_button, 2, row, 1, 1);
+#else
+ attach(*spin_button, 2, 3, row, row + 1, (Gtk::AttachOptions)0, (Gtk::AttachOptions)0, XPAD, YPAD);
+#endif
+
+ /* Signals */
+ _alpha_adjustment->signal_value_changed().connect(sigc::mem_fun(this, &ColorWheelSelector::_adjustmentChanged));
+ _slider->signal_grabbed.connect(sigc::mem_fun(*this, &ColorWheelSelector::_sliderGrabbed));
+ _slider->signal_released.connect(sigc::mem_fun(*this, &ColorWheelSelector::_sliderReleased));
+ _slider->signal_value_changed.connect(sigc::mem_fun(*this, &ColorWheelSelector::_sliderChanged));
+
+ g_signal_connect(G_OBJECT(_wheel), "changed", G_CALLBACK(_wheelChanged), this);
+}
+
+void ColorWheelSelector::on_show()
+{
+#if GTK_CHECK_VERSION(3, 0, 0)
+ Gtk::Grid::on_show();
+#else
+ Gtk::Table::on_show();
+#endif
+ _updateDisplay();
+}
+
+void ColorWheelSelector::_colorChanged()
+{
+ _updateDisplay();
+}
+
+void ColorWheelSelector::_adjustmentChanged()
+{
+ if (_updating) {
+ return;
+ }
+
+ // TODO check this. It looks questionable:
+ // if a value is entered between 0 and 1 exclusive, normalize it to (int) 0..255 or 0..100
+ gdouble value = _alpha_adjustment->get_value();
+ gdouble upper = _alpha_adjustment->get_upper();
+ if (value > 0.0 && value < 1.0) {
+ _alpha_adjustment->set_value(floor(value * upper + 0.5));
+ }
+
+ _color.preserveICC();
+ _color.setAlpha(ColorScales::getScaled(_alpha_adjustment->gobj()));
+}
+
+void ColorWheelSelector::_sliderGrabbed()
+{
+ _color.preserveICC();
+ _color.setHeld(true);
+}
+
+void ColorWheelSelector::_sliderReleased()
+{
+ _color.preserveICC();
+ _color.setHeld(false);
+}
+
+void ColorWheelSelector::_sliderChanged()
+{
+ if (_updating) {
+ return;
+ }
+
+ _color.preserveICC();
+ _color.setAlpha(ColorScales::getScaled(_alpha_adjustment->gobj()));
+}
+
+void ColorWheelSelector::_wheelChanged(GimpColorWheel *wheel, ColorWheelSelector *wheelSelector)
+{
+ if (wheelSelector->_updating) {
+ return;
+ }
+
+ gdouble h = 0;
+ gdouble s = 0;
+ gdouble v = 0;
+ gimp_color_wheel_get_color(wheel, &h, &s, &v);
+
+ float rgb[3] = { 0, 0, 0 };
+ sp_color_hsv_to_rgb_floatv(rgb, h, s, v);
+
+ SPColor color(rgb[0], rgb[1], rgb[2]);
+
+ guint32 start = color.toRGBA32(0x00);
+ guint32 mid = color.toRGBA32(0x7f);
+ guint32 end = color.toRGBA32(0xff);
+
+ wheelSelector->_slider->setColors(start, mid, end);
+
+ wheelSelector->_color.preserveICC();
+
+ wheelSelector->_color.setHeld(gimp_color_wheel_is_adjusting(wheel));
+ wheelSelector->_color.setColor(color);
+}
+
+void ColorWheelSelector::_updateDisplay()
+{
+#ifdef DUMP_CHANGE_INFO
+ g_message("ColorWheelSelector::_colorChanged( this=%p, %f, %f, %f, %f)", this, _color.color().v.c[0],
+ _color.color().v.c[1], _color.color().v.c[2], alpha);
+#endif
+
+ bool oldval = _updating;
+ _updating = true;
+ {
+ float hsv[3] = { 0, 0, 0 };
+ sp_color_rgb_to_hsv_floatv(hsv, _color.color().v.c[0], _color.color().v.c[1], _color.color().v.c[2]);
+ gimp_color_wheel_set_color(GIMP_COLOR_WHEEL(_wheel), hsv[0], hsv[1], hsv[2]);
+ }
+
+ guint32 start = _color.color().toRGBA32(0x00);
+ guint32 mid = _color.color().toRGBA32(0x7f);
+ guint32 end = _color.color().toRGBA32(0xff);
+
+ _slider->setColors(start, mid, end);
+
+ ColorScales::setScaled(_alpha_adjustment->gobj(), _color.alpha());
+
+ _updating = oldval;
+}
+
+
+Gtk::Widget *ColorWheelSelectorFactory::createWidget(Inkscape::UI::SelectedColor &color) const
+{
+ Gtk::Widget *w = Gtk::manage(new ColorWheelSelector(color));
+ return w;
+}
+
+Glib::ustring ColorWheelSelectorFactory::modeName() const { return gettext(ColorWheelSelector::MODE_NAME); }
+}
+}
+}
+/*
+ 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/color-wheel-selector.h b/src/ui/widget/color-wheel-selector.h
new file mode 100644
index 000000000..5711d417c
--- /dev/null
+++ b/src/ui/widget/color-wheel-selector.h
@@ -0,0 +1,101 @@
+/**
+ * @file
+ * Color selector widget containing GIMP color wheel and slider
+ */
+/* Authors:
+ * Tomasz Boczkowski <penginsbacon@gmail.com> (c++-sification)
+ *
+ * Copyright (C) 2014 Authors
+ *
+ * This code is in public domain
+ */
+#ifndef SEEN_SP_COLOR_WHEEL_SELECTOR_H
+#define SEEN_SP_COLOR_WHEEL_SELECTOR_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#if WITH_GTKMM_3_0
+#include <gtkmm/grid.h>
+#else
+#include <gtkmm/table.h>
+#endif
+
+#include "ui/selected-color.h"
+
+typedef struct _GimpColorWheel GimpColorWheel;
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+class ColorSlider;
+
+class ColorWheelSelector
+#if GTK_CHECK_VERSION(3, 0, 0)
+ : public Gtk::Grid
+#else
+ : public Gtk::Table
+#endif
+{
+public:
+ static const gchar *MODE_NAME;
+
+ ColorWheelSelector(SelectedColor &color);
+ virtual ~ColorWheelSelector();
+
+protected:
+ void _initUI();
+
+ void on_show();
+
+ void _colorChanged();
+ void _adjustmentChanged();
+ void _sliderGrabbed();
+ void _sliderReleased();
+ void _sliderChanged();
+ static void _wheelChanged(GimpColorWheel *wheel, ColorWheelSelector *cs);
+
+ void _updateDisplay();
+
+ SelectedColor &_color;
+ bool _updating;
+#if GTK_CHECK_VERSION(3, 0, 0)
+ Glib::RefPtr<Gtk::Adjustment> _alpha_adjustment;
+#else
+ Gtk::Adjustment *_alpha_adjustment;
+#endif
+ GtkWidget *_wheel;
+ Inkscape::UI::Widget::ColorSlider *_slider;
+
+private:
+ // By default, disallow copy constructor and assignment operator
+ ColorWheelSelector(const ColorWheelSelector &obj);
+ ColorWheelSelector &operator=(const ColorWheelSelector &obj);
+
+ sigc::connection _color_changed_connection;
+ sigc::connection _color_dragged_connection;
+};
+
+class ColorWheelSelectorFactory : public ColorSelectorFactory {
+public:
+ Gtk::Widget *createWidget(SelectedColor &color) const;
+ Glib::ustring modeName() const;
+};
+}
+}
+}
+
+#endif // SEEN_SP_COLOR_WHEEL_SELECTOR_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/entity-entry.cpp b/src/ui/widget/entity-entry.cpp
index 69173fa25..a8de2f384 100644
--- a/src/ui/widget/entity-entry.cpp
+++ b/src/ui/widget/entity-entry.cpp
@@ -188,8 +188,7 @@ EntityMultiLineEntry::on_changed()
Gtk::TextView *tv = static_cast<Gtk::TextView*>(s->get_child());
Glib::ustring text = tv->get_buffer()->get_text();
if (rdf_set_work_entity (doc, _entity, text.c_str())) {
- DocumentUndo::done(doc, SP_VERB_NONE,
- /* TODO: annotate */ "entity-entry.cpp:146");
+ DocumentUndo::done(doc, SP_VERB_NONE, "Document metadata updated");
}
_wr->setUpdating (false);
}
diff --git a/src/ui/widget/font-variants.cpp b/src/ui/widget/font-variants.cpp
new file mode 100644
index 000000000..5d1e40971
--- /dev/null
+++ b/src/ui/widget/font-variants.cpp
@@ -0,0 +1,719 @@
+/*
+ * Author:
+ * Tavmjong Bah <tavmjong@free.fr>
+ *
+ * Copyright (C) 2015 Tavmong Bah
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <gtkmm.h>
+#include <glibmm/i18n.h>
+#include <libnrtype/font-instance.h>
+#include <iostream>
+
+#include "font-variants.h"
+
+// For updating from selection
+#include "desktop.h"
+#include "selection.h"
+#include "style.h"
+#include "sp-text.h"
+#include "sp-tspan.h"
+#include "sp-tref.h"
+#include "sp-textpath.h"
+#include "sp-item-group.h"
+#include "xml/repr.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+ FontVariants::FontVariants () :
+ Gtk::VBox (),
+ _ligatures_frame ( Glib::ustring(_("Ligatures" )) ),
+ _ligatures_common ( Glib::ustring(_("Common" )) ),
+ _ligatures_discretionary ( Glib::ustring(_("Discretionary")) ),
+ _ligatures_historical ( Glib::ustring(_("Historical" )) ),
+ _ligatures_contextual ( Glib::ustring(_("Contextual" )) ),
+
+ _position_frame ( Glib::ustring(_("Position" )) ),
+ _position_normal ( Glib::ustring(_("Normal" )) ),
+ _position_sub ( Glib::ustring(_("Subscript" )) ),
+ _position_super ( Glib::ustring(_("Superscript" )) ),
+
+ _caps_frame ( Glib::ustring(_("Capitals" )) ),
+ _caps_normal ( Glib::ustring(_("Normal" )) ),
+ _caps_small ( Glib::ustring(_("Small" )) ),
+ _caps_all_small ( Glib::ustring(_("All small" )) ),
+ _caps_petite ( Glib::ustring(_("Petite" )) ),
+ _caps_all_petite ( Glib::ustring(_("All petite" )) ),
+ _caps_unicase ( Glib::ustring(_("Unicase" )) ),
+ _caps_titling ( Glib::ustring(_("Titling" )) ),
+
+ _numeric_frame ( Glib::ustring(_("Numeric" )) ),
+ _numeric_lining ( Glib::ustring(_("Lining" )) ),
+ _numeric_old_style ( Glib::ustring(_("Old Style" )) ),
+ _numeric_default_style ( Glib::ustring(_("Default Style")) ),
+ _numeric_proportional ( Glib::ustring(_("Proportional" )) ),
+ _numeric_tabular ( Glib::ustring(_("Tabular" )) ),
+ _numeric_default_width ( Glib::ustring(_("Default Width")) ),
+ _numeric_diagonal ( Glib::ustring(_("Diagonal" )) ),
+ _numeric_stacked ( Glib::ustring(_("Stacked" )) ),
+ _numeric_default_fractions( Glib::ustring(_("Default Fractions")) ),
+ _numeric_ordinal ( Glib::ustring(_("Ordinal" )) ),
+ _numeric_slashed_zero ( Glib::ustring(_("Slashed Zero" )) ),
+
+ _feature_frame ( Glib::ustring(_("Feature Settings")) ),
+ _feature_label ( Glib::ustring(_("Selection has different Feature Settings!")) ),
+
+ _ligatures_changed( false ),
+ _position_changed( false ),
+ _caps_changed( false ),
+ _numeric_changed( false )
+
+ {
+
+ // Ligatures --------------------------
+
+ // Add tooltips
+ _ligatures_common.set_tooltip_text(
+ _("Common ligatures. On by default. OpenType tables: 'liga', 'clig'"));
+ _ligatures_discretionary.set_tooltip_text(
+ _("Discretionary ligatures. Off by default. OpenType table: 'dlig'"));
+ _ligatures_historical.set_tooltip_text(
+ _("Historical ligatures. Off by default. OpenType table: 'hlig'"));
+ _ligatures_contextual.set_tooltip_text(
+ _("Contextual forms. On by default. OpenType table: 'calt'"));
+
+ // Add signals
+ _ligatures_common.signal_clicked().connect ( sigc::mem_fun(*this, &FontVariants::ligatures_callback) );
+ _ligatures_discretionary.signal_clicked().connect ( sigc::mem_fun(*this, &FontVariants::ligatures_callback) );
+ _ligatures_historical.signal_clicked().connect ( sigc::mem_fun(*this, &FontVariants::ligatures_callback) );
+ _ligatures_contextual.signal_clicked().connect ( sigc::mem_fun(*this, &FontVariants::ligatures_callback) );
+
+ // Add to frame
+ _ligatures_vbox.add( _ligatures_common );
+ _ligatures_vbox.add( _ligatures_discretionary );
+ _ligatures_vbox.add( _ligatures_historical );
+ _ligatures_vbox.add( _ligatures_contextual );
+ _ligatures_frame.add( _ligatures_vbox );
+ add( _ligatures_frame );
+
+ ligatures_init();
+
+ // Position ----------------------------------
+
+ // Add tooltips
+ _position_normal.set_tooltip_text( _("Normal position."));
+ _position_sub.set_tooltip_text( _("Subscript. OpenType table: 'subs'") );
+ _position_super.set_tooltip_text( _("Superscript. OpenType table: 'sups'") );
+
+ // Group buttons
+ Gtk::RadioButton::Group position_group = _position_normal.get_group();
+ _position_sub.set_group(position_group);
+ _position_super.set_group(position_group);
+
+ // Add signals
+ _position_normal.signal_pressed().connect ( sigc::mem_fun(*this, &FontVariants::position_callback) );
+ _position_sub.signal_pressed().connect ( sigc::mem_fun(*this, &FontVariants::position_callback) );
+ _position_super.signal_pressed().connect ( sigc::mem_fun(*this, &FontVariants::position_callback) );
+
+ // Add to frame
+ _position_vbox.add( _position_normal );
+ _position_vbox.add( _position_sub );
+ _position_vbox.add( _position_super );
+ _position_frame.add( _position_vbox );
+ add( _position_frame );
+
+ position_init();
+
+ // Caps ----------------------------------
+
+ // Add tooltips
+ _caps_normal.set_tooltip_text( _("Normal capitalization."));
+ _caps_small.set_tooltip_text( _("Small-caps (lowercase). OpenType table: 'smcp'"));
+ _caps_all_small.set_tooltip_text( _("All small-caps (uppercase and lowercase). OpenType tables: 'c2sc' and 'smcp'"));
+ _caps_petite.set_tooltip_text( _("Petite-caps (lowercase). OpenType table: 'pcap'"));
+ _caps_all_petite.set_tooltip_text( _("All petite-caps (uppercase and lowercase). OpenType tables: 'c2sc' and 'pcap'"));
+ _caps_unicase.set_tooltip_text( _("Unicase (small caps for uppercase, normal for lowercase). OpenType table: 'unic'"));
+ _caps_titling.set_tooltip_text( _("Titling caps (lighter-weight uppercase for use in titles). OpenType table: 'titl'"));
+
+ // Group buttons
+ Gtk::RadioButton::Group caps_group = _caps_normal.get_group();
+ _caps_small.set_group(caps_group);
+ _caps_all_small.set_group(caps_group);
+ _caps_petite.set_group(caps_group);
+ _caps_all_petite.set_group(caps_group);
+ _caps_unicase.set_group(caps_group);
+ _caps_titling.set_group(caps_group);
+
+ // Add signals
+ _caps_normal.signal_clicked().connect ( sigc::mem_fun(*this, &FontVariants::caps_callback) );
+ _caps_small.signal_clicked().connect ( sigc::mem_fun(*this, &FontVariants::caps_callback) );
+ _caps_all_small.signal_clicked().connect ( sigc::mem_fun(*this, &FontVariants::caps_callback) );
+ _caps_petite.signal_clicked().connect ( sigc::mem_fun(*this, &FontVariants::caps_callback) );
+ _caps_all_petite.signal_clicked().connect ( sigc::mem_fun(*this, &FontVariants::caps_callback) );
+ _caps_unicase.signal_clicked().connect ( sigc::mem_fun(*this, &FontVariants::caps_callback) );
+ _caps_titling.signal_clicked().connect ( sigc::mem_fun(*this, &FontVariants::caps_callback) );
+
+ // Add to frame
+ _caps_vbox.add( _caps_normal );
+ _caps_vbox.add( _caps_small );
+ _caps_vbox.add( _caps_all_small );
+ _caps_vbox.add( _caps_petite );
+ _caps_vbox.add( _caps_all_petite );
+ _caps_vbox.add( _caps_unicase );
+ _caps_vbox.add( _caps_titling );
+ _caps_frame.add( _caps_vbox );
+ add( _caps_frame );
+
+ caps_init();
+
+ // Numeric ------------------------------
+
+ // Add tooltips
+ _numeric_default_style.set_tooltip_text( _("Normal style."));
+ _numeric_lining.set_tooltip_text( _("Lining numerals. OpenType table: 'lnum'"));
+ _numeric_old_style.set_tooltip_text( _("Old style numerals. OpenType table: 'onum'"));
+ _numeric_default_width.set_tooltip_text( _("Normal widths."));
+ _numeric_proportional.set_tooltip_text( _("Proportional width numerals. OpenType table: 'pnum'"));
+ _numeric_tabular.set_tooltip_text( _("Same width numerals. OpenType table: 'tnum'"));
+ _numeric_default_fractions.set_tooltip_text( _("Normal fractions."));
+ _numeric_diagonal.set_tooltip_text( _("Diagonal fractions. OpenType table: 'frac'"));
+ _numeric_stacked.set_tooltip_text( _("Stacked fractions. OpenType table: 'afrc'"));
+ _numeric_ordinal.set_tooltip_text( _("Ordinals (raised 'th', etc.). OpenType table: 'ordn'"));
+ _numeric_slashed_zero.set_tooltip_text( _("Slashed zeros. OpenType table: 'zero'"));
+
+ // Group buttons
+ Gtk::RadioButton::Group style_group = _numeric_default_style.get_group();
+ _numeric_lining.set_group(style_group);
+ _numeric_old_style.set_group(style_group);
+
+ Gtk::RadioButton::Group width_group = _numeric_default_width.get_group();
+ _numeric_proportional.set_group(width_group);
+ _numeric_tabular.set_group(width_group);
+
+ Gtk::RadioButton::Group fraction_group = _numeric_default_fractions.get_group();
+ _numeric_diagonal.set_group(fraction_group);
+ _numeric_stacked.set_group(fraction_group);
+
+ // Add signals
+ _numeric_default_style.signal_clicked().connect ( sigc::mem_fun(*this, &FontVariants::numeric_callback) );
+ _numeric_lining.signal_clicked().connect ( sigc::mem_fun(*this, &FontVariants::numeric_callback) );
+ _numeric_old_style.signal_clicked().connect ( sigc::mem_fun(*this, &FontVariants::numeric_callback) );
+ _numeric_default_width.signal_clicked().connect ( sigc::mem_fun(*this, &FontVariants::numeric_callback) );
+ _numeric_proportional.signal_clicked().connect ( sigc::mem_fun(*this, &FontVariants::numeric_callback) );
+ _numeric_tabular.signal_clicked().connect ( sigc::mem_fun(*this, &FontVariants::numeric_callback) );
+ _numeric_default_fractions.signal_clicked().connect ( sigc::mem_fun(*this, &FontVariants::numeric_callback) );
+ _numeric_diagonal.signal_clicked().connect ( sigc::mem_fun(*this, &FontVariants::numeric_callback) );
+ _numeric_stacked.signal_clicked().connect ( sigc::mem_fun(*this, &FontVariants::numeric_callback) );
+ _numeric_ordinal.signal_clicked().connect ( sigc::mem_fun(*this, &FontVariants::numeric_callback) );
+ _numeric_slashed_zero.signal_clicked().connect ( sigc::mem_fun(*this, &FontVariants::numeric_callback) );
+
+ // Add to frame
+ _numeric_stylebox.add( _numeric_default_style );
+ _numeric_stylebox.add( _numeric_lining );
+ _numeric_stylebox.add( _numeric_old_style );
+ _numeric_vbox.add( _numeric_stylebox );
+ _numeric_widthbox.add( _numeric_default_width );
+ _numeric_widthbox.add( _numeric_proportional );
+ _numeric_widthbox.add( _numeric_tabular );
+ _numeric_vbox.add( _numeric_widthbox );
+ _numeric_fractionbox.add( _numeric_default_fractions );
+ _numeric_fractionbox.add( _numeric_diagonal );
+ _numeric_fractionbox.add( _numeric_stacked );
+ _numeric_vbox.add( _numeric_fractionbox );
+ _numeric_vbox.add( _numeric_ordinal );
+ _numeric_vbox.add( _numeric_slashed_zero );
+ _numeric_frame.add( _numeric_vbox );
+ add( _numeric_frame );
+
+
+ // Feature settings ---------------------
+
+ // Add tooltips
+ _feature_entry.set_tooltip_text( _("Feature settings in CSS form. No sanity checking is performed."));
+
+ // Add to frame
+ _feature_vbox.add( _feature_entry );
+ _feature_vbox.add( _feature_label );
+ _feature_frame.add( _feature_vbox );
+ add( _feature_frame );
+
+ // Add signals
+ //_feature_entry.signal_key_press_event().connect ( sigc::mem_fun(*this, &FontVariants::feature_callback) );
+ _feature_entry.signal_changed().connect( sigc::mem_fun(*this, &FontVariants::feature_callback) );
+
+ show_all_children();
+
+ }
+
+ void
+ FontVariants::ligatures_init() {
+ // std::cout << "FontVariants::ligatures_init()" << std::endl;
+ }
+
+ void
+ FontVariants::ligatures_callback() {
+ // std::cout << "FontVariants::ligatures_callback()" << std::endl;
+ _ligatures_changed = true;
+ _changed_signal.emit();
+ }
+
+ void
+ FontVariants::position_init() {
+ // std::cout << "FontVariants::position_init()" << std::endl;
+ }
+
+ void
+ FontVariants::position_callback() {
+ // std::cout << "FontVariants::position_callback()" << std::endl;
+ _position_changed = true;
+ _changed_signal.emit();
+ }
+
+ void
+ FontVariants::caps_init() {
+ // std::cout << "FontVariants::caps_init()" << std::endl;
+ }
+
+ void
+ FontVariants::caps_callback() {
+ // std::cout << "FontVariants::caps_callback()" << std::endl;
+ _caps_changed = true;
+ _changed_signal.emit();
+ }
+
+ void
+ FontVariants::numeric_init() {
+ // std::cout << "FontVariants::numeric_init()" << std::endl;
+ }
+
+ void
+ FontVariants::numeric_callback() {
+ // std::cout << "FontVariants::numeric_callback()" << std::endl;
+ _numeric_changed = true;
+ _changed_signal.emit();
+ }
+
+ void
+ FontVariants::feature_init() {
+ // std::cout << "FontVariants::feature_init()" << std::endl;
+ }
+
+ void
+ FontVariants::feature_callback() {
+ // std::cout << "FontVariants::feature_callback()" << std::endl;
+ _feature_changed = true;
+ _changed_signal.emit();
+ }
+
+ // Update GUI based on query.
+ void
+ FontVariants::update( SPStyle const *query, bool different_features, Glib::ustring& font_spec ) {
+
+ _ligatures_all = query->font_variant_ligatures.computed;
+ _ligatures_mix = query->font_variant_ligatures.value;
+
+ _ligatures_common.set_active( _ligatures_all & SP_CSS_FONT_VARIANT_LIGATURES_COMMON );
+ _ligatures_discretionary.set_active(_ligatures_all & SP_CSS_FONT_VARIANT_LIGATURES_DISCRETIONARY );
+ _ligatures_historical.set_active( _ligatures_all & SP_CSS_FONT_VARIANT_LIGATURES_HISTORICAL );
+ _ligatures_contextual.set_active( _ligatures_all & SP_CSS_FONT_VARIANT_LIGATURES_CONTEXTUAL );
+
+ _ligatures_common.set_inconsistent( _ligatures_mix & SP_CSS_FONT_VARIANT_LIGATURES_COMMON );
+ _ligatures_discretionary.set_inconsistent( _ligatures_mix & SP_CSS_FONT_VARIANT_LIGATURES_DISCRETIONARY );
+ _ligatures_historical.set_inconsistent( _ligatures_mix & SP_CSS_FONT_VARIANT_LIGATURES_HISTORICAL );
+ _ligatures_contextual.set_inconsistent( _ligatures_mix & SP_CSS_FONT_VARIANT_LIGATURES_CONTEXTUAL );
+
+ _position_all = query->font_variant_position.computed;
+ _position_mix = query->font_variant_position.value;
+
+ _position_normal.set_active( _position_all & SP_CSS_FONT_VARIANT_POSITION_NORMAL );
+ _position_sub.set_active( _position_all & SP_CSS_FONT_VARIANT_POSITION_SUB );
+ _position_super.set_active( _position_all & SP_CSS_FONT_VARIANT_POSITION_SUPER );
+
+ _position_normal.set_inconsistent( _position_mix & SP_CSS_FONT_VARIANT_POSITION_NORMAL );
+ _position_sub.set_inconsistent( _position_mix & SP_CSS_FONT_VARIANT_POSITION_SUB );
+ _position_super.set_inconsistent( _position_mix & SP_CSS_FONT_VARIANT_POSITION_SUPER );
+
+ _caps_all = query->font_variant_caps.computed;
+ _caps_mix = query->font_variant_caps.value;
+
+ _caps_normal.set_active( _caps_all & SP_CSS_FONT_VARIANT_CAPS_NORMAL );
+ _caps_small.set_active( _caps_all & SP_CSS_FONT_VARIANT_CAPS_SMALL );
+ _caps_all_small.set_active( _caps_all & SP_CSS_FONT_VARIANT_CAPS_ALL_SMALL );
+ _caps_petite.set_active( _caps_all & SP_CSS_FONT_VARIANT_CAPS_PETITE );
+ _caps_all_petite.set_active( _caps_all & SP_CSS_FONT_VARIANT_CAPS_ALL_PETITE );
+ _caps_unicase.set_active( _caps_all & SP_CSS_FONT_VARIANT_CAPS_UNICASE );
+ _caps_titling.set_active( _caps_all & SP_CSS_FONT_VARIANT_CAPS_TITLING );
+
+ _caps_normal.set_inconsistent( _caps_mix & SP_CSS_FONT_VARIANT_CAPS_NORMAL );
+ _caps_small.set_inconsistent( _caps_mix & SP_CSS_FONT_VARIANT_CAPS_SMALL );
+ _caps_all_small.set_inconsistent( _caps_mix & SP_CSS_FONT_VARIANT_CAPS_ALL_SMALL );
+ _caps_petite.set_inconsistent( _caps_mix & SP_CSS_FONT_VARIANT_CAPS_PETITE );
+ _caps_all_petite.set_inconsistent( _caps_mix & SP_CSS_FONT_VARIANT_CAPS_ALL_PETITE );
+ _caps_unicase.set_inconsistent( _caps_mix & SP_CSS_FONT_VARIANT_CAPS_UNICASE );
+ _caps_titling.set_inconsistent( _caps_mix & SP_CSS_FONT_VARIANT_CAPS_TITLING );
+
+ _numeric_all = query->font_variant_numeric.computed;
+ _numeric_mix = query->font_variant_numeric.value;
+
+ if (_numeric_all & SP_CSS_FONT_VARIANT_NUMERIC_LINING_NUMS) {
+ _numeric_lining.set_active();
+ } else if (_numeric_all & SP_CSS_FONT_VARIANT_NUMERIC_OLDSTYLE_NUMS) {
+ _numeric_old_style.set_active();
+ } else {
+ _numeric_default_style.set_active();
+ }
+
+ if (_numeric_all & SP_CSS_FONT_VARIANT_NUMERIC_PROPORTIONAL_NUMS) {
+ _numeric_proportional.set_active();
+ } else if (_numeric_all & SP_CSS_FONT_VARIANT_NUMERIC_TABULAR_NUMS) {
+ _numeric_tabular.set_active();
+ } else {
+ _numeric_default_width.set_active();
+ }
+
+ if (_numeric_all & SP_CSS_FONT_VARIANT_NUMERIC_DIAGONAL_FRACTIONS) {
+ _numeric_diagonal.set_active();
+ } else if (_numeric_all & SP_CSS_FONT_VARIANT_NUMERIC_STACKED_FRACTIONS) {
+ _numeric_stacked.set_active();
+ } else {
+ _numeric_default_fractions.set_active();
+ }
+
+ _numeric_ordinal.set_active( _numeric_all & SP_CSS_FONT_VARIANT_NUMERIC_ORDINAL );
+ _numeric_slashed_zero.set_active( _numeric_all & SP_CSS_FONT_VARIANT_NUMERIC_SLASHED_ZERO );
+
+
+ _numeric_lining.set_inconsistent( _numeric_mix & SP_CSS_FONT_VARIANT_NUMERIC_LINING_NUMS );
+ _numeric_old_style.set_inconsistent( _numeric_mix & SP_CSS_FONT_VARIANT_NUMERIC_OLDSTYLE_NUMS );
+ _numeric_proportional.set_inconsistent( _numeric_mix & SP_CSS_FONT_VARIANT_NUMERIC_PROPORTIONAL_NUMS );
+ _numeric_tabular.set_inconsistent( _numeric_mix & SP_CSS_FONT_VARIANT_NUMERIC_TABULAR_NUMS );
+ _numeric_diagonal.set_inconsistent( _numeric_mix & SP_CSS_FONT_VARIANT_NUMERIC_DIAGONAL_FRACTIONS );
+ _numeric_stacked.set_inconsistent( _numeric_mix & SP_CSS_FONT_VARIANT_NUMERIC_STACKED_FRACTIONS );
+ _numeric_ordinal.set_inconsistent( _numeric_mix & SP_CSS_FONT_VARIANT_NUMERIC_ORDINAL );
+ _numeric_slashed_zero.set_inconsistent( _numeric_mix & SP_CSS_FONT_VARIANT_NUMERIC_SLASHED_ZERO );
+
+ if( query->font_feature_settings.value )
+ _feature_entry.set_text( query->font_feature_settings.value );
+ if( different_features ) {
+ _feature_label.show();
+ } else {
+ _feature_label.hide();
+ }
+
+
+ // Disable/Enable based on available OpenType tables.
+ font_instance* res = font_factory::Default()->FaceFromFontSpecification( font_spec.c_str() );
+ if( res ) {
+
+ std::map<Glib::ustring,int>::iterator it;
+
+ if((it = res->openTypeTables.find("liga"))!= res->openTypeTables.end() ||
+ (it = res->openTypeTables.find("clig"))!= res->openTypeTables.end()) {
+ _ligatures_common.set_sensitive();
+ } else {
+ _ligatures_common.set_sensitive( false );
+ }
+
+ if((it = res->openTypeTables.find("dlig"))!= res->openTypeTables.end()) {
+ _ligatures_discretionary.set_sensitive();
+ } else {
+ _ligatures_discretionary.set_sensitive( false );
+ }
+
+ if((it = res->openTypeTables.find("hlig"))!= res->openTypeTables.end()) {
+ _ligatures_historical.set_sensitive();
+ } else {
+ _ligatures_historical.set_sensitive( false );
+ }
+
+ if((it = res->openTypeTables.find("calt"))!= res->openTypeTables.end()) {
+ _ligatures_contextual.set_sensitive();
+ } else {
+ _ligatures_contextual.set_sensitive( false );
+ }
+
+ if((it = res->openTypeTables.find("subs"))!= res->openTypeTables.end()) {
+ _position_sub.set_sensitive();
+ } else {
+ _position_sub.set_sensitive( false );
+ }
+
+ if((it = res->openTypeTables.find("sups"))!= res->openTypeTables.end()) {
+ _position_super.set_sensitive();
+ } else {
+ _position_super.set_sensitive( false );
+ }
+
+ if((it = res->openTypeTables.find("smcp"))!= res->openTypeTables.end()) {
+ _caps_small.set_sensitive();
+ } else {
+ _caps_small.set_sensitive( false );
+ }
+
+ if((it = res->openTypeTables.find("c2sc"))!= res->openTypeTables.end() &&
+ (it = res->openTypeTables.find("smcp"))!= res->openTypeTables.end()) {
+ _caps_all_small.set_sensitive();
+ } else {
+ _caps_all_small.set_sensitive( false );
+ }
+
+ if((it = res->openTypeTables.find("pcap"))!= res->openTypeTables.end()) {
+ _caps_petite.set_sensitive();
+ } else {
+ _caps_petite.set_sensitive( false );
+ }
+
+ if((it = res->openTypeTables.find("c2sc"))!= res->openTypeTables.end() &&
+ (it = res->openTypeTables.find("pcap"))!= res->openTypeTables.end()) {
+ _caps_all_petite.set_sensitive();
+ } else {
+ _caps_all_petite.set_sensitive( false );
+ }
+
+ if((it = res->openTypeTables.find("unic"))!= res->openTypeTables.end()) {
+ _caps_unicase.set_sensitive();
+ } else {
+ _caps_unicase.set_sensitive( false );
+ }
+
+ if((it = res->openTypeTables.find("titl"))!= res->openTypeTables.end()) {
+ _caps_titling.set_sensitive();
+ } else {
+ _caps_titling.set_sensitive( false );
+ }
+
+ if((it = res->openTypeTables.find("lnum"))!= res->openTypeTables.end()) {
+ _numeric_lining.set_sensitive();
+ } else {
+ _numeric_lining.set_sensitive( false );
+ }
+
+ if((it = res->openTypeTables.find("onum"))!= res->openTypeTables.end()) {
+ _numeric_old_style.set_sensitive();
+ } else {
+ _numeric_old_style.set_sensitive( false );
+ }
+
+ if((it = res->openTypeTables.find("pnum"))!= res->openTypeTables.end()) {
+ _numeric_proportional.set_sensitive();
+ } else {
+ _numeric_proportional.set_sensitive( false );
+ }
+
+ if((it = res->openTypeTables.find("tnum"))!= res->openTypeTables.end()) {
+ _numeric_tabular.set_sensitive();
+ } else {
+ _numeric_tabular.set_sensitive( false );
+ }
+
+ if((it = res->openTypeTables.find("frac"))!= res->openTypeTables.end()) {
+ _numeric_diagonal.set_sensitive();
+ } else {
+ _numeric_diagonal.set_sensitive( false );
+ }
+
+ if((it = res->openTypeTables.find("afrac"))!= res->openTypeTables.end()) {
+ _numeric_stacked.set_sensitive();
+ } else {
+ _numeric_stacked.set_sensitive( false );
+ }
+
+ if((it = res->openTypeTables.find("ordn"))!= res->openTypeTables.end()) {
+ _numeric_ordinal.set_sensitive();
+ } else {
+ _numeric_ordinal.set_sensitive( false );
+ }
+
+ if((it = res->openTypeTables.find("zero"))!= res->openTypeTables.end()) {
+ _numeric_slashed_zero.set_sensitive();
+ } else {
+ _numeric_slashed_zero.set_sensitive( false );
+ }
+
+ // Make list of tables not handled above... eventually add Gtk::Label with
+ // this info.
+ // std::map<Glib::ustring,int> table_copy = res->openTypeTables;
+ // if( (it = table_copy.find("liga")) != table_copy.end() ) table_copy.erase( it );
+ // if( (it = table_copy.find("clig")) != table_copy.end() ) table_copy.erase( it );
+ // if( (it = table_copy.find("dlig")) != table_copy.end() ) table_copy.erase( it );
+ // if( (it = table_copy.find("hlig")) != table_copy.end() ) table_copy.erase( it );
+ // if( (it = table_copy.find("calt")) != table_copy.end() ) table_copy.erase( it );
+ // if( (it = table_copy.find("subs")) != table_copy.end() ) table_copy.erase( it );
+ // if( (it = table_copy.find("sups")) != table_copy.end() ) table_copy.erase( it );
+ // if( (it = table_copy.find("smcp")) != table_copy.end() ) table_copy.erase( it );
+ // if( (it = table_copy.find("c2sc")) != table_copy.end() ) table_copy.erase( it );
+ // if( (it = table_copy.find("pcap")) != table_copy.end() ) table_copy.erase( it );
+ // if( (it = table_copy.find("unic")) != table_copy.end() ) table_copy.erase( it );
+ // if( (it = table_copy.find("titl")) != table_copy.end() ) table_copy.erase( it );
+ // if( (it = table_copy.find("lnum")) != table_copy.end() ) table_copy.erase( it );
+ // if( (it = table_copy.find("onum")) != table_copy.end() ) table_copy.erase( it );
+ // if( (it = table_copy.find("pnum")) != table_copy.end() ) table_copy.erase( it );
+ // if( (it = table_copy.find("tnum")) != table_copy.end() ) table_copy.erase( it );
+ // if( (it = table_copy.find("frac")) != table_copy.end() ) table_copy.erase( it );
+ // if( (it = table_copy.find("afrc")) != table_copy.end() ) table_copy.erase( it );
+ // if( (it = table_copy.find("ordn")) != table_copy.end() ) table_copy.erase( it );
+ // if( (it = table_copy.find("zero")) != table_copy.end() ) table_copy.erase( it );
+ // for(it = table_copy.begin(); it != table_copy.end(); ++it) {
+ // std::cout << "Other: " << it->first << " Occurances: " << it->second << std::endl;
+ // }
+
+ } else {
+ std::cerr << "FontVariants::update(): Couldn't find font_instance for: "
+ << font_spec << std::endl;
+ }
+
+
+ _ligatures_changed = false;
+ _position_changed = false;
+ _caps_changed = false;
+ _numeric_changed = false;
+ _feature_changed = false;
+ }
+
+ void
+ FontVariants::fill_css( SPCSSAttr *css ) {
+
+ // Ligatures
+ bool common = _ligatures_common.get_active();
+ bool discretionary = _ligatures_discretionary.get_active();
+ bool historical = _ligatures_historical.get_active();
+ bool contextual = _ligatures_contextual.get_active();
+
+ if( !common && !discretionary && !historical && !contextual ) {
+ sp_repr_css_set_property(css, "font-variant-ligatures", "none" );
+ } else if ( common && !discretionary && !historical && contextual ) {
+ sp_repr_css_set_property(css, "font-variant-ligatures", "normal" );
+ } else {
+ Glib::ustring css_string;
+ if ( !common )
+ css_string += "no-common-ligatures ";
+ if ( discretionary )
+ css_string += "discretionary-ligatures ";
+ if ( historical )
+ css_string += "historical-ligatures ";
+ if ( !contextual )
+ css_string += "no-contextual ";
+ sp_repr_css_set_property(css, "font-variant-ligatures", css_string.c_str() );
+ }
+
+ // Position
+ {
+ unsigned position_new = SP_CSS_FONT_VARIANT_POSITION_NORMAL;
+ Glib::ustring css_string;
+ if( _position_normal.get_active() ) {
+ css_string = "normal";
+ } else if( _position_sub.get_active() ) {
+ css_string = "sub";
+ position_new = SP_CSS_FONT_VARIANT_POSITION_SUB;
+ } else if( _position_super.get_active() ) {
+ css_string = "super";
+ position_new = SP_CSS_FONT_VARIANT_POSITION_SUPER;
+ }
+
+ // 'if' may not be necessary... need to test.
+ if( (_position_all != position_new) || ((_position_mix != 0) && _position_changed) ) {
+ sp_repr_css_set_property(css, "font-variant-position", css_string.c_str() );
+ }
+ }
+
+ // Caps
+ {
+ unsigned caps_new = SP_CSS_FONT_VARIANT_CAPS_NORMAL;
+ Glib::ustring css_string;
+ if( _caps_normal.get_active() ) {
+ css_string = "normal";
+ caps_new = SP_CSS_FONT_VARIANT_CAPS_NORMAL;
+ } else if( _caps_small.get_active() ) {
+ css_string = "small-caps";
+ caps_new = SP_CSS_FONT_VARIANT_CAPS_SMALL;
+ } else if( _caps_all_small.get_active() ) {
+ css_string = "all-small-caps";
+ caps_new = SP_CSS_FONT_VARIANT_CAPS_ALL_SMALL;
+ } else if( _caps_all_petite.get_active() ) {
+ css_string = "petite";
+ caps_new = SP_CSS_FONT_VARIANT_CAPS_PETITE;
+ } else if( _caps_all_petite.get_active() ) {
+ css_string = "all-petite";
+ caps_new = SP_CSS_FONT_VARIANT_CAPS_ALL_PETITE;
+ } else if( _caps_unicase.get_active() ) {
+ css_string = "unicase";
+ caps_new = SP_CSS_FONT_VARIANT_CAPS_UNICASE;
+ } else if( _caps_titling.get_active() ) {
+ css_string = "titling";
+ caps_new = SP_CSS_FONT_VARIANT_CAPS_TITLING;
+ }
+
+ // May not be necessary... need to test.
+ //if( (_caps_all != caps_new) || ((_caps_mix != 0) && _caps_changed) ) {
+ sp_repr_css_set_property(css, "font-variant-caps", css_string.c_str() );
+ //}
+ }
+
+ // Numeric
+ bool default_style = _numeric_default_style.get_active();
+ bool lining = _numeric_lining.get_active();
+ bool old_style = _numeric_old_style.get_active();
+
+ bool default_width = _numeric_default_width.get_active();
+ bool proportional = _numeric_proportional.get_active();
+ bool tabular = _numeric_tabular.get_active();
+
+ bool default_fractions = _numeric_default_fractions.get_active();
+ bool diagonal = _numeric_diagonal.get_active();
+ bool stacked = _numeric_stacked.get_active();
+
+ bool ordinal = _numeric_ordinal.get_active();
+ bool slashed_zero = _numeric_slashed_zero.get_active();
+
+ if (default_style & default_width & default_fractions & !ordinal & !slashed_zero) {
+ sp_repr_css_set_property(css, "font-variant-numeric", "normal");
+ } else {
+ Glib::ustring css_string;
+ if ( lining )
+ css_string += "lining-nums ";
+ if ( old_style )
+ css_string += "oldstyle-nums ";
+ if ( proportional )
+ css_string += "proportional-nums ";
+ if ( tabular )
+ css_string += "tabular-nums ";
+ if ( diagonal )
+ css_string += "diagonal-fractions ";
+ if ( stacked )
+ css_string += "stacked-fractions ";
+ if ( ordinal )
+ css_string += "ordinal ";
+ if ( slashed_zero )
+ css_string += "slashed-zero ";
+ sp_repr_css_set_property(css, "font-variant-numeric", css_string.c_str() );
+ }
+
+ // Feature settings
+ Glib::ustring feature_string = _feature_entry.get_text();
+ if( !feature_string.empty() || feature_string.compare( "normal" ) ) {
+ sp_repr_css_set_property(css, "font-feature-settings", feature_string.c_str());
+ }
+ }
+
+} // namespace Widget
+} // namespace UI
+} // namespace Inkscape
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0))
+ 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/font-variants.h b/src/ui/widget/font-variants.h
new file mode 100644
index 000000000..d4329feff
--- /dev/null
+++ b/src/ui/widget/font-variants.h
@@ -0,0 +1,162 @@
+/*
+ * Author:
+ * Tavmjong Bah <tavmjong@free.fr>
+ *
+ * Copyright (C) 2015 Tavmong Bah
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifndef INKSCAPE_UI_WIDGET_FONT_VARIANT_H
+#define INKSCAPE_UI_WIDGET_FONT_VARIANT_H
+
+#include <gtkmm/expander.h>
+#include <gtkmm/checkbutton.h>
+#include <gtkmm/radiobutton.h>
+#include <gtkmm/entry.h>
+
+class SPDesktop;
+class SPObject;
+class SPStyle;
+class SPCSSAttr;
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+/**
+ * A container for selecting font variants (OpenType Features).
+ */
+class FontVariants : public Gtk::VBox
+{
+
+public:
+
+ /**
+ * Constructor
+ */
+ FontVariants();
+
+protected:
+ // To start, use four check buttons.
+ Gtk::Expander _ligatures_frame;
+ Gtk::VBox _ligatures_vbox;
+ Gtk::CheckButton _ligatures_common;
+ Gtk::CheckButton _ligatures_discretionary;
+ Gtk::CheckButton _ligatures_historical;
+ Gtk::CheckButton _ligatures_contextual;
+
+ // Exclusive options
+ Gtk::Expander _position_frame;
+ Gtk::VBox _position_vbox;
+ Gtk::RadioButton _position_normal;
+ Gtk::RadioButton _position_sub;
+ Gtk::RadioButton _position_super;
+
+ // Exclusive options (maybe a dropdown menu to save space?)
+ Gtk::Expander _caps_frame;
+ Gtk::VBox _caps_vbox;
+ Gtk::RadioButton _caps_normal;
+ Gtk::RadioButton _caps_small;
+ Gtk::RadioButton _caps_all_small;
+ Gtk::RadioButton _caps_petite;
+ Gtk::RadioButton _caps_all_petite;
+ Gtk::RadioButton _caps_unicase;
+ Gtk::RadioButton _caps_titling;
+
+ // Complicated!
+ Gtk::Expander _numeric_frame;
+ Gtk::VBox _numeric_vbox;
+ Gtk::HBox _numeric_stylebox;
+ Gtk::RadioButton _numeric_lining;
+ Gtk::RadioButton _numeric_old_style;
+ Gtk::RadioButton _numeric_default_style;
+ Gtk::HBox _numeric_widthbox;
+ Gtk::RadioButton _numeric_proportional;
+ Gtk::RadioButton _numeric_tabular;
+ Gtk::RadioButton _numeric_default_width;
+ Gtk::HBox _numeric_fractionbox;
+ Gtk::RadioButton _numeric_diagonal;
+ Gtk::RadioButton _numeric_stacked;
+ Gtk::RadioButton _numeric_default_fractions;
+ Gtk::CheckButton _numeric_ordinal;
+ Gtk::CheckButton _numeric_slashed_zero;
+
+ Gtk::Expander _feature_frame;
+ Gtk::VBox _feature_vbox;
+ Gtk::Entry _feature_entry;
+ Gtk::Label _feature_label;
+
+private:
+ void ligatures_init();
+ void ligatures_callback();
+
+ void position_init();
+ void position_callback();
+
+ void caps_init();
+ void caps_callback();
+
+ void numeric_init();
+ void numeric_callback();
+
+ void feature_init();
+ void feature_callback();
+
+ // To determine if we need to write out property (may not be necessary)
+ unsigned _ligatures_all;
+ unsigned _position_all;
+ unsigned _caps_all;
+ unsigned _numeric_all;
+
+ unsigned _ligatures_mix;
+ unsigned _position_mix;
+ unsigned _caps_mix;
+ unsigned _numeric_mix;
+
+ bool _ligatures_changed;
+ bool _position_changed;
+ bool _caps_changed;
+ bool _numeric_changed;
+ bool _feature_changed;
+
+ sigc::signal<void> _changed_signal;
+
+public:
+
+ /**
+ * Update GUI based on query results.
+ */
+ void update( SPStyle const *query, bool different_features, Glib::ustring& font_spec );
+
+ /**
+ * Fill SPCSSAttr based on settings of buttons.
+ */
+ void fill_css( SPCSSAttr* css );
+
+ /**
+ * Let others know that user has changed GUI settings.
+ * (Used to enable 'Apply' and 'Default' buttons.)
+ */
+ sigc::connection connectChanged(sigc::slot<void> slot) {
+ return _changed_signal.connect(slot);
+ }
+};
+
+
+} // namespace Widget
+} // namespace UI
+} // namespace Inkscape
+
+#endif // INKSCAPE_UI_WIDGET_FONT_VARIANT_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0))
+ 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/object-composite-settings.cpp b/src/ui/widget/object-composite-settings.cpp
index 00a74c4fe..8acf083d0 100644
--- a/src/ui/widget/object-composite-settings.cpp
+++ b/src/ui/widget/object-composite-settings.cpp
@@ -125,7 +125,8 @@ ObjectCompositeSettings::_blendBlurValueChanged()
const Glib::ustring blendmode = _fe_cb.get_blend_mode();
//apply created filter to every selected item
- for (StyleSubject::iterator i = _subject->begin() ; i != _subject->end() ; ++i ) {
+ std::vector<SPObject*> sel=_subject->list();
+ for (std::vector<SPObject*>::const_iterator i = sel.begin() ; i != sel.end() ; ++i ) {
if (!SP_IS_ITEM(*i)) {
continue;
}
diff --git a/src/ui/widget/page-sizer.cpp b/src/ui/widget/page-sizer.cpp
index 0a5697661..19ab1a280 100644
--- a/src/ui/widget/page-sizer.cpp
+++ b/src/ui/widget/page-sizer.cpp
@@ -266,12 +266,14 @@ PageSizer::PageSizer(Registry & _wr)
_viewboxW.setDigits(2);
_viewboxH.setDigits(2);
+ _dimensionWidth.setRange( 0.00001, 10000000 );
+ _dimensionHeight.setRange( 0.00001, 10000000 );
_scaleX.setRange( 0.00001, 100000 );
_scaleY.setRange( 0.00001, 100000 );
_viewboxX.setRange( -100000, 100000 );
_viewboxY.setRange( -100000, 100000 );
- _viewboxW.setRange( 0, 200000 );
- _viewboxH.setRange( 0, 200000 );
+ _viewboxW.setRange( 0.01, 200000 );
+ _viewboxH.setRange( 0.01, 200000 );
_scaleY.set_sensitive (false); // We only want to display Y scale.
diff --git a/src/ui/widget/preferences-widget.cpp b/src/ui/widget/preferences-widget.cpp
index 72597e4d9..e906762e3 100644
--- a/src/ui/widget/preferences-widget.cpp
+++ b/src/ui/widget/preferences-widget.cpp
@@ -205,6 +205,7 @@ void PrefCheckButton::init(Glib::ustring const &label, Glib::ustring const &pref
void PrefCheckButton::on_toggled()
{
+ this->changed_signal.emit(this->get_active());
if (this->get_visible()) //only take action if the user toggled it
{
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
diff --git a/src/ui/widget/preferences-widget.h b/src/ui/widget/preferences-widget.h
index 8b75b8368..1d2d77699 100644
--- a/src/ui/widget/preferences-widget.h
+++ b/src/ui/widget/preferences-widget.h
@@ -59,6 +59,7 @@ class PrefCheckButton : public Gtk::CheckButton
public:
void init(Glib::ustring const &label, Glib::ustring const &prefs_path,
bool default_value);
+ sigc::signal<void, bool> changed_signal;
protected:
Glib::ustring _prefs_path;
void on_toggled();
diff --git a/src/ui/widget/style-subject.cpp b/src/ui/widget/style-subject.cpp
index a48370d9b..da3bbcd20 100644
--- a/src/ui/widget/style-subject.cpp
+++ b/src/ui/widget/style-subject.cpp
@@ -55,13 +55,11 @@ Inkscape::Selection *StyleSubject::Selection::_getSelection() const {
}
}
-StyleSubject::iterator StyleSubject::Selection::begin() {
+std::vector<SPObject*> StyleSubject::Selection::list(){
Inkscape::Selection *selection = _getSelection();
- if (selection) {
- return iterator(selection->list());
- } else {
- return iterator(NULL);
- }
+ if(selection)
+ return selection->list();
+ else return std::vector<SPObject*>();
}
Geom::OptRect StyleSubject::Selection::getBounds(SPItem::BBoxType type) {
@@ -104,8 +102,7 @@ void StyleSubject::Selection::setCSS(SPCSSAttr *css) {
}
StyleSubject::CurrentLayer::CurrentLayer() {
- _element.data = NULL;
- _element.next = NULL;
+ _element = NULL;
}
StyleSubject::CurrentLayer::~CurrentLayer() {
@@ -114,10 +111,10 @@ StyleSubject::CurrentLayer::~CurrentLayer() {
void StyleSubject::CurrentLayer::_setLayer(SPObject *layer) {
_layer_release.disconnect();
_layer_modified.disconnect();
- if (_element.data) {
- sp_object_unref(static_cast<SPObject *>(_element.data), NULL);
+ if (_element) {
+ sp_object_unref(_element, NULL);
}
- _element.data = layer;
+ _element = layer;
if (layer) {
sp_object_ref(layer, NULL);
_layer_release = layer->connectRelease(sigc::hide(sigc::bind(sigc::mem_fun(*this, &CurrentLayer::_setLayer), (SPObject *)NULL)));
@@ -127,19 +124,18 @@ void StyleSubject::CurrentLayer::_setLayer(SPObject *layer) {
}
SPObject *StyleSubject::CurrentLayer::_getLayer() const {
- return static_cast<SPObject *>(_element.data);
+ return _element;
}
-GSList *StyleSubject::CurrentLayer::_getLayerSList() const {
- if (_element.data) {
- return &_element;
- } else {
- return NULL;
- }
+SPObject *StyleSubject::CurrentLayer::_getLayerSList() const {
+ return _element;
+
}
-StyleSubject::iterator StyleSubject::CurrentLayer::begin() {
- return iterator(_getLayerSList());
+std::vector<SPObject*> StyleSubject::CurrentLayer::list(){
+ std::vector<SPObject*> list;
+ list.push_back(_element);
+ return list;
}
Geom::OptRect StyleSubject::CurrentLayer::getBounds(SPItem::BBoxType type) {
@@ -152,8 +148,10 @@ Geom::OptRect StyleSubject::CurrentLayer::getBounds(SPItem::BBoxType type) {
}
int StyleSubject::CurrentLayer::queryStyle(SPStyle *query, int property) {
- GSList *list = _getLayerSList();
- if (list) {
+ std::vector<SPItem*> list;
+ SPObject* i=_getLayerSList();
+ if (i) {
+ list.push_back((SPItem*)i);
return sp_desktop_query_style_from_list(list, query, property);
} else {
return QUERY_STYLE_NOTHING;
diff --git a/src/ui/widget/style-subject.h b/src/ui/widget/style-subject.h
index 47da91732..15a072f44 100644
--- a/src/ui/widget/style-subject.h
+++ b/src/ui/widget/style-subject.h
@@ -10,7 +10,6 @@
#ifndef SEEN_INKSCAPE_UI_WIDGET_STYLE_SUBJECT_H
#define SEEN_INKSCAPE_UI_WIDGET_STYLE_SUBJECT_H
-#include "util/glib-list-iterators.h"
#include <boost/optional.hpp>
#include <2geom/rect.h>
#include "sp-item.h"
@@ -35,7 +34,6 @@ public:
class Selection;
class CurrentLayer;
- typedef Util::GSListConstIterator<SPObject *> iterator;
StyleSubject();
virtual ~StyleSubject();
@@ -43,11 +41,10 @@ public:
void setDesktop(SPDesktop *desktop);
SPDesktop *getDesktop() const { return _desktop; }
- virtual iterator begin() = 0;
- virtual iterator end() { return iterator(NULL); }
virtual Geom::OptRect getBounds(SPItem::BBoxType type) = 0;
virtual int queryStyle(SPStyle *query, int property) = 0;
virtual void setCSS(SPCSSAttr *css) = 0;
+ virtual std::vector<SPObject*> list(){return std::vector<SPObject*>();};
sigc::connection connectChanged(sigc::signal<void>::slot_type slot) {
return _changed_signal.connect(slot);
@@ -67,10 +64,10 @@ public:
Selection();
~Selection();
- virtual iterator begin();
virtual Geom::OptRect getBounds(SPItem::BBoxType type);
virtual int queryStyle(SPStyle *query, int property);
virtual void setCSS(SPCSSAttr *css);
+ virtual std::vector<SPObject*> list();
protected:
virtual void _afterDesktopSwitch(SPDesktop *desktop);
@@ -88,10 +85,10 @@ public:
CurrentLayer();
~CurrentLayer();
- virtual iterator begin();
virtual Geom::OptRect getBounds(SPItem::BBoxType type);
virtual int queryStyle(SPStyle *query, int property);
virtual void setCSS(SPCSSAttr *css);
+ virtual std::vector<SPObject*> list();
protected:
virtual void _afterDesktopSwitch(SPDesktop *desktop);
@@ -99,12 +96,12 @@ protected:
private:
SPObject *_getLayer() const;
void _setLayer(SPObject *layer);
- GSList *_getLayerSList() const;
+ SPObject *_getLayerSList() const;
sigc::connection _layer_switched;
sigc::connection _layer_release;
sigc::connection _layer_modified;
- mutable GSList _element;
+ mutable SPObject* _element;
};
}