Logo Search packages:      
Sourcecode: inkscape version File versions  Download package

static gint pen_handle_button_press ( SPPenContext *const   pc,
GdkEventButton const &  bevent 
) [static]

Handle mouse button press event.

Definition at line 412 of file pen-context.cpp.

References Inkscape::GC::anchor(), Inkscape::Selection::clear(), Inkscape::MessageStack::flash(), SnapManager::freeSnapReturnByRef(), Inkscape::have_viable_layer(), Inkscape::UI::View::View::messageStack(), SPPenContext::npoints, SnapManager::setup(), Inkscape::Selection::singleItem(), sp_canvas_item_grab(), sp_draw_anchor_new(), spdc_endpoint_snap(), and spdc_pen_finish_segment().

Referenced by sp_pen_context_root_handler().

{
    if (pc->events_disabled) {
        // skip event processing if events are disabled
        return FALSE;
    }

    SPDrawContext * const dc = SP_DRAW_CONTEXT(pc);
    SPDesktop * const desktop = SP_EVENT_CONTEXT_DESKTOP(dc);
    Geom::Point const event_w(bevent.x, bevent.y);
    Geom::Point event_dt(desktop->w2d(event_w));
    SPEventContext *event_context = SP_EVENT_CONTEXT(pc);

    gint ret = FALSE;
    if (bevent.button == 1 && !event_context->space_panning
        // make sure this is not the last click for a waiting LPE (otherwise we want to finish the path)
        && pc->expecting_clicks_for_LPE != 1) {

        if (Inkscape::have_viable_layer(desktop, dc->_message_context) == false) {
            return TRUE;
        }

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

        pen_drag_origin_w = event_w;
        pen_within_tolerance = true;

        /* Test whether we hit any anchor. */
        SPDrawAnchor * const anchor = spdc_test_inside(pc, event_w);

        switch (pc->mode) {
            case SP_PEN_CONTEXT_MODE_CLICK:
                /* In click mode we add point on release */
                switch (pc->state) {
                    case SP_PEN_CONTEXT_POINT:
                    case SP_PEN_CONTEXT_CONTROL:
                    case SP_PEN_CONTEXT_CLOSE:
                        break;
                    case SP_PEN_CONTEXT_STOP:
                        /* This is allowed, if we just canceled curve */
                        pc->state = SP_PEN_CONTEXT_POINT;
                        break;
                    default:
                        break;
                }
                break;
            case SP_PEN_CONTEXT_MODE_DRAG:
                switch (pc->state) {
                    case SP_PEN_CONTEXT_STOP:
                        /* This is allowed, if we just canceled curve */
                    case SP_PEN_CONTEXT_POINT:
                        if (pc->npoints == 0) {

                            Geom::Point p;
                            if ((bevent.state & GDK_CONTROL_MASK) && (pc->polylines_only || pc->polylines_paraxial)) {
                                p = event_dt;
                                if (!(bevent.state & GDK_SHIFT_MASK)) {
                                    SnapManager &m = desktop->namedview->snap_manager;
                                    m.setup(desktop);
                                    m.freeSnapReturnByRef(p, Inkscape::SNAPSOURCE_NODE_HANDLE);
                                }
                              spdc_create_single_dot(event_context, p, "/tools/freehand/pen", bevent.state);
                              ret = TRUE;
                              break;
                            }

                            // TODO: Perhaps it would be nicer to rearrange the following case
                            // distinction so that the case of a waiting LPE is treated separately

                            /* Set start anchor */
                            pc->sa = anchor;
                            if (anchor && !sp_pen_context_has_waiting_LPE(pc)) {
                                /* Adjust point to anchor if needed; if we have a waiting LPE, we need
                                   a fresh path to be created so don't continue an existing one */
                                p = anchor->dp;
                                desktop->messageStack()->flash(Inkscape::NORMAL_MESSAGE, _("Continuing selected path"));
                            } else {
                                // This is the first click of a new curve; deselect item so that
                                // this curve is not combined with it (unless it is drawn from its
                                // anchor, which is handled by the sibling branch above)
                                Inkscape::Selection * const selection = sp_desktop_selection(desktop);
                                if (!(bevent.state & GDK_SHIFT_MASK) || sp_pen_context_has_waiting_LPE(pc)) {
                                    /* if we have a waiting LPE, we need a fresh path to be created
                                       so don't append to an existing one */
                                    selection->clear();
                                    desktop->messageStack()->flash(Inkscape::NORMAL_MESSAGE, _("Creating new path"));
                                } else if (selection->singleItem() && SP_IS_PATH(selection->singleItem())) {
                                    desktop->messageStack()->flash(Inkscape::NORMAL_MESSAGE, _("Appending to selected path"));
                                }

                                /* Create green anchor */
                                p = event_dt;
                                spdc_endpoint_snap(pc, p, bevent.state);
                                pc->green_anchor = sp_draw_anchor_new(pc, pc->green_curve, TRUE, p);
                            }
                            spdc_pen_set_initial_point(pc, p);
                        } else {

                            /* Set end anchor */
                            pc->ea = anchor;
                            Geom::Point p;
                            if (anchor) {
                                p = anchor->dp;
                                // we hit an anchor, will finish the curve (either with or without closing)
                                // in release handler
                                pc->state = SP_PEN_CONTEXT_CLOSE;

                                if (pc->green_anchor && pc->green_anchor->active) {
                                    // we clicked on the current curve start, so close it even if
                                    // we drag a handle away from it
                                    dc->green_closed = TRUE;
                                }
                                ret = TRUE;
                                break;

                            } else {
                                p = event_dt;
                                spdc_endpoint_snap(pc, p, bevent.state); /* Snap node only if not hitting anchor. */
                                spdc_pen_set_subsequent_point(pc, p, true);
                            }
                        }

                        pc->state = pc->polylines_only ? SP_PEN_CONTEXT_POINT : SP_PEN_CONTEXT_CONTROL;
                        ret = TRUE;
                        break;
                    case SP_PEN_CONTEXT_CONTROL:
                        g_warning("Button down in CONTROL state");
                        break;
                    case SP_PEN_CONTEXT_CLOSE:
                        g_warning("Button down in CLOSE state");
                        break;
                    default:
                        break;
                }
                break;
            default:
                break;
        }
    } else if (pc->expecting_clicks_for_LPE == 1 && pc->npoints != 0) {
        // when the last click for a waiting LPE occurs we want to finish the path
        spdc_pen_finish_segment(pc, event_dt, bevent.state);
        if (pc->green_closed) {
            // finishing at the start anchor, close curve
            spdc_pen_finish(pc, TRUE);
        } else {
            // finishing at some other anchor, finish curve but not close
            spdc_pen_finish(pc, FALSE);
        }

        ret = TRUE;
    } else if (bevent.button == 3 && pc->npoints != 0) {
        // right click - finish path
        spdc_pen_finish(pc, FALSE);
        ret = TRUE;
    }

    if (pc->expecting_clicks_for_LPE > 0) {
        --pc->expecting_clicks_for_LPE;
    }

    return ret;
}

Here is the call graph for this function:

Here is the caller graph for this function:


Generated by  Doxygen 1.6.0   Back to index