static void spdc_pen_finish (SPPenContext *pc, gboolean closed) { SPDrawContext *dc; dc = SP_DRAW_CONTEXT (pc); g_print ("Finishing pen\n"); sp_curve_reset (dc->red_curve); spdc_concat_colors_and_flush (dc, closed); dc->sa = NULL; dc->ea = NULL; dc->npoints = 0; pc->state = SP_PEN_CONTEXT_POINT; sp_canvas_item_hide (pc->c0); sp_canvas_item_hide (pc->c1); sp_canvas_item_hide (pc->cl0); sp_canvas_item_hide (pc->cl1); if (dc->green_anchor) { dc->green_anchor = sp_draw_anchor_destroy (dc->green_anchor); } }
static void sp_pen_context_setup (SPEventContext *ec) { SPPenContext *pc; pc = SP_PEN_CONTEXT (ec); if (((SPEventContextClass *) pen_parent_class)->setup) ((SPEventContextClass *) pen_parent_class)->setup (ec); /* Pen indicators */ pc->c0 = sp_canvas_item_new (SP_DT_CONTROLS (SP_EVENT_CONTEXT_DESKTOP (ec)), SP_TYPE_CTRL, "shape", SP_CTRL_SHAPE_CIRCLE, "size", 4.0, "filled", 0, "fill_color", 0xff00007f, "stroked", 1, "stroke_color", 0x0000ff7f, NULL); pc->c1 = sp_canvas_item_new (SP_DT_CONTROLS (SP_EVENT_CONTEXT_DESKTOP (ec)), SP_TYPE_CTRL, "shape", SP_CTRL_SHAPE_CIRCLE, "size", 4.0, "filled", 0, "fill_color", 0xff00007f, "stroked", 1, "stroke_color", 0x0000ff7f, NULL); pc->cl0 = sp_canvas_item_new (SP_DT_CONTROLS (SP_EVENT_CONTEXT_DESKTOP (ec)), SP_TYPE_CTRLLINE, NULL); sp_ctrlline_set_rgba32 (SP_CTRLLINE (pc->cl0), 0x0000007f); pc->cl1 = sp_canvas_item_new (SP_DT_CONTROLS (SP_EVENT_CONTEXT_DESKTOP (ec)), SP_TYPE_CTRLLINE, NULL); sp_ctrlline_set_rgba32 (SP_CTRLLINE (pc->cl1), 0x0000007f); sp_canvas_item_hide (pc->c0); sp_canvas_item_hide (pc->c1); sp_canvas_item_hide (pc->cl0); sp_canvas_item_hide (pc->cl1); sp_event_context_read (ec, "mode"); }
static void sp_dropper_context_setup(SPEventContext *ec) { SPDropperContext *dc = SP_DROPPER_CONTEXT(ec); if (((SPEventContextClass *) parent_class)->setup) { ((SPEventContextClass *) parent_class)->setup(ec); } /* TODO: have a look at sp_dyna_draw_context_setup where the same is done.. generalize? at least make it an arcto! */ SPCurve *c = new SPCurve(); const double C1 = 0.552; c->moveto(-1,0); c->curveto(-1, C1, -C1, 1, 0, 1 ); c->curveto(C1, 1, 1, C1, 1, 0 ); c->curveto(1, -C1, C1, -1, 0, -1 ); c->curveto(-C1, -1, -1, -C1, -1, 0 ); c->closepath(); dc->area = sp_canvas_bpath_new(sp_desktop_controls(ec->desktop), c); c->unref(); sp_canvas_bpath_set_fill(SP_CANVAS_BPATH(dc->area), 0x00000000,(SPWindRule)0); sp_canvas_bpath_set_stroke(SP_CANVAS_BPATH(dc->area), 0x0000007f, 1.0, SP_STROKE_LINEJOIN_MITER, SP_STROKE_LINECAP_BUTT); sp_canvas_item_hide(dc->area); Inkscape::Preferences *prefs = Inkscape::Preferences::get(); if (prefs->getBool("/tools/dropper/selcue")) { ec->enableSelectionCue(); } if (prefs->getBool("/tools/dropper/gradientdrag")) { ec->enableGrDrag(); } }
/** * Set flag in knot, with side effects. */ void sp_knot_set_flag(SPKnot *knot, guint flag, bool set) { g_assert(knot != NULL); g_assert(SP_IS_KNOT(knot)); if (set) { knot->flags |= flag; } else { knot->flags &= ~flag; } switch (flag) { case SP_KNOT_VISIBLE: if (set) { sp_canvas_item_show(knot->item); } else { sp_canvas_item_hide(knot->item); } break; case SP_KNOT_MOUSEOVER: case SP_KNOT_DRAGGING: sp_knot_set_ctrl_state(knot); break; case SP_KNOT_GRABBED: break; default: g_assert_not_reached(); break; } }
void Inkscape::Rubberband::move(Geom::Point const &p) { if (!_started) return; _end = p; _desktop->scroll_to_point(p); _touchpath_curve->lineto(p); Geom::Point next = _desktop->d2w(p); // we want the points to be at most 0.5 screen pixels apart, // so that we don't lose anything small; // if they are farther apart, we interpolate more points if (_points.size() > 0 && Geom::L2(next-_points.back()) > 0.5) { Geom::Point prev = _points.back(); int subdiv = 2 * (int) round(Geom::L2(next-prev) + 0.5); for (int i = 1; i <= subdiv; i ++) { _points.push_back(prev + ((double)i/subdiv) * (next - prev)); } } else { _points.push_back(next); } if (_mode == RUBBERBAND_MODE_RECT) { if (_rect == NULL) { _rect = static_cast<CtrlRect *>(sp_canvas_item_new(sp_desktop_controls(_desktop), SP_TYPE_CTRLRECT, NULL)); } _rect->setRectangle(Geom::Rect(_start, _end)); sp_canvas_item_show(_rect); if (_touchpath) sp_canvas_item_hide(_touchpath); } else if (_mode == RUBBERBAND_MODE_TOUCHPATH) { if (_touchpath == NULL) { _touchpath = sp_canvas_bpath_new(sp_desktop_sketch(_desktop), NULL); sp_canvas_bpath_set_stroke(SP_CANVAS_BPATH(_touchpath), 0xff0000ff, 1.0, SP_STROKE_LINEJOIN_MITER, SP_STROKE_LINECAP_BUTT); sp_canvas_bpath_set_fill(SP_CANVAS_BPATH(_touchpath), 0, SP_WIND_RULE_NONZERO); } sp_canvas_bpath_set_bpath(SP_CANVAS_BPATH(_touchpath), _touchpath_curve); sp_canvas_item_show(_touchpath); if (_rect) sp_canvas_item_hide(_rect); } }
virtual bool _eventHandler(SPEventContext *event_context, GdkEvent *event) { if (event->type == GDK_KEY_PRESS && shortcut_key(event->key) == GDK_Escape && sp_canvas_item_is_visible(_rubber)) { _cancel = true; sp_canvas_item_hide(_rubber); return true; } return ControlPoint::_eventHandler(event_context, event); }
SelectorPoint(SPDesktop *d, SPCanvasGroup *group, Selector *s) : ControlPoint(d, Geom::Point(0,0), Gtk::ANCHOR_CENTER, SP_CTRL_SHAPE_SQUARE, 1, &invisible_cset, group) , _selector(s) , _cancel(false) { setVisible(false); _rubber = static_cast<CtrlRect*>(sp_canvas_item_new(sp_desktop_controls(_desktop), SP_TYPE_CTRLRECT, NULL)); sp_canvas_item_hide(_rubber); }
static void spdc_pen_set_ctrl (SPPenContext *pc, NRPointF *p, guint state) { SPDrawContext *dc; dc = SP_DRAW_CONTEXT (pc); sp_canvas_item_show (pc->c1); sp_canvas_item_show (pc->cl1); if (dc->npoints == 2) { dc->p[1] = *p; sp_canvas_item_hide (pc->c0); sp_canvas_item_hide (pc->cl0); sp_ctrl_moveto (SP_CTRL (pc->c1), dc->p[1].x, dc->p[1].y); sp_ctrlline_set_coords (SP_CTRLLINE (pc->cl1), dc->p[0].x, dc->p[0].y, dc->p[1].x, dc->p[1].y); } else if (dc->npoints == 5) { dc->p[4] = *p; sp_canvas_item_show (pc->c0); sp_canvas_item_show (pc->cl0); if (((pc->mode == SP_PEN_CONTEXT_MODE_CLICK) && (state & GDK_CONTROL_MASK)) || ((pc->mode == SP_PEN_CONTEXT_MODE_DRAG) && !(state & GDK_MOD1_MASK))) { gdouble dx, dy; dx = p->x - dc->p[3].x; dy = p->y - dc->p[3].y; dc->p[2].x = dc->p[3].x - dx; dc->p[2].y = dc->p[3].y - dy; sp_curve_reset (dc->red_curve); sp_curve_moveto (dc->red_curve, dc->p[0].x, dc->p[0].y); sp_curve_curveto (dc->red_curve, dc->p[1].x, dc->p[1].y, dc->p[2].x, dc->p[2].y, dc->p[3].x, dc->p[3].y); sp_canvas_bpath_set_bpath (SP_CANVAS_BPATH (dc->red_bpath), dc->red_curve); } sp_ctrl_moveto (SP_CTRL (pc->c0), dc->p[2].x, dc->p[2].y); sp_ctrlline_set_coords (SP_CTRLLINE (pc->cl0), dc->p[3].x, dc->p[3].y, dc->p[2].x, dc->p[2].y); sp_ctrl_moveto (SP_CTRL (pc->c1), dc->p[4].x, dc->p[4].y); sp_ctrlline_set_coords (SP_CTRLLINE (pc->cl1), dc->p[3].x, dc->p[3].y, dc->p[4].x, dc->p[4].y); } else { g_warning ("Something bad happened - npoints is %d", dc->npoints); } }
static gint sp_dropper_context_root_handler(SPEventContext *event_context, GdkEvent *event) { SPDropperContext *dc = (SPDropperContext *) event_context; int ret = FALSE; SPDesktop *desktop = event_context->desktop; Inkscape::Preferences *prefs = Inkscape::Preferences::get(); int pick = prefs->getInt("/tools/dropper/pick", SP_DROPPER_PICK_VISIBLE); bool setalpha = prefs->getBool("/tools/dropper/setalpha", true); switch (event->type) { case GDK_BUTTON_PRESS: if (event->button.button == 1 && !event_context->space_panning) { dc->centre = Geom::Point(event->button.x, event->button.y); dc->dragging = TRUE; ret = TRUE; } break; case GDK_MOTION_NOTIFY: if (event->motion.state & GDK_BUTTON2_MASK) { // pass on middle-drag ret = FALSE; break; } else if (!event_context->space_panning) { // otherwise, constantly calculate color no matter is any button pressed or not double rw = 0.0; double W(0), R(0), G(0), B(0), A(0); if (dc->dragging) { // calculate average // radius rw = std::min(Geom::L2(Geom::Point(event->button.x, event->button.y) - dc->centre), 400.0); if (rw == 0) { // happens sometimes, little idea why... break; } Geom::Point const cd = desktop->w2d(dc->centre); Geom::Matrix const w2dt = desktop->w2d(); const double scale = rw * w2dt.descrim(); Geom::Matrix const sm( Geom::Scale(scale, scale) * Geom::Translate(cd) ); sp_canvas_item_affine_absolute(dc->area, sm); sp_canvas_item_show(dc->area); /* Get buffer */ const int x0 = (int) floor(dc->centre[Geom::X] - rw); const int y0 = (int) floor(dc->centre[Geom::Y] - rw); const int x1 = (int) ceil(dc->centre[Geom::X] + rw); const int y1 = (int) ceil(dc->centre[Geom::Y] + rw); if ((x1 > x0) && (y1 > y0)) { NRPixBlock pb; nr_pixblock_setup_fast(&pb, NR_PIXBLOCK_MODE_R8G8B8A8P, x0, y0, x1, y1, TRUE); /* fixme: (Lauris) */ sp_canvas_arena_render_pixblock(SP_CANVAS_ARENA(sp_desktop_drawing(desktop)), &pb); for (int y = y0; y < y1; y++) { const unsigned char *s = NR_PIXBLOCK_PX(&pb) + (y - y0) * pb.rs; for (int x = x0; x < x1; x++) { const double dx = x - dc->centre[Geom::X]; const double dy = y - dc->centre[Geom::Y]; const double w = exp(-((dx * dx) + (dy * dy)) / (rw * rw)); W += w; R += w * s[0]; G += w * s[1]; B += w * s[2]; A += w * s[3]; s += 4; } } nr_pixblock_release(&pb); R = (R + 0.001) / (255.0 * W); G = (G + 0.001) / (255.0 * W); B = (B + 0.001) / (255.0 * W); A = (A + 0.001) / (255.0 * W); R = CLAMP(R, 0.0, 1.0); G = CLAMP(G, 0.0, 1.0); B = CLAMP(B, 0.0, 1.0); A = CLAMP(A, 0.0, 1.0); } } else { // pick single pixel NRPixBlock pb; int x = (int) floor(event->button.x); int y = (int) floor(event->button.y); nr_pixblock_setup_fast(&pb, NR_PIXBLOCK_MODE_R8G8B8A8P, x, y, x+1, y+1, TRUE); sp_canvas_arena_render_pixblock(SP_CANVAS_ARENA(sp_desktop_drawing(desktop)), &pb); const unsigned char *s = NR_PIXBLOCK_PX(&pb); R = s[0] / 255.0; G = s[1] / 255.0; B = s[2] / 255.0; A = s[3] / 255.0; } if (pick == SP_DROPPER_PICK_VISIBLE) { // compose with page color guint32 bg = sp_desktop_namedview(desktop)->pagecolor; R = R + (SP_RGBA32_R_F(bg)) * (1 - A); G = G + (SP_RGBA32_G_F(bg)) * (1 - A); B = B + (SP_RGBA32_B_F(bg)) * (1 - A); A = 1.0; } else { // un-premultiply color channels if (A > 0) { R /= A; G /= A; B /= A; } } if (fabs(A) < 1e-4) { A = 0; // suppress exponentials, CSS does not allow that } // remember color dc->R = R; dc->G = G; dc->B = B; dc->alpha = A; // status message double alpha_to_set = setalpha? dc->alpha : 1.0; guint32 c32 = SP_RGBA32_F_COMPOSE(R, G, B, alpha_to_set); gchar c[64]; sp_svg_write_color(c, sizeof(c), c32); // alpha of color under cursor, to show in the statusbar // locale-sensitive printf is OK, since this goes to the UI, not into SVG gchar *alpha = g_strdup_printf(_(" alpha %.3g"), alpha_to_set); // where the color is picked, to show in the statusbar gchar *where = dc->dragging ? g_strdup_printf(_(", averaged with radius %d"), (int) rw) : g_strdup_printf(_(" under cursor")); // message, to show in the statusbar const gchar *message = dc->dragging ? _("<b>Release mouse</b> to set color.") : _("<b>Click</b> to set fill, <b>Shift+click</b> to set stroke; <b>drag</b> to average color in area; with <b>Alt</b> to pick inverse color; <b>Ctrl+C</b> to copy the color under mouse to clipboard"); event_context->defaultMessageContext()->setF( Inkscape::NORMAL_MESSAGE, "<b>%s%s</b>%s. %s", c, (pick == SP_DROPPER_PICK_VISIBLE)? "" : alpha, where, message ); g_free(where); g_free(alpha); ret = TRUE; } break; case GDK_BUTTON_RELEASE: if (event->button.button == 1 && !event_context->space_panning) { sp_canvas_item_hide(dc->area); dc->dragging = FALSE; double alpha_to_set = setalpha? dc->alpha : 1.0; // do the actual color setting sp_desktop_set_color(desktop, (event->button.state & GDK_MOD1_MASK)? ColorRGBA(1 - dc->R, 1 - dc->G, 1 - dc->B, alpha_to_set) : ColorRGBA(dc->R, dc->G, dc->B, alpha_to_set), false, !(event->button.state & GDK_SHIFT_MASK)); // REJON: set aux. toolbar input to hex color! if (!(sp_desktop_selection(desktop)->isEmpty())) { sp_document_done(sp_desktop_document(desktop), SP_VERB_CONTEXT_DROPPER, _("Set picked color")); } ret = TRUE; } break; case GDK_KEY_PRESS: switch (get_group0_keyval(&event->key)) { case GDK_Up: case GDK_Down: case GDK_KP_Up: case GDK_KP_Down: // prevent the zoom field from activation if (!MOD__CTRL_ONLY) { ret = TRUE; } break; case GDK_Escape: sp_desktop_selection(desktop)->clear(); default: break; } break; default: break; } if (!ret) { if (((SPEventContextClass *) parent_class)->root_handler) { ret = ((SPEventContextClass *) parent_class)->root_handler(event_context, event); } } return ret; }
virtual void ungrabbed(GdkEventButton *event) { if (_cancel) return; sp_canvas_item_hide(_rubber); Geom::Rect sel(_start, position()); _selector->signal_area.emit(sel, event); }
void sp_sel_trans_init (SPSelTrans * seltrans, SPDesktop * desktop) { gint i; g_return_if_fail (seltrans != NULL); g_return_if_fail (desktop != NULL); g_return_if_fail (SP_IS_DESKTOP (desktop)); seltrans->desktop = desktop; seltrans->state = SP_SELTRANS_STATE_SCALE; seltrans->show = SP_SELTRANS_SHOW_CONTENT; seltrans->transform = SP_SELTRANS_TRANSFORM_OPTIMIZE; seltrans->items = NULL; seltrans->transforms = NULL; seltrans->nitems = 0; seltrans->spp = nr_new (NRPointF, SP_SELTRANS_SPP_SIZE); seltrans->grabbed = FALSE; seltrans->show_handles = TRUE; for (i = 0; i < 8; i++) seltrans->shandle[i] = NULL; for (i = 0; i < 8; i++) seltrans->rhandle[i] = NULL; seltrans->chandle = NULL; sp_sel_trans_update_volatile_state (seltrans); seltrans->center.x = (seltrans->box.x0 + seltrans->box.x1) / 2; seltrans->center.y = (seltrans->box.y0 + seltrans->box.y1) / 2; sp_sel_trans_update_handles (seltrans); seltrans->selection = SP_DT_SELECTION (desktop); g_signal_connect (G_OBJECT (seltrans->selection), "changed", G_CALLBACK (sp_sel_trans_sel_changed), seltrans); g_signal_connect (G_OBJECT (seltrans->selection), "modified", G_CALLBACK (sp_sel_trans_sel_modified), seltrans); seltrans->norm = sp_canvas_item_new (SP_DT_CONTROLS (desktop), SP_TYPE_CTRL, "anchor", GTK_ANCHOR_CENTER, "mode", SP_CTRL_MODE_COLOR, "shape", SP_CTRL_SHAPE_BITMAP, "size", 13.0, "filled", TRUE, "fill_color", 0x00000000, "stroked", TRUE, "stroke_color", 0x000000a0, "pixbuf", handles[12], NULL); seltrans->grip = sp_canvas_item_new (SP_DT_CONTROLS (desktop), SP_TYPE_CTRL, "anchor", GTK_ANCHOR_CENTER, "mode", SP_CTRL_MODE_XOR, "shape", SP_CTRL_SHAPE_CROSS, "size", 7.0, "filled", TRUE, "fill_color", 0xffffff7f, "stroked", TRUE, "stroke_color", 0xffffffff, "pixbuf", handles[12], NULL); sp_canvas_item_hide (seltrans->grip); sp_canvas_item_hide (seltrans->norm); seltrans->l1 = sp_canvas_item_new (SP_DT_CONTROLS (desktop), SP_TYPE_CTRLLINE, NULL); sp_canvas_item_hide (seltrans->l1); seltrans->l2 = sp_canvas_item_new (SP_DT_CONTROLS (desktop), SP_TYPE_CTRLLINE, NULL); sp_canvas_item_hide (seltrans->l2); seltrans->l3 = sp_canvas_item_new (SP_DT_CONTROLS (desktop), SP_TYPE_CTRLLINE, NULL); sp_canvas_item_hide (seltrans->l3); seltrans->l4 = sp_canvas_item_new (SP_DT_CONTROLS (desktop), SP_TYPE_CTRLLINE, NULL); sp_canvas_item_hide (seltrans->l4); seltrans->stamp_cache = NULL; }
void sp_sel_trans_ungrab (SPSelTrans * seltrans) { SPItem * item; const GSList * l; gchar tstr[80]; NRPointD p; unsigned int updh; g_return_if_fail (seltrans->grabbed); updh = TRUE; if (!seltrans->empty && seltrans->changed) { l = sp_selection_item_list (SP_DT_SELECTION (seltrans->desktop)); tstr[79] = '\0'; while (l != NULL) { item = SP_ITEM (l->data); /* fixme: We do not have to set it here (Lauris) */ if (seltrans->show == SP_SELTRANS_SHOW_OUTLINE) { NRMatrixF i2d, i2dnew; sp_item_i2d_affine (item, &i2d); nr_matrix_multiply_ffd (&i2dnew, &i2d, &seltrans->current); sp_item_set_i2d_affine (item, &i2dnew); } if (seltrans->transform == SP_SELTRANS_TRANSFORM_OPTIMIZE) { sp_item_write_transform (item, SP_OBJECT_REPR (item), &item->transform); /* because item/repr affines may be out of sync, invoke reread */ /* fixme: We should test equality to avoid unnecessary rereads */ /* fixme: This probably is not needed (Lauris) */ sp_object_read_attr (SP_OBJECT (item), "transform"); } else { if (sp_svg_transform_write (tstr, 79, &item->transform)) { sp_repr_set_attr (SP_OBJECT (item)->repr, "transform", tstr); } else { sp_repr_set_attr (SP_OBJECT (item)->repr, "transform", NULL); } } l = l->next; } p = seltrans->center; seltrans->center.x = NR_MATRIX_DF_TRANSFORM_X (&seltrans->current, p.x, p.y); seltrans->center.y = NR_MATRIX_DF_TRANSFORM_Y (&seltrans->current, p.x, p.y); sp_document_done (SP_DT_DOCUMENT (seltrans->desktop)); sp_selection_changed (SP_DT_SELECTION (seltrans->desktop)); updh = FALSE; } if (seltrans->items) { int i; for (i = 0; i < seltrans->nitems; i++) sp_object_unref (SP_OBJECT (seltrans->items[i]), NULL); nr_free (seltrans->items); seltrans->items = NULL; } if (seltrans->transforms) { nr_free (seltrans->transforms); seltrans->transforms = NULL; } seltrans->nitems = 0; seltrans->grabbed = FALSE; seltrans->show_handles = TRUE; sp_canvas_item_hide (seltrans->norm); sp_canvas_item_hide (seltrans->grip); if (seltrans->show == SP_SELTRANS_SHOW_OUTLINE) { sp_canvas_item_hide (seltrans->l1); sp_canvas_item_hide (seltrans->l2); sp_canvas_item_hide (seltrans->l3); sp_canvas_item_hide (seltrans->l4); } sp_sel_trans_update_volatile_state (seltrans); if (updh) sp_sel_trans_update_handles (seltrans); if (seltrans->stamp_cache) { g_slist_free(seltrans->stamp_cache); seltrans->stamp_cache = NULL; } }
gint sp_pen_context_root_handler (SPEventContext *ec, GdkEvent *event) { SPDrawContext *dc; SPPenContext *pc; SPDesktop *dt; NRPointF p; gint ret; SPDrawAnchor *anchor; NRPointF fp; dc = SP_DRAW_CONTEXT (ec); pc = SP_PEN_CONTEXT (ec); dt = ec->desktop; ret = FALSE; switch (event->type) { case GDK_BUTTON_PRESS: if (event->button.button == 1) { #if 0 /* Grab mouse, so release will not pass unnoticed */ dc->grab = SP_CANVAS_ITEM (dt->acetate); sp_canvas_item_grab (dc->grab, SPDC_EVENT_MASK, NULL, event->button.time); #endif /* Find desktop coordinates */ sp_desktop_w2d_xy_point (dt, &fp, event->button.x, event->button.y); p.x = fp.x; p.y = fp.y; /* Test, whether we hit any anchor */ anchor = test_inside (dc, event->button.x, event->button.y); 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 cancelled 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 cancelled curve */ case SP_PEN_CONTEXT_POINT: if (dc->npoints == 0) { /* Set start anchor */ dc->sa = anchor; if (anchor) { /* Adjust point to anchor if needed */ p = anchor->dp; } else { /* Create green anchor */ dc->green_anchor = sp_draw_anchor_new (dc, dc->green_curve, TRUE, p.x, p.y); } spdc_pen_set_point (pc, &p, event->motion.state); } else { /* Set end anchor */ dc->ea = anchor; spdc_pen_set_point (pc, &p, event->motion.state); if (dc->green_anchor && dc->green_anchor->active) { pc->state = SP_PEN_CONTEXT_CLOSE; ret = TRUE; break; } } pc->state = 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; } } break; case GDK_MOTION_NOTIFY: #if 1 if ((event->motion.state & GDK_BUTTON1_MASK) && !dc->grab) { /* Grab mouse, so release will not pass unnoticed */ dc->grab = SP_CANVAS_ITEM (dt->acetate); sp_canvas_item_grab (dc->grab, SPDC_EVENT_MASK, NULL, event->button.time); } #endif /* Find desktop coordinates */ sp_desktop_w2d_xy_point (dt, &fp, event->motion.x, event->motion.y); p.x = fp.x; p.y = fp.y; /* Test, whether we hit any anchor */ anchor = test_inside (dc, event->button.x, event->button.y); if (!anchor) { /* Snap only if not hitting anchor */ spdc_endpoint_snap (dc, &p, event->motion.state); } switch (pc->mode) { case SP_PEN_CONTEXT_MODE_CLICK: switch (pc->state) { case SP_PEN_CONTEXT_POINT: if (dc->npoints != 0) { /* Only set point, if we are already appending */ /* fixme: Snapping */ spdc_pen_set_point (pc, &p, event->motion.state); ret = TRUE; } break; case SP_PEN_CONTEXT_CONTROL: case SP_PEN_CONTEXT_CLOSE: /* Placing controls is last operation in CLOSE state */ /* fixme: Snapping */ spdc_pen_set_ctrl (pc, &p, event->motion.state); ret = TRUE; break; case SP_PEN_CONTEXT_STOP: /* This is perfectly valid */ break; default: break; } break; case SP_PEN_CONTEXT_MODE_DRAG: switch (pc->state) { case SP_PEN_CONTEXT_POINT: if (dc->npoints > 0) { /* Only set point, if we are already appending */ /* fixme: Snapping */ spdc_pen_set_point (pc, &p, event->motion.state); ret = TRUE; } break; case SP_PEN_CONTEXT_CONTROL: case SP_PEN_CONTEXT_CLOSE: /* Placing controls is last operation in CLOSE state */ /* fixme: Snapping */ spdc_pen_set_ctrl (pc, &p, event->motion.state); ret = TRUE; break; case SP_PEN_CONTEXT_STOP: /* This is perfectly valid */ break; default: break; } break; default: break; } break; case GDK_BUTTON_RELEASE: if (event->button.button == 1) { /* Find desktop coordinates */ sp_desktop_w2d_xy_point (dt, &fp, event->motion.x, event->motion.y); p.x = fp.x; p.y = fp.y; /* Test, whether we hit any anchor */ anchor = test_inside (dc, event->button.x, event->button.y); switch (pc->mode) { case SP_PEN_CONTEXT_MODE_CLICK: switch (pc->state) { case SP_PEN_CONTEXT_POINT: if (dc->npoints == 0) { /* Start new thread only with button release */ if (anchor) { p = anchor->dp; } dc->sa = anchor; spdc_pen_set_point (pc, &p, event->motion.state); } else { /* Set end anchor here */ dc->ea = anchor; } pc->state = SP_PEN_CONTEXT_CONTROL; ret = TRUE; break; case SP_PEN_CONTEXT_CONTROL: /* End current segment */ spdc_pen_finish_segment (pc, &p, event->button.state); pc->state = SP_PEN_CONTEXT_POINT; ret = TRUE; break; case SP_PEN_CONTEXT_CLOSE: /* End current segment */ spdc_pen_finish_segment (pc, &p, event->button.state); spdc_pen_finish (pc, TRUE); pc->state = SP_PEN_CONTEXT_POINT; ret = TRUE; break; case SP_PEN_CONTEXT_STOP: /* This is allowed, if we just cancelled curve */ pc->state = SP_PEN_CONTEXT_POINT; ret = TRUE; break; default: break; } break; case SP_PEN_CONTEXT_MODE_DRAG: switch (pc->state) { case SP_PEN_CONTEXT_POINT: case SP_PEN_CONTEXT_CONTROL: spdc_pen_finish_segment (pc, &p, event->button.state); break; case SP_PEN_CONTEXT_CLOSE: spdc_pen_finish_segment (pc, &p, event->button.state); spdc_pen_finish (pc, TRUE); break; case SP_PEN_CONTEXT_STOP: /* This is allowed, if we just cancelled curve */ break; default: break; } pc->state = SP_PEN_CONTEXT_POINT; ret = TRUE; break; default: break; } #if 1 if (dc->grab) { /* Release grab now */ sp_canvas_item_ungrab (dc->grab, event->button.time); dc->grab = NULL; } #endif ret = TRUE; } break; case GDK_2BUTTON_PRESS: spdc_pen_finish (pc, FALSE); ret = TRUE; break; case GDK_KEY_PRESS: /* fixme: */ switch (event->key.keyval) { case GDK_Return: spdc_pen_finish (pc, FALSE); ret = TRUE; break; case GDK_Escape: pc->state = SP_PEN_CONTEXT_STOP; spdc_reset_colors (dc); sp_canvas_item_hide (pc->c0); sp_canvas_item_hide (pc->c1); sp_canvas_item_hide (pc->cl0); sp_canvas_item_hide (pc->cl1); ret = TRUE; break; case GDK_BackSpace: if (sp_curve_is_empty (dc->green_curve)) { /* Same as cancel */ pc->state = SP_PEN_CONTEXT_STOP; spdc_reset_colors (dc); sp_canvas_item_hide (pc->c0); sp_canvas_item_hide (pc->c1); sp_canvas_item_hide (pc->cl0); sp_canvas_item_hide (pc->cl1); ret = TRUE; break; } else { NRPointF pt; ArtBpath *p; gint e; /* Reset red curve */ sp_curve_reset (dc->red_curve); /* Destroy topmost green bpath */ gtk_object_destroy (GTK_OBJECT (dc->green_bpaths->data)); dc->green_bpaths = g_slist_remove (dc->green_bpaths, dc->green_bpaths->data); /* Get last segment */ p = SP_CURVE_BPATH (dc->green_curve); e = SP_CURVE_LENGTH (dc->green_curve); if (e < 2) { g_warning ("Green curve length is %d", e); break; } dc->p[0].x = p[e - 2].x3; dc->p[0].y = p[e - 2].y3; dc->p[1].x = p[e - 1].x1; dc->p[1].y = p[e - 1].y1; if (dc->npoints < 4) { pt.x = p[e - 1].x3; pt.y = p[e - 1].y3; } else { pt.x = dc->p[3].x; pt.y = dc->p[3].y; } dc->npoints = 2; sp_curve_backspace (dc->green_curve); sp_canvas_item_hide (pc->c0); sp_canvas_item_hide (pc->c1); sp_canvas_item_hide (pc->cl0); sp_canvas_item_hide (pc->cl1); pc->state = SP_PEN_CONTEXT_POINT; spdc_pen_set_point (pc, &pt, event->motion.state); ret = TRUE; } break; default: break; } break; default: break; } if (!ret) { if (((SPEventContextClass *) pen_parent_class)->root_handler) return ((SPEventContextClass *) pen_parent_class)->root_handler (ec, event); } return ret; }