Пример #1
0
/**
 * Make the argument dialog transient to the currently active document
 * window.
 */
void sp_transientize(GtkWidget *dialog)
{
    Inkscape::Preferences *prefs = Inkscape::Preferences::get();
#ifndef WIN32  // FIXME: Temporary Win32 special code to enable transient dialogs
    // _set_skip_taskbar_hint makes transient dialogs NON-transient! When dialogs
    // are made transient (_set_transient_for), they are already removed from
    // the taskbar in Win32.
    if (prefs->getBool( "/options/dialogsskiptaskbar/value")) {
        gtk_window_set_skip_taskbar_hint (GTK_WINDOW (dialog), TRUE);
    }
#endif

    gint transient_policy = prefs->getIntLimited("/options/transientpolicy/value", 1, 0, 2);

#ifdef WIN32 // Win32 special code to enable transient dialogs
    transient_policy = 2;
#endif

    if (transient_policy) {

    // if there's an active document window, attach dialog to it as a transient:

        if ( SP_ACTIVE_DESKTOP )
        {
            SP_ACTIVE_DESKTOP->setWindowTransient (dialog, transient_policy);
        }
    }
} // end of sp_transientize()
Пример #2
0
/**
 * A function called when the window gets focus.
 *
 * This function gets called on a focus event.  It figures out how much
 * time is required for a transition, and the number of steps that'll take,
 * and sets up the _trans_timer function to do the work.  If the transition
 * time is set to 0 ms it just calls _trans_timer once with _steps equal to
 * zero so that the transition happens instantaneously.  This occurs on
 * windows as opacity changes cause flicker there.
 */
void FloatingBehavior::_focus_event (void)
{
    Inkscape::Preferences *prefs = Inkscape::Preferences::get();
    _steps = 0;
    _trans_focus = prefs->getDoubleLimited("/dialogs/transparency/on-focus", 0.95, 0.0, 1.0);
    _trans_blur = prefs->getDoubleLimited("/dialogs/transparency/on-blur", 0.50, 0.0, 1.0);
    _trans_time = prefs->getIntLimited("/dialogs/transparency/animate-time", 100, 0, 5000);

    if (_trans_time != 0) {
        float diff = _trans_focus - _trans_blur;
        if (diff < 0.0) diff *= -1.0;

        while (diff > 0.05) {
            _steps++;
            diff = diff / 2.0;
        }

        if (_steps != 0) {
            Glib::signal_timeout().connect(sigc::mem_fun(this, &FloatingBehavior::_trans_timer), _trans_time / _steps);
        }
    }
    _trans_timer();

    return;
}
Пример #3
0
DialogManager &DialogManager::getInstance()
{
    Inkscape::Preferences *prefs = Inkscape::Preferences::get();
    int dialogs_type = prefs->getIntLimited("/options/dialogtype/value", DOCK, 0, 1);

    /* Use singleton behavior for floating dialogs */
    if (dialogs_type == FLOATING) {
        static DialogManager *instance = 0;

        if (!instance)
            instance = new DialogManager();
        return *instance;
    }

    return *new DialogManager();
}
Пример #4
0
void
FloatingBehavior::onDesktopActivated (SPDesktop *desktop)
{
    Inkscape::Preferences *prefs = Inkscape::Preferences::get();
    gint transient_policy = prefs->getIntLimited("/options/transientpolicy/value", 1, 0, 2);

#ifdef WIN32 // Win32 special code to enable transient dialogs
    transient_policy = 2;
#endif

    if (!transient_policy)
        return;

    GtkWindow *dialog_win = GTK_WINDOW(_d->gobj());

    if (_dialog.retransientize_suppress) {
         /* if retransientizing of this dialog is still forbidden after
          * previous call warning turned off because it was confusingly fired
          * when loading many files from command line
          */

         // g_warning("Retranzientize aborted! You're switching windows too fast!");
        return;
    }

    if (dialog_win)
    {
        _dialog.retransientize_suppress = true; // disallow other attempts to retranzientize this dialog

        desktop->setWindowTransient (dialog_win);

        /*
         * This enables "aggressive" transientization,
         * i.e. dialogs always emerging on top when you switch documents. Note
         * however that this breaks "click to raise" policy of a window
         * manager because the switched-to document will be raised at once
         * (so that its transients also could raise)
         */
        if (transient_policy == 2 && ! _dialog._hiddenF12 && !_dialog._user_hidden) {
            // without this, a transient window not always emerges on top
            gtk_window_present (dialog_win);
        }
    }

    // we're done, allow next retransientizing not sooner than after 120 msec
    g_timeout_add (120, (GSourceFunc) sp_retransientize_again, (gpointer) _d);
}
Пример #5
0
void
sp_transientize_callback ( SPDesktop *desktop, win_data *wd )
{
    Inkscape::Preferences *prefs = Inkscape::Preferences::get();
    gint transient_policy = prefs->getIntLimited( "/options/transientpolicy/value", 1, 0, 2);

#ifdef WIN32 // Win32 special code to enable transient dialogs
    transient_policy = 1;
#endif

    if (!transient_policy)
        return;

    if (wd->win)
    {
        desktop->setWindowTransient (wd->win, transient_policy);
    }
}
Пример #6
0
static gchar* getImageEditorName() {
    Inkscape::Preferences *prefs = Inkscape::Preferences::get();
    gchar* value = 0;
    Glib::ustring choices = prefs->getString("/options/bitmapeditor/choices");
    if (!choices.empty()) {
        gchar** splits = g_strsplit(choices.data(), ",", 0);
        gint numIems = g_strv_length(splits);

        int setting = prefs->getIntLimited("/options/bitmapeditor/value", 0, 0, numIems);
        value = g_strdup(splits[setting]);

        g_strfreev(splits);
    }

    if (!value) {
        value = g_strdup("gimp");
    }
    return value;
}
Пример #7
0
/**
 *  This class is provided as a container for Inkscape's various
 *  dialogs.  This allows Inkscape::Application to treat the various
 *  dialogs it invokes, as abstractions.
 *
 *  DialogManager is essentially a cache of dialogs.  It lets us
 *  initialize dialogs lazily - instead of constructing them during
 *  application startup, they're constructed the first time they're
 *  actually invoked by Inkscape::Application.  The constructed
 *  dialog is held here after that, so future invokations of the
 *  dialog don't need to get re-constructed each time.  The memory for
 *  the dialogs are then reclaimed when the DialogManager is destroyed.
 *
 *  In addition, DialogManager also serves as a signal manager for
 *  dialogs.  It provides a set of signals that can be sent to all
 *  dialogs for doing things such as hiding/unhiding them, etc.
 *  DialogManager ensures that every dialog it handles will listen
 *  to these signals.
 *
 */
