Ejemplo n.º 1
0
bool
Dialog::_onEvent(GdkEvent *event)
{
    bool ret = false;

    switch (event->type) {
        case GDK_KEY_PRESS: {
            switch (get_group0_keyval (&event->key)) {
                case GDK_Escape: {
                    _defocus();
                    ret = true;
                    break;
                }
                case GDK_F4:
                case GDK_w:
                case GDK_W: {
                    if (mod_ctrl_only(event->key.state)) {
                        _close();
                        ret = true;
                    }
                    break;
                }
                default: { // pass keypress to the canvas
                    break;
                }
            }
        }
        default:
            ;
    }

    return ret;
}
Ejemplo n.º 2
0
/**
 * Callback for handling all pencil context events.
 */
gint
sp_pencil_context_root_handler(SPEventContext *const ec, GdkEvent *event)
{
    SPPencilContext *const pc = SP_PENCIL_CONTEXT(ec);

    gint ret = FALSE;

    switch (event->type) {
        case GDK_BUTTON_PRESS:
            ret = pencil_handle_button_press(pc, event->button);
            break;

        case GDK_MOTION_NOTIFY:
            ret = pencil_handle_motion_notify(pc, event->motion);
            break;

        case GDK_BUTTON_RELEASE:
            ret = pencil_handle_button_release(pc, event->button);
            break;

        case GDK_KEY_PRESS:
            ret = pencil_handle_key_press(pc, get_group0_keyval (&event->key), event->key.state);
            break;

        case GDK_KEY_RELEASE:
            ret = pencil_handle_key_release(pc, get_group0_keyval (&event->key), event->key.state);
            break;

        default:
            break;
    }

    if (!ret) {
        gint (*const parent_root_handler)(SPEventContext *, GdkEvent *)
            = ((SPEventContextClass *) pencil_parent_class)->root_handler;
        if (parent_root_handler) {
            ret = parent_root_handler(ec, event);
        }
    }

    return ret;
}
Ejemplo n.º 3
0
static bool on_window_key_press(GdkEventKey* event)
{
	unsigned int shortcut;
	shortcut = get_group0_keyval (event) |
	           ( event->state & GDK_SHIFT_MASK ?
	             SP_SHORTCUT_SHIFT_MASK : 0 ) |
	           ( event->state & GDK_CONTROL_MASK ?
	             SP_SHORTCUT_CONTROL_MASK : 0 ) |
	           ( event->state & GDK_MOD1_MASK ?
	             SP_SHORTCUT_ALT_MASK : 0 );
	return sp_shortcut_invoke (shortcut, SP_ACTIVE_DESKTOP);
}
Ejemplo n.º 4
0
bool ZoomTool::root_handler(GdkEvent* event) {
    Inkscape::Preferences *prefs = Inkscape::Preferences::get();
	
    tolerance = prefs->getIntLimited("/options/dragtolerance/value", 0, 0, 100);
    double const zoom_inc = prefs->getDoubleLimited("/options/zoomincrement/value", M_SQRT2, 1.01, 10);

    bool ret = false;

    switch (event->type) {
        case GDK_BUTTON_PRESS:
        {
            Geom::Point const button_w(event->button.x, event->button.y);
            Geom::Point const button_dt(desktop->w2d(button_w));

            if (event->button.button == 1 && !this->space_panning) {
                // save drag origin
                xp = (gint) event->button.x;
                yp = (gint) event->button.y;
                within_tolerance = true;

                Inkscape::Rubberband::get(desktop)->start(desktop, button_dt);

                escaped = false;

                ret = true;
            } else if (event->button.button == 3) {
                double const zoom_rel( (event->button.state & GDK_SHIFT_MASK)
                                       ? zoom_inc
                                       : 1 / zoom_inc );

                desktop->zoom_relative_keep_point(button_dt, zoom_rel);
                ret = true;
            }
			
			sp_canvas_item_grab(SP_CANVAS_ITEM(desktop->acetate),
								GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK,
								NULL, event->button.time);

			this->grabbed = SP_CANVAS_ITEM(desktop->acetate);
            break;
        }

	case GDK_MOTION_NOTIFY:
            if ((event->motion.state & GDK_BUTTON1_MASK) && !this->space_panning) {
                ret = true;

                if ( within_tolerance
                     && ( abs( (gint) event->motion.x - xp ) < tolerance )
                     && ( abs( (gint) event->motion.y - yp ) < 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;

                Geom::Point const motion_w(event->motion.x, event->motion.y);
                Geom::Point const motion_dt(desktop->w2d(motion_w));
                Inkscape::Rubberband::get(desktop)->move(motion_dt);
                gobble_motion_events(GDK_BUTTON1_MASK);
            }
            break;

      	case GDK_BUTTON_RELEASE:
        {
            Geom::Point const button_w(event->button.x, event->button.y);
            Geom::Point const button_dt(desktop->w2d(button_w));

            if ( event->button.button == 1  && !this->space_panning) {
                Geom::OptRect const b = Inkscape::Rubberband::get(desktop)->getRectangle();

                if (b && !within_tolerance) {
                    desktop->set_display_area(*b, 10);
                } else if (!escaped) {
                    double const zoom_rel( (event->button.state & GDK_SHIFT_MASK)
                                           ? 1 / zoom_inc
                                           : zoom_inc );

                    desktop->zoom_relative_keep_point(button_dt, zoom_rel);
                }

                ret = true;
            }

            Inkscape::Rubberband::get(desktop)->stop();
			
			if (this->grabbed) {
				sp_canvas_item_ungrab(this->grabbed, event->button.time);
				this->grabbed = NULL;
			}
			
            xp = yp = 0;
            escaped = false;
            break;
        }
        case GDK_KEY_PRESS:
            switch (get_group0_keyval (&event->key)) {
                case GDK_KEY_Escape:
                    if (!Inkscape::Rubberband::get(desktop)->is_started()) {
                        Inkscape::SelectionHelper::selectNone(desktop);
                    }

                    Inkscape::Rubberband::get(desktop)->stop();
                    xp = yp = 0;
                    escaped = true;
                    ret = true;
                    break;

                case GDK_KEY_Up:
                case GDK_KEY_Down:
                case GDK_KEY_KP_Up:
                case GDK_KEY_KP_Down:
                    // prevent the zoom field from activation
                    if (!MOD__CTRL_ONLY(event))
                        ret = true;
                    break;

                case GDK_KEY_Shift_L:
                case GDK_KEY_Shift_R:
                    this->cursor_shape = cursor_zoom_out_xpm;
                    this->sp_event_context_update_cursor();
                    break;

                case GDK_KEY_Delete:
                case GDK_KEY_KP_Delete:
                case GDK_KEY_BackSpace:
                    ret = this->deleteSelectedDrag(MOD__CTRL_ONLY(event));
                    break;

                default:
			break;
		}
		break;
	case GDK_KEY_RELEASE:
            switch (get_group0_keyval (&event->key)) {
            	case GDK_KEY_Shift_L:
            	case GDK_KEY_Shift_R:
                    this->cursor_shape = cursor_zoom_xpm;
                    this->sp_event_context_update_cursor();
                    break;
            	default:
                    break;
            }
            break;
	default:
            break;
    }

    if (!ret) {
    	ret = ToolBase::root_handler(event);
    }

    return ret;
}
Ejemplo n.º 5
0
static gint
sp_select_context_root_handler(SPEventContext *event_context, GdkEvent *event)
{
    SPItem *item = NULL;
    SPItem *item_at_point = NULL, *group_at_point = NULL, *item_in_group = NULL;
    gint ret = FALSE;

    SPDesktop *desktop = event_context->desktop;
    SPSelectContext *sc = SP_SELECT_CONTEXT(event_context);
    Inkscape::SelTrans *seltrans = sc->_seltrans;
    Inkscape::Selection *selection = sp_desktop_selection(desktop);
    Inkscape::Preferences *prefs = Inkscape::Preferences::get();

    // make sure we still have valid objects to move around
    if (sc->item && SP_OBJECT_DOCUMENT( SP_OBJECT(sc->item))==NULL) {
        sp_select_context_abort(event_context);
    }

    switch (event->type) {
        case GDK_2BUTTON_PRESS:
            if (event->button.button == 1) {
                if (!selection->isEmpty()) {
                    SPItem *clicked_item = (SPItem *) selection->itemList()->data;
                    if (SP_IS_GROUP(clicked_item) && !SP_IS_BOX3D(clicked_item)) { // enter group if it's not a 3D box
                        desktop->setCurrentLayer(reinterpret_cast<SPObject *>(clicked_item));
                        sp_desktop_selection(desktop)->clear();
                        sc->dragging = false;
                        sp_event_context_discard_delayed_snap_event(event_context);

                        desktop->canvas->end_forced_full_redraws();
                    } else { // switch tool
                        Geom::Point const button_pt(event->button.x, event->button.y);
                        Geom::Point const p(desktop->w2d(button_pt));
                        tools_switch_by_item (desktop, clicked_item, p);
                    }
                } else {
                    sp_select_context_up_one_layer(desktop);
                }
                ret = TRUE;
            }
            break;
        case GDK_BUTTON_PRESS:
            if (event->button.button == 1 && !event_context->space_panning) {

                // save drag origin
                xp = (gint) event->button.x;
                yp = (gint) event->button.y;
                within_tolerance = true;

                Geom::Point const button_pt(event->button.x, event->button.y);
                Geom::Point const p(desktop->w2d(button_pt));
                if (event->button.state & GDK_MOD1_MASK)
                    Inkscape::Rubberband::get(desktop)->setMode(RUBBERBAND_MODE_TOUCHPATH);
                Inkscape::Rubberband::get(desktop)->start(desktop, p);
                if (sc->grabbed) {
                    sp_canvas_item_ungrab(sc->grabbed, event->button.time);
                    sc->grabbed = NULL;
                }
                sp_canvas_item_grab(SP_CANVAS_ITEM(desktop->acetate),
                                    GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK,
                                    NULL, event->button.time);
                sc->grabbed = SP_CANVAS_ITEM(desktop->acetate);

                // remember what modifiers were on before button press
                sc->button_press_shift = (event->button.state & GDK_SHIFT_MASK) ? true : false;
                sc->button_press_ctrl = (event->button.state & GDK_CONTROL_MASK) ? true : false;
                sc->button_press_alt = (event->button.state & GDK_MOD1_MASK) ? true : false;

                sc->moved = FALSE;

                rb_escaped = drag_escaped = 0;

                ret = TRUE;
            } else if (event->button.button == 3) {
                // right click; do not eat it so that right-click menu can appear, but cancel dragging & rubberband
                sp_select_context_abort(event_context);
            }
            break;

        case GDK_MOTION_NOTIFY:
        	tolerance = prefs->getIntLimited("/options/dragtolerance/value", 0, 0, 100);
        	if (event->motion.state & GDK_BUTTON1_MASK && !event_context->space_panning) {
                Geom::Point const motion_pt(event->motion.x, event->motion.y);
                Geom::Point const p(desktop->w2d(motion_pt));

                if ( within_tolerance
                     && ( abs( (gint) event->motion.x - xp ) < tolerance )
                     && ( abs( (gint) event->motion.y - yp ) < 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 && !sc->button_press_shift && !selection->isEmpty())) {
                    // if it's not click and ctrl or alt was pressed (the latter with some selection
                    // but not with shift) we want to drag rather than rubberband
                  	sc->dragging = TRUE;
                    desktop->setCursor(SP_SELECT_D_CURSOR);
                    
                    desktop->canvas->force_full_redraw_after_interruptions(5);
                }

                if (sc->dragging) {
                    /* 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
                    Inkscape::Rubberband::get(desktop)->stop();
                    SP_EVENT_CONTEXT(sc)->defaultMessageContext()->clear();
                    item_at_point = desktop->item_at_point(Geom::Point(event->button.x, event->button.y), FALSE);
                    if (!item_at_point) // if no item at this point, try at the click point (bug 1012200)
                        item_at_point = desktop->item_at_point(Geom::Point(xp, yp), FALSE);
                    if (item_at_point || sc->moved || sc->button_press_alt) {
                        // drag only if starting from an item, or if something is already grabbed, or if alt-dragging
                        if (!sc->moved) {
                            item_in_group = desktop->item_at_point(Geom::Point(event->button.x, event->button.y), TRUE);
                            group_at_point = desktop->group_at_point(Geom::Point(event->button.x, event->button.y));
                            if (SP_IS_LAYER(selection->single()))
                                group_at_point = SP_GROUP(selection->single());

                            // group-at-point is meant to be topmost item if it's a group,
                            // not topmost group of all items at point
                            if (group_at_point != item_in_group &&
                                !(group_at_point && item_at_point &&
                                  group_at_point->isAncestorOf(item_at_point)))
                                group_at_point = NULL;

                            // if neither a group nor an item (possibly in a group) at point are selected, set selection to the item at point
                            if ((!item_in_group || !selection->includes(item_in_group)) &&
                                (!group_at_point || !selection->includes(group_at_point))
                                && !sc->button_press_alt) {
                                // select what is under cursor
                                if (!seltrans->isEmpty()) {
                                    seltrans->resetState();
                                }
                                // when simply ctrl-dragging, we don't want to go into groups
                                if (item_at_point && !selection->includes(item_at_point))
                                    selection->set(item_at_point);
                            } // otherwise, do not change selection so that dragging selected-within-group items, as well as alt-dragging, is possible
                            seltrans->grab(p, -1, -1, FALSE, TRUE);
                            sc->moved = TRUE;
                        }
                        if (!seltrans->isEmpty())
                            seltrans->moveTo(p, event->button.state);
                        desktop->scroll_to_point(p);
                        gobble_motion_events(GDK_BUTTON1_MASK);
                        ret = TRUE;
                    } else {
                        sc->dragging = FALSE;
                        sp_event_context_discard_delayed_snap_event(event_context);
                        desktop->canvas->end_forced_full_redraws();
                    }
                } else {
                    if (Inkscape::Rubberband::get(desktop)->is_started()) {
                        Inkscape::Rubberband::get(desktop)->move(p);
                        if (Inkscape::Rubberband::get(desktop)->getMode() == RUBBERBAND_MODE_TOUCHPATH) {
                            event_context->defaultMessageContext()->set(Inkscape::NORMAL_MESSAGE, _("<b>Draw over</b> objects to select them; release <b>Alt</b> to switch to rubberband selection"));
                        } else {
                            event_context->defaultMessageContext()->set(Inkscape::NORMAL_MESSAGE, _("<b>Drag around</b> objects to select them; press <b>Alt</b> to switch to touch selection"));
                        }
                        gobble_motion_events(GDK_BUTTON1_MASK);
                    }
                }
            }
            break;
        case GDK_BUTTON_RELEASE:
            xp = yp = 0;
            if ((event->button.button == 1) && (sc->grabbed) && !event_context->space_panning) {
                if (sc->dragging) {
                    if (sc->moved) {
                        // item has been moved
                        seltrans->ungrab();
                        sc->moved = FALSE;
                    } else if (sc->item && !drag_escaped) {
                        // item has not been moved -> simply a click, do selecting
                        if (!selection->isEmpty()) {
                            if (event->button.state & GDK_SHIFT_MASK) {
                                // with shift, toggle selection
                                seltrans->resetState();
                                selection->toggle(sc->item);
                            } else {
                                SPObject* single = selection->single();
                                // without shift, increase state (i.e. toggle scale/rotation handles)
                                if (selection->includes(sc->item)) {
                                    seltrans->increaseState();
                                } else if (SP_IS_LAYER(single) && single->isAncestorOf(sc->item)) {
                                    seltrans->increaseState();
                                } else {
                                    seltrans->resetState();
                                    selection->set(sc->item);
                                }
                            }
                        } else { // simple or shift click, no previous selection
                            seltrans->resetState();
                            selection->set(sc->item);
                        }
                    }
                    sc->dragging = FALSE;
                    desktop->setCursor(SP_SELECT_CURSOR);
                    sp_event_context_discard_delayed_snap_event(event_context);
                    desktop->canvas->end_forced_full_redraws();

                    if (sc->item) {
                        sp_object_unref( SP_OBJECT(sc->item), NULL);
                    }
                    sc->item = NULL;
                } else {
                    Inkscape::Rubberband *r = Inkscape::Rubberband::get(desktop);
                    if (r->is_started() && !within_tolerance) {
                        // this was a rubberband drag
                        GSList *items = NULL;
                        if (r->getMode() == RUBBERBAND_MODE_RECT) {
                            Geom::OptRect const b = r->getRectangle();
                            items = sp_document_items_in_box(sp_desktop_document(desktop), desktop->dkey, *b);
                        } else if (r->getMode() == RUBBERBAND_MODE_TOUCHPATH) {
                            items = sp_document_items_at_points(sp_desktop_document(desktop), desktop->dkey, r->getPoints());
                        }

                        seltrans->resetState();
                        r->stop();
                        SP_EVENT_CONTEXT(sc)->defaultMessageContext()->clear();

                        if (event->button.state & GDK_SHIFT_MASK) {
                            // with shift, add to selection
                            selection->addList (items);
                        } else {
                            // without shift, simply select anew
                            selection->setList (items);
                        }
                        g_slist_free (items);
                    } else { // it was just a click, or a too small rubberband
                        r->stop();
                        if (sc->button_press_shift && !rb_escaped && !drag_escaped) {
                            // this was a shift+click or alt+shift+click, select what was clicked upon

                            sc->button_press_shift = false;

                            if (sc->button_press_ctrl) {
                                // go into groups, honoring Alt
                                item = sp_event_context_find_item (desktop,
                                                   Geom::Point(event->button.x, event->button.y), event->button.state & GDK_MOD1_MASK, TRUE);
                                sc->button_press_ctrl = FALSE;
                            } else {
                                // don't go into groups, honoring Alt
                                item = sp_event_context_find_item (desktop,
                                                   Geom::Point(event->button.x, event->button.y), event->button.state & GDK_MOD1_MASK, FALSE);
                            }

                            if (item) {
                                selection->toggle(item);
                                item = NULL;
                            }

                        } else if ((sc->button_press_ctrl || sc->button_press_alt) && !rb_escaped && !drag_escaped) { // ctrl+click, alt+click

                            item = sp_event_context_find_item (desktop,
                                         Geom::Point(event->button.x, event->button.y), sc->button_press_alt, sc->button_press_ctrl);

                            sc->button_press_ctrl = FALSE;
                            sc->button_press_alt = FALSE;

                            if (item) {
                                if (selection->includes(item)) {
                                    seltrans->increaseState();
                                } else {
                                    seltrans->resetState();
                                    selection->set(item);
                                }
                                item = NULL;
                            }

                        } else { // click without shift, simply deselect, unless with Alt or something was cancelled
                            if (!selection->isEmpty()) {
                                if (!(rb_escaped) && !(drag_escaped) && !(event->button.state & GDK_MOD1_MASK))
                                    selection->clear();
                                rb_escaped = 0;
                                ret = TRUE;
                            }
                        }
                    }
                    ret = TRUE;
                }
                if (sc->grabbed) {
                    sp_canvas_item_ungrab(sc->grabbed, event->button.time);
                    sc->grabbed = NULL;
                }

                desktop->updateNow();
            }
            if (event->button.button == 1) {
                Inkscape::Rubberband::get(desktop)->stop(); // might have been started in another tool!
            }
            sc->button_press_shift = false;
            sc->button_press_ctrl = false;
            sc->button_press_alt = false;
            break;

        case GDK_KEY_PRESS: // keybindings for select context

			{
			{
        	guint keyval = get_group0_keyval(&event->key);
            bool alt = ( MOD__ALT
                                    || (keyval == GDK_Alt_L)
                                    || (keyval == GDK_Alt_R)
                                    || (keyval == GDK_Meta_L)
                                    || (keyval == GDK_Meta_R));

            if (!key_is_a_modifier (keyval)) {
                    event_context->defaultMessageContext()->clear();
            } else if (sc->grabbed || seltrans->isGrabbed()) {
                if (Inkscape::Rubberband::get(desktop)->is_started()) {
                    // if Alt then change cursor to moving cursor:
                    if (alt) {
                        Inkscape::Rubberband::get(desktop)->setMode(RUBBERBAND_MODE_TOUCHPATH);
                    }
                } else {
                // do not change the statusbar text when mousekey is down to move or transform the object,
                // because the statusbar text is already updated somewhere else.
                   break;
                }
            } else {
                    sp_event_show_modifier_tip (event_context->defaultMessageContext(), event,
                                                _("<b>Ctrl</b>: click to select in groups; drag to move hor/vert"),
                                                _("<b>Shift</b>: click to toggle select; drag for rubberband selection"),
                                                _("<b>Alt</b>: click to select under; drag to move selected or select by touch"));
                    // if Alt and nonempty selection, show moving cursor ("move selected"):
                    if (alt && !selection->isEmpty() && !desktop->isWaitingCursor()) {
                        desktop->setCursor(SP_SELECT_D_CURSOR);
                    }
                    //*/
                    break;
            }
			}

            gdouble const nudge = prefs->getDoubleLimited("/options/nudgedistance/value", 2, 0, 1000); // in px
			gdouble const offset = prefs->getDoubleLimited("/options/defaultscale/value", 2, 0, 1000);
			int const snaps = prefs->getInt("/options/rotationsnapsperpi/value", 12);

			switch (get_group0_keyval (&event->key)) {
                case GDK_Left: // move selection left
                case GDK_KP_Left:
                case GDK_KP_4:
                    if (!MOD__CTRL) { // not ctrl
                        gint mul = 1 + gobble_key_events(
                            get_group0_keyval(&event->key), 0); // with any mask
                        if (MOD__ALT) { // alt
                            if (MOD__SHIFT) sp_selection_move_screen(desktop, mul*-10, 0); // shift
                            else sp_selection_move_screen(desktop, mul*-1, 0); // no shift
                        }
                        else { // no alt
                            if (MOD__SHIFT) sp_selection_move(desktop, mul*-10*nudge, 0); // shift
                            else sp_selection_move(desktop, mul*-nudge, 0); // no shift
                        }
                        ret = TRUE;
                    }
                    break;
                case GDK_Up: // move selection up
                case GDK_KP_Up:
                case GDK_KP_8:
                    if (!MOD__CTRL) { // not ctrl
                        gint mul = 1 + gobble_key_events(
                            get_group0_keyval(&event->key), 0); // with any mask
                        if (MOD__ALT) { // alt
                            if (MOD__SHIFT) sp_selection_move_screen(desktop, 0, mul*10); // shift
                            else sp_selection_move_screen(desktop, 0, mul*1); // no shift
                        }
                        else { // no alt
                            if (MOD__SHIFT) sp_selection_move(desktop, 0, mul*10*nudge); // shift
                            else sp_selection_move(desktop, 0, mul*nudge); // no shift
                        }
                        ret = TRUE;
                    }
                    break;
                case GDK_Right: // move selection right
                case GDK_KP_Right:
                case GDK_KP_6:
                    if (!MOD__CTRL) { // not ctrl
                        gint mul = 1 + gobble_key_events(
                            get_group0_keyval(&event->key), 0); // with any mask
                        if (MOD__ALT) { // alt
                            if (MOD__SHIFT) sp_selection_move_screen(desktop, mul*10, 0); // shift
                            else sp_selection_move_screen(desktop, mul*1, 0); // no shift
                        }
                        else { // no alt
                            if (MOD__SHIFT) sp_selection_move(desktop, mul*10*nudge, 0); // shift
                            else sp_selection_move(desktop, mul*nudge, 0); // no shift
                        }
                        ret = TRUE;
                    }
                    break;
                case GDK_Down: // move selection down
                case GDK_KP_Down:
                case GDK_KP_2:
                    if (!MOD__CTRL) { // not ctrl
                        gint mul = 1 + gobble_key_events(
                            get_group0_keyval(&event->key), 0); // with any mask
                        if (MOD__ALT) { // alt
                            if (MOD__SHIFT) sp_selection_move_screen(desktop, 0, mul*-10); // shift
                            else sp_selection_move_screen(desktop, 0, mul*-1); // no shift
                        }
                        else { // no alt
                            if (MOD__SHIFT) sp_selection_move(desktop, 0, mul*-10*nudge); // shift
                            else sp_selection_move(desktop, 0, mul*-nudge); // no shift
                        }
                        ret = TRUE;
                    }
                    break;
                case GDK_Escape:
                    if (!sp_select_context_abort(event_context))
                        selection->clear();
                    ret = TRUE;
                    break;
                case GDK_a:
                case GDK_A:
                    if (MOD__CTRL_ONLY) {
                        sp_edit_select_all(desktop);
                        ret = TRUE;
                    }
                    break;
                case GDK_space:
                    /* stamping mode: show outline mode moving */
                    /* FIXME: Is next condition ok? (lauris) */
                    if (sc->dragging && sc->grabbed) {
                        seltrans->stamp();
                        ret = TRUE;
                    }
                    break;
                case GDK_x:
                case GDK_X:
                    if (MOD__ALT_ONLY) {
                        desktop->setToolboxFocusTo ("altx");
                        ret = TRUE;
                    }
                    break;
                case GDK_bracketleft:
                    if (MOD__ALT) {
                        gint mul = 1 + gobble_key_events(
                            get_group0_keyval(&event->key), 0); // with any mask
                        sp_selection_rotate_screen(selection, mul*1);
                    } else if (MOD__CTRL) {
                        sp_selection_rotate(selection, 90);
                    } else if (snaps) {
                        sp_selection_rotate(selection, 180.0/snaps);
                    }
                    ret = TRUE;
                    break;
                case GDK_bracketright:
                    if (MOD__ALT) {
                        gint mul = 1 + gobble_key_events(
                            get_group0_keyval(&event->key), 0); // with any mask
                        sp_selection_rotate_screen(selection, -1*mul);
                    } else if (MOD__CTRL) {
                        sp_selection_rotate(selection, -90);
                    } else if (snaps) {
                        sp_selection_rotate(selection, -180.0/snaps);
                    }
                    ret = TRUE;
                    break;
                case GDK_less:
                case GDK_comma:
                    if (MOD__ALT) {
                        gint mul = 1 + gobble_key_events(
                            get_group0_keyval(&event->key), 0); // with any mask
                        sp_selection_scale_screen(selection, -2*mul);
                    } else if (MOD__CTRL) {
                        sp_selection_scale_times(selection, 0.5);
                    } else {
                        gint mul = 1 + gobble_key_events(
                            get_group0_keyval(&event->key), 0); // with any mask
                        sp_selection_scale(selection, -offset*mul);
                    }
                    ret = TRUE;
                    break;
                case GDK_greater:
                case GDK_period:
                    if (MOD__ALT) {
                        gint mul = 1 + gobble_key_events(
                            get_group0_keyval(&event->key), 0); // with any mask
                        sp_selection_scale_screen(selection, 2*mul);
                    } else if (MOD__CTRL) {
                        sp_selection_scale_times(selection, 2);
                    } else {
                        gint mul = 1 + gobble_key_events(
                            get_group0_keyval(&event->key), 0); // with any mask
                        sp_selection_scale(selection, offset*mul);
                    }
                    ret = TRUE;
                    break;
                case GDK_Return:
                    if (MOD__CTRL_ONLY) {
                        if (selection->singleItem()) {
                            SPItem *clicked_item = selection->singleItem();
                            if ( SP_IS_GROUP(clicked_item) ||
                                 SP_IS_BOX3D(clicked_item)) { // enter group or a 3D box
                                desktop->setCurrentLayer(reinterpret_cast<SPObject *>(clicked_item));
                                sp_desktop_selection(desktop)->clear();
                            } else {
                                SP_EVENT_CONTEXT(sc)->desktop->messageStack()->flash(Inkscape::NORMAL_MESSAGE, _("Selected object is not a group. Cannot enter."));
                            }
                        }
                        ret = TRUE;
                    }
                    break;
                case GDK_BackSpace:
                    if (MOD__CTRL_ONLY) {
                        sp_select_context_up_one_layer(desktop);
                        ret = TRUE;
                    }
                    break;
                case GDK_s:
                case GDK_S:
                    if (MOD__SHIFT_ONLY) {
                        if (!selection->isEmpty()) {
                            seltrans->increaseState();
                        }
                        ret = TRUE;
                    }
                    break;
                case GDK_g:
                case GDK_G:
                    if (MOD__SHIFT_ONLY) {
                        sp_selection_to_guides(desktop);
                        ret = true;
                    }
                    break;
                default:
                    break;
            }
            break;
			}
        case GDK_KEY_RELEASE:
            {
            guint keyval = get_group0_keyval(&event->key);
            if (key_is_a_modifier (keyval))
                event_context->defaultMessageContext()->clear();

            bool alt = ( MOD__ALT
                         || (keyval == GDK_Alt_L)
                         || (keyval == GDK_Alt_R)
                         || (keyval == GDK_Meta_L)
                         || (keyval == GDK_Meta_R));

            if (Inkscape::Rubberband::get(desktop)->is_started()) {
                // if Alt then change cursor to moving cursor:
                if (alt) {
                    Inkscape::Rubberband::get(desktop)->setMode(RUBBERBAND_MODE_RECT);
                }
            }
            }
            // set cursor to default.
            if (!desktop->isWaitingCursor()) {
                desktop->setCursor(event_context->cursor_shape);
            }
            break;
        default:
            break;
    }

    if (!ret) {
        if (((SPEventContextClass *) parent_class)->root_handler)
            ret = ((SPEventContextClass *) parent_class)->root_handler(event_context, event);
    }

    return ret;
}
Ejemplo n.º 6
0
static gint
sp_select_context_item_handler(SPEventContext *event_context, SPItem *item, GdkEvent *event)
{
    gint ret = FALSE;

    SPDesktop *desktop = event_context->desktop;
    SPSelectContext *sc = SP_SELECT_CONTEXT(event_context);
    Inkscape::SelTrans *seltrans = sc->_seltrans;

    Inkscape::Preferences *prefs = Inkscape::Preferences::get();
    tolerance = prefs->getIntLimited("/options/dragtolerance/value", 0, 0, 100);

    // make sure we still have valid objects to move around
    if (sc->item && SP_OBJECT_DOCUMENT( SP_OBJECT(sc->item))==NULL) {
        sp_select_context_abort(event_context);
    }

    switch (event->type) {
        case GDK_BUTTON_PRESS:
            if (event->button.button == 1 && !event_context->space_panning) {
                /* Left mousebutton */

                // save drag origin
                xp = (gint) event->button.x;
                yp = (gint) event->button.y;
                within_tolerance = true;

                // remember what modifiers were on before button press
                sc->button_press_shift = (event->button.state & GDK_SHIFT_MASK) ? true : false;
                sc->button_press_ctrl = (event->button.state & GDK_CONTROL_MASK) ? true : false;
                sc->button_press_alt = (event->button.state & GDK_MOD1_MASK) ? true : false;

                if (event->button.state & (GDK_SHIFT_MASK | GDK_CONTROL_MASK | GDK_MOD1_MASK)) {
                    // 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 {
                    sc->dragging = TRUE;
                    sc->moved = FALSE;

                    desktop->setCursor(SP_SELECT_D_CURSOR);
                    
                    desktop->canvas->force_full_redraw_after_interruptions(5);

                    // remember the clicked item in sc->item:
                    if (sc->item) {
                        sp_object_unref(sc->item, NULL);
                        sc->item = NULL;
                    }
                    sc->item = sp_event_context_find_item (desktop,
                                              Geom::Point(event->button.x, event->button.y), event->button.state & GDK_MOD1_MASK, FALSE);
                    sp_object_ref(sc->item, NULL);

                    rb_escaped = drag_escaped = 0;

                    if (sc->grabbed) {
                        sp_canvas_item_ungrab(sc->grabbed, event->button.time);
                        sc->grabbed = NULL;
                    }
                    sp_canvas_item_grab(SP_CANVAS_ITEM(desktop->drawing),
                                        GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_PRESS_MASK |
                                        GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK,
                                        NULL, event->button.time);
                    sc->grabbed = SP_CANVAS_ITEM(desktop->drawing);

                    desktop->canvas->force_full_redraw_after_interruptions(5);

                    ret = TRUE;
                }
            } else if (event->button.button == 3) {
                // right click; do not eat it so that right-click menu can appear, but cancel dragging & rubberband
                sp_select_context_abort(event_context);
            }
            break;

        case GDK_ENTER_NOTIFY:
        {
            if (!desktop->isWaitingCursor() && !sc->dragging) {
                desktop->setCursor(SP_SELECT_CURSOR);
            }
            break;
        }

        case GDK_LEAVE_NOTIFY:
            if (!desktop->isWaitingCursor() && !sc->dragging)
                desktop->setCursor(event_context->cursor_shape);
            break;

        case GDK_KEY_PRESS:
            if (get_group0_keyval (&event->key) == GDK_space) {
                if (sc->dragging && sc->grabbed) {
                    /* stamping mode: show content mode moving */
                    seltrans->stamp();
                    ret = TRUE;
                }
            }
            break;

        default:
            break;
    }

    if (!ret) {
        if (((SPEventContextClass *) parent_class)->item_handler)
            ret = ((SPEventContextClass *) parent_class)->item_handler(event_context, item, event);
    }

    return ret;
}
Ejemplo n.º 7
0
gboolean
spinbutton_keypress (GtkWidget *w, GdkEventKey *event, gpointer data)
{
    SPWidget *spw = (SPWidget *) data;
    gdouble v;
    gdouble step;
    gdouble page;

	switch (get_group0_keyval (event)) {
	case GDK_KEY_Escape: // defocus
		spinbutton_undo (w);
		spinbutton_defocus(GTK_WIDGET(spw));
		return TRUE; // I consumed the event
		break;
	case GDK_KEY_Return: // defocus
	case GDK_KEY_KP_Enter:
		spinbutton_defocus (GTK_WIDGET(spw));
		return TRUE; // I consumed the event
		break;
	case GDK_KEY_Tab:
	case GDK_KEY_ISO_Left_Tab:
		// set the flag meaning "do not leave toolbar when changing value"
		g_object_set_data (G_OBJECT (spw), "stay", GINT_TO_POINTER(TRUE));
		return FALSE; // I didn't consume the event
		break;

	// The following keys are processed manually because GTK implements them in strange ways
	// (increments start with double step value and seem to grow as you press the key continuously)

	case GDK_KEY_Up:
	case GDK_KEY_KP_Up:
		g_object_set_data (G_OBJECT (spw), "stay", GINT_TO_POINTER(TRUE));
		v = gtk_spin_button_get_value(GTK_SPIN_BUTTON (w));
	    gtk_spin_button_get_increments(GTK_SPIN_BUTTON (w), &step, &page);
		v += step;
		gtk_spin_button_set_value(GTK_SPIN_BUTTON(w), v);
		return TRUE; // I consumed the event
		break;
	case GDK_KEY_Down:
	case GDK_KEY_KP_Down:
		g_object_set_data (G_OBJECT (spw), "stay", GINT_TO_POINTER(TRUE));
		v = gtk_spin_button_get_value(GTK_SPIN_BUTTON (w));
	    gtk_spin_button_get_increments(GTK_SPIN_BUTTON (w), &step, &page);
		v -= step;
		gtk_spin_button_set_value(GTK_SPIN_BUTTON(w), v);
		return TRUE; // I consumed the event
		break;
	case GDK_KEY_Page_Up:
	case GDK_KEY_KP_Page_Up:
		g_object_set_data (G_OBJECT (spw), "stay", GINT_TO_POINTER(TRUE));
		v = gtk_spin_button_get_value(GTK_SPIN_BUTTON (w));
	    gtk_spin_button_get_increments(GTK_SPIN_BUTTON (w), &step, &page);
		v += page;
		gtk_spin_button_set_value(GTK_SPIN_BUTTON(w), v);
		return TRUE; // I consumed the event
		break;
	case GDK_KEY_Page_Down:
	case GDK_KEY_KP_Page_Down:
		g_object_set_data (G_OBJECT (spw), "stay", GINT_TO_POINTER(TRUE));
		v = gtk_spin_button_get_value(GTK_SPIN_BUTTON (w));
	    gtk_spin_button_get_increments(GTK_SPIN_BUTTON (w), &step, &page);
		v -= page;
		gtk_spin_button_set_value(GTK_SPIN_BUTTON(w), v);
		return TRUE; // I consumed the event
		break;
	case GDK_KEY_z:
	case GDK_KEY_Z:
		g_object_set_data (G_OBJECT (spw), "stay", GINT_TO_POINTER(TRUE));
		if (event->state & GDK_CONTROL_MASK) {
			spinbutton_undo (w);
			return TRUE; // I consumed the event
		}
		break;
	default:
		return FALSE;
		break;
	}
	return FALSE; // I didn't consume the event
}
Ejemplo n.º 8
0
static gint sp_box3d_context_root_handler(SPEventContext *event_context, GdkEvent *event)
{
    static bool dragging;

    SPDesktop *desktop = event_context->desktop;
    SPDocument *document = sp_desktop_document (desktop);
    Inkscape::Selection *selection = sp_desktop_selection (desktop);
    Inkscape::Preferences *prefs = Inkscape::Preferences::get();
    int const snaps = prefs->getInt("/options/rotationsnapsperpi/value", 12);

    Box3DContext *bc = SP_BOX3D_CONTEXT(event_context);
    Persp3D *cur_persp = document->getCurrentPersp3D();

    event_context->tolerance = prefs->getIntLimited("/options/dragtolerance/value", 0, 0, 100);

    gint ret = FALSE;
    switch (event->type) {
    case GDK_BUTTON_PRESS:
        if ( event->button.button == 1  && !event_context->space_panning) {
            Geom::Point const button_w(event->button.x,
                                       event->button.y);

            // save drag origin
            event_context->xp = (gint) button_w[Geom::X];
            event_context->yp = (gint) button_w[Geom::Y];
            event_context->within_tolerance = true;

            // remember clicked item, *not* disregarding groups (since a 3D box is a group), honoring Alt
            event_context->item_to_select = sp_event_context_find_item (desktop, button_w, event->button.state & GDK_MOD1_MASK, event->button.state & GDK_CONTROL_MASK);

            dragging = true;

            /*  */
            Geom::Point button_dt(desktop->w2d(button_w));
            bc->drag_origin = from_2geom(button_dt);
            bc->drag_ptB = from_2geom(button_dt);
            bc->drag_ptC = from_2geom(button_dt);

            // This can happen after saving when the last remaining perspective was purged and must be recreated.
            if (!cur_persp) {
                sp_box3d_context_ensure_persp_in_defs(document);
                cur_persp = document->getCurrentPersp3D();
            }

            /* Projective preimages of clicked point under current perspective */
            bc->drag_origin_proj = cur_persp->perspective_impl->tmat.preimage (from_2geom(button_dt), 0, Proj::Z);
            bc->drag_ptB_proj = bc->drag_origin_proj;
            bc->drag_ptC_proj = bc->drag_origin_proj;
            bc->drag_ptC_proj.normalize();
            bc->drag_ptC_proj[Proj::Z] = 0.25;

            /* Snap center */
            SnapManager &m = desktop->namedview->snap_manager;
            m.setup(desktop, true, bc->item);
            m.freeSnapReturnByRef(button_dt, Inkscape::SNAPSOURCE_NODE_HANDLE);
            bc->center = from_2geom(button_dt);

            sp_canvas_item_grab(SP_CANVAS_ITEM(desktop->acetate),
                                ( GDK_KEY_PRESS_MASK |
                                  GDK_BUTTON_RELEASE_MASK       |
                                  GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK       |
                                  GDK_BUTTON_PRESS_MASK ),
                                NULL, event->button.time);
            ret = TRUE;
        }
        break;
    case GDK_MOTION_NOTIFY:
        if ( dragging
             && ( event->motion.state & GDK_BUTTON1_MASK )  && !event_context->space_panning)
        {
            if ( event_context->within_tolerance
                 && ( abs( (gint) event->motion.x - event_context->xp ) < event_context->tolerance )
                 && ( abs( (gint) event->motion.y - event_context->yp ) < event_context->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 draw, not click), then always process the
            // motion notify coordinates as given (no snapping back to origin)
            event_context->within_tolerance = false;

            Geom::Point const motion_w(event->motion.x,
                                       event->motion.y);
            Geom::Point motion_dt(desktop->w2d(motion_w));

            SnapManager &m = desktop->namedview->snap_manager;
            m.setup(desktop, true, bc->item);
            m.freeSnapReturnByRef(motion_dt, Inkscape::SNAPSOURCE_NODE_HANDLE);

            bc->ctrl_dragged  = event->motion.state & GDK_CONTROL_MASK;

            if (event->motion.state & GDK_SHIFT_MASK && !bc->extruded && bc->item) {
                // once shift is pressed, set bc->extruded
                bc->extruded = true;
            }

            if (!bc->extruded) {
                bc->drag_ptB = from_2geom(motion_dt);
                bc->drag_ptC = from_2geom(motion_dt);

                bc->drag_ptB_proj = cur_persp->perspective_impl->tmat.preimage (from_2geom(motion_dt), 0, Proj::Z);
                bc->drag_ptC_proj = bc->drag_ptB_proj;
                bc->drag_ptC_proj.normalize();
                bc->drag_ptC_proj[Proj::Z] = 0.25;
            } else {
                // Without Ctrl, motion of the extruded corner is constrained to the
                // perspective line from drag_ptB to vanishing point Y.
                if (!bc->ctrl_dragged) {
                    /* snapping */
                    Box3D::PerspectiveLine pline (bc->drag_ptB, Proj::Z, document->getCurrentPersp3D());
                    bc->drag_ptC = pline.closest_to (from_2geom(motion_dt));

                    bc->drag_ptB_proj.normalize();
                    bc->drag_ptC_proj = cur_persp->perspective_impl->tmat.preimage (bc->drag_ptC, bc->drag_ptB_proj[Proj::X], Proj::X);
                } else {
                    bc->drag_ptC = from_2geom(motion_dt);

                    bc->drag_ptB_proj.normalize();
                    bc->drag_ptC_proj = cur_persp->perspective_impl->tmat.preimage (from_2geom(motion_dt), bc->drag_ptB_proj[Proj::X], Proj::X);
                }
                m.freeSnapReturnByRef(bc->drag_ptC, Inkscape::SNAPSOURCE_NODE_HANDLE);
            }

            sp_box3d_drag(*bc, event->motion.state);

            ret = TRUE;
        } else if (!sp_event_context_knot_mouseover(bc)) {
            SnapManager &m = desktop->namedview->snap_manager;
            m.setup(desktop);

            Geom::Point const motion_w(event->motion.x, event->motion.y);
            Geom::Point motion_dt(desktop->w2d(motion_w));
            m.preSnap(Inkscape::SnapCandidatePoint(motion_dt, Inkscape::SNAPSOURCE_NODE_HANDLE));
        }
        break;
    case GDK_BUTTON_RELEASE:
        event_context->xp = event_context->yp = 0;
        if ( event->button.button == 1  && !event_context->space_panning) {
            dragging = false;
            sp_event_context_discard_delayed_snap_event(event_context);

            if (!event_context->within_tolerance) {
                // we've been dragging, finish the box
                sp_box3d_finish(bc);
            } else if (event_context->item_to_select) {
                // no dragging, select clicked item if any
                if (event->button.state & GDK_SHIFT_MASK) {
                    selection->toggle(event_context->item_to_select);
                } else {
                    selection->set(event_context->item_to_select);
                }
            } else {
                // click in an empty space
                selection->clear();
            }

            event_context->item_to_select = NULL;
            ret = TRUE;
            sp_canvas_item_ungrab(SP_CANVAS_ITEM(desktop->acetate),
                                  event->button.time);
        }
        break;
    case GDK_KEY_PRESS:
        switch (get_group0_keyval (&event->key)) {
        case GDK_Up:
        case GDK_Down:
        case GDK_KP_Up:
        case GDK_KP_Down:
            // prevent the zoom field from activation
            if (!MOD__CTRL_ONLY)
                ret = TRUE;
            break;

        case GDK_bracketright:
            persp3d_rotate_VP (document->getCurrentPersp3D(), Proj::X, -180/snaps, MOD__ALT);
            sp_document_done(document, SP_VERB_CONTEXT_3DBOX,
                             _("Change perspective (angle of PLs)"));
            ret = true;
            break;

        case GDK_bracketleft:
            persp3d_rotate_VP (document->getCurrentPersp3D(), Proj::X, 180/snaps, MOD__ALT);
            sp_document_done(document, SP_VERB_CONTEXT_3DBOX,
                             _("Change perspective (angle of PLs)"));
            ret = true;
            break;

        case GDK_parenright:
            persp3d_rotate_VP (document->getCurrentPersp3D(), Proj::Y, -180/snaps, MOD__ALT);
            sp_document_done(document, SP_VERB_CONTEXT_3DBOX,
                             _("Change perspective (angle of PLs)"));
            ret = true;
            break;

        case GDK_parenleft:
            persp3d_rotate_VP (document->getCurrentPersp3D(), Proj::Y, 180/snaps, MOD__ALT);
            sp_document_done(document, SP_VERB_CONTEXT_3DBOX,
                             _("Change perspective (angle of PLs)"));
            ret = true;
            break;

        case GDK_braceright:
            persp3d_rotate_VP (document->getCurrentPersp3D(), Proj::Z, -180/snaps, MOD__ALT);
            sp_document_done(document, SP_VERB_CONTEXT_3DBOX,
                             _("Change perspective (angle of PLs)"));
            ret = true;
            break;

        case GDK_braceleft:
            persp3d_rotate_VP (document->getCurrentPersp3D(), Proj::Z, 180/snaps, MOD__ALT);
            sp_document_done(document, SP_VERB_CONTEXT_3DBOX,
                             _("Change perspective (angle of PLs)"));
            ret = true;
            break;

        /* TODO: what is this???
        case GDK_O:
            if (MOD__CTRL && MOD__SHIFT) {
                Box3D::create_canvas_point(persp3d_get_VP(document()->getCurrentPersp3D(), Proj::W).affine(),
                                           6, 0xff00ff00);
            }
            ret = true;
            break;
        */

        case GDK_g:
        case GDK_G:
            if (MOD__SHIFT_ONLY) {
                sp_selection_to_guides(desktop);
                ret = true;
            }
            break;

        case GDK_p:
        case GDK_P:
            if (MOD__SHIFT_ONLY) {
                if (document->getCurrentPersp3D()) {
                    persp3d_print_debugging_info (document->getCurrentPersp3D());
                }
                ret = true;
            }
            break;

        case GDK_x:
        case GDK_X:
            if (MOD__ALT_ONLY) {
                desktop->setToolboxFocusTo ("altx-box3d");
                ret = TRUE;
            }
            if (MOD__SHIFT_ONLY) {
                persp3d_toggle_VPs(selection->perspList(), Proj::X);
                bc->_vpdrag->updateLines(); // FIXME: Shouldn't this be done automatically?
                ret = true;
            }
            break;

        case GDK_y:
        case GDK_Y:
            if (MOD__SHIFT_ONLY) {
                persp3d_toggle_VPs(selection->perspList(), Proj::Y);
                bc->_vpdrag->updateLines(); // FIXME: Shouldn't this be done automatically?
                ret = true;
            }
            break;

        case GDK_z:
        case GDK_Z:
            if (MOD__SHIFT_ONLY) {
                persp3d_toggle_VPs(selection->perspList(), Proj::Z);
                bc->_vpdrag->updateLines(); // FIXME: Shouldn't this be done automatically?
                ret = true;
            }
            break;

        case GDK_Escape:
            sp_desktop_selection(desktop)->clear();
            //TODO: make dragging escapable by Esc
            break;

        case GDK_space:
            if (dragging) {
                sp_canvas_item_ungrab(SP_CANVAS_ITEM(desktop->acetate),
                                      event->button.time);
                dragging = false;
                sp_event_context_discard_delayed_snap_event(event_context);
                if (!event_context->within_tolerance) {
                    // we've been dragging, finish the box
                    sp_box3d_finish(bc);
                }
                // do not return true, so that space would work switching to selector
            }
            break;

        default:
            break;
        }
        break;
    default:
        break;
    }

    if (!ret) {
        if (((SPEventContextClass *) parent_class)->root_handler) {
            ret = ((SPEventContextClass *) parent_class)->root_handler(event_context, event);
        }
    }

    return ret;
}
static gint sp_dropper_context_root_handler(SPEventContext *event_context, GdkEvent *event)
{
    SPDropperContext *dc = (SPDropperContext *) event_context;
    int ret = FALSE;
    SPDesktop *desktop = event_context->desktop;
    Inkscape::Preferences *prefs = Inkscape::Preferences::get();

    int pick = prefs->getInt("/tools/dropper/pick", SP_DROPPER_PICK_VISIBLE);
    bool setalpha = prefs->getBool("/tools/dropper/setalpha", true);

    switch (event->type) {
	case GDK_BUTTON_PRESS:
            if (event->button.button == 1 && !event_context->space_panning) {
                dc->centre = Geom::Point(event->button.x, event->button.y);
                dc->dragging = TRUE;
                ret = TRUE;
            }
            break;
	case GDK_MOTION_NOTIFY:
            if (event->motion.state & GDK_BUTTON2_MASK) {
                // pass on middle-drag
                ret = FALSE;
                break;
            } else if (!event_context->space_panning) {
                // otherwise, constantly calculate color no matter is any button pressed or not

                double rw = 0.0;
                double W(0), R(0), G(0), B(0), A(0);

                if (dc->dragging) {
                    // calculate average

                    // radius
                    rw = std::min(Geom::L2(Geom::Point(event->button.x, event->button.y) - dc->centre), 400.0);

                    if (rw == 0) { // happens sometimes, little idea why...
                        break;
                    }

                    Geom::Point const cd = desktop->w2d(dc->centre);
                    Geom::Matrix const w2dt = desktop->w2d();
                    const double scale = rw * w2dt.descrim();
                    Geom::Matrix const sm( Geom::Scale(scale, scale) * Geom::Translate(cd) );
                    sp_canvas_item_affine_absolute(dc->area, sm);
                    sp_canvas_item_show(dc->area);

                    /* Get buffer */
                    const int x0 = (int) floor(dc->centre[Geom::X] - rw);
                    const int y0 = (int) floor(dc->centre[Geom::Y] - rw);
                    const int x1 = (int) ceil(dc->centre[Geom::X] + rw);
                    const int y1 = (int) ceil(dc->centre[Geom::Y] + rw);

                    if ((x1 > x0) && (y1 > y0)) {
                        NRPixBlock pb;
                        nr_pixblock_setup_fast(&pb, NR_PIXBLOCK_MODE_R8G8B8A8P, x0, y0, x1, y1, TRUE);
                        /* fixme: (Lauris) */
                        sp_canvas_arena_render_pixblock(SP_CANVAS_ARENA(sp_desktop_drawing(desktop)), &pb);
                        for (int y = y0; y < y1; y++) {
                            const unsigned char *s = NR_PIXBLOCK_PX(&pb) + (y - y0) * pb.rs;
                            for (int x = x0; x < x1; x++) {
                                const double dx = x - dc->centre[Geom::X];
                                const double dy = y - dc->centre[Geom::Y];
                                const double w = exp(-((dx * dx) + (dy * dy)) / (rw * rw));
                                W += w;
                                R += w * s[0];
                                G += w * s[1];
                                B += w * s[2];
                                A += w * s[3];
                                s += 4;
                            }
                        }
                        nr_pixblock_release(&pb);

                        R = (R + 0.001) / (255.0 * W);
                        G = (G + 0.001) / (255.0 * W);
                        B = (B + 0.001) / (255.0 * W);
                        A = (A + 0.001) / (255.0 * W);

                        R = CLAMP(R, 0.0, 1.0);
                        G = CLAMP(G, 0.0, 1.0);
                        B = CLAMP(B, 0.0, 1.0);
                        A = CLAMP(A, 0.0, 1.0);
                    }

                } else {
                    // pick single pixel
                    NRPixBlock pb;
                    int x = (int) floor(event->button.x);
                    int y = (int) floor(event->button.y);
                    nr_pixblock_setup_fast(&pb, NR_PIXBLOCK_MODE_R8G8B8A8P, x, y, x+1, y+1, TRUE);
                    sp_canvas_arena_render_pixblock(SP_CANVAS_ARENA(sp_desktop_drawing(desktop)), &pb);
                    const unsigned char *s = NR_PIXBLOCK_PX(&pb);

                    R = s[0] / 255.0;
                    G = s[1] / 255.0;
                    B = s[2] / 255.0;
                    A = s[3] / 255.0;
                }

                if (pick == SP_DROPPER_PICK_VISIBLE) {
                    // compose with page color
                    guint32 bg = sp_desktop_namedview(desktop)->pagecolor;
                    R = R + (SP_RGBA32_R_F(bg)) * (1 - A);
                    G = G + (SP_RGBA32_G_F(bg)) * (1 - A);
                    B = B + (SP_RGBA32_B_F(bg)) * (1 - A);
                    A = 1.0;
                } else {
                    // un-premultiply color channels
                    if (A > 0) {
                        R /= A;
                        G /= A;
                        B /= A;
                    }
                }

                if (fabs(A) < 1e-4) {
                    A = 0; // suppress exponentials, CSS does not allow that
                }

                // remember color
                dc->R = R;
                dc->G = G;
                dc->B = B;
                dc->alpha = A;

                // status message
                double alpha_to_set = setalpha? dc->alpha : 1.0;
                guint32 c32 = SP_RGBA32_F_COMPOSE(R, G, B, alpha_to_set);

                gchar c[64];
                sp_svg_write_color(c, sizeof(c), c32);

                // alpha of color under cursor, to show in the statusbar
                // locale-sensitive printf is OK, since this goes to the UI, not into SVG
                gchar *alpha = g_strdup_printf(_(" alpha %.3g"), alpha_to_set);
                // where the color is picked, to show in the statusbar
                gchar *where = dc->dragging ? g_strdup_printf(_(", averaged with radius %d"), (int) rw) : g_strdup_printf(_(" under cursor"));
                // message, to show in the statusbar
                const gchar *message = dc->dragging ? _("<b>Release mouse</b> to set color.") : _("<b>Click</b> to set fill, <b>Shift+click</b> to set stroke; <b>drag</b> to average color in area; with <b>Alt</b> to pick inverse color; <b>Ctrl+C</b> to copy the color under mouse to clipboard");
                event_context->defaultMessageContext()->setF(
                    Inkscape::NORMAL_MESSAGE,
                    "<b>%s%s</b>%s. %s", c,
                    (pick == SP_DROPPER_PICK_VISIBLE)? "" : alpha,
                    where, message
                    );

                g_free(where);
                g_free(alpha);

                ret = TRUE;
            }
            break;
	case GDK_BUTTON_RELEASE:
            if (event->button.button == 1 && !event_context->space_panning)
            {
                sp_canvas_item_hide(dc->area);
                dc->dragging = FALSE;

                double alpha_to_set = setalpha? dc->alpha : 1.0;

                // do the actual color setting
                sp_desktop_set_color(desktop,
                                     (event->button.state & GDK_MOD1_MASK)?
                                     ColorRGBA(1 - dc->R, 1 - dc->G, 1 - dc->B, alpha_to_set) : ColorRGBA(dc->R, dc->G, dc->B, alpha_to_set),
                                     false,  !(event->button.state & GDK_SHIFT_MASK));

                // REJON: set aux. toolbar input to hex color!


                if (!(sp_desktop_selection(desktop)->isEmpty())) {
                    sp_document_done(sp_desktop_document(desktop), SP_VERB_CONTEXT_DROPPER, 
                                     _("Set picked color"));
                }

                ret = TRUE;
            }
            break;
	case GDK_KEY_PRESS:
            switch (get_group0_keyval(&event->key)) {
		case GDK_Up:
		case GDK_Down:
		case GDK_KP_Up:
		case GDK_KP_Down:
                    // prevent the zoom field from activation
                    if (!MOD__CTRL_ONLY) {
                        ret = TRUE;
                    }
                    break;
		case GDK_Escape:
                    sp_desktop_selection(desktop)->clear();
		default:
                    break;
            }
            break;
	default:
            break;
    }

    if (!ret) {
        if (((SPEventContextClass *) parent_class)->root_handler) {
            ret = ((SPEventContextClass *) parent_class)->root_handler(event_context, event);
        }
    }

    return ret;
}
static gint
sp_gradient_context_root_handler(SPEventContext *event_context, GdkEvent *event)
{
    static bool dragging;

    SPDesktop *desktop = event_context->desktop;
    Inkscape::Selection *selection = sp_desktop_selection (desktop);
    Inkscape::Preferences *prefs = Inkscape::Preferences::get();

    SPGradientContext *rc = SP_GRADIENT_CONTEXT(event_context);

    event_context->tolerance = prefs->getIntLimited("/options/dragtolerance/value", 0, 0, 100);
    double const nudge = prefs->getDoubleLimited("/options/nudgedistance/value", 2, 0, 1000); // in px

    GrDrag *drag = event_context->_grdrag;
    g_assert (drag);

    gint ret = FALSE;
    switch (event->type) {
    case GDK_2BUTTON_PRESS:
        if ( event->button.button == 1 ) {
            bool over_line = false;
            SPCtrlLine *line = NULL;
            if (drag->lines) {
                for (GSList *l = drag->lines; (l != NULL) && (!over_line); l = l->next) {
                    line = (SPCtrlLine*) l->data;
                    over_line |= sp_gradient_context_is_over_line (rc, (SPItem*) line, Geom::Point(event->motion.x, event->motion.y));
                }
            }
            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(rc, SP_ITEM(selection->itemList()->data), rc->mousepoint_doc, event->button.time);
            } else {
                for (GSList const* i = selection->itemList(); i != NULL; i = i->next) {
                    SPItem *item = SP_ITEM(i->data);
                    SPGradientType new_type = (SPGradientType) prefs->getInt("/tools/gradient/newgradient", SP_GRADIENT_TYPE_LINEAR);
                    guint new_fill = prefs->getInt("/tools/gradient/newfillorstroke", 1);

                    SPGradient *vector = sp_gradient_vector_for_object(sp_desktop_document(desktop), desktop,                                                                                   SP_OBJECT (item), new_fill);

                    SPGradient *priv = sp_item_set_gradient(item, vector, new_type, new_fill);
                    sp_gradient_reset_to_userspace(priv, item);
                }

                sp_document_done (sp_desktop_document (desktop), SP_VERB_CONTEXT_GRADIENT,
                                  _("Create default gradient"));
            }
            ret = TRUE;
        }
        break;
    case GDK_BUTTON_PRESS:
        if ( event->button.button == 1 && !event_context->space_panning ) {
            Geom::Point button_w(event->button.x, event->button.y);

            // save drag origin
            event_context->xp = (gint) button_w[Geom::X];
            event_context->yp = (gint) button_w[Geom::Y];
            event_context->within_tolerance = true;

            dragging = true;

            Geom::Point button_dt = to_2geom(desktop->w2d(button_w));
            if (event->button.state & GDK_SHIFT_MASK) {
                Inkscape::Rubberband::get(desktop)->start(desktop, from_2geom(button_dt));
            } else {
                // remember clicked item, disregarding groups, honoring Alt; do nothing with Crtl to
                // enable Ctrl+doubleclick of exactly the selected item(s)
                if (!(event->button.state & GDK_CONTROL_MASK))
                    event_context->item_to_select = sp_event_context_find_item (desktop, button_w, event->button.state & GDK_MOD1_MASK, TRUE);

                /* Snap center to nearest magnetic point */
                SnapManager &m = desktop->namedview->snap_manager;
                m.setup(desktop);
                m.freeSnapReturnByRef(Inkscape::SnapPreferences::SNAPPOINT_NODE, button_dt);
                rc->origin = from_2geom(button_dt);
            }

            ret = TRUE;
        }
        break;
    case GDK_MOTION_NOTIFY:
        if ( dragging
             && ( event->motion.state & GDK_BUTTON1_MASK ) && !event_context->space_panning )
        {
            if ( event_context->within_tolerance
                 && ( abs( (gint) event->motion.x - event_context->xp ) < event_context->tolerance )
                 && ( abs( (gint) event->motion.y - event_context->yp ) < event_context->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 draw, not click), then always process the
            // motion notify coordinates as given (no snapping back to origin)
            event_context->within_tolerance = false;

            Geom::Point const motion_w(event->motion.x,
                                     event->motion.y);
            Geom::Point const motion_dt = event_context->desktop->w2d(motion_w);

            if (Inkscape::Rubberband::get(desktop)->is_started()) {
                Inkscape::Rubberband::get(desktop)->move(motion_dt);
                event_context->defaultMessageContext()->set(Inkscape::NORMAL_MESSAGE, _("<b>Draw around</b> handles to select them"));
            } else {
                sp_gradient_drag(*rc, motion_dt, event->motion.state, event->motion.time);
            }
            gobble_motion_events(GDK_BUTTON1_MASK);

            ret = TRUE;
        } else {
            bool over_line = false;
            if (drag->lines) {
                for (GSList *l = drag->lines; l != NULL; l = l->next) {
                    over_line |= sp_gradient_context_is_over_line (rc, (SPItem*) l->data, Geom::Point(event->motion.x, event->motion.y));
                }
            }

            if (rc->cursor_addnode && !over_line) {
                event_context->cursor_shape = cursor_gradient_xpm;
                sp_event_context_update_cursor(event_context);
                rc->cursor_addnode = false;
            } else if (!rc->cursor_addnode && over_line) {
                event_context->cursor_shape = cursor_gradient_add_xpm;
                sp_event_context_update_cursor(event_context);
                rc->cursor_addnode = true;
            }
        }
        break;
    case GDK_BUTTON_RELEASE:
        event_context->xp = event_context->yp = 0;
        if ( event->button.button == 1 && !event_context->space_panning ) {
            if ( (event->button.state & GDK_CONTROL_MASK) && (event->button.state & GDK_MOD1_MASK ) ) {
                bool over_line = false;
                SPCtrlLine *line = NULL;
                if (drag->lines) {
                    for (GSList *l = drag->lines; (l != NULL) && (!over_line); l = l->next) {
                        line = (SPCtrlLine*) l->data;
                        over_line = sp_gradient_context_is_over_line (rc, (SPItem*) line, Geom::Point(event->motion.x, event->motion.y));
                        if (over_line)
                            break;
                    }
                }
                if (over_line && line) {
                    sp_gradient_context_add_stop_near_point(rc, line->item, rc->mousepoint_doc, 0);
                    ret = TRUE;
                }
            } else {
                dragging = false;

                // unless clicked with Ctrl (to enable Ctrl+doubleclick).  
                if (event->button.state & GDK_CONTROL_MASK) {
                    ret = TRUE;
                    break;
                }

                if (!event_context->within_tolerance) {
                    // we've been dragging, either do nothing (grdrag handles that),
                    // or rubberband-select if we have rubberband
                    Inkscape::Rubberband::Rubberband *r = Inkscape::Rubberband::get(desktop);
                    if (r->is_started() && !event_context->within_tolerance) {
                        // this was a rubberband drag
                        if (r->getMode() == RUBBERBAND_MODE_RECT) {
                            Geom::OptRect const b = r->getRectangle();
                            drag->selectRect(*b);
                        }
                    }

                } else if (event_context->item_to_select) {
                    // no dragging, select clicked item if any
                    if (event->button.state & GDK_SHIFT_MASK) {
                        selection->toggle(event_context->item_to_select);
                    } else {
                        selection->set(event_context->item_to_select);
                    }
                } else {
                    // click in an empty space; do the same as Esc
                    if (drag->selected) {
                        drag->deselectAll();
                    } else {
                        selection->clear();
                    }
                }

                event_context->item_to_select = NULL;
                ret = TRUE;
            }
            Inkscape::Rubberband::get(desktop)->stop(); 
        }
        break;
    case GDK_KEY_PRESS:
        switch (get_group0_keyval (&event->key)) {
        case GDK_Alt_L:
        case GDK_Alt_R:
        case GDK_Control_L:
        case GDK_Control_R:
        case GDK_Shift_L:
        case GDK_Shift_R:
        case GDK_Meta_L:  // Meta is when you press Shift+Alt (at least on my machine)
        case GDK_Meta_R:
            sp_event_show_modifier_tip (event_context->defaultMessageContext(), event,
                                        _("<b>Ctrl</b>: snap gradient angle"),
                                        _("<b>Shift</b>: draw gradient around the starting point"),
                                        NULL);
            break;

        case GDK_x:
        case GDK_X:
            if (MOD__ALT_ONLY) {
                desktop->setToolboxFocusTo ("altx-grad");
                ret = TRUE;
            }
            break;

        case GDK_A:
        case GDK_a:
            if (MOD__CTRL_ONLY && drag->isNonEmpty()) {
                drag->selectAll();
                ret = TRUE;
            }
            break;

        case GDK_L:
        case GDK_l:
            if (MOD__CTRL_ONLY && drag->isNonEmpty() && drag->hasSelection()) {
                sp_gradient_simplify(rc, 1e-4);
                ret = TRUE;
            }
            break;

        case GDK_Escape:
            if (drag->selected) {
                drag->deselectAll();
            } else {
                selection->clear();
            }
            ret = TRUE;
            //TODO: make dragging escapable by Esc
            break;

        case GDK_Left: // move handle left
        case GDK_KP_Left:
        case GDK_KP_4:
            if (!MOD__CTRL) { // not ctrl
                gint mul = 1 + gobble_key_events(
                    get_group0_keyval(&event->key), 0); // with any mask
                if (MOD__ALT) { // alt
                    if (MOD__SHIFT) drag->selected_move_screen(mul*-10, 0); // shift
                    else drag->selected_move_screen(mul*-1, 0); // no shift
                }
                else { // no alt
                    if (MOD__SHIFT) drag->selected_move(mul*-10*nudge, 0); // shift
                    else drag->selected_move(mul*-nudge, 0); // no shift
                }
                ret = TRUE;
            }
            break;
        case GDK_Up: // move handle up
        case GDK_KP_Up:
        case GDK_KP_8:
            if (!MOD__CTRL) { // not ctrl
                gint mul = 1 + gobble_key_events(
                    get_group0_keyval(&event->key), 0); // with any mask
                if (MOD__ALT) { // alt
                    if (MOD__SHIFT) drag->selected_move_screen(0, mul*10); // shift
                    else drag->selected_move_screen(0, mul*1); // no shift
                }
                else { // no alt
                    if (MOD__SHIFT) drag->selected_move(0, mul*10*nudge); // shift
                    else drag->selected_move(0, mul*nudge); // no shift
                }
                ret = TRUE;
            }
            break;
        case GDK_Right: // move handle right
        case GDK_KP_Right:
        case GDK_KP_6:
            if (!MOD__CTRL) { // not ctrl
                gint mul = 1 + gobble_key_events(
                    get_group0_keyval(&event->key), 0); // with any mask
                if (MOD__ALT) { // alt
                    if (MOD__SHIFT) drag->selected_move_screen(mul*10, 0); // shift
                    else drag->selected_move_screen(mul*1, 0); // no shift
                }
                else { // no alt
                    if (MOD__SHIFT) drag->selected_move(mul*10*nudge, 0); // shift
                    else drag->selected_move(mul*nudge, 0); // no shift
                }
                ret = TRUE;
            }
            break;
        case GDK_Down: // move handle down
        case GDK_KP_Down:
        case GDK_KP_2:
            if (!MOD__CTRL) { // not ctrl
                gint mul = 1 + gobble_key_events(
                    get_group0_keyval(&event->key), 0); // with any mask
                if (MOD__ALT) { // alt
                    if (MOD__SHIFT) drag->selected_move_screen(0, mul*-10); // shift
                    else drag->selected_move_screen(0, mul*-1); // no shift
                }
                else { // no alt
                    if (MOD__SHIFT) drag->selected_move(0, mul*-10*nudge); // shift
                    else drag->selected_move(0, mul*-nudge); // no shift
                }
                ret = TRUE;
            }
            break;
        case GDK_r:
        case GDK_R:
            if (MOD__SHIFT_ONLY) {
                // First try selected dragger
                if (drag && drag->selected) {
                    drag->selected_reverse_vector();
                } else { // If no drag or no dragger selected, act on selection (both fill and stroke gradients)
                    for (GSList const* i = selection->itemList(); i != NULL; i = i->next) {
                        sp_item_gradient_reverse_vector (SP_ITEM(i->data), true);
                        sp_item_gradient_reverse_vector (SP_ITEM(i->data), false);
                    }
                }
                // we did an undoable action
                sp_document_done (sp_desktop_document (desktop), SP_VERB_CONTEXT_GRADIENT,
                                  _("Invert gradient"));
                ret = TRUE;
            }
            break;

        case GDK_Insert:
        case GDK_KP_Insert:
            // with any modifiers:
            sp_gradient_context_add_stops_between_selected_stops (rc);
            ret = TRUE;
            break;

        case GDK_Delete:
        case GDK_KP_Delete:
        case GDK_BackSpace:
            if ( drag->selected ) {
                drag->deleteSelected(MOD__CTRL_ONLY);
                ret = TRUE;
            }
            break;
        default:
            break;
        }
        break;
    case GDK_KEY_RELEASE:
        switch (get_group0_keyval (&event->key)) {
        case GDK_Alt_L:
        case GDK_Alt_R:
        case GDK_Control_L:
        case GDK_Control_R:
        case GDK_Shift_L:
        case GDK_Shift_R:
        case GDK_Meta_L:  // Meta is when you press Shift+Alt
        case GDK_Meta_R:
            event_context->defaultMessageContext()->clear();
            break;
        default:
            break;
        }
        break;
    default:
        break;
    }

    if (!ret) {
        if (((SPEventContextClass *) parent_class)->root_handler) {
            ret = ((SPEventContextClass *) parent_class)->root_handler(event_context, event);
        }
    }

    return ret;
}
Ejemplo n.º 11
0
static gint sp_zoom_context_root_handler(SPEventContext *event_context, GdkEvent *event)
{
    SPDesktop *desktop = event_context->desktop;
    Inkscape::Preferences *prefs = Inkscape::Preferences::get();
	
	SPZoomContext *zc = SP_ZOOM_CONTEXT(event_context);
    tolerance = prefs->getIntLimited("/options/dragtolerance/value", 0, 0, 100);
    double const zoom_inc = prefs->getDoubleLimited("/options/zoomincrement/value", M_SQRT2, 1.01, 10);

    gint ret = FALSE;

    switch (event->type) {
        case GDK_BUTTON_PRESS:
        {
            Geom::Point const button_w(event->button.x, event->button.y);
            Geom::Point const button_dt(desktop->w2d(button_w));
            if (event->button.button == 1 && !event_context->space_panning) {
                // save drag origin
                xp = (gint) event->button.x;
                yp = (gint) event->button.y;
                within_tolerance = true;

                Inkscape::Rubberband::get(desktop)->start(desktop, button_dt);

                escaped = false;

                ret = TRUE;
            } else if (event->button.button == 3) {
                double const zoom_rel( (event->button.state & GDK_SHIFT_MASK)
                                       ? zoom_inc
                                       : 1 / zoom_inc );
                desktop->zoom_relative_keep_point(button_dt, zoom_rel);
                ret = TRUE;
            }
			
			sp_canvas_item_grab(SP_CANVAS_ITEM(desktop->acetate),
								GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK,
								NULL, event->button.time);
			zc->grabbed = SP_CANVAS_ITEM(desktop->acetate);
				
            break;
        }

	case GDK_MOTION_NOTIFY:
            if (event->motion.state & GDK_BUTTON1_MASK && !event_context->space_panning) {
                ret = TRUE;

                if ( within_tolerance
                     && ( abs( (gint) event->motion.x - xp ) < tolerance )
                     && ( abs( (gint) event->motion.y - yp ) < 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;

                Geom::Point const motion_w(event->motion.x, event->motion.y);
                Geom::Point const motion_dt(desktop->w2d(motion_w));
                Inkscape::Rubberband::get(desktop)->move(motion_dt);
                gobble_motion_events(GDK_BUTTON1_MASK);
            }
            break;

      	case GDK_BUTTON_RELEASE:
        {
            Geom::Point const button_w(event->button.x, event->button.y);
            Geom::Point const button_dt(desktop->w2d(button_w));
            if ( event->button.button == 1  && !event_context->space_panning) {
                Geom::OptRect const b = Inkscape::Rubberband::get(desktop)->getRectangle();
                if (b && !within_tolerance) {
                    desktop->set_display_area(*b, 10);
                } else if (!escaped) {
                    double const zoom_rel( (event->button.state & GDK_SHIFT_MASK)
                                           ? 1 / zoom_inc
                                           : zoom_inc );
                    desktop->zoom_relative_keep_point(button_dt, zoom_rel);
                }
                ret = TRUE;
            } 
            Inkscape::Rubberband::get(desktop)->stop();
			
			if (zc->grabbed) {
				sp_canvas_item_ungrab(zc->grabbed, event->button.time);
				zc->grabbed = NULL;
			}
			
            xp = yp = 0;
            escaped = false;
            break;
        }
        case GDK_KEY_PRESS:
            switch (get_group0_keyval (&event->key)) {
                case GDK_Escape:
                    Inkscape::Rubberband::get(desktop)->stop();
                    xp = yp = 0;
                    escaped = true;
                    ret = TRUE;
                    break;
                case GDK_Up:
                case GDK_Down:
                case GDK_KP_Up:
                case GDK_KP_Down:
                    // prevent the zoom field from activation
                    if (!MOD__CTRL_ONLY)
                        ret = TRUE;
                    break;
                case GDK_Shift_L:
                case GDK_Shift_R:
                    event_context->cursor_shape = SP_ZOOM_OUT_CURSOR;
                    sp_event_context_update_cursor(event_context);
                    break;
                default:
			break;
		}
		break;
	case GDK_KEY_RELEASE:
            switch (get_group0_keyval (&event->key)) {
		case GDK_Shift_L:
		case GDK_Shift_R:
                    event_context->cursor_shape = SP_ZOOM_CURSOR;
                    sp_event_context_update_cursor(event_context);
                    break;
		default:
                    break;
		}
            break;
	default:
            break;
    }

    if (!ret) {
        if (((SPEventContextClass *) parent_class)->root_handler) {
            ret = ((SPEventContextClass *) parent_class)->root_handler(event_context, event);
        }
    }

    return ret;
}
Ejemplo n.º 12
0
/**
 * Called to handle events on knots.
 */
static int sp_knot_handler(SPCanvasItem */*item*/, GdkEvent *event, SPKnot *knot)
{
    g_assert(knot != NULL);
    g_assert(SP_IS_KNOT(knot));

    /* Run client universal event handler, if present */

    gboolean consumed = FALSE;

    g_signal_emit(knot, knot_signals[EVENT], 0, event, &consumed);

    if (consumed) {
        return TRUE;
    }

    g_object_ref(knot);
    Inkscape::Preferences *prefs = Inkscape::Preferences::get();
    tolerance = prefs->getIntLimited("/options/dragtolerance/value", 0, 0, 100);

    switch (event->type) {
	case GDK_2BUTTON_PRESS:
            if (event->button.button == 1) {
                g_signal_emit(knot, knot_signals[DOUBLECLICKED], 0, event->button.state);

                grabbed = FALSE;
                moved = FALSE;
                consumed = TRUE;
            }
            break;
	case GDK_BUTTON_PRESS:
            if (event->button.button == 1 && !knot->desktop->event_context->space_panning) {
                Geom::Point const p = knot->desktop->w2d(Geom::Point(event->button.x, event->button.y));
                sp_knot_start_dragging(knot, p, (gint) event->button.x, (gint) event->button.y, event->button.time);
                consumed = TRUE;
            }
            break;
	case GDK_BUTTON_RELEASE:
            if (event->button.button == 1 && !knot->desktop->event_context->space_panning) {
                knot->pressure = 0;
                if (transform_escaped) {
                    transform_escaped = false;
                    consumed = TRUE;
                } else {
                    sp_knot_set_flag(knot, SP_KNOT_GRABBED, FALSE);
                    if (!nograb) {
                        sp_canvas_item_ungrab(knot->item, event->button.time);
                    }
                    if (moved) {
                        sp_knot_set_flag(knot,
                                         SP_KNOT_DRAGGING,
                                         FALSE);
                        g_signal_emit(knot,
                                      knot_signals[UNGRABBED], 0,
                                      event->button.state);
                        knot->_ungrabbed_signal.emit(knot);
                    } else {
                        g_signal_emit(knot,
                                      knot_signals[CLICKED], 0,
                                      event->button.state);
                        knot->_click_signal.emit(knot, event->button.state);
                    }
                    grabbed = FALSE;
                    moved = FALSE;
                    consumed = TRUE;
                }
            }
            break;
	case GDK_MOTION_NOTIFY:
            if (grabbed && !knot->desktop->event_context->space_panning) {
                consumed = TRUE;

                if ( within_tolerance
                     && ( abs( (gint) event->motion.x - xp ) < tolerance )
                     && ( abs( (gint) event->motion.y - yp ) < 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 (gdk_event_get_axis (event, GDK_AXIS_PRESSURE, &knot->pressure))
                    knot->pressure = CLAMP (knot->pressure, 0, 1);
                else
                    knot->pressure = 0.5;

                if (!moved) {
                    g_signal_emit(knot,
                                  knot_signals[GRABBED], 0,
                                  event->motion.state);
                    sp_knot_set_flag(knot,
                                     SP_KNOT_DRAGGING,
                                     TRUE);
                }
                Geom::Point const motion_w(event->motion.x, event->motion.y);
                Geom::Point const motion_dt = knot->desktop->w2d(motion_w);
                Geom::Point p = motion_dt - knot->grabbed_rel_pos;
                sp_knot_request_position (knot, p, event->motion.state);
                knot->desktop->scroll_to_point (motion_dt);
                knot->desktop->set_coordinate_status(knot->pos); // display the coordinate of knot, not cursor - they may be different!
                if (event->motion.state & GDK_BUTTON1_MASK)
                    gobble_motion_events(GDK_BUTTON1_MASK);
                moved = TRUE;
            }
            break;
	case GDK_ENTER_NOTIFY:
            sp_knot_set_flag(knot, SP_KNOT_MOUSEOVER, TRUE);
            sp_knot_set_flag(knot, SP_KNOT_GRABBED, FALSE);

            if (knot->tip) {
                knot->desktop->event_context->defaultMessageContext()->set(Inkscape::NORMAL_MESSAGE, knot->tip);
            }

            grabbed = FALSE;
            moved = FALSE;
            consumed = TRUE;
            break;
	case GDK_LEAVE_NOTIFY:
            sp_knot_set_flag(knot, SP_KNOT_MOUSEOVER, FALSE);
            sp_knot_set_flag(knot, SP_KNOT_GRABBED, FALSE);

            if (knot->tip) {
                knot->desktop->event_context->defaultMessageContext()->clear();
            }

            grabbed = FALSE;
            moved = FALSE;

            consumed = TRUE;
            break;
	case GDK_KEY_PRESS: // keybindings for knot
            switch (get_group0_keyval(&event->key)) {
		case GDK_Escape:
                    sp_knot_set_flag(knot, SP_KNOT_GRABBED, FALSE);
                    if (!nograb) {
                        sp_canvas_item_ungrab(knot->item, event->button.time);
                    }
                    if (moved) {
                        sp_knot_set_flag(knot,
                                         SP_KNOT_DRAGGING,
                                         FALSE);
                        g_signal_emit(knot,
                                      knot_signals[UNGRABBED], 0,
                                      event->button.state);
                        sp_document_undo(sp_desktop_document(knot->desktop));
                        knot->desktop->messageStack()->flash(Inkscape::NORMAL_MESSAGE, _("Node or handle drag canceled."));
                        transform_escaped = true;
                        consumed = TRUE;
                    }
                    grabbed = FALSE;
                    moved = FALSE;
                    break;
		default:
                    consumed = FALSE;
                    break;
            }
            break;
	default:
            break;
    }

    g_object_unref(knot);

    return consumed;
}
Ejemplo n.º 13
0
static gint
sp_spiral_context_root_handler(SPEventContext *event_context, GdkEvent *event)
{
    static gboolean dragging;

    SPDesktop *desktop = event_context->desktop;
    Inkscape::Selection *selection = sp_desktop_selection (desktop);
    SPSpiralContext *sc = SP_SPIRAL_CONTEXT(event_context);

    Inkscape::Preferences *prefs = Inkscape::Preferences::get();
    event_context->tolerance = prefs->getIntLimited("/options/dragtolerance/value", 0, 0, 100);

    gint ret = FALSE;

    switch (event->type) {
        case GDK_BUTTON_PRESS:
            if (event->button.button == 1 && !event_context->space_panning) {

                dragging = TRUE;
                sc->center = Inkscape::setup_for_drag_start(desktop, event_context, event);

                SnapManager &m = desktop->namedview->snap_manager;
                m.setup(desktop);
                Geom::Point pt2g = to_2geom(sc->center);
                m.freeSnapReturnByRef(Inkscape::SnapPreferences::SNAPPOINT_NODE, pt2g);
                sc->center = from_2geom(pt2g);

                sp_canvas_item_grab(SP_CANVAS_ITEM(desktop->acetate),
                                    ( GDK_KEY_PRESS_MASK |
                                      GDK_BUTTON_RELEASE_MASK |
                                      GDK_POINTER_MOTION_MASK |
                                      GDK_POINTER_MOTION_HINT_MASK |
                                      GDK_BUTTON_PRESS_MASK    ),
                                    NULL, event->button.time);
                ret = TRUE;
            }
            break;
        case GDK_MOTION_NOTIFY:
            if (dragging && (event->motion.state & GDK_BUTTON1_MASK) && !event_context->space_panning) {

                if ( event_context->within_tolerance
                     && ( abs( (gint) event->motion.x - event_context->xp ) < event_context->tolerance )
                     && ( abs( (gint) event->motion.y - event_context->yp ) < event_context->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 draw, not click), then always process the
                // motion notify coordinates as given (no snapping back to origin)
                event_context->within_tolerance = false;

                Geom::Point const motion_w(event->motion.x, event->motion.y);
                Geom::Point motion_dt(event_context->desktop->w2d(motion_w));
                
                SnapManager &m = desktop->namedview->snap_manager;
                m.setup(desktop, true, sc->item);
                m.freeSnapReturnByRef(Inkscape::SnapPreferences::SNAPPOINT_NODE, motion_dt);
                sp_spiral_drag(sc, from_2geom(motion_dt), event->motion.state);

                gobble_motion_events(GDK_BUTTON1_MASK);

                ret = TRUE;
            }
            break;
        case GDK_BUTTON_RELEASE:
            event_context->xp = event_context->yp = 0;
            if (event->button.button == 1 && !event_context->space_panning) {
                dragging = FALSE;
                if (!event_context->within_tolerance) {
                    // we've been dragging, finish the spiral
                    sp_spiral_finish(sc);
                } else if (event_context->item_to_select) {
                    // no dragging, select clicked item if any
                    if (event->button.state & GDK_SHIFT_MASK) {
                        selection->toggle(event_context->item_to_select);
                    } else {
                        selection->set(event_context->item_to_select);
                    }
                } else {
                    // click in an empty space
                    selection->clear();
                }

                event_context->item_to_select = NULL;
                ret = TRUE;
                sp_canvas_item_ungrab(SP_CANVAS_ITEM(desktop->acetate), event->button.time);
            }
            break;
        case GDK_KEY_PRESS:
            switch (get_group0_keyval(&event->key)) {
                case GDK_Alt_R:
                case GDK_Control_L:
                case GDK_Control_R:
                case GDK_Shift_L:
                case GDK_Shift_R:
                case GDK_Meta_L:  // Meta is when you press Shift+Alt (at least on my machine)
                case GDK_Meta_R:
                    sp_event_show_modifier_tip(event_context->defaultMessageContext(), event,
                                               _("<b>Ctrl</b>: snap angle"),
                                               NULL,
                                               _("<b>Alt</b>: lock spiral radius"));
                    break;
                case GDK_Up:
                case GDK_Down:
                case GDK_KP_Up:
                case GDK_KP_Down:
                    // prevent the zoom field from activation
                    if (!MOD__CTRL_ONLY)
                        ret = TRUE;
                    break;
                case GDK_x:
                case GDK_X:
                    if (MOD__ALT_ONLY) {
                        desktop->setToolboxFocusTo ("altx-spiral");
                        ret = TRUE;
                    }
                    break;
                case GDK_Escape:
                    sp_desktop_selection(desktop)->clear();
                    //TODO: make dragging escapable by Esc
                    break;

                case GDK_space:
                    if (dragging) {
                        sp_canvas_item_ungrab(SP_CANVAS_ITEM(desktop->acetate),
                                              event->button.time);
                        dragging = false;
                        if (!event_context->within_tolerance) {
                            // we've been dragging, finish the rect
                            sp_spiral_finish(sc);
                        }
                        // do not return true, so that space would work switching to selector
                    }
                    break;

                default:
                    break;
            }
            break;
        case GDK_KEY_RELEASE:
            switch (get_group0_keyval(&event->key)) {
                case GDK_Alt_L:
                case GDK_Alt_R:
                case GDK_Control_L:
                case GDK_Control_R:
                case GDK_Shift_L:
                case GDK_Shift_R:
                case GDK_Meta_L:  // Meta is when you press Shift+Alt
                case GDK_Meta_R:
                    event_context->defaultMessageContext()->clear();
                    break;
                default:
                    break;
            }
            break;
        default:
            break;
    }

    if (!ret) {
        if (((SPEventContextClass *) parent_class)->root_handler)
            ret = ((SPEventContextClass *) parent_class)->root_handler(event_context, event);
    }

    return ret;
}