cin_db Makefile tweak, awdw vicon stop draw lock rework,
[goodguy/cinelerra.git] / cinelerra-5.1 / plugins / tracer / tracerwindow.C
1 /*
2  * CINELERRA
3  * Copyright (C) 2014 Adam Williams <broadcast at earthling dot net>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  *
19  */
20
21 #include "automation.h"
22 #include "bcdisplayinfo.h"
23 #include "clip.h"
24 #include "tracer.h"
25 #include "tracerwindow.h"
26 #include "cstrdup.h"
27 #include "cwindow.h"
28 #include "cwindowgui.h"
29 #include "edl.h"
30 #include "edlsession.h"
31 #include "language.h"
32 #include "mainerror.h"
33 #include "mwindow.h"
34 #include "plugin.h"
35 #include "pluginserver.h"
36 #include "theme.h"
37 #include "track.h"
38
39 #define COLOR_W xS(50)
40 #define COLOR_H yS(30)
41
42 TracerNum::TracerNum(TracerWindow *gui, int x, int y, float output)
43  : BC_TumbleTextBox(gui, output, -32767.0f, 32767.0f, x, y, xS(120))
44 {
45         this->gui = gui;
46         set_increment(1);
47         set_precision(1);
48 }
49
50 TracerNum::~TracerNum()
51 {
52 }
53
54 int TracerPointX::handle_event()
55 {
56         if( !TracerNum::handle_event() ) return 0;
57         TracerPointList *point_list = gui->point_list;
58         int hot_point = point_list->get_selection_number(0, 0);
59         TracerPoints &points = gui->plugin->config.points;
60         int sz = points.size();
61         if( hot_point >= 0 && hot_point < sz ) {
62                 float v = atof(get_text());
63                 points[hot_point]->x = v;
64                 point_list->set_point(hot_point, PT_X, v);
65         }
66         point_list->update_list(hot_point);
67         gui->send_configure_change();
68         return 1;
69 }
70 int TracerPointY::handle_event()
71 {
72         if( !TracerNum::handle_event() ) return 0;
73         TracerPointList *point_list = gui->point_list;
74         int hot_point = point_list->get_selection_number(0, 0);
75         TracerPoints &points = gui->plugin->config.points;
76         int sz = points.size();
77         if( hot_point >= 0 && hot_point < sz ) {
78                 float v = atof(get_text());
79                 points[hot_point]->y = v;
80                 point_list->set_point(hot_point, PT_Y, v);
81         }
82         point_list->update_list(hot_point);
83         gui->send_configure_change();
84         return 1;
85 }
86
87 TracerWindow::TracerWindow(Tracer *plugin)
88  : PluginClientWindow(plugin, xS(460), yS(420), xS(460), yS(420), 0)
89 {
90         this->plugin = plugin;
91         this->title_x = 0;    this->point_x = 0;
92         this->title_y = 0;    this->point_y = 0;
93         this->new_point = 0;  this->del_point = 0;
94         this->point_up = 0;   this->point_dn = 0;
95         this->drag = 0;       this->draw = 0;
96         this->button_no = 0;  this->invert = 0;
97         this->title_r = 0;    this->title_s = 0;
98         this->feather = 0;    this->radius = 0;
99         this->last_x = 0;     this->last_y = 0;
100         this->point_list = 0; this->pending_config = 0;
101 }
102
103 TracerWindow::~TracerWindow()
104 {
105         delete point_x;
106         delete point_y;
107 }
108
109 void TracerWindow::create_objects()
110 {
111         int x = xS(10), y = yS(10);
112         int margin = plugin->get_theme()->widget_border;
113         int hot_point = plugin->selected;
114         add_subwindow(title_x = new BC_Title(x, y, _("X:")));
115         int x1 = x + title_x->get_w() + margin;
116         TracerPoints &points = plugin->config.points;
117         TracerPoint *pt = hot_point >= 0 && hot_point<points.size() ?
118                 points[hot_point] : 0;
119         point_x = new TracerPointX(this, x1, y, !pt ? 0 : pt->x);
120         point_x->create_objects();
121         x1 += point_x->get_w() + margin + xS(20);
122         add_subwindow(new_point = new TracerNewPoint(this, plugin, x1, y));
123         x1 += new_point->get_w() + margin + xS(30);
124         add_subwindow(point_up = new TracerPointUp(this, x1, y));
125         y += point_x->get_h() + margin;
126         add_subwindow(title_y = new BC_Title(x, y, _("Y:")));
127         x1 = x + title_y->get_w() + margin;
128         point_y = new TracerPointY(this, x1, y, !pt ? 0 : pt->y);
129         point_y->create_objects();
130         x1 += point_y->get_w() + margin + xS(20);
131         add_subwindow(del_point = new TracerDelPoint(this, plugin, x1, y));
132         x1 += del_point->get_w() + margin + xS(30);
133         add_subwindow(point_dn = new TracerPointDn(this, x1, y));
134         y += point_y->get_h() + margin + yS(10);
135
136         add_subwindow(drag = new TracerDrag(this, x, y));
137         if( plugin->drag ) {
138                 if( !grab(plugin->server->mwindow->cwindow->gui) )
139                         eprintf("drag enabled, but compositor already grabbed\n");
140         }
141         x1 = x + drag->get_w() + margin + xS(20);
142         add_subwindow(draw = new TracerDraw(this, x1, y));
143         x1 += draw->get_w() + margin + xS(20);
144         add_subwindow(fill = new TracerFill(this, x1, y));
145         x1 += drag->get_w() + margin + xS(20);
146         int y1 = y + yS(3);
147         add_subwindow(reset = new TracerReset(this, plugin, x1, y1));
148         y1 += reset->get_h() + margin;
149         add_subwindow(invert = new TracerInvert(this, plugin, x1, y1));
150         y += drag->get_h() + margin + yS(15);
151
152         x1 = x + xS(80);
153         add_subwindow(title_r = new BC_Title(x, y, _("Feather:")));
154         add_subwindow(feather = new TracerFeather(this, x1, y, xS(150)));
155         y += feather->get_h() + margin;
156         add_subwindow(title_s = new BC_Title(x, y, _("Radius:")));
157         add_subwindow(radius = new TracerRadius(this, x1, y, xS(150)));
158         y += radius->get_h() + margin + yS(5);
159
160         add_subwindow(point_list = new TracerPointList(this, plugin, x, y));
161         point_list->update(plugin->selected);
162         y += point_list->get_h() + yS(10);
163
164         add_subwindow(new BC_Title(x, y, _(
165                 "Btn1: select/drag point\n"
166                 "Btn2: drag all points\n"
167                 "Btn3: add point on nearest line\n"
168                 "Btn3: shift: append point to end\n"
169                 "Wheel: rotate, centered on cursor\n"
170                 "Wheel: shift: scale, centered on cursor\n")));
171         show_window(1);
172 }
173
174 void TracerWindow::send_configure_change()
175 {
176         pending_config = 0;
177         plugin->send_configure_change();
178 }
179
180 int TracerWindow::grab_event(XEvent *event)
181 {
182         int ret = do_grab_event(event);
183         if( pending_config && !grab_event_count() )
184                 send_configure_change();
185         return ret;
186 }
187
188 int TracerWindow::do_grab_event(XEvent *event)
189 {
190         switch( event->type ) {
191         case ButtonPress: break;
192         case ButtonRelease: break;
193         case MotionNotify: break;
194         default:
195                 return 0;
196         }
197
198         MWindow *mwindow = plugin->server->mwindow;
199         CWindowGUI *cwindow_gui = mwindow->cwindow->gui;
200         CWindowCanvas *canvas = cwindow_gui->canvas;
201         int cursor_x, cursor_y;
202         cwindow_gui->get_relative_cursor(cursor_x, cursor_y);
203         cursor_x -= canvas->view_x;
204         cursor_y -= canvas->view_y;
205
206         if( !button_no ) {
207                 if( cursor_x < 0 || cursor_x >= canvas->view_w ||
208                     cursor_y < 0 || cursor_y >= canvas->view_h )
209                         return 0;
210         }
211
212         switch( event->type ) {
213         case ButtonPress:
214                 if( button_no ) return 0;
215                 button_no = event->xbutton.button;
216                 break;
217         case ButtonRelease:
218                 if( !button_no ) return 0;
219                 button_no = 0;
220                 return 1;
221         case MotionNotify:
222                 if( !button_no ) return 0;
223                 break;
224         default:
225                 return 0;
226         }
227
228         float output_x = cursor_x, output_y = cursor_y, track_x, track_y;
229         canvas->canvas_to_output(mwindow->edl, 0, output_x, output_y);
230         plugin->output_to_track(output_x, output_y, track_x, track_y);
231         point_x->update((int64_t)track_x);
232         point_y->update((int64_t)track_y);
233         TracerPoints &points = plugin->config.points;
234
235         switch( event->type ) {
236         case ButtonPress: {
237                 float s = 1.02;
238                 float th = M_PI/360.f; // .5 deg per wheel_btn
239                 int shift_down = event->xbutton.state & ShiftMask;
240                 switch( button_no ) {
241                 case WHEEL_DOWN:
242                         s = 0.98;
243                         th = -th;  // fall thru
244                 case WHEEL_UP: {
245                         // shift_down scale, !shift_down rotate
246                         float st = sin(th), ct = cos(th);
247                         int sz = points.size();
248                         for( int i=0; i<sz; ++i ) {
249                                 TracerPoint *pt = points[i];
250                                 float px = pt->x - track_x, py = pt->y - track_y;
251                                 float nx = shift_down ? px*s : px*ct + py*st;
252                                 float ny = shift_down ? py*s : py*ct - px*st;
253                                 point_list->set_point(i, PT_X, pt->x = nx + track_x);
254                                 point_list->set_point(i, PT_Y, pt->y = ny + track_y);
255                         }
256                         point_list->update(-1);
257                         button_no = 0;
258                         break; }
259                 case RIGHT_BUTTON: {
260                         // shift_down adds to end
261                         int sz = !shift_down ? points.size() : 0;
262                         int k = !shift_down ? -1 : points.size()-1;
263                         float mx = FLT_MAX;
264                         for( int i=0; i<sz; ++i ) {
265                                 // pt on line pt[i+0]..pt[i+1] nearest cursor_x,cursor_y
266                                 TracerPoint *pt0 = points[i+0];
267                                 TracerPoint *pt1 = i+1<sz ? points[i+1] : points[0];
268                                 float x0 = pt0->x, y0 = pt0->y;
269                                 float x1 = pt1->x, y1 = pt1->y;
270                                 float dx = x1-x0, dy = y1-y0;
271                                 float rr = dx*dx + dy*dy;
272                                 if( !rr ) continue;
273                                 float u = ((x1-track_x)*dx + (y1-track_y)*dy) / rr;
274                                 if( u < 0 || u > 1 ) continue;  // past endpts
275                                 float x = x0*u + x1*(1-u);
276                                 float y = y0*u + y1*(1-u);
277                                 dx = track_x-x;  dy = track_y-y;
278                                 float dd = dx*dx + dy*dy;       // d**2 closest approach
279                                 if( mx > dd ) { mx = dd;  k = i; }
280                         }
281                         TracerPoint *pt = points[sz=plugin->new_point()];
282                         int hot_point = k+1;
283                         for( int i=sz; i>hot_point; --i ) points[i] = points[i-1];
284                         points[hot_point] = pt;
285                         pt->x = track_x;  pt->y = track_y;
286                         point_list->update(hot_point);
287                         break; }
288                 case LEFT_BUTTON: {
289                         int hot_point = -1, sz = points.size();
290                         if( sz > 0 ) {
291                                 TracerPoint *pt = points[hot_point=0];
292                                 double dist = DISTANCE(track_x,track_y, pt->x,pt->y);
293                                 for( int i=1; i<sz; ++i ) {
294                                         pt = points[i];
295                                         double d = DISTANCE(track_x,track_y, pt->x,pt->y);
296                                         if( d >= dist ) continue;
297                                         dist = d;  hot_point = i;
298                                 }
299                                 pt = points[hot_point];
300                                 float cx, cy;
301                                 plugin->track_to_output(pt->x, pt->y, cx, cy);
302                                 canvas->output_to_canvas(mwindow->edl, 0, cx, cy);
303                                 dist = DISTANCE(cursor_x, cursor_y, cx,cy);
304                                 if( dist >= HANDLE_W ) hot_point = -1;
305                         }
306                         if( hot_point >= 0 && sz > 0 ) {
307                                 TracerPoint *pt = points[hot_point];
308                                 point_list->set_point(hot_point, PT_X, pt->x = track_x);
309                                 point_list->set_point(hot_point, PT_Y, pt->y = track_y);
310                                 point_list->update_list(hot_point);
311                         }
312                         break; }
313                 }
314                 break; }
315         case MotionNotify: {
316                 switch( button_no ) {
317                 case LEFT_BUTTON: {
318                         int hot_point = point_list->get_selection_number(0, 0);
319                         if( hot_point >= 0 && hot_point < points.size() ) {
320                                 TracerPoint *pt = points[hot_point];
321                                 if( pt->x == track_x && pt->y == track_y ) break;
322                                 point_list->set_point(hot_point, PT_X, pt->x = track_x);
323                                 point_list->set_point(hot_point, PT_Y, pt->y = track_y);
324                                 point_x->update(pt->x);
325                                 point_y->update(pt->y);
326                                 point_list->update_list(hot_point);
327                         }
328                         break; }
329                 case MIDDLE_BUTTON: {
330                         float dx = track_x - last_x, dy = track_y - last_y;
331                         int sz = points.size();
332                         for( int i=0; i<sz; ++i ) {
333                                 TracerPoint *pt = points[i];
334                                 point_list->set_point(i, PT_X, pt->x += dx);
335                                 point_list->set_point(i, PT_Y, pt->y += dy);
336                         }
337                         int hot_point = point_list->get_selection_number(0, 0);
338                         if( hot_point >= 0 && hot_point < sz ) {
339                                 TracerPoint *pt = points[hot_point];
340                                 point_x->update(pt->x);
341                                 point_y->update(pt->y);
342                                 point_list->update_list(hot_point);
343                         }
344                         break; }
345                 }
346                 break; }
347         }
348
349         last_x = track_x;  last_y = track_y;
350         pending_config = 1;
351         return 1;
352 }
353
354 void TracerWindow::done_event(int result)
355 {
356         ungrab(client->server->mwindow->cwindow->gui);
357 }
358
359 TracerPointList::TracerPointList(TracerWindow *gui, Tracer *plugin, int x, int y)
360  : BC_ListBox(x, y, xS(360), yS(130), LISTBOX_TEXT)
361 {
362         this->gui = gui;
363         this->plugin = plugin;
364         titles[PT_X] = _("X");    widths[PT_X] = xS(90);
365         titles[PT_Y] = _("Y");    widths[PT_Y] = yS(90);
366 }
367 TracerPointList::~TracerPointList()
368 {
369         clear();
370 }
371 void TracerPointList::clear()
372 {
373         for( int i=PT_SZ; --i>=0; )
374                 cols[i].remove_all_objects();
375 }
376
377 int TracerPointList::column_resize_event()
378 {
379         for( int i=PT_SZ; --i>=0; )
380                 widths[i] = get_column_width(i);
381         return 1;
382 }
383
384 int TracerPointList::handle_event()
385 {
386         int hot_point = get_selection_number(0, 0);
387         const char *x_text = "", *y_text = "";
388         TracerPoints &points = plugin->config.points;
389
390         int sz = points.size();
391         if( hot_point >= 0 && sz > 0 ) {
392                 x_text = gui->point_list->cols[PT_X].get(hot_point)->get_text();
393                 y_text = gui->point_list->cols[PT_Y].get(hot_point)->get_text();
394         }
395         gui->point_x->update(x_text);
396         gui->point_y->update(y_text);
397         update(hot_point);
398         gui->send_configure_change();
399         return 1;
400 }
401
402 int TracerPointList::selection_changed()
403 {
404         handle_event();
405         return 1;
406 }
407
408 void TracerPointList::new_point(const char *xp, const char *yp)
409 {
410         cols[PT_X].append(new BC_ListBoxItem(xp));
411         cols[PT_Y].append(new BC_ListBoxItem(yp));
412 }
413
414 void TracerPointList::del_point(int i)
415 {
416         for( int sz1=cols[0].size()-1, c=PT_SZ; --c>=0; )
417                 cols[c].remove_object_number(sz1-i);
418 }
419
420 void TracerPointList::set_point(int i, int c, float v)
421 {
422         char s[BCSTRLEN]; sprintf(s,"%0.4f",v);
423         set_point(i,c,s);
424 }
425 void TracerPointList::set_point(int i, int c, const char *cp)
426 {
427         cols[c].get(i)->set_text(cp);
428 }
429
430 int TracerPointList::set_selected(int k)
431 {
432         TracerPoints &points = plugin->config.points;
433         int sz = points.size();
434         if( !sz ) return -1;
435         bclamp(k, 0, sz-1);
436         update_selection(&cols[0], k);
437         return k;
438 }
439 void TracerPointList::update_list(int k)
440 {
441         int sz = plugin->config.points.size();
442         if( k < 0 || k >= sz ) k = -1;
443         plugin->selected = k;
444         update_selection(&cols[0], k);
445         int xpos = get_xposition(), ypos = get_yposition();
446         BC_ListBox::update(&cols[0], &titles[0],&widths[0],PT_SZ, xpos,ypos,k);
447         center_selection();
448 }
449 void TracerPointList::update(int k)
450 {
451         clear();
452         TracerPoints &points = plugin->config.points;
453         int sz = points.size();
454         for( int i=0; i<sz; ++i ) {
455                 TracerPoint *pt = points[i];
456                 char xtxt[BCSTRLEN];  sprintf(xtxt,"%0.4f", pt->x);
457                 char ytxt[BCSTRLEN];  sprintf(ytxt,"%0.4f", pt->y);
458                 new_point(xtxt, ytxt);
459         }
460         if( k >= 0 && k < sz ) {
461                 gui->point_x->update(gui->point_list->cols[PT_X].get(k)->get_text());
462                 gui->point_y->update(gui->point_list->cols[PT_Y].get(k)->get_text());
463         }
464         update_list(k);
465 }
466
467 void TracerWindow::update_gui()
468 {
469         TracerConfig &config = plugin->config;
470         drag->update(plugin->drag);
471         draw->update(config.draw);
472         fill->update(config.fill);
473         feather->update(config.feather);
474         radius->update(config.radius);
475         invert->update(config.invert);
476         point_list->update(-1);
477 }
478
479
480 TracerPointUp::TracerPointUp(TracerWindow *gui, int x, int y)
481  : BC_GenericButton(x, y, _("Up"))
482 {
483         this->gui = gui;
484 }
485 TracerPointUp::~TracerPointUp()
486 {
487 }
488
489 int TracerPointUp::handle_event()
490 {
491         TracerPoints &points = gui->plugin->config.points;
492         int sz = points.size();
493         int hot_point = gui->point_list->get_selection_number(0, 0);
494
495         if( sz > 1 && hot_point > 0 ) {
496                 TracerPoint *&pt0 = points[hot_point];
497                 TracerPoint *&pt1 = points[--hot_point];
498                 TracerPoint *t = pt0;  pt0 = pt1;  pt1 = t;
499                 gui->point_list->update(hot_point);
500         }
501         gui->send_configure_change();
502         return 1;
503 }
504
505 TracerPointDn::TracerPointDn(TracerWindow *gui, int x, int y)
506  : BC_GenericButton(x, y, _("Dn"))
507 {
508         this->gui = gui;
509 }
510 TracerPointDn::~TracerPointDn()
511 {
512 }
513
514 int TracerPointDn::handle_event()
515 {
516         TracerPoints &points = gui->plugin->config.points;
517         int sz = points.size();
518         int hot_point = gui->point_list->get_selection_number(0, 0);
519         if( sz > 1 && hot_point < sz-1 ) {
520                 TracerPoint *&pt0 = points[hot_point];
521                 TracerPoint *&pt1 = points[++hot_point];
522                 TracerPoint *t = pt0;  pt0 = pt1;  pt1 = t;
523                 gui->point_list->update(hot_point);
524         }
525         gui->send_configure_change();
526         return 1;
527 }
528
529 TracerDrag::TracerDrag(TracerWindow *gui, int x, int y)
530  : BC_CheckBox(x, y, gui->plugin->drag, _("Drag"))
531 {
532         this->gui = gui;
533 }
534 int TracerDrag::handle_event()
535 {
536         CWindowGUI *cwindow_gui = gui->plugin->server->mwindow->cwindow->gui;
537         int value = get_value();
538         if( value ) {
539                 if( !gui->grab(cwindow_gui) ) {
540                         update(value = 0);
541                         flicker(10,50);
542                 }
543         }
544         else
545                 gui->ungrab(cwindow_gui);
546         gui->plugin->drag = value;
547         gui->send_configure_change();
548         return 1;
549 }
550 int TracerWindow::handle_ungrab()
551 {
552         CWindowGUI *cwindow_gui = plugin->server->mwindow->cwindow->gui;
553         int ret = ungrab(cwindow_gui);
554         if( ret ) {
555                 drag->update(0);
556                 plugin->drag = 0;
557         }
558         return ret;
559 }
560
561
562 TracerDraw::TracerDraw(TracerWindow *gui, int x, int y)
563  : BC_CheckBox(x, y, gui->plugin->config.draw, _("Draw"))
564 {
565         this->gui = gui;
566 }
567 int TracerDraw::handle_event()
568 {
569         gui->plugin->config.draw = get_value();
570         gui->send_configure_change();
571         return 1;
572 }
573
574 TracerFill::TracerFill(TracerWindow *gui, int x, int y)
575  : BC_CheckBox(x, y, gui->plugin->config.fill, _("Fill"))
576 {
577         this->gui = gui;
578 }
579 int TracerFill::handle_event()
580 {
581         gui->plugin->config.fill = get_value();
582         gui->send_configure_change();
583         return 1;
584 }
585
586 TracerFeather::TracerFeather(TracerWindow *gui, int x, int y, int w)
587  : BC_ISlider(x,y,0,w,w, -50,50, gui->plugin->config.feather)
588 {
589         this->gui = gui;
590 }
591 int TracerFeather::handle_event()
592 {
593         gui->plugin->config.feather = get_value();
594         gui->send_configure_change();
595         return 1;
596 }
597
598 TracerRadius::TracerRadius(TracerWindow *gui, int x, int y, int w)
599  : BC_FSlider(x,y, 0,w,w, -5.f,5.f, gui->plugin->config.radius)
600 {
601         this->gui = gui;
602 }
603 int TracerRadius::handle_event()
604 {
605         gui->plugin->config.radius = get_value();
606         gui->send_configure_change();
607         return 1;
608 }
609
610 TracerNewPoint::TracerNewPoint(TracerWindow *gui, Tracer *plugin, int x, int y)
611  : BC_GenericButton(x, y, xS(100), _("New"))
612 {
613         this->gui = gui;
614         this->plugin = plugin;
615 }
616 TracerNewPoint::~TracerNewPoint()
617 {
618 }
619 int TracerNewPoint::handle_event()
620 {
621         int k = plugin->new_point();
622         gui->point_list->update(k);
623         gui->send_configure_change();
624         return 1;
625 }
626
627 TracerDelPoint::TracerDelPoint(TracerWindow *gui, Tracer *plugin, int x, int y)
628  : BC_GenericButton(x, y, xS(100), C_("Del"))
629 {
630         this->gui = gui;
631         this->plugin = plugin;
632 }
633 TracerDelPoint::~TracerDelPoint()
634 {
635 }
636 int TracerDelPoint::handle_event()
637 {
638         int hot_point = gui->point_list->get_selection_number(0, 0);
639         TracerPoints &points = plugin->config.points;
640         if( hot_point >= 0 && hot_point < points.size() ) {
641                 plugin->config.del_point(hot_point);
642                 gui->point_list->update(--hot_point);
643                 gui->send_configure_change();
644         }
645         return 1;
646 }
647
648 TracerReset::TracerReset(TracerWindow *gui, Tracer *plugin, int x, int y)
649  : BC_GenericButton(x, y, _("Reset"))
650 {
651         this->gui = gui;
652         this->plugin = plugin;
653 }
654 TracerReset::~TracerReset()
655 {
656 }
657 int TracerReset::handle_event()
658 {
659         TracerConfig &config = plugin->config;
660         if( !plugin->drag ) {
661                 MWindow *mwindow = plugin->server->mwindow;
662                 CWindowGUI *cwindow_gui = mwindow->cwindow->gui;
663                 if( gui->grab(cwindow_gui) )
664                         plugin->drag = 1;
665                 else
666                         gui->drag->flicker(10,50);
667         }
668         config.draw = 1;
669         config.fill = 0;
670         config.invert = 0;
671         config.feather = 0;
672         config.radius = 1;
673         plugin->selected = -1;
674         TracerPoints &points = plugin->config.points;
675         points.remove_all_objects();
676         gui->point_list->update(-1);
677         gui->update_gui();
678         gui->send_configure_change();
679         return 1;
680 }
681
682 TracerInvert::TracerInvert(TracerWindow *gui, Tracer *plugin, int x, int y)
683  : BC_CheckBox(x, y, gui->plugin->config.invert, _("Invert"))
684 {
685         this->gui = gui;
686         this->plugin = plugin;
687 }
688 TracerInvert::~TracerInvert()
689 {
690 }
691 int TracerInvert::handle_event()
692 {
693         plugin->config.invert = get_value();
694         gui->send_configure_change();
695         return 1;
696 }
697