DialogManager::DialogManager() {

    using namespace Behavior;
    using namespace Inkscape::UI::Dialogs; // temporary

    Inkscape::Preferences *prefs = Inkscape::Preferences::get();
    int dialogs_type = prefs->getIntLimited("/options/dialogtype/value", DOCK, 0, 1);

    if (dialogs_type == FLOATING) {
        registerFactory("AlignAndDistribute",  &create<AlignAndDistribute,   FloatingBehavior>);
        registerFactory("DocumentMetadata",    &create<DocumentMetadata,     FloatingBehavior>);
        registerFactory("DocumentProperties",  &create<DocumentProperties,   FloatingBehavior>);
        registerFactory("ExtensionEditor",     &create<ExtensionEditor,      FloatingBehavior>);
        registerFactory("FillAndStroke",       &create<FillAndStroke,        FloatingBehavior>);
        registerFactory("FilterEffectsDialog", &create<FilterEffectsDialog,  FloatingBehavior>);
        registerFactory("Find",                &create<Find,                 FloatingBehavior>);
        registerFactory("Glyphs",              &create<GlyphsPanel,          FloatingBehavior>);
        registerFactory("IconPreviewPanel",    &create<IconPreviewPanel,     FloatingBehavior>);
        registerFactory("InkscapePreferences", &create<InkscapePreferences,  FloatingBehavior>);
        registerFactory("LayersPanel",         &create<LayersPanel,          FloatingBehavior>);
        registerFactory("LivePathEffect",      &create<LivePathEffectEditor, FloatingBehavior>);
        registerFactory("Memory",              &create<Memory,               FloatingBehavior>);
        registerFactory("Messages",            &create<Messages,             FloatingBehavior>);
        registerFactory("ObjectAttributes",    &create<ObjectAttributes,     FloatingBehavior>);
        registerFactory("ObjectProperties",    &create<ObjectProperties,     FloatingBehavior>);
//        registerFactory("PrintColorsPreviewDialog",      &create<PrintColorsPreviewDialog,       FloatingBehavior>);
        registerFactory("Script",              &create<ScriptDialog,         FloatingBehavior>);
#ifdef ENABLE_SVG_FONTS
        registerFactory("SvgFontsDialog",      &create<SvgFontsDialog,       FloatingBehavior>);
#endif
        registerFactory("Swatches",            &create<SwatchesPanel,        FloatingBehavior>);
        registerFactory("Symbols",             &create<SymbolsDialog,        FloatingBehavior>);
        registerFactory("TileDialog",          &create<TileDialog,           FloatingBehavior>);
        registerFactory("Trace",               &create<TraceDialog,          FloatingBehavior>);
        registerFactory("Transformation",      &create<Transformation,       FloatingBehavior>);
        registerFactory("UndoHistory",         &create<UndoHistory,          FloatingBehavior>);
        registerFactory("InputDevices",        &create<InputDialog,          FloatingBehavior>);
        registerFactory("TextFont",            &create<TextEdit,             FloatingBehavior>);
        registerFactory("SpellCheck",          &create<SpellCheck,           FloatingBehavior>);
        registerFactory("Export",              &create<Export,               FloatingBehavior>);
        registerFactory("XmlTree",             &create<XmlTree,              FloatingBehavior>);
        registerFactory("CloneTiler",          &create<CloneTiler,           FloatingBehavior>);

    } else {

        registerFactory("AlignAndDistribute",  &create<AlignAndDistribute,   DockBehavior>);
        registerFactory("DocumentMetadata",    &create<DocumentMetadata,     DockBehavior>);
        registerFactory("DocumentProperties",  &create<DocumentProperties,   DockBehavior>);
        registerFactory("ExtensionEditor",     &create<ExtensionEditor,      DockBehavior>);
        registerFactory("FillAndStroke",       &create<FillAndStroke,        DockBehavior>);
        registerFactory("FilterEffectsDialog", &create<FilterEffectsDialog,  DockBehavior>);
        registerFactory("Find",                &create<Find,                 DockBehavior>);
        registerFactory("Glyphs",              &create<GlyphsPanel,          DockBehavior>);
        registerFactory("IconPreviewPanel",    &create<IconPreviewPanel,     DockBehavior>);
        registerFactory("InkscapePreferences", &create<InkscapePreferences,  DockBehavior>);
        registerFactory("LayersPanel",         &create<LayersPanel,          DockBehavior>);
        registerFactory("LivePathEffect",      &create<LivePathEffectEditor, DockBehavior>);
        registerFactory("Memory",              &create<Memory,               DockBehavior>);
        registerFactory("Messages",            &create<Messages,             DockBehavior>);
        registerFactory("ObjectAttributes",    &create<ObjectAttributes,     DockBehavior>);
        registerFactory("ObjectProperties",    &create<ObjectProperties,     DockBehavior>);
//        registerFactory("PrintColorsPreviewDialog",      &create<PrintColorsPreviewDialog,       DockBehavior>);
        registerFactory("Script",              &create<ScriptDialog,         DockBehavior>);
#ifdef ENABLE_SVG_FONTS
        registerFactory("SvgFontsDialog",      &create<SvgFontsDialog,       DockBehavior>);
#endif
        registerFactory("Swatches",            &create<SwatchesPanel,        DockBehavior>);
        registerFactory("Symbols",             &create<SymbolsDialog,        DockBehavior>);
        registerFactory("TileDialog",          &create<TileDialog,           DockBehavior>);
        registerFactory("Trace",               &create<TraceDialog,          DockBehavior>);
        registerFactory("Transformation",      &create<Transformation,       DockBehavior>);
        registerFactory("UndoHistory",         &create<UndoHistory,          DockBehavior>);
        registerFactory("InputDevices",        &create<InputDialog,          DockBehavior>);
        registerFactory("TextFont",            &create<TextEdit,             DockBehavior>);
        registerFactory("SpellCheck",          &create<SpellCheck,           DockBehavior>);
        registerFactory("Export",              &create<Export,               DockBehavior>);
        registerFactory("XmlTree",             &create<XmlTree,              DockBehavior>);
        registerFactory("CloneTiler",          &create<CloneTiler,           DockBehavior>);

    }
}
Пример #8
0
Dock::Dock(Gtk::Orientation orientation)
    : _gdl_dock(gdl_dock_new()),
#if WITH_GDL_3_6
      _gdl_dock_bar(GDL_DOCK_BAR(gdl_dock_bar_new(G_OBJECT(_gdl_dock)))),
