control-point.cpp revision 7bf204ae2ff892315b88fb170ae57bb92415ce54
550N/A * Desktop-bound visual control object - implementation 550N/A * Krzysztof KosiĆski <tweenk.pl@gmail.com> 550N/A * Copyright (C) 2009 Authors 550N/A * Released under GNU GPL, read the file 'COPYING' for more information 550N/A// class and member documentation goes here... 550N/A * @brief Draggable point, the workhorse of on-canvas editing. 550N/A * Control points (formerly known as knots) are graphical representations of some significant 550N/A * point in the drawing. The drawing can be changed by dragging the point and the things that are 550N/A * attached to it with the mouse. Example things that could be edited with draggable points 550N/A * are gradient stops, the place where text is attached to a path, text kerns, nodes and handles 550N/A * in a path, and many more. 550N/A * @par Control point event handlers 550N/A * The control point has several virtual methods which allow you to react to things that 550N/A * happen to it. The most important ones are the grabbed, dragged, ungrabbed and moved functions. 550N/A * When a drag happens, the order of calls is as follows: * The control point can also respond to clicks and double clicks. On a double click, * clicked() is called, followed by doubleclicked(). When deriving from SelectableControlPoint, * you need to manually call the superclass version at the appropriate point in your handler. * @par Which method to override? * You might wonder which hook to use when you want to do things when the point is relocated. * - If the point is used to edit an object, override the move() method. * - If the point can usually be dragged wherever you like but can optionally be constrained * to axes or the like, add a handler for <tt>signal_dragged</tt> that modifies its new * - If the point has additional canvas items tied to it (like handle lines), override * the setPosition() method. * @enum ControlPoint::State * Enumeration representing the possible states of the control point, used to determine * @var ControlPoint::STATE_NORMAL * @var ControlPoint::STATE_MOUSEOVER * Mouse is hovering over the control point * @var ControlPoint::STATE_CLICKED * First mouse button pressed over the control point // Default colors for control points {
0xffffff00,
0x01000000},
// normal fill, stroke {
0xff0000ff,
0x01000000},
// mouseover fill, stroke {
0x0000ffff,
0x01000000}
// clicked fill, stroke/** Holds the currently mouseovered control point. */ /** Emitted when the mouseovered point changes. The parameter is the new mouseovered point. * When a point ceases to be mouseovered, the parameter will be NULL. */ /** Stores the window point over which the cursor was during the last mouse button press */ /** Stores the desktop point from which the last drag was initiated */ /** Events which should be captured when a handle is being dragged. */ /** A color set which you can use to create an invisible control that can still receive events. * @relates ControlPoint */ {
0x00000000,
0x00000000},
{
0x00000000,
0x00000000},
* Create a regular control point. * Derive to have constructors with a reasonable number of parameters. * @param d Desktop for this control * @param initial_pos Initial position of the control point in desktop coordinates * @param anchor Where is the control point rendered relative to its desktop coordinates * @param shape Shape of the control point: square, diamond, circle... * @param size Pixel size of the visual representation * @param cset Colors of the point * @param group The canvas group the point's canvas item should be created in * Create a control point with a pixbuf-based visual representation. * @param d Desktop for this control * @param initial_pos Initial position of the control point in desktop coordinates * @param anchor Where is the control point rendered relative to its desktop coordinates * @param pixbuf Pixbuf to be used as the visual representation * @param cset Colors of the point * @param group The canvas group the point's canvas item should be created in // avoid storing invalid points in mouseovered_point //sp_canvas_item_hide(_canvas_item); /** Relocate the control point without side effects. * Overload this method only if there is an additional graphical representation * that must be updated (like the lines that connect handles to nodes). If you override it, * you must also call the superclass implementation of the method. * @todo Investigate whether this method should be protected */ /** Move the control point to new position with side effects. * This is called after each drag. Override this method if only some positions make sense * for a control point (like a point that must always be on a path and can't modify it), * or when moving a control point changes the positions of other points. */ /** Apply an arbitrary affine transformation to a control point. This is used * by ControlPointSelection, and is important for things like nodes with handles. * The default implementation simply moves the point according to the transform. */ /** Set the visibility of the control point. An invisible point is not drawn on the canvas * and cannot receive any events. If you want to have an invisible point that can respond * to events, use <tt>invisible_cset</tt> as its color set. */ return static_cast<
unsigned int>(
ret);
// re-routes events into the virtual function // main event callback, which emits all other callbacks. // NOTE the static variables below are shared for all points! // TODO handle clicks and drags from other buttons too // offset from the pointer hotspot to the center of the grabbed knot in desktop coords // number of last doubleclicked button // 1st mouse button click. internally, start dragging, but do not emit signals // or change position until drag tolerance is exceeded. // route all events to this handler // store the button number for next release // if we are here, it means the tolerance was just exceeded. // _drag_initiated might change during the above virtual call // this guarantees smooth redraws while dragging // the new position is passed by reference and can be changed in the handlers. // If we have any pending snap event, then invoke it now! // (This is needed because we might not have snapped on the latest GDK_MOTION_NOTIFY event // if the mouse speed was too high. This is inherent to the snap-delay mechanism. // We must snap at some point in time though, and this is our last chance) // PS: For other contexts this is handled already in sp_event_context_item_handler or // sp_event_context_root_handler // it is the end of a drag // it is the end of a click // update tips on modifier state change // TODO add ESC keybinding as drag cancel return true;
// this prevents the tool from overwriting the drag tip // we need to return true if there was a tip available, otherwise the tool's // handler will process this event and set the tool's message, overwriting // do not propagate events during grab - it might cause problems if (
visible) {
// invisible points shouldn't get mouseovered /** Transfer the grab to another point. This method allows one to create a draggable point * that should be dragged instead of the one that received the grabbed signal. * This is used to implement dragging out handles in the new node tool, for example. * This method will NOT emit the ungrab signal of @c prev_point, because this would complicate * using it with selectable control points. If you use this method while dragging, you must emit * the ungrab signal yourself. * Note that this will break horribly if you try to transfer grab between points in different * desktops, which doesn't make much sense anyway. */ * @brief Change the state of the knot * Alters the appearance of the knot to match one of the states: normal, mouseover // dummy implementations for handlers // they are here to avoid unused param warnings c-file-style:"stroustrup" c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :