Code

remove commented includes; #ifdef HAVE_CONFIG_H
[inkscape.git] / src / lpe-tool-context.cpp
1 /*
2  * LPEToolContext: a context for a generic tool composed of subtools that are given by LPEs
3  *
4  * Authors:
5  *   Maximilian Albert <maximilian.albert@gmail.com>
6  *   Lauris Kaplinski <lauris@kaplinski.com>
7  *
8  * Copyright (C) 1998 The Free Software Foundation
9  * Copyright (C) 1999-2005 authors
10  * Copyright (C) 2001-2002 Ximian, Inc.
11  * Copyright (C) 2008 Maximilian Albert
12  *
13  * Released under GNU GPL, read the file 'COPYING' for more information
14  */
16 #ifdef HAVE_CONFIG_H
17 #include "config.h"
18 #endif
20 #include "forward.h"
21 #include "pixmaps/cursor-node.xpm"
22 #include "pixmaps/cursor-crosshairs.xpm"
23 #include <gtk/gtk.h>
24 #include "desktop.h"
25 #include "message-context.h"
26 #include "prefs-utils.h"
27 #include "shape-editor.h"
28 #include "selection.h"
29 #include "desktop-handles.h"
31 #include "lpe-tool-context.h"
33 static void sp_lpetool_context_class_init(SPLPEToolContextClass *klass);
34 static void sp_lpetool_context_init(SPLPEToolContext *erc);
35 static void sp_lpetool_context_dispose(GObject *object);
37 static void sp_lpetool_context_setup(SPEventContext *ec);
38 static void sp_lpetool_context_set(SPEventContext *ec, gchar const *key, gchar const *val);
39 static gint sp_lpetool_context_root_handler(SPEventContext *ec, GdkEvent *event);
41 void sp_lpetool_context_selection_changed(Inkscape::Selection *selection, gpointer data);
43 const int num_subtools = 4;
45 Inkscape::LivePathEffect::EffectType lpesubtools[] = {
46     Inkscape::LivePathEffect::LINE_SEGMENT,
47     Inkscape::LivePathEffect::ANGLE_BISECTOR,
48     Inkscape::LivePathEffect::CIRCLE_3PTS,
49     Inkscape::LivePathEffect::PERP_BISECTOR,
50 };
52 static SPPenContextClass *lpetool_parent_class = 0;
54 GType sp_lpetool_context_get_type(void)
55 {
56     static GType type = 0;
57     if (!type) {
58         GTypeInfo info = {
59             sizeof(SPLPEToolContextClass),
60             0, // base_init
61             0, // base_finalize
62             (GClassInitFunc)sp_lpetool_context_class_init,
63             0, // class_finalize
64             0, // class_data
65             sizeof(SPLPEToolContext),
66             0, // n_preallocs
67             (GInstanceInitFunc)sp_lpetool_context_init,
68             0 // value_table
69         };
70         type = g_type_register_static(SP_TYPE_PEN_CONTEXT, "SPLPEToolContext", &info, static_cast<GTypeFlags>(0));
71     }
72     return type;
73 }
75 static void
76 sp_lpetool_context_class_init(SPLPEToolContextClass *klass)
77 {
78     GObjectClass *object_class = (GObjectClass *) klass;
79     SPEventContextClass *event_context_class = (SPEventContextClass *) klass;
81     lpetool_parent_class = (SPPenContextClass*)g_type_class_peek_parent(klass);
83     object_class->dispose = sp_lpetool_context_dispose;
85     event_context_class->setup = sp_lpetool_context_setup;
86     event_context_class->set = sp_lpetool_context_set;
87     event_context_class->root_handler = sp_lpetool_context_root_handler;
88 }
90 static void
91 sp_lpetool_context_init(SPLPEToolContext *lc)
92 {
93     lc->cursor_shape = cursor_crosshairs_xpm;
94     lc->hot_x = 7;
95     lc->hot_y = 7;
97     new (&lc->sel_changed_connection) sigc::connection();
99     //lc->tool_state = LPETOOL_STATE_NODE;
102 static void
103 sp_lpetool_context_dispose(GObject *object)
105     SPLPEToolContext *lc = SP_LPETOOL_CONTEXT(object);
106     delete lc->shape_editor;
108     lc->sel_changed_connection.disconnect();
109     lc->sel_changed_connection.~connection();
111     G_OBJECT_CLASS(lpetool_parent_class)->dispose(object);
114 static void
115 sp_lpetool_context_setup(SPEventContext *ec)
117     SPLPEToolContext *lc = SP_LPETOOL_CONTEXT(ec);
119     if (((SPEventContextClass *) lpetool_parent_class)->setup)
120         ((SPEventContextClass *) lpetool_parent_class)->setup(ec);
122     Inkscape::Selection *selection = sp_desktop_selection (ec->desktop);
123     SPItem *item = selection->singleItem();
125     lc->sel_changed_connection.disconnect();
126     lc->sel_changed_connection =
127         selection->connectChanged(sigc::bind(sigc::ptr_fun(&sp_lpetool_context_selection_changed), (gpointer)lc));
129     //lc->my_nc = new NodeContextCpp(lc->desktop, lc->prefs_repr, lc->key);
130     lc->shape_editor = new ShapeEditor(ec->desktop);
132 // TODO temp force:
133     ec->enableSelectionCue();
135     if (item) {
136         lc->shape_editor->set_item(item, SH_NODEPATH);
137         lc->shape_editor->set_item(item, SH_KNOTHOLDER);
138     }
140     if (prefs_get_int_attribute("tools.lpetool", "selcue", 0) != 0) {
141         ec->enableSelectionCue();
142     }
144     lc->_message_context = new Inkscape::MessageContext((ec->desktop)->messageStack());
146     lc->shape_editor->update_statusbar();
149 /**
150 \brief  Callback that processes the "changed" signal on the selection;
151 destroys old and creates new nodepath and reassigns listeners to the new selected item's repr
152 */
153 void
154 sp_lpetool_context_selection_changed(Inkscape::Selection *selection, gpointer data)
156     SPLPEToolContext *lc = SP_LPETOOL_CONTEXT(data);
158     // TODO: update ShapeEditorsCollective instead
159     lc->shape_editor->unset_item(SH_NODEPATH);
160     lc->shape_editor->unset_item(SH_KNOTHOLDER);
161     SPItem *item = selection->singleItem();
162     lc->shape_editor->set_item(item, SH_NODEPATH);
163     lc->shape_editor->set_item(item, SH_KNOTHOLDER);
164     lc->shape_editor->update_statusbar();
167 static void
168 sp_lpetool_context_set(SPEventContext *ec, gchar const *key, gchar const *val)
170     // FIXME: how to set this correcly? the value from preferences-skeleton.h doesn't seem to get
171     // read (it wants to set drag = 1)
172     lpetool_parent_class->set(ec, key, "drag");
174     /**
175     //pass on up to parent class to handle common attributes.
176     if ( lpetool_parent_class->set ) {
177         lpetool_parent_class->set(ec, key, val);
178     }
179     **/
182 /**
183 void
184 sp_erc_update_toolbox (SPDesktop *desktop, const gchar *id, double value)
186     desktop->setToolboxAdjustmentValue (id, value);
188 **/
190 gint
191 sp_lpetool_context_root_handler(SPEventContext *event_context, GdkEvent *event)
193     //g_print ("sp_lpetool_context_root_handler()\n");
194     SPLPEToolContext *lc = SP_LPETOOL_CONTEXT(event_context);
195     SPDesktop *desktop = event_context->desktop;
196     Inkscape::Selection *selection = sp_desktop_selection (desktop);
198     //gint ret = FALSE;
199     bool ret = false;
201     if (sp_pen_context_has_waiting_LPE(lc)) {
202         // quit when we are waiting for a LPE to be applied
203         g_print ("LPETool has waiting LPE. We call the pen tool parent context and return\n");
204         ret = ((SPEventContextClass *) lpetool_parent_class)->root_handler(event_context, event);
205         return ret;
206     }
208     switch (event->type) {
209         case GDK_BUTTON_PRESS:
210             g_print ("GDK_BUTTON_PRESS\n");
211             if (event->button.button == 1 && !event_context->space_panning) {
212                 g_print ("   ... (passed if construct)\n");
213                 // save drag origin
214                 event_context->xp = (gint) event->button.x;
215                 event_context->yp = (gint) event->button.y;
216                 event_context->within_tolerance = true;
217                 lc->shape_editor->cancel_hit();
219                 using namespace Inkscape::LivePathEffect;
221                 int mode = prefs_get_int_attribute("tools.lpetool", "mode", 0);
222                 EffectType type = lpesubtools[mode];
223                 g_print ("Activating mode %d\n", mode);
225                 // save drag origin
226                 bool over_stroke = lc->shape_editor->is_over_stroke(NR::Point(event->button.x, event->button.y), true);
227                 g_print ("over_stroke: %s\n", over_stroke ? "true" : "false");
229                 sp_pen_context_wait_for_LPE_mouse_clicks(lc, type, Effect::acceptsNumClicks(type));
231                 // we pass the mouse click on to pen tool as the first click which it should collect
232                 ret = ((SPEventContextClass *) lpetool_parent_class)->root_handler(event_context, event);
234                 /**
235                 SPDesktop *desktop = SP_EVENT_CONTEXT_DESKTOP(dc);
237                 NR::Point const button_w(event->button.x,
238                                          event->button.y);
239                 NR::Point const button_dt(desktop->w2d(button_w));
241                 if (Inkscape::have_viable_layer(desktop, dc->_message_context) == false) {
242                     return TRUE;
243                 }
245                 sp_lpetool_reset(dc, button_dt);
246                 sp_lpetool_extinput(dc, event);
247                 sp_lpetool_apply(dc, button_dt);
248                 dc->accumulated->reset();
249                 if (dc->repr) {
250                     dc->repr = NULL;
251                 }
253                 Inkscape::Rubberband::get()->start(desktop, button_dt);
254                 Inkscape::Rubberband::get()->setMode(RUBBERBAND_MODE_TOUCHPATH);
256                 // initialize first point
257                 dc->npoints = 0;
259                 sp_canvas_item_grab(SP_CANVAS_ITEM(desktop->acetate),
260                                     ( GDK_KEY_PRESS_MASK |
261                                       GDK_BUTTON_RELEASE_MASK |
262                                       GDK_POINTER_MOTION_MASK |
263                                       GDK_BUTTON_PRESS_MASK ),
264                                     NULL,
265                                     event->button.time);
267                 ret = TRUE;
269                 sp_canvas_force_full_redraw_after_interruptions(desktop->canvas, 3);
270                 dc->is_drawing = true;
271                 **/
272             }
273             break;
274         case GDK_MOTION_NOTIFY:
275         {
276             if (!lc->shape_editor->has_nodepath() || selection->singleItem() == NULL) {
277                 break;
278             }
280             bool over_stroke = false;
281             over_stroke = lc->shape_editor->is_over_stroke(NR::Point(event->motion.x, event->motion.y), false);
283             if (over_stroke) {
284                 event_context->cursor_shape = cursor_node_xpm;
285                 event_context->hot_x = 1;
286                 event_context->hot_y = 1;
287                 sp_event_context_update_cursor(event_context);
288             } else {
289                 lc->cursor_shape = cursor_crosshairs_xpm;
290                 lc->hot_x = 7;
291                 lc->hot_y = 7;
292                 sp_event_context_update_cursor(event_context);
293             }
294         /**
295         {
296             NR::Point const motion_w(event->motion.x,
297                                      event->motion.y);
298             NR::Point motion_dt(desktop->w2d(motion_w));
299             sp_lpetool_extinput(dc, event);
301             dc->_message_context->clear();
303             if ( dc->is_drawing && (event->motion.state & GDK_BUTTON1_MASK) && !event_context->space_panning) {
304                 dc->dragging = TRUE;
306                 dc->_message_context->set(Inkscape::NORMAL_MESSAGE, _("<b>Drawing</b> an lpetool stroke"));
308                 if (!sp_lpetool_apply(dc, motion_dt)) {
309                     ret = TRUE;
310                     break;
311                 }
313                 if ( dc->cur != dc->last ) {
314                     sp_lpetool_brush(dc);
315                     g_assert( dc->npoints > 0 );
316                     fit_and_split(dc, FALSE);
317                 }
318                 ret = TRUE;
319             }
320             Inkscape::Rubberband::get()->move(motion_dt);
321         }
322         **/
323         }
324         break;
327     case GDK_BUTTON_RELEASE:
328     /**
329     {
330         NR::Point const motion_w(event->button.x, event->button.y);
331         NR::Point const motion_dt(desktop->w2d(motion_w));
333         sp_canvas_item_ungrab(SP_CANVAS_ITEM(desktop->acetate), event->button.time);
334         sp_canvas_end_forced_full_redraws(desktop->canvas);
335         dc->is_drawing = false;
337         if (dc->dragging && event->button.button == 1 && !event_context->space_panning) {
338             dc->dragging = FALSE;
340             NR::Maybe<NR::Rect> const b = Inkscape::Rubberband::get()->getRectangle();
342             sp_lpetool_apply(dc, motion_dt);
344             // Remove all temporary line segments
345             while (dc->segments) {
346                 gtk_object_destroy(GTK_OBJECT(dc->segments->data));
347                 dc->segments = g_slist_remove(dc->segments, dc->segments->data);
348             }
350             // Create object
351             fit_and_split(dc, TRUE);
352             accumulate_lpetool(dc);
353             set_to_accumulated(dc); // performs document_done
355             // reset accumulated curve
356             dc->accumulated->reset();
358             clear_current(dc);
359             if (dc->repr) {
360                 dc->repr = NULL;
361             }
363             Inkscape::Rubberband::get()->stop();
364             dc->_message_context->clear();
365             ret = TRUE;
366         }
367         break;
368     }
369     **/
371     case GDK_KEY_PRESS:
372         /**
373         switch (get_group0_keyval (&event->key)) {
374         case GDK_Up:
375         case GDK_KP_Up:
376             if (!MOD__CTRL_ONLY) {
377                 dc->angle += 5.0;
378                 if (dc->angle > 90.0)
379                     dc->angle = 90.0;
380                 sp_erc_update_toolbox (desktop, "lpetool-angle", dc->angle);
381                 ret = TRUE;
382             }
383             break;
384         case GDK_Down:
385         case GDK_KP_Down:
386             if (!MOD__CTRL_ONLY) {
387                 dc->angle -= 5.0;
388                 if (dc->angle < -90.0)
389                     dc->angle = -90.0;
390                 sp_erc_update_toolbox (desktop, "lpetool-angle", dc->angle);
391                 ret = TRUE;
392             }
393             break;
394         case GDK_Right:
395         case GDK_KP_Right:
396             if (!MOD__CTRL_ONLY) {
397                 dc->width += 0.01;
398                 if (dc->width > 1.0)
399                     dc->width = 1.0;
400                 sp_erc_update_toolbox (desktop, "altx-lpetool", dc->width * 100); // the same spinbutton is for alt+x
401                 ret = TRUE;
402             }
403             break;
404         case GDK_Left:
405         case GDK_KP_Left:
406             if (!MOD__CTRL_ONLY) {
407                 dc->width -= 0.01;
408                 if (dc->width < 0.01)
409                     dc->width = 0.01;
410                 sp_erc_update_toolbox (desktop, "altx-lpetool", dc->width * 100);
411                 ret = TRUE;
412             }
413             break;
414         case GDK_Home:
415         case GDK_KP_Home:
416             dc->width = 0.01;
417             sp_erc_update_toolbox (desktop, "altx-lpetool", dc->width * 100);
418             ret = TRUE;
419             break;
420         case GDK_End:
421         case GDK_KP_End:
422             dc->width = 1.0;
423             sp_erc_update_toolbox (desktop, "altx-lpetool", dc->width * 100);
424             ret = TRUE;
425             break;
426         case GDK_x:
427         case GDK_X:
428             if (MOD__ALT_ONLY) {
429                 desktop->setToolboxFocusTo ("altx-lpetool");
430                 ret = TRUE;
431             }
432             break;
433         case GDK_Escape:
434             Inkscape::Rubberband::get()->stop();
435             if (dc->is_drawing) {
436                 // if drawing, cancel, otherwise pass it up for deselecting
437                 lpetool_cancel (dc);
438                 ret = TRUE;
439             }
440             break;
441         case GDK_z:
442         case GDK_Z:
443             if (MOD__CTRL_ONLY && dc->is_drawing) {
444                 // if drawing, cancel, otherwise pass it up for undo
445                 lpetool_cancel (dc);
446                 ret = TRUE;
447             }
448             break;
449         default:
450             break;
451         }
452         **/
453         break;
455     case GDK_KEY_RELEASE:
456         /**
457         switch (get_group0_keyval(&event->key)) {
458             case GDK_Control_L:
459             case GDK_Control_R:
460                 dc->_message_context->clear();
461                 break;
462             default:
463                 break;
464         }
465         **/
467     default:
468         break;
469     }
471     if (!ret) {
472         if (((SPEventContextClass *) lpetool_parent_class)->root_handler) {
473             ret = ((SPEventContextClass *) lpetool_parent_class)->root_handler(event_context, event);
474         }
475     }
477     return ret;
480 /*
481   Local Variables:
482   mode:c++
483   c-file-style:"stroustrup"
484   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
485   indent-tabs-mode:nil
486   fill-column:99
487   End:
488 */
489 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :