author | Jon A. Cruz <jon@joncruz.org> | |
Sat, 18 Dec 2010 06:03:56 +0000 (22:03 -0800) | ||
committer | Jon A. Cruz <jon@joncruz.org> | |
Sat, 18 Dec 2010 06:03:56 +0000 (22:03 -0800) |
22 files changed:
index b46477de16bf581366e880e4caa08cb948d7f7de..ee52b8c30b447a061776e5bce298c2a17c4e2c3a 100644 (file)
path = 'M %f,%f Q %f,%f %f,%f' % (vals[groups['10']][0], vals[groups['20']][0], vals[groups['10']][1], vals[groups['20']][1], vals[groups['10']][2], vals[groups['20']][2])
attribs = {'d': path, 'style': style}
inkex.etree.SubElement(layer, 'path', attribs)
+ if not (vals[groups['70']][0] & 3) and len(vals[groups['10']]) == 5 and len(vals[groups['20']]) == 5:
+ path = 'M %f,%f Q %f,%f %f,%f Q %f,%f %f,%f' % (vals[groups['10']][0], vals[groups['20']][0], vals[groups['10']][1], vals[groups['20']][1], vals[groups['10']][2], vals[groups['20']][2], vals[groups['10']][3], vals[groups['20']][3], vals[groups['10']][4], vals[groups['20']][4])
+ attribs = {'d': path, 'style': style}
+ inkex.etree.SubElement(layer, 'path', attribs)
def export_CIRCLE():
# mandatory group codes : (10, 20, 40) (x, y, radius)
@@ -322,7 +326,7 @@ parser.add_option("--font", action="store", type="string", dest="font", default=
parser.add_option("--tab", action="store", type="string", dest="tab", default="Options")
parser.add_option("--inputhelp", action="store", type="string", dest="inputhelp", default="")
(options, args) = parser.parse_args(inkex.sys.argv[1:])
-doc = inkex.etree.parse(StringIO('<svg xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"></svg>'))
+doc = inkex.etree.parse(StringIO('<svg xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" width="%s" height="%s"></svg>' % (210*90/25.4, 297*90/25.4)))
desc = inkex.etree.SubElement(doc.getroot(), 'desc', {})
defs = inkex.etree.SubElement(doc.getroot(), 'defs', {})
marker = inkex.etree.SubElement(defs, 'marker', {'id': 'DistanceX', 'orient': 'auto', 'refX': '0.0', 'refY': '0.0', 'style': 'overflow:visible'})
diff --git a/share/extensions/gcodetools_all_in_one.inx b/share/extensions/gcodetools_all_in_one.inx
index 0f566fc7b257f6367edee579519921bf2c391329..85d7cfbee79d3c98c1017d82848ffc4d9ad4a909 100644 (file)
</_param>
</page>
- <page name='area' _gui-text='Area'>
+ <page name='area' msgctxt="gcodetools extension" _gui-text='Area'>
<param name="max-area-curves" type="int" min="0" max="1000" _gui-text="Maximum area cutting curves:">100</param>
<param name="area-inkscape-radius" type="float" min="-1000" max="1000" _gui-text="Area width:">-10</param>
index 718ae0d9f6cccea69b47db277829ac3e25540dea..53ceeafaa4e2875bbd6e7f5a47fbb43230a63dc7 100644 (file)
<dependency type="executable" location="extensions">inkex.py</dependency>
<param name='active-tab' type="notebook">
- <page name='area' _gui-text='Area'>
+ <page name='area' msgctxt="gcodetools extension" _gui-text='Area'>
<param name="max-area-curves" type="int" min="0" max="1000" _gui-text="Maximum area cutting curves:">100</param>
<param name="area-inkscape-radius" type="float" min="-1000" max="1000" _gui-text="Area width:">-10</param>
index 264e33ab667693dcf81c1eda498ab3a247869434..63a919806d6ef38b1d6602bcf78aee02e23903da 100644 (file)
<page name="measure" _gui-text="Measure">
<param name="type" type="enum" _gui-text="Measurement Type: ">
<_item value="length">Length</_item>
- <_item value="area">Area</_item>
+ <_item msgctxt="measure extension" value="area">Area</_item>
</param>
<param name="fontsize" type="int" min="1" max="1000" _gui-text="Font size (px):">12</param>
<param name="offset" type="float" min="-10000" max="10000" _gui-text="Offset (px):">-6</param>
index 61f56e3f7fec8ac12aa32c4d3e1434937700173a..d741e2de096a98bda3b7b5a9d3254cd7f3bae644 100644 (file)
#include "svg/css-ostringstream.h"
#include "widgets/icon.h"
#include <xml/repr.h>
+#include "util/ege-appear-time-tracker.h"
using Inkscape::DocumentUndo;
+using ege::AppearTimeTracker;
#define VB_MARGIN 4
#define MIN_ONSCREEN_DISTANCE 50
void
sp_text_edit_dialog (void)
{
+ bool wantTiming = Inkscape::Preferences::get()->getBool("/dialogs/debug/trackAppear", false);
+ GTimer *timer = wantTiming ? g_timer_new() : 0;
+
if (!dlg) {
gchar title[500];
sp_text_edit_dialog_read_selection (dlg, TRUE, TRUE);
}
+ if ( wantTiming ) {
+ // Time tracker takes ownership of the timer.
+ AppearTimeTracker *tracker = new AppearTimeTracker(timer, GTK_WIDGET(dlg), "DialogText");
+ tracker->setAutodelete(true);
+ timer = 0;
+ }
+
gtk_window_present ((GtkWindow *) dlg);
} // end of sp_text_edit_dialog()
index c90cde490ba02dfd0812b1c57a19ddadfbe2934f..d25bdad723550b097117e8b346b2014b93241f8d 100644 (file)
--- a/src/dialogs/xml-tree.cpp
+++ b/src/dialogs/xml-tree.cpp
#include "../widgets/sp-xmlview-attr-list.h"
#include "../widgets/sp-xmlview-content.h"
#include "../widgets/sp-xmlview-tree.h"
+#include "util/ege-appear-time-tracker.h"
using Inkscape::DocumentUndo;
+using ege::AppearTimeTracker;
#define MIN_ONSCREEN_DISTANCE 50
void sp_xml_tree_dialog()
{
SPDesktop *desktop = SP_ACTIVE_DESKTOP;
-
if (!desktop) {
return;
}
+ bool wantTiming = Inkscape::Preferences::get()->getBool("/dialogs/debug/trackAppear", false);
+ GTimer *timer = wantTiming ? g_timer_new() : 0;
+
if (dlg == NULL)
{ // very long block
tree_reset_context();
} // end of if (dlg == NULL)
+ if ( wantTiming ) {
+ // Time tracker takes ownership of the timer.
+ AppearTimeTracker *tracker = new AppearTimeTracker(timer, GTK_WIDGET(dlg), "DialogXMLEditor");
+ tracker->setAutodelete(true);
+ timer = 0;
+ }
+
gtk_window_present((GtkWindow *) dlg);
g_assert(desktop != NULL);
index ff31c91c4910178b544ec84608ff7f76fa59037e..0c49690cce5b70d585cf003335271f410491b267 100644 (file)
#include "ui/dialog/floating-behavior.h"
#include "ui/dialog/dock-behavior.h"
//#include "ui/dialog/print-colors-preview-dialog.h"
+#include "util/ege-appear-time-tracker.h"
#include "preferences.h"
#ifdef ENABLE_SVG_FONTS
* Shows the named dialog, creating it if necessary.
*/
void DialogManager::showDialog(GQuark name) {
- Dialog *dialog=getDialog(name);
- if (dialog) {
+ bool wantTiming = Inkscape::Preferences::get()->getBool("/dialogs/debug/trackAppear", false);
+ GTimer *timer = (wantTiming) ? g_timer_new() : 0; // if needed, must be created/started before getDialog()
+ Dialog *dialog = getDialog(name);
+ if ( dialog ) {
+ if ( wantTiming ) {
+ gchar const * nameStr = g_quark_to_string(name);
+ ege::AppearTimeTracker *tracker = new ege::AppearTimeTracker(timer, dialog->gobj(), nameStr);
+ tracker->setAutodelete(true);
+ timer = 0;
+ }
dialog->present();
}
+
+ if ( timer ) {
+ g_timer_destroy(timer);
+ timer = 0;
+ }
}
} // namespace Dialog
index 0c234003e210397eab05d96b5237bd28e00d599e..19bcadc0056fe4e3a8e4521057319efaacb1fd2e 100644 (file)
contents->pack_start(_notebook, true, true);
- _notebook.append_page(_page_fill, _createPageTabLabel(_("Fill"), INKSCAPE_ICON_OBJECT_FILL));
+ _notebook.append_page(_page_fill, _createPageTabLabel(_("_Fill"), INKSCAPE_ICON_OBJECT_FILL));
_notebook.append_page(_page_stroke_paint, _createPageTabLabel(_("Stroke _paint"), INKSCAPE_ICON_OBJECT_STROKE));
_notebook.append_page(_page_stroke_style, _createPageTabLabel(_("Stroke st_yle"), INKSCAPE_ICON_OBJECT_STROKE_STYLE));
index 91e0bc2c242d367a8b1fc12496593f779f012b22..baa53f76ea920b8e4d208393b25184e4f11e679b 100644 (file)
@@ -290,7 +290,7 @@ void ControlPointSelection::_pointDragged(Geom::Point &new_pos, GdkEventMotion *
{
Geom::Point abs_delta = new_pos - _original_positions[_grabbed_point];
double fdist = Geom::distance(_original_positions[_grabbed_point], _original_positions[_farthest_point]);
- if (held_alt(*event) && fdist > 0) {
+ if (held_only_alt(*event) && fdist > 0) {
// Sculpting
for (iterator i = _points.begin(); i != _points.end(); ++i) {
SelectableControlPoint *cur = (*i);
index ef1c764bbb35c0f35161a42093fa59e2c0c1dad8..082ac194b962e85a2501f99120814896689fbd27 100644 (file)
void MultiPathManipulator::shiftSelection(int dir)
{
- invokeForAll(&PathManipulator::shiftSelection, dir);
+ if (empty()) return;
+
+ // 1. find last selected node
+ // 2. select the next node; if the last node or nothing is selected,
+ // select first node
+ MapType::iterator last_i;
+ SubpathList::iterator last_j;
+ NodeList::iterator last_k;
+ bool anything_found = false;
+
+ for (MapType::iterator i = _mmap.begin(); i != _mmap.end(); ++i) {
+ SubpathList &sp = i->second->subpathList();
+ for (SubpathList::iterator j = sp.begin(); j != sp.end(); ++j) {
+ for (NodeList::iterator k = (*j)->begin(); k != (*j)->end(); ++k) {
+ if (k->selected()) {
+ last_i = i;
+ last_j = j;
+ last_k = k;
+ anything_found = true;
+ // when tabbing backwards, we want the first node
+ if (dir == -1) goto exit_loop;
+ }
+ }
+ }
+ }
+ exit_loop:
+
+ // NOTE: we should not assume the _selection contains only nodes
+ // in future it might also contain handles and other types of control points
+ // this is why we use a flag instead in the loop above, instead of calling
+ // selection.empty()
+ if (!anything_found) {
+ // select first / last node
+ // this should never fail because there must be at least 1 non-empty manipulator
+ if (dir == 1) {
+ _selection.insert((*_mmap.begin()->second->subpathList().begin())->begin().ptr());
+ } else {
+ _selection.insert((--(*--(--_mmap.end())->second->subpathList().end())->end()).ptr());
+ }
+ return;
+ }
+
+ // three levels deep - w00t!
+ if (dir == 1) {
+ if (++last_k == (*last_j)->end()) {
+ // here, last_k points to the node to be selected
+ ++last_j;
+ if (last_j == last_i->second->subpathList().end()) {
+ ++last_i;
+ if (last_i == _mmap.end()) {
+ last_i = _mmap.begin();
+ }
+ last_j = last_i->second->subpathList().begin();
+ }
+ last_k = (*last_j)->begin();
+ }
+ } else {
+ if (!last_k || last_k == (*last_j)->begin()) {
+ if (last_j == last_i->second->subpathList().begin()) {
+ if (last_i == _mmap.begin()) {
+ last_i = _mmap.end();
+ }
+ --last_i;
+ last_j = last_i->second->subpathList().end();
+ }
+ --last_j;
+ last_k = (*last_j)->end();
+ }
+ --last_k;
+ }
+ _selection.clear();
+ _selection.insert(last_k.ptr());
}
void MultiPathManipulator::invertSelectionInSubpaths()
reason = _("Scale nodes vertically");
key = "node:scale:y";
break;
+ case COMMIT_MOUSE_SKEW_X:
+ reason = _("Skew nodes horizontally");
+ key = "node:skew:x";
+ break;
+ case COMMIT_MOUSE_SKEW_Y:
+ reason = _("Skew nodes vertically");
+ key = "node:skew:y";
+ break;
case COMMIT_FLIP_X:
reason = _("Flip nodes horizontally");
break;
diff --git a/src/ui/tool/node.cpp b/src/ui/tool/node.cpp
index 12d04dd2b74541e3e4b804c73e600000f4ae16a2..fea02d399f64c01cbd30bfcee4948736eadaa1b4 100644 (file)
--- a/src/ui/tool/node.cpp
+++ b/src/ui/tool/node.cpp
Handle *towards_second = node_towards ? node_towards->handleToward(_parent) : NULL;
if (Geom::are_near(new_pos, _parent->position())) {
- // The handle becomes degenerate. If the segment between it and the node
+ // The handle becomes degenerate.
+ // Adjust node type as necessary.
+ if (other->isDegenerate()) {
+ // If both handles become degenerate, convert to parent cusp node
+ _parent->setType(NODE_CUSP, false);
+ } else {
+ // Only 1 handle becomes degenerate
+ switch (_parent->type()) {
+ case NODE_AUTO:
+ case NODE_SYMMETRIC:
+ _parent->setType(NODE_SMOOTH, false);
+ break;
+ default:
+ // do nothing for other node types
+ break;
+ }
+ }
+ // If the segment between the handle and the node
// in its direction becomes linear and there are smooth nodes
// at its ends, make their handles colinear with the segment
- if (towards && towards->isDegenerate()) {
+ if (towards && towards_second->isDegenerate()) {
if (node_towards->type() == NODE_SMOOTH) {
- towards_second->setDirection(*_parent, *node_towards);
+ towards->setDirection(*_parent, *node_towards);
}
if (_parent->type() == NODE_SMOOTH) {
other->setDirection(*node_towards, *_parent);
void Handle::setPosition(Geom::Point const &p)
{
+ Geom::Point old_pos = position();
ControlPoint::setPosition(p);
sp_ctrlline_set_coords(SP_CTRLLINE(_handle_line), _parent->position(), position());
if (Geom::are_near(position(), _parent->position()))
_degenerate = true;
else _degenerate = false;
+
if (_parent->_handles_shown && _parent->visible() && !_degenerate) {
setVisible(true);
} else {
setVisible(false);
}
- // If both handles become degenerate, convert to parent cusp node
- if (_parent->isDegenerate()) {
- _parent->setType(NODE_CUSP, false);
- }
}
void Handle::setLength(double len)
void Handle::retract()
{
- setPosition(_parent->position());
+ move(_parent->position());
}
void Handle::setDirection(Geom::Point const &from, Geom::Point const &to)
}
}
+bool Handle::_eventHandler(GdkEvent *event)
+{
+ switch (event->type)
+ {
+ case GDK_KEY_PRESS:
+ switch (shortcut_key(event->key))
+ {
+ case GDK_s:
+ case GDK_S:
+ if (held_only_shift(event->key) && _parent->_type == NODE_CUSP) {
+ // when Shift+S is pressed when hovering over a handle belonging to a cusp node,
+ // hold this handle in place; otherwise process normally
+ // this handle is guaranteed not to be degenerate
+ other()->move(_parent->position() - (position() - _parent->position()));
+ _parent->setType(NODE_SMOOTH, false);
+ _parent->_pm().update(); // magic triple combo to add undo event
+ _parent->_pm().writeXML();
+ _parent->_pm()._commit(_("Change node type"));
+ return true;
+ }
+ break;
+ default: break;
+ }
+ default: break;
+ }
+
+ return ControlPoint::_eventHandler(event);
+}
+
bool Handle::grabbed(GdkEventMotion *)
{
_saved_other_pos = other()->position();
Geom::Point origin = _last_drag_origin();
SnapManager &sm = _desktop->namedview->snap_manager;
bool snap = sm.someSnapperMightSnap();
+ boost::optional<Inkscape::Snapper::SnapConstraint> ctrl_constraint;
// with Alt, preserve length
if (held_alt(*event)) {
// note: if snapping to the original position is only desired in the original
// direction of the handle, change to Ray instead of Line
Geom::Line original_line(parent_pos, origin);
+ 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));
- if (Geom::distance(snap_pos, new_pos) < Geom::distance(orig_pos, new_pos)) {
- new_pos = snap_pos;
- } else {
- new_pos = orig_pos;
+ Geom::Point result = snap_pos;
+ ctrl_constraint = Inkscape::Snapper::SnapConstraint(parent_pos, parent_pos - snap_pos);
+ if (Geom::distance(orig_pos, new_pos) < Geom::distance(result, new_pos)) {
+ result = orig_pos;
+ ctrl_constraint = Inkscape::Snapper::SnapConstraint(parent_pos, parent_pos - orig_pos);
}
- snap = false;
+ if (Geom::distance(perp_pos, new_pos) < Geom::distance(result, new_pos)) {
+ result = perp_pos;
+ ctrl_constraint = Inkscape::Snapper::SnapConstraint(parent_pos, parent_pos - perp_pos);
+ }
+ new_pos = result;
}
std::vector<Inkscape::SnapCandidatePoint> unselected;
}
sm.setupIgnoreSelection(_desktop, true, &unselected);
- Node *node_away = (this == &_parent->_front ? _parent->_prev() : _parent->_next());
+ Node *node_away = _parent->nodeAwayFrom(this);
if (_parent->type() == NODE_SMOOTH && Node::_is_line_segment(_parent, node_away)) {
Inkscape::Snapper::SnapConstraint cl(_parent->position(),
_parent->position() - node_away->position());
Inkscape::SnappedPoint p;
p = sm.constrainedSnap(Inkscape::SnapCandidatePoint(new_pos, SNAPSOURCE_NODE_HANDLE), cl);
new_pos = p.getPoint();
+ } else if (ctrl_constraint) {
+ // NOTE: this is subtly wrong.
+ // We should get all possible constraints and snap along them using
+ // multipleConstrainedSnaps, instead of first snapping to angle and the to objects
+ Inkscape::SnappedPoint p;
+ p = sm.constrainedSnap(Inkscape::SnapCandidatePoint(new_pos, SNAPSOURCE_NODE_HANDLE), *ctrl_constraint);
+ new_pos = p.getPoint();
} else {
sm.freeSnapReturnByRef(new_pos, SNAPSOURCE_NODE_HANDLE);
}
diff --git a/src/ui/tool/node.h b/src/ui/tool/node.h
index 0194f5053176936f7ee0ef62543cb02fa32d2403..b5d4d88f2045c424edfa7882ba427386434cd1fa 100644 (file)
--- a/src/ui/tool/node.h
+++ b/src/ui/tool/node.h
protected:
Handle(NodeSharedData const &data, Geom::Point const &initial_pos, Node *parent);
+ virtual bool _eventHandler(GdkEvent *event);
virtual void dragged(Geom::Point &, GdkEventMotion *);
virtual bool grabbed(GdkEventMotion *);
virtual void ungrabbed(GdkEventButton *);
index 5ae9c4137255c7ab9cc1db66f7cb700045190448..ea7f3412d0de9fae0f60e6f434972fe4c8330525 100644 (file)
/** Select all nodes in subpaths that have something selected. */
void PathManipulator::selectSubpaths()
{
- for (std::list<SubpathPtr>::iterator i = _subpaths.begin(); i != _subpaths.end(); ++i) {
+ for (SubpathList::iterator i = _subpaths.begin(); i != _subpaths.end(); ++i) {
NodeList::iterator sp_start = (*i)->begin(), sp_end = (*i)->end();
for (NodeList::iterator j = sp_start; j != sp_end; ++j) {
if (j->selected()) {
}
}
-/** Move the selection forward or backward by one node in each subpath, based on the sign
- * of the parameter. */
-void PathManipulator::shiftSelection(int dir)
-{
- if (dir == 0) return;
- if (_num_selected == 0) {
- // select the first node of the path.
- SubpathList::iterator s = _subpaths.begin();
- if (s == _subpaths.end()) return;
- NodeList::iterator n = (*s)->begin();
- if (n != (*s)->end())
- _selection.insert(n.ptr());
- return;
- }
- // We cannot do any tricks here, like iterating in different directions based on
- // the sign and only setting the selection of nodes behind us, because it would break
- // for closed paths.
- for (SubpathList::iterator i = _subpaths.begin(); i != _subpaths.end(); ++i) {
- std::deque<bool> sels; // I hope this is specialized for bools!
- unsigned num = 0;
-
- for (NodeList::iterator j = (*i)->begin(); j != (*i)->end(); ++j) {
- sels.push_back(j->selected());
- _selection.erase(j.ptr());
- ++num;
- }
- if (num == 0) continue; // should never happen! zero-node subpaths are not allowed
-
- num = 0;
- // In closed subpath, shift the selection cyclically. In an open one,
- // let the selection 'slide into nothing' at ends.
- if (dir > 0) {
- if ((*i)->closed()) {
- bool last = sels.back();
- sels.pop_back();
- sels.push_front(last);
- } else {
- sels.push_front(false);
- }
- } else {
- if ((*i)->closed()) {
- bool first = sels.front();
- sels.pop_front();
- sels.push_back(first);
- } else {
- sels.push_back(false);
- num = 1;
- }
- }
-
- for (NodeList::iterator j = (*i)->begin(); j != (*i)->end(); ++j) {
- if (sels[num]) _selection.insert(j.ptr());
- ++num;
- }
- }
-}
-
/** Invert selection in the selected subpaths. */
void PathManipulator::invertSelectionInSubpaths()
{
NodeList::iterator k = j.next();
Node *n = new Node(_multi_path_manipulator._path_data.node_data, *j);
- // Move the new node to the bottom of the Z-order. This way you can drag all
- // nodes that were selected before this operation without deselecting
- // everything because there is a new node above.
- n->sink();
+ if (k) {
+ // Move the new node to the bottom of the Z-order. This way you can drag all
+ // nodes that were selected before this operation without deselecting
+ // everything because there is a new node above.
+ n->sink();
+ }
n->front()->setPosition(*j->front());
j->front()->retract();
j->setType(NODE_CUSP, false);
(*i)->insert(k, n);
- // We need to manually call the selection change callback to refresh
- // the handle display correctly.
- // This call changes num_selected, but we call this once for a selected node
- // and once for an unselected node, so in the end the number stays correct.
- _selectionChanged(j.ptr(), true);
- _selectionChanged(n, false);
+ if (k) {
+ // We need to manually call the selection change callback to refresh
+ // the handle display correctly.
+ // This call changes num_selected, but we call this once for a selected node
+ // and once for an unselected node, so in the end the number stays correct.
+ _selectionChanged(j.ptr(), true);
+ _selectionChanged(n, false);
+ } else {
+ // select the new end node instead of the node just before it
+ _selection.erase(j.ptr());
+ _selection.insert(n);
+ break; // this was the end node, nothing more to do
+ }
}
}
}
index 87b88fc77495bfb4c141bb2a936eec1f1d968d53..8a0167e595111ff38785cce37c9fe1bbc8e859d5 100644 (file)
SPPath *item() { return _path; }
void selectSubpaths();
- void shiftSelection(int dir);
void invertSelectionInSubpaths();
void insertNodes();
NodeList::iterator extremeNode(NodeList::iterator origin, bool search_selected,
bool search_unselected, bool closest);
+ // this is necessary for Tab-selection in MultiPathManipulator
+ SubpathList &subpathList() { return _subpaths; }
+
static bool is_item_type(void *item);
private:
typedef NodeList Subpath;
index ef93a3767c32777722c67854f5fd6d19c66e7a14..cafd592a3622017f42f62fafdd7253bd1b17f461 100644 (file)
#include "desktop-handles.h"
#include "display/sodipodi-ctrlrect.h"
#include "preferences.h"
+#include "snap.h"
+#include "sp-namedview.h"
#include "ui/tool/commit-events.h"
#include "ui/tool/control-point.h"
#include "ui/tool/event-utils.h"
}
protected:
-
+ virtual void dragged(Geom::Point &new_pos, GdkEventMotion *event) {
+ SnapManager &sm = _desktop->namedview->snap_manager;
+ sm.setup(_desktop);
+ bool snap = !held_shift(*event) && sm.someSnapperMightSnap();
+ if (held_control(*event)) {
+ // constrain to axes
+ Geom::Point origin = _last_drag_origin();
+ std::vector<Inkscape::Snapper::SnapConstraint> constraints;
+ constraints.push_back(Inkscape::Snapper::SnapConstraint(origin, Geom::Point(1, 0)));
+ constraints.push_back(Inkscape::Snapper::SnapConstraint(origin, Geom::Point(0, 1)));
+ new_pos = sm.multipleConstrainedSnaps(Inkscape::SnapCandidatePoint(new_pos,
+ SNAPSOURCE_ROTATION_CENTER), constraints, held_shift(*event)).getPoint();
+ } else if (snap) {
+ sm.freeSnapReturnByRef(new_pos, SNAPSOURCE_ROTATION_CENTER);
+ }
+ sm.unSetup();
+ }
virtual Glib::ustring _getTip(unsigned /*state*/) {
return C_("Transform handle tip",
"<b>Rotation center</b>: drag to change the origin of transforms");
index 3097306009a3fb36751c8b9aec216fabb49cfb0a..aba3a18e82ee9428f0f523c6926873fcfc52a3fc 100644 (file)
SimpleFilterModifier::SimpleFilterModifier(int flags)
: _lb_blend(_("_Blend mode:")),
- _lb_blur(_("Blur:"), Gtk::ALIGN_LEFT),
+ _lb_blur(_("_Blur:"), Gtk::ALIGN_LEFT, Gtk::ALIGN_CENTER, true),
_blend(BlendModeConverter, SP_ATTR_INVALID, false),
_blur(0, 0, 100, 1, 0.01, 1)
{
diff --git a/src/ui/widget/object-composite-settings.cpp b/src/ui/widget/object-composite-settings.cpp
index 1de425da376b97856680a119645773f65f6017ea..997c2f0dc87acf371af7715e3536de0ae38059f0 100644 (file)
_opacity_tag(Glib::ustring(history_prefix) + ":opacity"),
_opacity_vbox(false, 0),
_opacity_label_box(false, 0),
- _opacity_label(_("Opacity (%):"), 0.0, 1.0, true),
+ _opacity_label(_("_Opacity (%):"), 0.0, 1.0, true),
_opacity_adjustment(100.0, 0.0, 100.0, 1.0, 1.0, 0.0),
_opacity_hscale(_opacity_adjustment),
_opacity_spin_button(_opacity_adjustment, 0.01, 1),
_opacity_hscale.set_draw_value(false);
_opacity_hscale.set_update_policy(Gtk::UPDATE_DELAYED);
_opacity_adjustment.signal_value_changed().connect(sigc::mem_fun(*this, &ObjectCompositeSettings::_opacityValueChanged));
+ _opacity_label.set_mnemonic_widget(_opacity_hscale);
show_all_children();
index d2f0055315e0155baa22d2b1bbf2f574a6f62039..deff951d44f4f06bdf2d39ecb43c3861360a36d7 100644 (file)
--- a/src/util/Makefile_insert
+++ b/src/util/Makefile_insert
util/compose.hpp \
util/copy.h \
util/enums.h \
+ util/ege-appear-time-tracker.cpp \
+ util/ege-appear-time-tracker.h \
util/ege-tags.h \
util/ege-tags.cpp \
util/filter-list.h \
diff --git a/src/util/ege-appear-time-tracker.cpp b/src/util/ege-appear-time-tracker.cpp
--- /dev/null
@@ -0,0 +1,162 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Appear Time Tracker.
+ *
+ * The Initial Developer of the Original Code is
+ * Jon A. Cruz.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+
+#include "ege-appear-time-tracker.h"
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+
+namespace ege
+{
+
+namespace {
+
+void unhookHandler( gulong &id, GtkWidget *obj )
+{
+ if ( id ) {
+ if ( obj ) {
+ g_signal_handler_disconnect( G_OBJECT(obj), id );
+ }
+ id = 0;
+ }
+}
+
+} // namespace
+
+
+AppearTimeTracker::AppearTimeTracker(GTimer *timer, GtkWidget *widget, gchar const* name) :
+ _name(name ? name : ""),
+ _timer(timer),
+ _widget(widget),
+ _topMost(widget),
+ _autodelete(false),
+ _mapId(0),
+ _realizeId(0),
+ _hierarchyId(0)
+
+{
+ while (_topMost->parent) {
+ _topMost = _topMost->parent;
+ }
+ _mapId = g_signal_connect( G_OBJECT(_topMost), "map-event", G_CALLBACK(mapCB), this );
+ _realizeId = g_signal_connect( G_OBJECT(_topMost), "realize", G_CALLBACK(realizeCB), this );
+ _hierarchyId = g_signal_connect( G_OBJECT(_widget), "hierarchy-changed", G_CALLBACK(hierarchyCB), this );
+}
+
+AppearTimeTracker::~AppearTimeTracker()
+{
+ if ( _timer ) {
+ g_timer_destroy(_timer);
+ _timer = 0;
+ }
+
+ unhookHandler( _mapId, _topMost );
+ unhookHandler( _realizeId, _topMost );
+ unhookHandler( _hierarchyId, _widget );
+}
+
+void AppearTimeTracker::stop() {
+ if (_timer) {
+ g_timer_stop(_timer);
+ }
+}
+
+void AppearTimeTracker::setAutodelete(bool autodelete)
+{
+ if ( autodelete != _autodelete ) {
+ _autodelete = autodelete;
+ }
+}
+
+void AppearTimeTracker::report(gchar const* msg)
+{
+ gulong msCount = 0;
+ gdouble secs = g_timer_elapsed( _timer, &msCount );
+ g_message("Time ended at %2.3f with [%s] on [%s]", secs, msg, _name.c_str());
+}
+
+void AppearTimeTracker::handleHierarchyChange( GtkWidget * /*prevTop*/ )
+{
+ GtkWidget *newTop = _widget;
+ while (newTop->parent) {
+ newTop = newTop->parent;
+ }
+
+ if ( newTop != _topMost ) {
+ unhookHandler( _mapId, _topMost );
+ unhookHandler( _realizeId, _topMost );
+
+ _topMost = newTop;
+ _mapId = g_signal_connect( G_OBJECT(_topMost), "map-event", G_CALLBACK(mapCB), this );
+ _realizeId = g_signal_connect( G_OBJECT(_topMost), "realize", G_CALLBACK(realizeCB), this );
+ }
+}
+
+gboolean AppearTimeTracker::mapCB(GtkWidget * /*widget*/, GdkEvent * /*event*/, gpointer userData)
+{
+ AppearTimeTracker *tracker = reinterpret_cast<AppearTimeTracker*>(userData);
+ tracker->report("MAP");
+ if ( tracker->_autodelete ) {
+ delete tracker;
+ }
+ return FALSE;
+}
+
+void AppearTimeTracker::realizeCB(GtkWidget * /*widget*/, gpointer userData)
+{
+ AppearTimeTracker *tracker = reinterpret_cast<AppearTimeTracker*>(userData);
+ tracker->report("REALIZE");
+}
+
+void AppearTimeTracker::hierarchyCB(GtkWidget * /*widget*/, GtkWidget *prevTop, gpointer userData)
+{
+ AppearTimeTracker *tracker = reinterpret_cast<AppearTimeTracker*>(userData);
+ tracker->handleHierarchyChange( prevTop );
+}
+
+} // namespace ege
+
+/*
+ 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/util/ege-appear-time-tracker.h b/src/util/ege-appear-time-tracker.h
--- /dev/null
@@ -0,0 +1,89 @@
+#ifndef SEEN_APPEAR_TIME_TRACKER_H
+#define SEEN_APPEAR_TIME_TRACKER_H
+
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Appear Time Tracker.
+ *
+ * The Initial Developer of the Original Code is
+ * Jon A. Cruz.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include <glib/gtimer.h>
+#include <glibmm/ustring.h>
+
+typedef union _GdkEvent GdkEvent;
+typedef struct _GtkWidget GtkWidget;
+
+namespace ege
+{
+
+class AppearTimeTracker {
+public:
+ AppearTimeTracker(GTimer *timer, GtkWidget *widget, gchar const* name);
+ ~AppearTimeTracker();
+
+ void stop();
+
+ bool isAutodelete() const { return _autodelete; }
+ void setAutodelete(bool autodelete);
+
+private:
+ Glib::ustring _name;
+ GTimer *_timer;
+ GtkWidget *_widget;
+ GtkWidget *_topMost;
+ bool _autodelete;
+ gulong _mapId;
+ gulong _realizeId;
+ gulong _hierarchyId;
+
+ static gboolean mapCB(GtkWidget *widget, GdkEvent *event, gpointer userData);
+ static void realizeCB(GtkWidget *widget, gpointer userData);
+ static void hierarchyCB(GtkWidget *widget, GtkWidget *prevTop, gpointer userData);
+
+ void report(gchar const* msg);
+ void handleHierarchyChange( GtkWidget *prevTop );
+};
+
+} // namespace ege
+
+#endif // SEEN_APPEAR_TIME_TRACKER_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/verbs.cpp b/src/verbs.cpp
index c1726ecd412b5bbc46f9b78a0272a85262cefab4..00a82624bddac847137f697289181fa21b99f4f6 100644 (file)
--- a/src/verbs.cpp
+++ b/src/verbs.cpp
N_("Raise the current layer"), INKSCAPE_ICON_LAYER_RAISE),
new LayerVerb(SP_VERB_LAYER_LOWER, "LayerLower", N_("_Lower Layer"),
N_("Lower the current layer"), INKSCAPE_ICON_LAYER_LOWER),
- new LayerVerb(SP_VERB_LAYER_DUPLICATE, "LayerDuplicate", N_("Duplicate Current Layer"),
+ new LayerVerb(SP_VERB_LAYER_DUPLICATE, "LayerDuplicate", N_("D_uplicate Current Layer"),
N_("Duplicate an existing layer"), NULL),
new LayerVerb(SP_VERB_LAYER_DELETE, "LayerDelete", N_("_Delete Current Layer"),
N_("Delete the current layer"), INKSCAPE_ICON_LAYER_DELETE),
index 57e58cd5e4d4795f98c8eb8c9bd3017b7b7353aa..4620b15328e0137603f11dcf50078cf0426513a5 100644 (file)
#include "ui/widget/layer-selector.h"
#include "ui/widget/selected-style.h"
#include "ui/uxmanager.h"
+#include "util/ege-appear-time-tracker.h"
// We're in the "widgets" directory, so no need to explicitly prefix these:
#include "button.h"
using Inkscape::UnitTracker;
using Inkscape::UI::UXManager;
using Inkscape::UI::ToolboxFactory;
+using ege::AppearTimeTracker;
#ifdef WITH_INKBOARD
#endif
return Geom::Point(x,y);
}
+static GTimer *overallTimer = 0;
+
/**
* Registers SPDesktopWidget class and returns its type number.
*/
0 // value_table
};
type = g_type_register_static(SP_TYPE_VIEW_WIDGET, "SPDesktopWidget", &info, static_cast<GTypeFlags>(0));
+ // Begin a timer to watch for the first desktop to appear on-screen
+ overallTimer = g_timer_new();
}
return type;
}
gtk_widget_grab_focus (GTK_WIDGET(dtw->canvas));
- {
- g_message("FIRE UP");
-
- gtk_widget_add_events( eventbox, GDK_STRUCTURE_MASK );
-
- gboolean fooMap(GtkWidget *widget, GdkEvent *event, gpointer userData);
- g_signal_connect( G_OBJECT(eventbox), "map-event", G_CALLBACK(fooMap), dtw );
-
- void fooReal(GtkWidget *widget, gpointer userData);
- g_signal_connect( G_OBJECT(eventbox), "map-event", G_CALLBACK(fooReal), dtw );
+ // If this is the first desktop created, report the time it takes to show up
+ if ( overallTimer ) {
+ if ( prefs->getBool("/dialogs/debug/trackAppear", false) ) {
+ // Time tracker takes ownership of the timer.
+ AppearTimeTracker *tracker = new AppearTimeTracker(overallTimer, GTK_WIDGET(dtw), "first SPDesktopWidget");
+ tracker->setAutodelete(true);
+ } else {
+ g_timer_destroy(overallTimer);
+ }
+ overallTimer = 0;
}
}
-gboolean fooMap(GtkWidget *widget, GdkEvent *event, gpointer userData) {
- checkTime( "MAP");
- return FALSE;
-}
-
-void fooReal(GtkWidget *widget, gpointer userData)
-{
- checkTime("REALIZE");
-}
-
/**
* Called before SPDesktopWidget destruction.
*/