select-context.cpp revision a6235dd0ae24eff3d072a3baf9448fced32338aa
#define __SP_SELECT_CONTEXT_C__
/*
* Selection and transformation context
*
* Author:
* Lauris Kaplinski <lauris@kaplinski.com>
* bulia byak <buliabyak@users.sf.net>
*
* Copyright (C) 1999-2005 authors
*
* Released under GNU GPL, read the file 'COPYING' for more information
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <gdk/gdkkeysyms.h>
#include "macros.h"
#include "rubberband.h"
#include "document.h"
#include "selection.h"
#include "seltrans-handles.h"
#include "sp-cursor.h"
#include "pixmaps/cursor-select-m.xpm"
#include "pixmaps/cursor-select-d.xpm"
#include "pixmaps/handles.xpm"
#include "select-context.h"
#include "selection-chemistry.h"
#include "desktop.h"
#include "desktop-handles.h"
#include "sp-root.h"
#include "prefs-utils.h"
#include "tools-switch.h"
#include "message-stack.h"
#include "selection-describer.h"
#include "seltrans.h"
static gint sp_select_context_item_handler(SPEventContext *event_context, SPItem *item, GdkEvent *event);
static SPEventContextClass *parent_class;
static gint rb_escaped = 0; // if non-zero, rubberband was canceled by esc, so the next button release should not deselect
static bool within_tolerance = false;
{
if (!type) {
sizeof(SPSelectContextClass),
sizeof(SPSelectContext),
4,
NULL, /* value_table */
};
}
return type;
}
static void
{
// cursors in select context
// selection handles
}
static void
{
sc->button_press_shift = false;
sc->button_press_ctrl = false;
sc->button_press_alt = false;
}
static void
{
ec->enableGrDrag(false);
}
delete sc->_describer;
if (CursorSelectDragging) {
}
if (CursorSelectMouseover) {
}
}
static void
{
}
select_context->_describer = new Inkscape::SelectionDescriber(desktop->selection, desktop->messageStack());
ec->enableGrDrag();
}
}
static void
{
} else {
}
}
}
static bool
{
drag_escaped = 1;
// only undo if the item is still valid
}
} else if (sc->button_press_ctrl) {
// NOTE: This is a workaround to a bug.
// When the ctrl key is held, sc->item is not defined
// so in this case (only), we skip the object doc check
}
SP_EVENT_CONTEXT(sc)->desktop->messageStack()->flash(Inkscape::NORMAL_MESSAGE, _("Move canceled."));
return true;
}
} else {
rb_escaped = 1;
SP_EVENT_CONTEXT(sc)->desktop->messageStack()->flash(Inkscape::NORMAL_MESSAGE, _("Selection canceled."));
return true;
}
}
return false;
}
bool
key == GDK_Control_L ||
key == GDK_Control_R ||
key == GDK_Shift_L ||
key == GDK_Shift_R ||
key == GDK_Meta_R);
}
void
{
/* Click in empty place, go up one level -- but don't leave a layer to root.
*
* (Rationale: we don't usually allow users to go to the root, since that
* detracts from the layer metaphor: objects at the root level can in front
* of or behind layers. Whereas it's fine to go to the root if editing
* a document that has no layers (e.g. a non-Inkscape document).)
*
* Once we support editing SVG "islands" (e.g. <svg> embedded in an xhtml
* document), we might consider further restricting the below to disallow
* leaving a layer to go to a non-layer.
*/
if (current_layer) {
if ( parent
&& ( SP_OBJECT_PARENT(parent)
|| !( SP_IS_GROUP(current_layer)
{
}
}
}
static gint
{
// make sure we still have valid objects to move around
}
case GDK_BUTTON_PRESS:
/* Left mousebutton */
// save drag origin
within_tolerance = true;
// remember what modifiers were on before button press
// if shift or ctrl was pressed, do not move objects;
// pass the event to root handler which will perform rubberband, shift-click, ctrl-click, ctrl-drag
} else {
// remember the clicked item in sc->item:
rb_escaped = drag_escaped = 0;
}
// right click; do not eat it so that right-click menu can appear, but cancel dragging & rubberband
}
break;
case GDK_ENTER_NOTIFY:
{
break;
}
case GDK_LEAVE_NOTIFY:
break;
case GDK_KEY_PRESS:
/* stamping mode: show content mode moving */
}
}
break;
default:
break;
}
if (!ret) {
}
return ret;
}
static gint
{
gdouble const nudge = prefs_get_double_attribute_limited("options.nudgedistance", "value", 2, 0, 1000); // in px
gdouble const offset = prefs_get_double_attribute_limited("options.defaultscale", "value", 2, 0, 1000);
// make sure we still have valid objects to move around
}
case GDK_2BUTTON_PRESS:
} else { // switch tool
}
} else {
}
}
break;
case GDK_BUTTON_PRESS:
// save drag origin
within_tolerance = true;
// remember what modifiers were on before button press
rb_escaped = drag_escaped = 0;
// right click; do not eat it so that right-click menu can appear, but cancel dragging & rubberband
}
break;
case GDK_MOTION_NOTIFY:
if ( within_tolerance
break; // do not drag if we're within tolerance from origin
}
// Once the user has moved farther than tolerance from the original location
// (indicating they intend to move the object, not click), then always process the
// motion notify coordinates as given (no snapping back to origin)
within_tolerance = false;
if (sc->button_press_ctrl || sc->button_press_alt) // if ctrl or alt was pressed and it's not click, we want to drag rather than rubberband
/* User has dragged fast, so we get events on root (lauris)*/
// not only that; we will end up here when ctrl-dragging as well
// and also when we started within tolerance, but trespassed tolerance outside of item
if (!item_at_point) // if no item at this point, try at the click point (bug 1012200)
// drag only if starting from an item, or if something is already grabbed, or if alt-dragging
// if neither a group nor an item (possibly in a group) at point are selected, set selection to the item at point
&& !sc->button_press_alt) {
// select what is under cursor
seltrans->resetState();
}
// when simply ctrl-dragging, we don't want to go into groups
} // otherwise, do not change selection so that dragging selected-within-group items, as well as alt-dragging, is possible
}
if (desktop->scroll_to_point(&p))
// unfortunately in complex drawings, gobbling results in losing grab of the object, for some mysterious reason
; //gobble_motion_events(GDK_BUTTON1_MASK);
} else {
}
} else {
}
}
break;
case GDK_BUTTON_RELEASE:
// item has been moved
// item has not been moved -> simply a click, do selecting
// with shift, toggle selection
seltrans->resetState();
} else {
} else {
seltrans->resetState();
}
}
} else { // simple or shift click, no previous selection
seltrans->resetState();
}
}
}
} else {
// this was a rubberband drag
seltrans->resetState();
// find out affected items:
// with shift, add to selection
} else {
// without shift, simply select anew
}
} else { // it was just a click, or a too small rubberband
// this was a shift-click, select what was clicked upon
sc->button_press_shift = false;
if (sc->button_press_ctrl) {
// go into groups, honoring Alt
} else {
// don't go into groups, honoring Alt
}
if (item) {
}
if (item) {
} else {
seltrans->resetState();
}
}
} else { // click without shift, simply deselect, unless with Alt or something was cancelled
rb_escaped = 0;
}
}
}
}
}
}
sc->button_press_shift = false;
sc->button_press_ctrl = false;
sc->button_press_alt = false;
break;
case GDK_KEY_PRESS: // keybindings for select context
} else {
_("<b>Shift</b>: toggle select, force rubberband, disable snapping"),
_("<b>Alt</b>: select under, move selected"));
break;
}
case GDK_Left: // move selection left
case GDK_KP_Left:
case GDK_KP_4:
if (!MOD__CTRL) { // not ctrl
if (MOD__ALT) { // alt
}
else { // no alt
}
}
break;
case GDK_Up: // move selection up
case GDK_KP_Up:
case GDK_KP_8:
if (!MOD__CTRL) { // not ctrl
if (MOD__ALT) { // alt
}
else { // no alt
}
}
break;
case GDK_Right: // move selection right
case GDK_KP_Right:
case GDK_KP_6:
if (!MOD__CTRL) { // not ctrl
if (MOD__ALT) { // alt
}
else { // no alt
}
}
break;
case GDK_Down: // move selection down
case GDK_KP_Down:
case GDK_KP_2:
if (!MOD__CTRL) { // not ctrl
if (MOD__ALT) { // alt
}
else { // no alt
}
}
break;
case GDK_Escape:
break;
case GDK_a:
case GDK_A:
if (MOD__CTRL_ONLY) {
}
break;
case GDK_Tab: // Tab - cycle selection forward
}
break;
case GDK_ISO_Left_Tab: // Shift Tab - cycle selection backward
}
break;
case GDK_space:
/* stamping mode: show outline mode moving */
/* FIXME: Is next condition ok? (lauris) */
}
break;
case GDK_x:
case GDK_X:
if (MOD__ALT_ONLY) {
}
break;
case GDK_bracketleft:
if (MOD__ALT) {
} else if (MOD__CTRL) {
} else if (snaps) {
}
break;
case GDK_bracketright:
if (MOD__ALT) {
} else if (MOD__CTRL) {
} else if (snaps) {
}
break;
case GDK_less:
case GDK_comma:
if (MOD__ALT) {
} else if (MOD__CTRL) {
} else {
}
break;
case GDK_greater:
case GDK_period:
if (MOD__ALT) {
} else if (MOD__CTRL) {
} else {
}
break;
case GDK_Return:
if (MOD__CTRL_ONLY) {
if (selection->singleItem()) {
} else {
SP_EVENT_CONTEXT(sc)->desktop->messageStack()->flash(Inkscape::NORMAL_MESSAGE, _("Selected object is not a group. Cannot enter."));
}
}
}
break;
case GDK_BackSpace:
if (MOD__CTRL_ONLY) {
}
break;
default:
break;
}
break;
case GDK_KEY_RELEASE:
break;
default:
break;
}
if (!ret) {
}
return ret;
}
/*
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 :