#else
      _gdl_dock_bar(GDL_DOCK_BAR(gdl_dock_bar_new(GDL_DOCK(_gdl_dock)))),
#endif
      _scrolled_window (Gtk::manage(new Gtk::ScrolledWindow))
{
#if WITH_GDL_3_6
    gtk_orientable_set_orientation(GTK_ORIENTABLE(_gdl_dock_bar),
                                   static_cast<GtkOrientation>(orientation));
#else
    gdl_dock_bar_set_orientation(_gdl_dock_bar,
                                 static_cast<GtkOrientation>(orientation));
#endif

#if WITH_GTKMM_3_0
    switch(orientation) {
        case Gtk::ORIENTATION_VERTICAL:
            _dock_box = Gtk::manage(new Gtk::Box(Gtk::ORIENTATION_HORIZONTAL));
            break;
        case Gtk::ORIENTATION_HORIZONTAL:
            _dock_box = Gtk::manage(new Gtk::Box(Gtk::ORIENTATION_VERTICAL));
    }
    
    _paned = Gtk::manage(new Gtk::Paned(orientation));
#else
    switch (orientation) {
        case Gtk::ORIENTATION_VERTICAL:
            _dock_box = Gtk::manage(new Gtk::HBox());
            _paned = Gtk::manage(new Gtk::VPaned());
            break;
        case Gtk::ORIENTATION_HORIZONTAL:
            _dock_box = Gtk::manage(new Gtk::VBox());
            _paned = Gtk::manage(new Gtk::HPaned());
    }
#endif

    _scrolled_window->add(*_dock_box);
    _scrolled_window->set_policy(Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);

    _paned->pack1(*Glib::wrap(GTK_WIDGET(_gdl_dock)), false, false);
    _paned->pack2(_filler, true, false);

    _dock_box->pack_start(*_paned, Gtk::PACK_EXPAND_WIDGET);
    _dock_box->pack_end(*Gtk::manage(Glib::wrap(GTK_WIDGET(_gdl_dock_bar))), Gtk::PACK_SHRINK);
    _dock_box->get_parent()->set_resize_mode(Gtk::RESIZE_PARENT);

    _scrolled_window->set_size_request(0);

    Inkscape::Preferences *prefs = Inkscape::Preferences::get();
    GdlSwitcherStyle gdl_switcher_style =
        static_cast<GdlSwitcherStyle>(prefs->getIntLimited("/options/dock/switcherstyle",
                                                                      GDL_SWITCHER_STYLE_BOTH, 0, 4));

    GdlDockMaster* master = NULL;
    
    g_object_get(GDL_DOCK_OBJECT(_gdl_dock),
            "master", &master,
            NULL);
    
    g_object_set(master,
            "switcher-style", gdl_switcher_style,
            NULL);

    GdlDockBarStyle gdl_dock_bar_style =
        static_cast<GdlDockBarStyle>(prefs->getIntLimited("/options/dock/dockbarstyle",
                                                                     GDL_DOCK_BAR_BOTH, 0, 3));

    gdl_dock_bar_set_style(_gdl_dock_bar, gdl_dock_bar_style);


    INKSCAPE.signal_dialogs_hide.connect(sigc::mem_fun(*this, &Dock::hide));
    INKSCAPE.signal_dialogs_unhide.connect(sigc::mem_fun(*this, &Dock::show));

    g_signal_connect(_paned->gobj(), "button-press-event", G_CALLBACK(_on_paned_button_event), (void *)this);
    g_signal_connect(_paned->gobj(), "button-release-event", G_CALLBACK(_on_paned_button_event), (void *)this);

    signal_layout_changed().connect(sigc::mem_fun(*this, &Inkscape::UI::Widget::Dock::_onLayoutChanged));
}
Пример #9
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 */
    bool consumed = knot->event_signal.emit(knot, event);

    if (consumed) {
        return true;
    }

    knot_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) {
                knot->doubleclicked_signal.emit(knot, event->button.state);

                grabbed = FALSE;
                moved = FALSE;
                consumed = TRUE;
            }
            break;
    case GDK_BUTTON_PRESS:
            if ((event->button.button == 1) && knot->desktop && knot->desktop->event_context && !knot->desktop->event_context->space_panning) {
                Geom::Point const p = knot->desktop->w2d(Geom::Point(event->button.x, event->button.y));
                knot->startDragging(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 && knot->desktop->event_context && !knot->desktop->event_context->space_panning) {
                // If we have any pending snap event, then invoke it now
                if (knot->desktop->event_context->_delayed_snap_event) {
                    sp_event_context_snap_watchdog_callback(knot->desktop->event_context->_delayed_snap_event);
                }

                sp_event_context_discard_delayed_snap_event(knot->desktop->event_context);

                knot->pressure = 0;

                if (transform_escaped) {
                    transform_escaped = false;
                    consumed = TRUE;
                } else {
                    knot->setFlag(SP_KNOT_GRABBED, FALSE);

                    if (!nograb) {
                        sp_canvas_item_ungrab(knot->item, event->button.time);
                    }

                    if (moved) {
                        knot->setFlag(SP_KNOT_DRAGGING, FALSE);

                        knot->ungrabbed_signal.emit(knot, event->button.state);
                    } else {
                        knot->click_signal.emit(knot, event->button.state);
                    }

                    grabbed = FALSE;
                    moved = FALSE;
                    consumed = TRUE;
                }
            }
            if (tools_isactive(knot->desktop, TOOLS_NODES)) {
                Inkscape::UI::Tools::NodeTool *nt = static_cast<Inkscape::UI::Tools::NodeTool*>(knot->desktop->event_context);
                nt->update_helperpath();
            }
            break;
    case GDK_MOTION_NOTIFY:
            if (grabbed && knot->desktop && knot->desktop->event_context && !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) {
                    knot->grabbed_signal.emit(knot, event->motion.state);

                    knot->setFlag(SP_KNOT_DRAGGING, TRUE);
                }

                sp_event_context_snap_delay_handler(knot->desktop->event_context, NULL, knot, (GdkEventMotion *)event, Inkscape::UI::Tools::DelayedSnapEvent::KNOT_HANDLER);
                sp_knot_handler_request_position(event, knot);
                moved = TRUE;
            }
            if (tools_isactive(knot->desktop, TOOLS_NODES)) {
                Inkscape::UI::Tools::NodeTool *nt = static_cast<Inkscape::UI::Tools::NodeTool*>(knot->desktop->event_context);
                nt->update_helperpath();
            }
            break;
    case GDK_ENTER_NOTIFY:
            knot->setFlag(SP_KNOT_MOUSEOVER, TRUE);
            knot->setFlag(SP_KNOT_GRABBED, FALSE);

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

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

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

            grabbed = FALSE;
            moved = FALSE;
            consumed = TRUE;
            break;
    case GDK_KEY_PRESS: // keybindings for knot
            switch (Inkscape::UI::Tools::get_group0_keyval(&event->key)) {
                case GDK_KEY_Escape:
                            knot->setFlag(SP_KNOT_GRABBED, FALSE);

                            if (!nograb) {
                                sp_canvas_item_ungrab(knot->item, event->button.time);
                            }

                            if (moved) {
                                knot->setFlag(SP_KNOT_DRAGGING, FALSE);

                                knot->ungrabbed_signal.emit(knot, event->button.state);

                                DocumentUndo::undo(knot->desktop->getDocument());
                                knot->desktop->messageStack()->flash(Inkscape::NORMAL_MESSAGE, _("Node or handle drag canceled."));
                                transform_escaped = true;
                                consumed = TRUE;
                            }

                            grabbed = FALSE;
                            moved = FALSE;

                            sp_event_context_discard_delayed_snap_event(knot->desktop->event_context);
                            break;
                default:
                            consumed = FALSE;
                            break;
                    }
                    break;
    default:
            break;
    }

    knot_unref(knot);

    return consumed || grabbed;
}
Пример #10
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;
}
Пример #11
0
ControlManagerImpl::ControlManagerImpl(ControlManager &manager) :
    _manager(manager),
    _sizeChangedSignal(),
    _prefHook(*this),
    _size(3),
    _resize(3),
    _itemList(),
    _sizeTable()
{
    Inkscape::Preferences *prefs = Inkscape::Preferences::get();
    prefs->addObserver(_prefHook);

    _size = prefs->getIntLimited("/options/grabsize/value", 3, 1, 7);

    _typeTable[CTRL_TYPE_UNKNOWN] = SP_TYPE_CTRL;
    _typeTable[CTRL_TYPE_ADJ_HANDLE] = SP_TYPE_CTRL;
    _typeTable[CTRL_TYPE_ANCHOR] = SP_TYPE_CTRL;
    _typeTable[CTRL_TYPE_INVISIPOINT] = SP_TYPE_CTRL;
    _typeTable[CTRL_TYPE_NODE_AUTO] = SP_TYPE_CTRL;
    _typeTable[CTRL_TYPE_NODE_CUSP] = SP_TYPE_CTRL;
    _typeTable[CTRL_TYPE_NODE_SMOOTH] = SP_TYPE_CTRL;
    _typeTable[CTRL_TYPE_NODE_SYMETRICAL] = SP_TYPE_CTRL;

    _typeTable[CTRL_TYPE_LINE] = SP_TYPE_CTRLLINE;


    // -------
    _ctrlToShape[CTRL_TYPE_UNKNOWN] = SP_CTRL_SHAPE_DIAMOND;
    _ctrlToShape[CTRL_TYPE_NODE_CUSP] = SP_CTRL_SHAPE_DIAMOND;
    _ctrlToShape[CTRL_TYPE_NODE_SMOOTH] = SP_CTRL_SHAPE_SQUARE;
    _ctrlToShape[CTRL_TYPE_NODE_AUTO] = SP_CTRL_SHAPE_CIRCLE;
    _ctrlToShape[CTRL_TYPE_NODE_SYMETRICAL] = SP_CTRL_SHAPE_SQUARE;

    _ctrlToShape[CTRL_TYPE_ADJ_HANDLE] = SP_CTRL_SHAPE_CIRCLE;
    _ctrlToShape[CTRL_TYPE_INVISIPOINT] = SP_CTRL_SHAPE_SQUARE;

    // -------

    _resizeOnSelect.insert(CTRL_TYPE_NODE_AUTO);
    _resizeOnSelect.insert(CTRL_TYPE_NODE_CUSP);
    _resizeOnSelect.insert(CTRL_TYPE_NODE_SMOOTH);
    _resizeOnSelect.insert(CTRL_TYPE_NODE_SYMETRICAL);

    // -------

    {
        int sizes[] = {8, 8, 8, 8, 8, 8, 8};
        _sizeTable[CTRL_TYPE_UNKNOWN] = std::vector<int>(sizes, sizes + (sizeof(sizes) / sizeof(sizes[0])));
    }
    {
        int sizes[] = {2, 4, 6, 8, 10, 12, 14};
        _sizeTable[CTRL_TYPE_ANCHOR] = std::vector<int>(sizes, sizes + (sizeof(sizes) / sizeof(sizes[0])));
    }
    {
        int sizes[] = {2, 4, 7, 8, 9, 10, 12};
        _sizeTable[CTRL_TYPE_ADJ_HANDLE] = std::vector<int>(sizes, sizes + (sizeof(sizes) / sizeof(sizes[0])));
    }
    {
        int sizes[] = {4, 6, 8, 10, 12, 14, 16};
        _sizeTable[CTRL_TYPE_POINT] = std::vector<int>(sizes, sizes + (sizeof(sizes) / sizeof(sizes[0])));
        _sizeTable[CTRL_TYPE_ROTATE] = std::vector<int>(sizes, sizes + (sizeof(sizes) / sizeof(sizes[0])));
        _sizeTable[CTRL_TYPE_SIZER] = std::vector<int>(sizes, sizes + (sizeof(sizes) / sizeof(sizes[0])));
        _sizeTable[CTRL_TYPE_SHAPER] = std::vector<int>(sizes, sizes + (sizeof(sizes) / sizeof(sizes[0])));
    }
    {
        int sizes[] = {5, 7, 9, 10, 11, 12, 13};
        _sizeTable[CTRL_TYPE_NODE_AUTO] = std::vector<int>(sizes, sizes + (sizeof(sizes) / sizeof(sizes[0])));
        _sizeTable[CTRL_TYPE_NODE_CUSP] = std::vector<int>(sizes, sizes + (sizeof(sizes) / sizeof(sizes[0])));
    }
    {
        int sizes[] = {3, 5, 7, 8, 9, 10, 11};
        _sizeTable[CTRL_TYPE_NODE_SMOOTH] = std::vector<int>(sizes, sizes + (sizeof(sizes) / sizeof(sizes[0])));
        _sizeTable[CTRL_TYPE_NODE_SYMETRICAL] = std::vector<int>(sizes, sizes + (sizeof(sizes) / sizeof(sizes[0])));
    }
    {
        int sizes[] = {1, 1, 1, 1, 1, 1, 1};
        _sizeTable[CTRL_TYPE_INVISIPOINT] = std::vector<int>(sizes, sizes + (sizeof(sizes) / sizeof(sizes[0])));
    }
}
Пример #12
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;
}
Пример #13
0
static gint
pencil_handle_motion_notify(SPPencilContext *const pc, GdkEventMotion const &mevent)
{
    if ((mevent.state & GDK_CONTROL_MASK) && (mevent.state & GDK_BUTTON1_MASK)) {
        // mouse was accidentally moved during Ctrl+click;
        // ignore the motion and create a single point
        pc->is_drawing = false;
        return TRUE;
    }
    gint ret = FALSE;
    SPDesktop *const dt = pc->desktop;

    SPEventContext *event_context = SP_EVENT_CONTEXT(pc);
    if (event_context->space_panning || mevent.state & GDK_BUTTON2_MASK || mevent.state & GDK_BUTTON3_MASK) {
        // allow scrolling
        return FALSE;
    }

    if ( ( mevent.state & GDK_BUTTON1_MASK ) && !pc->grab && pc->is_drawing) {
        /* Grab mouse, so release will not pass unnoticed */
        pc->grab = SP_CANVAS_ITEM(dt->acetate);
        sp_canvas_item_grab(pc->grab, ( GDK_KEY_PRESS_MASK | GDK_BUTTON_PRESS_MASK   |
                                        GDK_BUTTON_RELEASE_MASK |
                                        GDK_POINTER_MOTION_MASK  ),
                            NULL, mevent.time);
    }

    /* Find desktop coordinates */
    Geom::Point p = dt->w2d(Geom::Point(mevent.x, mevent.y));

    /* Test whether we hit any anchor. */
    SPDrawAnchor *anchor = spdc_test_inside(pc, Geom::Point(mevent.x, mevent.y));

    if (pencil_within_tolerance) {
        Inkscape::Preferences *prefs = Inkscape::Preferences::get();
        gint const tolerance = prefs->getIntLimited("/options/dragtolerance/value", 0, 0, 100);
        if ( Geom::LInfty( Geom::Point(mevent.x,mevent.y) - pencil_drag_origin_w ) < tolerance ) {
            return FALSE;   // 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)
    pencil_within_tolerance = false;

    switch (pc->state) {
        case SP_PENCIL_CONTEXT_ADDLINE:
            /* Set red endpoint */
            if (anchor) {
                p = anchor->dp;
            } else {
                Geom::Point ptnr(p);
                spdc_endpoint_snap(pc, ptnr, mevent.state);
                p = ptnr;
            }
            spdc_set_endpoint(pc, p);
            ret = TRUE;
            break;
        default:
            /* We may be idle or already freehand */
            if ( mevent.state & GDK_BUTTON1_MASK && pc->is_drawing ) {
                pc->state = SP_PENCIL_CONTEXT_FREEHAND;
                if ( !pc->sa && !pc->green_anchor ) {
                    /* Create green anchor */
                    pc->green_anchor = sp_draw_anchor_new(pc, pc->green_curve, TRUE, pc->p[0]);
                }
                /** \todo
                 * fixme: I am not sure whether we want to snap to anchors
                 * in middle of freehand (Lauris)
                 */
                SnapManager &m = dt->namedview->snap_manager;
                
                if (anchor) {
                    p = anchor->dp;
                } else if ((mevent.state & GDK_SHIFT_MASK) == 0) {
                    m.setup(dt);
                    Inkscape::SnappedPoint const s = m.freeSnap(Inkscape::SnapPreferences::SNAPPOINT_NODE, p);
                    if (s.getSnapped()) {
                    	s.getPoint(p);
                    	pc->prev_snap_was_succesful = true;
                    } else {
                    	pc->prev_snap_was_succesful = false;
                    }
                }
                if ( pc->npoints != 0) { // buttonpress may have happened before we entered draw context!
                	if (!(pc->prev_snap_was_succesful && m.snapprefs.getSnapPostponedGlobally())) {
	                    // When snapping is enabled but temporarily on hold because the mouse is moving 
                        // fast, then we don't want to add nodes off-grid
                        spdc_add_freehand_point(pc, p, mevent.state);
	                    ret = TRUE;
                	}
                }

                if (anchor && !pc->anchor_statusbar) {
                    pc->_message_context->set(Inkscape::NORMAL_MESSAGE, _("<b>Release</b> here to close and finish the path."));
                    pc->anchor_statusbar = true;
                } else if (!anchor && pc->anchor_statusbar) {
                    pc->_message_context->clear();
                    pc->anchor_statusbar = false;
                } else if (!anchor) {
                    pc->_message_context->set(Inkscape::NORMAL_MESSAGE, _("Drawing a freehand path"));
                }

            } else {
                if (anchor && !pc->anchor_statusbar) {
                    pc->_message_context->set(Inkscape::NORMAL_MESSAGE, _("<b>Drag</b> to continue the path from this point."));
                    pc->anchor_statusbar = true;
                } else if (!anchor && pc->anchor_statusbar) {
                    pc->_message_context->clear();
                    pc->anchor_statusbar = false;
                }
            }
            break;
    }
    return ret;
}
Пример #14
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;
}
Пример #15
0
/**
Handles all keyboard and mouse input for meshs.
*/
static gint
sp_mesh_context_root_handler(SPEventContext *event_context, GdkEvent *event)
{
    // static int count = 0;
    // std::cout << "sp_mesh_context_root_handler: " << count++ << std::endl;
    static bool dragging;

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

    SPMeshContext *rc = SP_MESH_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, "px"); // in px

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

    gint ret = FALSE;
    switch (event->type) {

    case GDK_2BUTTON_PRESS:

#ifdef DEBUG_MESH
        std::cout << "sp_mesh_context_root_handler: GDK_2BUTTON_PRESS" << std::endl;
#endif

        // Double click:
        //  If over a mesh line, divide mesh row/column
        //  If not over a line, create new gradients for selected objects.

        if ( event->button.button == 1 ) {

            // Are we over a mesh line?
            bool over_line = false;
            SPCtrlCurve *line = NULL;
            if (drag->lines) {
                for (GSList *l = drag->lines; (l != NULL) && (!over_line); l = l->next) {
                    line = (SPCtrlCurve*) l->data;
                    over_line |= sp_mesh_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_mesh_context_split_near_point(rc, SP_ITEM(selection->itemList()->data), rc->mousepoint_doc, event->button.time);

            } else {
                // Create a new gradient with default coordinates.

                for (GSList const* i = selection->itemList(); i != NULL; i = i->next) {

                    SPItem *item = SP_ITEM(i->data);
                    SPGradientType new_type = SP_GRADIENT_TYPE_MESH;
                    Inkscape::PaintTarget fsmode = (prefs->getInt("/tools/gradient/newfillorstroke", 1) != 0) ? Inkscape::FOR_FILL : Inkscape::FOR_STROKE;

#ifdef DEBUG_MESH
                    std::cout << "sp_mesh_context_root_handler: creating new mesh on: " << (fsmode == Inkscape::FOR_FILL ? "Fill" : "Stroke") << std::endl;
#endif
                    SPGradient *vector = sp_gradient_vector_for_object(sp_desktop_document(desktop), desktop, item, fsmode);

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

                DocumentUndo::done(sp_desktop_document (desktop), SP_VERB_CONTEXT_MESH,
                                   _("Create default mesh"));
            }
            ret = TRUE;
        }
        break;

    case GDK_BUTTON_PRESS:

#ifdef DEBUG_MESH
        std::cout << "sp_mesh_context_root_handler: GDK_BUTTON_PRESS" << std::endl;
#endif
        // Button down
        //  If Shift key down: do rubber band selection
        //  Else set origin for drag. A drag creates a new gradient if one does not exist
 
        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 = desktop->w2d(button_w);
            if (event->button.state & GDK_SHIFT_MASK) {
                Inkscape::Rubberband::get(desktop)->start(desktop, 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);

                if (!selection->isEmpty()) {
                    SnapManager &m = desktop->namedview->snap_manager;
                    m.setup(desktop);
                    m.freeSnapReturnByRef(button_dt, Inkscape::SNAPSOURCE_NODE_HANDLE);
                    m.unSetup();
                }
                rc->origin = button_dt;
            }

            ret = TRUE;
        }
        break;

    case GDK_MOTION_NOTIFY:

        // Mouse move

        if ( dragging
             && ( event->motion.state & GDK_BUTTON1_MASK ) && !event_context->space_panning )
        {
 
#ifdef DEBUG_MESH
            std::cout << "sp_mesh_context_root_handler: GDK_MOTION_NOTIFY: Dragging" << std::endl;
#endif
            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 {
                // Create new gradient with coordinates determined by drag.
                sp_mesh_drag(*rc, motion_dt, event->motion.state, event->motion.time);
            }
            gobble_motion_events(GDK_BUTTON1_MASK);

            ret = TRUE;

        } else {
            // Not dragging

            // Do snapping
            if (!drag->mouseOver() && !selection->isEmpty()) {
                SnapManager &m = desktop->namedview->snap_manager;
                m.setup(desktop);

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

                m.preSnap(Inkscape::SnapCandidatePoint(motion_dt, Inkscape::SNAPSOURCE_OTHER_HANDLE));
                m.unSetup();
            }

            // Highlight corner node corresponding to side or tensor node
            if( drag->mouseOver() ) {
                // MESH FIXME: Light up corresponding corner node corresponding to node we are over.
                // See "pathflash" in ui/tools/node-tool.cpp for ideas.
                // Use desktop->add_temporary_canvasitem( SPCanvasItem, milliseconds );
            }

            // Change cursor shape if over line
            bool over_line = false;
            if (drag->lines) {
                for (GSList *l = drag->lines; l != NULL; l = l->next) {
                    over_line |= sp_mesh_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:

#ifdef DEBUG_MESH
        std::cout << "sp_mesh_context_root_handler: GDK_BUTTON_RELEASE" << std::endl;
#endif

        event_context->xp = event_context->yp = 0;
        if ( event->button.button == 1 && !event_context->space_panning ) {

            // Check if over line
            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_mesh_context_is_over_line (rc, (SPItem*) line, Geom::Point(event->motion.x, event->motion.y));
                    if (over_line)
                        break;
                }
            }

            if ( (event->button.state & GDK_CONTROL_MASK) && (event->button.state & GDK_MOD1_MASK ) ) {
                if (over_line && line) {
                    sp_mesh_context_split_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 *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) {
                    if (over_line && line) {
                        // Clicked on an existing mesh line, don't change selection. This stops
                        // possible change in selection during a double click with overlapping objects
                    }
                    else {
                        // 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:

#ifdef DEBUG_MESH
        std::cout << "sp_mesh_context_root_handler: GDK_KEY_PRESS" << std::endl;
#endif

        // FIXME: tip
        switch (get_group0_keyval (&event->key)) {
        case GDK_KEY_Alt_L:
        case GDK_KEY_Alt_R:
        case GDK_KEY_Control_L:
        case GDK_KEY_Control_R:
        case GDK_KEY_Shift_L:
        case GDK_KEY_Shift_R:
        case GDK_KEY_Meta_L:  // Meta is when you press Shift+Alt (at least on my machine)
        case GDK_KEY_Meta_R:
            sp_event_show_modifier_tip (event_context->defaultMessageContext(), event,
                                        _("FIXME<b>Ctrl</b>: snap mesh angle"),
                                        _("FIXME<b>Shift</b>: draw mesh around the starting point"),
                                        NULL);
            break;

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

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

        case GDK_KEY_Left: // move handle left
        case GDK_KEY_KP_Left:
        case GDK_KEY_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_KEY_Up: // move handle up
        case GDK_KEY_KP_Up:
        case GDK_KEY_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_KEY_Right: // move handle right
        case GDK_KEY_KP_Right:
        case GDK_KEY_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_KEY_Down: // move handle down
        case GDK_KEY_KP_Down:
        case GDK_KEY_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_KEY_Insert:
        case GDK_KEY_KP_Insert:
            // with any modifiers:
            //sp_gradient_context_add_stops_between_selected_stops (rc);
            std::cout << "Inserting stops between selected stops not implemented yet" << std::endl;
            ret = TRUE;
            break;

        case GDK_KEY_Delete:
        case GDK_KEY_KP_Delete:
        case GDK_KEY_BackSpace:
            if ( drag->selected ) {
                std::cout << "Deleting mesh stops not implemented yet" << std::endl;
                ret = TRUE;
            }
            break;

        // Mesh Operations --------------------------------------------

        case GDK_KEY_b:  // Toggle mesh side between lineto and curveto.
        case GDK_KEY_B: 
            if (MOD__ALT && drag->isNonEmpty() && drag->hasSelection()) {
                sp_mesh_context_corner_operation ( rc, MG_CORNER_SIDE_TOGGLE );
                ret = TRUE;
            }
            break;

        case GDK_KEY_c:  // Convert mesh side from generic Bezier to Bezier approximating arc,
        case GDK_KEY_C:  // preserving handle direction.
            if (MOD__ALT && drag->isNonEmpty() && drag->hasSelection()) {
                sp_mesh_context_corner_operation ( rc, MG_CORNER_SIDE_ARC );
                ret = TRUE;
            }
            break;

        case GDK_KEY_g:  // Toggle mesh tensor points on/off
        case GDK_KEY_G: 
            if (MOD__ALT && drag->isNonEmpty() && drag->hasSelection()) {
                sp_mesh_context_corner_operation ( rc, MG_CORNER_TENSOR_TOGGLE );
                ret = TRUE;
            }
            break;

        case GDK_KEY_j:  // Smooth corner color
        case GDK_KEY_J:
            if (MOD__ALT && drag->isNonEmpty() && drag->hasSelection()) {
                sp_mesh_context_corner_operation ( rc, MG_CORNER_COLOR_SMOOTH );
                ret = TRUE;
            }
            break;

        case GDK_KEY_k:  // Pick corner color
        case GDK_KEY_K:
            if (MOD__ALT && drag->isNonEmpty() && drag->hasSelection()) {
                sp_mesh_context_corner_operation ( rc, MG_CORNER_COLOR_PICK );
                ret = TRUE;
            }
            break;

        default:
            break;
        }

        break;

    case GDK_KEY_RELEASE:

#ifdef DEBUG_MESH
        std::cout << "sp_mesh_context_root_handler: GDK_KEY_RELEASE" << std::endl;
#endif
        switch (get_group0_keyval (&event->key)) {
        case GDK_KEY_Alt_L:
        case GDK_KEY_Alt_R:
        case GDK_KEY_Control_L:
        case GDK_KEY_Control_R:
        case GDK_KEY_Shift_L:
        case GDK_KEY_Shift_R:
        case GDK_KEY_Meta_L:  // Meta is when you press Shift+Alt
        case GDK_KEY_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;
}
Пример #16
0
cmsHTRANSFORM Inkscape::CMSSystem::getDisplayTransform()
{
    Inkscape::Preferences *prefs = Inkscape::Preferences::get();
    bool fromDisplay = prefs->getBool( "/options/displayprofile/from_display");
    if ( fromDisplay ) {
        if ( transf ) {
            cmsDeleteTransform(transf);
            transf = 0;
        }
        return 0;
    }

    bool warn = prefs->getBool( "/options/softproof/gamutwarn");
    int intent = prefs->getIntLimited( "/options/displayprofile/intent", 0, 0, 3 );
    int proofIntent = prefs->getIntLimited( "/options/softproof/intent", 0, 0, 3 );
    bool bpc = prefs->getBool( "/options/softproof/bpc");
#if defined(cmsFLAGS_PRESERVEBLACK)
    bool preserveBlack = prefs->getBool( "/options/softproof/preserveblack");
#endif //defined(cmsFLAGS_PRESERVEBLACK)
    Glib::ustring colorStr = prefs->getString("/options/softproof/gamutcolor");

#if WITH_GTKMM_3_0
    Gdk::RGBA gamutColor( colorStr.empty() ? "#808080" : colorStr );
#else
    Gdk::Color gamutColor( colorStr.empty() ? "#808080" : colorStr );
#endif

    if ( (warn != gamutWarn)
            || (lastIntent != intent)
            || (lastProofIntent != proofIntent)
            || (bpc != lastBPC)
#if defined(cmsFLAGS_PRESERVEBLACK)
            || (preserveBlack != lastPreserveBlack)
#endif // defined(cmsFLAGS_PRESERVEBLACK)
            || (gamutColor != lastGamutColor)
       ) {
        gamutWarn = warn;
        free_transforms();
        lastIntent = intent;
        lastProofIntent = proofIntent;
        lastBPC = bpc;
#if defined(cmsFLAGS_PRESERVEBLACK)
        lastPreserveBlack = preserveBlack;
#endif // defined(cmsFLAGS_PRESERVEBLACK)
        lastGamutColor = gamutColor;
    }

    // Fetch these now, as they might clear the transform as a side effect.
    cmsHPROFILE hprof = getSystemProfileHandle();
    cmsHPROFILE proofProf = hprof ? getProofProfileHandle() : 0;

    if ( !transf ) {
        if ( hprof && proofProf ) {
            cmsUInt32Number dwFlags = cmsFLAGS_SOFTPROOFING;
            if ( gamutWarn ) {
                dwFlags |= cmsFLAGS_GAMUTCHECK;

#if WITH_GTKMM_3_0
                gushort gamutColor_r = gamutColor.get_red_u();
                gushort gamutColor_g = gamutColor.get_green_u();
                gushort gamutColor_b = gamutColor.get_blue_u();
#else
                gushort gamutColor_r = gamutColor.get_red();
                gushort gamutColor_g = gamutColor.get_green();
                gushort gamutColor_b = gamutColor.get_blue();
#endif

#if HAVE_LIBLCMS1
                cmsSetAlarmCodes(gamutColor_r >> 8, gamutColor_g >> 8, gamutColor_b >> 8);
#elif HAVE_LIBLCMS2
                cmsUInt16Number newAlarmCodes[cmsMAXCHANNELS] = {0};
                newAlarmCodes[0] = gamutColor_r;
                newAlarmCodes[1] = gamutColor_g;
                newAlarmCodes[2] = gamutColor_b;
                newAlarmCodes[3] = ~0;
                cmsSetAlarmCodes(newAlarmCodes);
#endif
            }
            if ( bpc ) {
                dwFlags |= cmsFLAGS_BLACKPOINTCOMPENSATION;
            }
#if defined(cmsFLAGS_PRESERVEBLACK)
            if ( preserveBlack ) {
                dwFlags |= cmsFLAGS_PRESERVEBLACK;
            }
#endif // defined(cmsFLAGS_PRESERVEBLACK)
            transf = cmsCreateProofingTransform( ColorProfileImpl::getSRGBProfile(), TYPE_BGRA_8, hprof, TYPE_BGRA_8, proofProf, intent, proofIntent, dwFlags );
        } else if ( hprof ) {
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;
}
Пример #18
0
static gint sp_dt_ruler_event(GtkWidget *widget, GdkEvent *event, SPDesktopWidget *dtw, bool horiz)
{
    static bool clicked = false;
    static bool dragged = false;
    static SPCanvasItem *guide = NULL;
    static Geom::Point normal;
    int wx, wy;
    static gint xp = 0, yp = 0; // where drag started

    SPDesktop *desktop = dtw->desktop;
    GdkWindow *window = gtk_widget_get_window(GTK_WIDGET(dtw->canvas));

    gint width, height;

#if GTK_CHECK_VERSION(3,0,0)
    GdkDevice *device = gdk_event_get_device(event);
    gdk_window_get_device_position(window, device, &wx, &wy, NULL);
    gdk_window_get_geometry(window, NULL /*x*/, NULL /*y*/, &width, &height);
#else
    gdk_window_get_pointer(window, &wx, &wy, NULL);
    gdk_window_get_geometry(window, NULL /*x*/, NULL /*y*/, &width, &height, NULL/*depth*/);
#endif
    
    Geom::Point const event_win(wx, wy);

    switch (event->type) {
    case GDK_BUTTON_PRESS:
            if (event->button.button == 1) {
                clicked = true;
                dragged = false;
                // save click origin
                xp = (gint) event->button.x;
                yp = (gint) event->button.y;

                Geom::Point const event_w(sp_canvas_window_to_world(dtw->canvas, event_win));
                Geom::Point const event_dt(desktop->w2d(event_w));

                // calculate the normal of the guidelines when dragged from the edges of rulers.
                Geom::Point normal_bl_to_tr(-1.,1.); //bottomleft to topright
                Geom::Point normal_tr_to_bl(1.,1.); //topright to bottomleft
                normal_bl_to_tr.normalize();
                normal_tr_to_bl.normalize();
                Inkscape::CanvasGrid * grid = sp_namedview_get_first_enabled_grid(desktop->namedview);
                if (grid){
                    if (grid->getGridType() == Inkscape::GRID_AXONOMETRIC ) {
                        Inkscape::CanvasAxonomGrid *axonomgrid = dynamic_cast<Inkscape::CanvasAxonomGrid *>(grid);
                        if (event->button.state & GDK_CONTROL_MASK) {
                            // guidelines normal to gridlines
                            normal_bl_to_tr = Geom::Point::polar(-axonomgrid->angle_rad[0], 1.0);
                            normal_tr_to_bl = Geom::Point::polar(axonomgrid->angle_rad[2], 1.0);
                        } else {
                            normal_bl_to_tr = rot90(Geom::Point::polar(axonomgrid->angle_rad[2], 1.0));
                            normal_tr_to_bl = rot90(Geom::Point::polar(-axonomgrid->angle_rad[0], 1.0));
                        }
                    }
                }
                if (horiz) {
                    if (wx < 50) {
                        normal = normal_bl_to_tr;
                    } else if (wx > width - 50) {
                        normal = normal_tr_to_bl;
                    } else {
                        normal = Geom::Point(0.,1.);
                    }
                } else {
                    if (wy < 50) {
                        normal = normal_bl_to_tr;
                    } else if (wy > height - 50) {
                        normal = normal_tr_to_bl;
                    } else {
                        normal = Geom::Point(1.,0.);
                    }
                }

                guide = sp_guideline_new(desktop->guides, NULL, event_dt, normal);
                sp_guideline_set_color(SP_GUIDELINE(guide), desktop->namedview->guidehicolor);

#if GTK_CHECK_VERSION(3,0,0)
                gdk_device_grab(device,
                                gtk_widget_get_window(widget), 
                                GDK_OWNERSHIP_NONE,
                                FALSE,
                                (GdkEventMask)(GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK ),
                                NULL,
                                event->button.time);
#else
                gdk_pointer_grab(gtk_widget_get_window (widget), FALSE,
                                 (GdkEventMask)(GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK ),
                                 NULL, NULL,
                                 event->button.time);
#endif
            }
            break;
    case GDK_MOTION_NOTIFY:
            if (clicked) {
                Geom::Point const event_w(sp_canvas_window_to_world(dtw->canvas, event_win));
                Geom::Point event_dt(desktop->w2d(event_w));

                Inkscape::Preferences *prefs = Inkscape::Preferences::get();
                gint tolerance = prefs->getIntLimited("/options/dragtolerance/value", 0, 0, 100);
                if ( ( abs( (gint) event->motion.x - xp ) < tolerance )
                        && ( abs( (gint) event->motion.y - yp ) < tolerance ) ) {
                    break;
                }

                dragged = true;

                // explicitly show guidelines; if I draw a guide, I want them on
                if ((horiz ? wy : wx) >= 0) {
                    desktop->namedview->setGuides(true);
                }

                if (!(event->motion.state & GDK_SHIFT_MASK)) {
                    sp_dt_ruler_snap_new_guide(desktop, guide, event_dt, normal);
                }
                sp_guideline_set_normal(SP_GUIDELINE(guide), normal);
                sp_guideline_set_position(SP_GUIDELINE(guide), event_dt);

                desktop->set_coordinate_status(event_dt);
            }
            break;
    case GDK_BUTTON_RELEASE:
            if (clicked && event->button.button == 1) {
                sp_event_context_discard_delayed_snap_event(desktop->event_context);

#if GTK_CHECK_VERSION(3,0,0)
                gdk_device_ungrab(device, event->button.time);
#else
                gdk_pointer_ungrab(event->button.time);
#endif

                Geom::Point const event_w(sp_canvas_window_to_world(dtw->canvas, event_win));
                Geom::Point event_dt(desktop->w2d(event_w));

                if (!(event->button.state & GDK_SHIFT_MASK)) {
                    sp_dt_ruler_snap_new_guide(desktop, guide, event_dt, normal);
                }

                sp_canvas_item_destroy(guide);
                guide = NULL;
                if ((horiz ? wy : wx) >= 0) {
                    Inkscape::XML::Document *xml_doc = desktop->doc()->getReprDoc();
                    Inkscape::XML::Node *repr = xml_doc->createElement("sodipodi:guide");

                    // If root viewBox set, interpret guides in terms of viewBox (90/96)
                    double newx = event_dt.x();
                    double newy = event_dt.y();

                    SPRoot *root = desktop->doc()->getRoot();
                    if( root->viewBox_set ) {
                        newx = newx * root->viewBox.width()  / root->width.computed;
                        newy = newy * root->viewBox.height() / root->height.computed;
                    }
                    sp_repr_set_point(repr, "position", Geom::Point( newx, newy ));
                    sp_repr_set_point(repr, "orientation", normal);
                    desktop->namedview->appendChild(repr);
                    Inkscape::GC::release(repr);
                    DocumentUndo::done(desktop->getDocument(), SP_VERB_NONE,
                                     _("Create guide"));
                }
                desktop->set_coordinate_status(event_dt);

                if (!dragged) {
                    // Ruler click (without drag) toggle the guide visibility on and off
                    Inkscape::XML::Node *repr = desktop->namedview->getRepr();
                    sp_namedview_toggle_guides(desktop->getDocument(), repr);
                    
                }

                clicked = false;
                dragged = false;
            }
    default:
            break;
    }

    return FALSE;
}
Пример #19
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;
}
Пример #20
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;
}
Пример #21
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;
}
Пример #22
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;
}