eaaa0b5ca3c01c33269688d22ee172c289fc7ff8
[goodguy/cinelerra.git] / cinelerra-5.1 / plugins / crikey / crikeywindow.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 "crikey.h"
25 #include "crikeywindow.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 50
40 #define COLOR_H 30
41
42 CriKeyNum::CriKeyNum(CriKeyWindow *gui, int x, int y, float output)
43  : BC_TumbleTextBox(gui, output, -32767.0f, 32767.0f, x, y, 120)
44 {
45         this->gui = gui;
46         set_increment(1);
47         set_precision(1);
48 }
49
50 CriKeyNum::~CriKeyNum()
51 {
52 }
53
54 int CriKeyPointX::handle_event()
55 {
56         if( !CriKeyNum::handle_event() ) return 0;
57         CriKeyPointList *point_list = gui->point_list;
58         int hot_point = point_list->get_selection_number(0, 0);
59         CriKeyPoints &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 CriKeyPointY::handle_event()
71 {
72         if( !CriKeyNum::handle_event() ) return 0;
73         CriKeyPointList *point_list = gui->point_list;
74         int hot_point = point_list->get_selection_number(0, 0);
75         CriKeyPoints &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 int CriKeyDrawModeItem::handle_event()
88 {
89         ((CriKeyDrawMode *)get_popup_menu())->update(id);
90         return 1;
91 }
92 CriKeyDrawMode::CriKeyDrawMode(CriKeyWindow *gui, int x, int y)
93  : BC_PopupMenu(x, y, 100, "", 1)
94 {
95         this->gui = gui;
96         draw_modes[DRAW_ALPHA]     = _("Alpha");
97         draw_modes[DRAW_EDGE]      = _("Edge");
98         draw_modes[DRAW_MASK]      = _("Mask");
99         mode = -1;
100 }
101 void CriKeyDrawMode::create_objects()
102 {
103         for( int i=0; i<DRAW_MODES; ++i )
104                 add_item(new CriKeyDrawModeItem(draw_modes[i], i));
105         update(gui->plugin->config.draw_mode, 0);
106 }
107 void CriKeyDrawMode::update(int mode, int send)
108 {
109         if( this->mode == mode ) return;
110         this->mode = mode;
111         set_text(draw_modes[mode]);
112         gui->plugin->config.draw_mode = mode;
113         if( send ) gui->send_configure_change();
114 }
115
116
117 CriKeyWindow::CriKeyWindow(CriKey *plugin)
118  : PluginClientWindow(plugin, 380, 400, 380, 400, 0)
119 {
120         this->plugin = plugin;
121         this->title_x = 0;    this->point_x = 0;
122         this->title_y = 0;    this->point_y = 0;
123         this->new_point = 0;  this->del_point = 0;
124         this->point_up = 0;   this->point_dn = 0;
125         this->drag = 0;       this->dragging = 0;
126         this->last_x = 0;     this->last_y = 0;
127         this->point_list = 0; this->pending_config = 0;
128 }
129
130 CriKeyWindow::~CriKeyWindow()
131 {
132 }
133
134 void CriKeyWindow::create_objects()
135 {
136         int x = 10, y = 10;
137         int margin = plugin->get_theme()->widget_border;
138         BC_Title *title;
139         add_subwindow(title = new BC_Title(x, y+5, _("Draw mode:")));
140         int x1 = x + title->get_w() + 10 + margin;
141         add_subwindow(draw_mode = new CriKeyDrawMode(this, x1, y));
142         draw_mode->create_objects();
143         y += draw_mode->get_h() + 10 + margin;
144
145         CriKeyPoint *pt = plugin->config.points[plugin->config.selected];
146         add_subwindow(title_x = new BC_Title(x, y, _("X:")));
147         x1 = x + title_x->get_w() + margin;
148         point_x = new CriKeyPointX(this, x1, y, pt->x);
149         point_x->create_objects();
150         x1 += point_x->get_w() + margin;
151         add_subwindow(new_point = new CriKeyNewPoint(this, plugin, x1, y));
152         x1 += new_point->get_w() + margin;
153         add_subwindow(point_up = new CriKeyPointUp(this, x1, y));
154         y += point_x->get_h() + margin;
155         add_subwindow(title_y = new BC_Title(x, y, _("Y:")));
156         x1 = x + title_y->get_w() + margin;
157         point_y = new CriKeyPointY(this, x1, y, pt->y);
158         point_y->create_objects();
159         x1 += point_y->get_w() + margin;
160         add_subwindow(del_point = new CriKeyDelPoint(this, plugin, x1, y));
161         x1 += del_point->get_w() + margin;
162         add_subwindow(point_dn = new CriKeyPointDn(this, x1, y));
163         y += point_y->get_h() + margin + 10;
164         add_subwindow(title = new BC_Title(x, y, _("Threshold:")));
165         y += title->get_h() + margin;
166         add_subwindow(threshold = new CriKeyThreshold(this, x, y, get_w() - x * 2));
167         y += threshold->get_h() + margin;
168
169         add_subwindow(drag = new CriKeyDrag(this, x, y));
170         if( plugin->config.drag ) {
171                 if( !grab(plugin->server->mwindow->cwindow->gui) )
172                         eprintf("drag enabled, but compositor already grabbed\n");
173         }
174         x1 = x + drag->get_w() + margin + 32;
175         add_subwindow(reset = new CriKeyReset(this, plugin, x1, y+3));
176         y += drag->get_h() + margin;
177
178         add_subwindow(point_list = new CriKeyPointList(this, plugin, x, y));
179         point_list->update(plugin->config.selected);
180
181         y += point_list->get_h() + 10;
182         add_subwindow(notes = new BC_Title(x, y,
183                  _("Right click in composer: create new point\n"
184                    "Shift-left click in Enable field:\n"
185                    "  if any off, turns all on\n"
186                    "  if all on, turns rest off.")));
187         show_window(1);
188 }
189
190 void CriKeyWindow::send_configure_change()
191 {
192         pending_config = 0;
193         plugin->send_configure_change();
194 }
195 int CriKeyWindow::check_configure_change(int ret)
196 {
197         if( pending_config && !grab_event_count() )
198                 send_configure_change();
199         return ret;
200 }
201
202 int CriKeyWindow::grab_event(XEvent *event)
203 {
204         switch( event->type ) {
205         case ButtonPress: break;
206         case ButtonRelease: break;
207         case MotionNotify: break;
208         default:
209                 return check_configure_change(0);
210         }
211
212         MWindow *mwindow = plugin->server->mwindow;
213         CWindowGUI *cwindow_gui = mwindow->cwindow->gui;
214         CWindowCanvas *canvas = cwindow_gui->canvas;
215         int cx, cy;  cwindow_gui->get_relative_cursor(cx, cy);
216         cx -= mwindow->theme->ccanvas_x;
217         cy -= mwindow->theme->ccanvas_y;
218
219         if( !dragging ) {
220                 if( cx < 0 || cx >= mwindow->theme->ccanvas_w ||
221                     cy < 0 || cy >= mwindow->theme->ccanvas_h )
222                         return check_configure_change(0);
223         }
224
225         switch( event->type ) {
226         case ButtonPress:
227                 if( dragging ) return check_configure_change(0);
228                 if( event->xbutton.button == WHEEL_UP )  return threshold->wheel_event(1);
229                 if( event->xbutton.button == WHEEL_DOWN ) return threshold->wheel_event(-1);
230                 dragging = event->xbutton.state & ShiftMask ? -1 : 1;
231                 break;
232         case ButtonRelease:
233                 if( !dragging ) return check_configure_change(0);
234                 dragging = 0;
235                 return 1;
236         case MotionNotify:
237                 if( !dragging ) return check_configure_change(0);
238                 break;
239         default:
240                 return check_configure_change(0);
241         }
242
243         float cursor_x = cx, cursor_y = cy;
244         canvas->canvas_to_output(mwindow->edl, 0, cursor_x, cursor_y);
245         int64_t position = plugin->get_source_position();
246         float projector_x, projector_y, projector_z;
247         Track *track = plugin->server->plugin->track;
248         int track_w = track->track_w, track_h = track->track_h;
249         track->automation->get_projector(
250                 &projector_x, &projector_y, &projector_z,
251                 position, PLAY_FORWARD);
252         projector_x += mwindow->edl->session->output_w / 2;
253         projector_y += mwindow->edl->session->output_h / 2;
254         float output_x = (cursor_x - projector_x) / projector_z + track_w / 2;
255         float output_y = (cursor_y - projector_y) / projector_z + track_h / 2;
256         point_x->update((int64_t)(output_x));
257         point_y->update((int64_t)(output_y));
258         CriKeyPoints &points = plugin->config.points;
259
260         if( dragging > 0 ) {
261                 switch( event->type ) {
262                 case ButtonPress: {
263                         int button_no = event->xbutton.button;
264                         int hot_point = -1;
265                         if( button_no == RIGHT_BUTTON ) {
266                                 hot_point = plugin->new_point();
267                                 CriKeyPoint *pt = points[hot_point];
268                                 pt->x = output_x;  pt->y = output_y;
269                                 point_list->update(hot_point);
270                                 break;
271                         }
272                         int sz = points.size();
273                         if( hot_point < 0 && sz > 0 ) {
274                                 CriKeyPoint *pt = points[hot_point=0];
275                                 double dist = DISTANCE(output_x,output_y, pt->x,pt->y);
276                                 for( int i=1; i<sz; ++i ) {
277                                         pt = points[i];
278                                         double d = DISTANCE(output_x,output_y, pt->x,pt->y);
279                                         if( d >= dist ) continue;
280                                         dist = d;  hot_point = i;
281                                 }
282                                 pt = points[hot_point];
283                                 float px = (pt->x - track_w / 2) * projector_z + projector_x;
284                                 float py = (pt->y - track_h / 2) * projector_z + projector_y;
285                                 dist = DISTANCE(px, py, cursor_x,cursor_y);
286                                 if( dist >= HANDLE_W ) hot_point = -1;
287                         }
288                         if( hot_point >= 0 && sz > 0 ) {
289                                 CriKeyPoint *pt = points[hot_point];
290                                 point_list->set_point(hot_point, PT_X, pt->x = output_x);
291                                 for( int i=0; i<sz; ++i ) {
292                                         pt = points[i];
293                                         pt->e = i==hot_point ? !pt->e : 0;
294                                         point_list->set_point(i, PT_E, pt->e ? "*" : "");
295                                 }
296                                 point_list->update_list(hot_point);
297                         }
298                         break; }
299                 case MotionNotify: {
300                         int hot_point = point_list->get_selection_number(0, 0);
301                         if( hot_point >= 0 && hot_point < points.size() ) {
302                                 CriKeyPoint *pt = points[hot_point];
303                                 if( pt->x == output_x && pt->y == output_y ) break;
304                                 point_list->set_point(hot_point, PT_X, pt->x = output_x);
305                                 point_list->set_point(hot_point, PT_Y, pt->y = output_y);
306                                 point_x->update(pt->x);
307                                 point_y->update(pt->y);
308                                 point_list->update_list(hot_point);
309                         }
310                         break; }
311                 }
312         }
313         else {
314                 switch( event->type ) {
315                 case MotionNotify: {
316                         float dx = output_x - last_x, dy = output_y - last_y;
317                         int sz = points.size();
318                         for( int i=0; i<sz; ++i ) {
319                                 CriKeyPoint *pt = points[i];
320                                 point_list->set_point(i, PT_X, pt->x += dx);
321                                 point_list->set_point(i, PT_Y, pt->y += dy);
322                         }
323                         int hot_point = point_list->get_selection_number(0, 0);
324                         if( hot_point >= 0 && hot_point < sz ) {
325                                 CriKeyPoint *pt = points[hot_point];
326                                 point_x->update(pt->x);
327                                 point_y->update(pt->y);
328                                 point_list->update_list(hot_point);
329                         }
330                         break; }
331                 }
332         }
333
334         last_x = output_x;  last_y = output_y;
335         if( !grab_event_count() ) 
336                 send_configure_change();
337         else
338                 pending_config = 1;
339         return 1;
340 }
341
342 void CriKeyWindow::done_event(int result)
343 {
344         ungrab(client->server->mwindow->cwindow->gui);
345 }
346
347 CriKeyPointList::CriKeyPointList(CriKeyWindow *gui, CriKey *plugin, int x, int y)
348  : BC_ListBox(x, y, 360, 130, LISTBOX_TEXT)
349 {
350         this->gui = gui;
351         this->plugin = plugin;
352         titles[PT_E] = _("E");    widths[PT_E] = 50;
353         titles[PT_X] = _("X");    widths[PT_X] = 90;
354         titles[PT_Y] = _("Y");    widths[PT_Y] = 90;
355         titles[PT_T] = _("T");    widths[PT_T] = 70;
356         titles[PT_TAG] = _("Tag");  widths[PT_TAG] = 50;
357 }
358 CriKeyPointList::~CriKeyPointList()
359 {
360         clear();
361 }
362 void CriKeyPointList::clear()
363 {
364         for( int i=PT_SZ; --i>=0; )
365                 cols[i].remove_all_objects();
366 }
367
368 int CriKeyPointList::column_resize_event()
369 {
370         for( int i=PT_SZ; --i>=0; )
371                 widths[i] = get_column_width(i);
372         return 1;
373 }
374
375 int CriKeyPointList::handle_event()
376 {
377         int hot_point = get_selection_number(0, 0);
378         const char *x_text = "", *y_text = "";
379         float t = plugin->config.threshold;
380         CriKeyPoints &points = plugin->config.points;
381
382         int sz = points.size();
383         if( hot_point >= 0 && sz > 0 ) {
384                 if( get_cursor_x() < widths[0] ) {
385                         if( shift_down() ) {
386                                 int all_on = points[0]->e;
387                                 for( int i=1; i<sz && all_on; ++i ) all_on = points[i]->e;
388                                 int e = !all_on ? 1 : 0;
389                                 for( int i=0; i<sz; ++i ) points[i]->e = e;
390                                 points[hot_point]->e = 1;
391                         }
392                         else
393                                 points[hot_point]->e = !points[hot_point]->e;
394                 }
395                 x_text = gui->point_list->cols[PT_X].get(hot_point)->get_text();
396                 y_text = gui->point_list->cols[PT_Y].get(hot_point)->get_text();
397                 t = points[hot_point]->t;
398         }
399         gui->point_x->update(x_text);
400         gui->point_y->update(y_text);
401         gui->threshold->update(t);
402         update(hot_point);
403         gui->send_configure_change();
404         return 1;
405 }
406
407 int CriKeyPointList::selection_changed()
408 {
409         handle_event();
410         return 1;
411 }
412
413 void CriKeyPointList::new_point(const char *ep, const char *xp, const char *yp,
414                 const char *tp, const char *tag)
415 {
416         cols[PT_E].append(new BC_ListBoxItem(ep));
417         cols[PT_X].append(new BC_ListBoxItem(xp));
418         cols[PT_Y].append(new BC_ListBoxItem(yp));
419         cols[PT_T].append(new BC_ListBoxItem(tp));
420         cols[PT_TAG].append(new BC_ListBoxItem(tag));
421 }
422
423 void CriKeyPointList::del_point(int i)
424 {
425         for( int sz1=cols[0].size()-1, c=PT_SZ; --c>=0; )
426                 cols[c].remove_object_number(sz1-i);
427 }
428
429 void CriKeyPointList::set_point(int i, int c, float v)
430 {
431         char s[BCSTRLEN]; sprintf(s,"%0.4f",v);
432         set_point(i,c,s);
433 }
434 void CriKeyPointList::set_point(int i, int c, const char *cp)
435 {
436         cols[c].get(i)->set_text(cp);
437 }
438
439 int CriKeyPointList::set_selected(int k)
440 {
441         CriKeyPoints &points = plugin->config.points;
442         int sz = points.size();
443         if( !sz ) return -1;
444         bclamp(k, 0, sz-1);
445         for( int i=0; i<sz; ++i ) points[i]->e = 0;
446         points[k]->e = 1;
447         update_selection(&cols[0], k);
448         return k;
449 }
450 void CriKeyPointList::update_list(int k)
451 {
452         int xpos = get_xposition(), ypos = get_yposition();
453         if( k < 0 ) k = get_selection_number(0, 0);
454         update_selection(&cols[0], k);
455         BC_ListBox::update(&cols[0], &titles[0],&widths[0],PT_SZ, xpos,ypos,k);
456         center_selection();
457 }
458 void CriKeyPointList::update(int k)
459 {
460         clear();
461         CriKeyPoints &points = plugin->config.points;
462         int sz = points.size();
463         for( int i=0; i<sz; ++i ) {
464                 CriKeyPoint *pt = points[i];
465                 char etxt[BCSTRLEN];  sprintf(etxt,"%s", pt->e ? "*" : "");
466                 char xtxt[BCSTRLEN];  sprintf(xtxt,"%0.4f", pt->x);
467                 char ytxt[BCSTRLEN];  sprintf(ytxt,"%0.4f", pt->y);
468                 char ttxt[BCSTRLEN];  sprintf(ttxt,"%0.4f", pt->t);
469                 char ttag[BCSTRLEN];  sprintf(ttag,"%d", pt->tag);
470                 new_point(etxt, xtxt, ytxt, ttxt, ttag);
471         }
472         if( k >= 0 && k < sz ) {
473                 gui->point_x->update(gui->point_list->cols[PT_X].get(k)->get_text());
474                 gui->point_y->update(gui->point_list->cols[PT_Y].get(k)->get_text());
475                 plugin->config.selected = k;
476         }
477
478         update_list(k);
479 }
480
481 void CriKeyWindow::update_gui()
482 {
483         draw_mode->update(plugin->config.draw_mode);
484         threshold->update(plugin->config.threshold);
485         drag->update(plugin->config.drag);
486         point_list->update(-1);
487 }
488
489
490 CriKeyThreshold::CriKeyThreshold(CriKeyWindow *gui, int x, int y, int w)
491  : BC_FSlider(x, y, 0, w, w, 0, 1, gui->plugin->config.threshold, 0)
492 {
493         this->gui = gui;
494         set_precision(0.005);
495         set_pagination(0.01, 0.1);
496 }
497
498 int CriKeyThreshold::wheel_event(int v)
499 {
500         if( v > 0 ) increase_value();
501         else if( v < 0 ) decrease_value();
502         handle_event();
503         enable();
504         return 1;
505 }
506
507 int CriKeyThreshold::handle_event()
508 {
509         float v = get_value();
510         gui->plugin->config.threshold = v;
511         int hot_point = gui->point_list->get_selection_number(0, 0);
512         if( hot_point >= 0 ) {
513                 CriKeyPoints &points = gui->plugin->config.points;
514                 CriKeyPoint *pt = points[hot_point];
515                 pt->t = v;  pt->e = 1;
516                 gui->point_list->update(hot_point);
517         }
518         gui->send_configure_change();
519         return 1;
520 }
521
522
523 CriKeyPointUp::CriKeyPointUp(CriKeyWindow *gui, int x, int y)
524  : BC_GenericButton(x, y, _("Up"))
525 {
526         this->gui = gui;
527 }
528 CriKeyPointUp::~CriKeyPointUp()
529 {
530 }
531
532 int CriKeyPointUp::handle_event()
533 {
534         CriKeyPoints &points = gui->plugin->config.points;
535         int sz = points.size();
536         int hot_point = gui->point_list->get_selection_number(0, 0);
537
538         if( sz > 1 && hot_point > 0 ) {
539                 CriKeyPoint *&pt0 = points[hot_point];
540                 CriKeyPoint *&pt1 = points[--hot_point];
541                 CriKeyPoint *t = pt0;  pt0 = pt1;  pt1 = t;
542                 gui->point_list->update(hot_point);
543         }
544         gui->send_configure_change();
545         return 1;
546 }
547
548 CriKeyPointDn::CriKeyPointDn(CriKeyWindow *gui, int x, int y)
549  : BC_GenericButton(x, y, _("Dn"))
550 {
551         this->gui = gui;
552 }
553 CriKeyPointDn::~CriKeyPointDn()
554 {
555 }
556
557 int CriKeyPointDn::handle_event()
558 {
559         CriKeyPoints &points = gui->plugin->config.points;
560         int sz = points.size();
561         int hot_point = gui->point_list->get_selection_number(0, 0);
562         if( sz > 1 && hot_point < sz-1 ) {
563                 CriKeyPoint *&pt0 = points[hot_point];
564                 CriKeyPoint *&pt1 = points[++hot_point];
565                 CriKeyPoint *t = pt0;  pt0 = pt1;  pt1 = t;
566                 gui->point_list->update(hot_point);
567         }
568         gui->send_configure_change();
569         return 1;
570 }
571
572 CriKeyDrag::CriKeyDrag(CriKeyWindow *gui, int x, int y)
573  : BC_CheckBox(x, y, gui->plugin->config.drag, _("Drag"))
574 {
575         this->gui = gui;
576 }
577 int CriKeyDrag::handle_event()
578 {
579         CWindowGUI *cwindow_gui = gui->plugin->server->mwindow->cwindow->gui;
580         int value = get_value();
581         if( value ) {
582                 if( !gui->grab(cwindow_gui) ) {
583                         update(value = 0);
584                         flicker(10,50);
585                 }
586         }
587         else
588                 gui->ungrab(cwindow_gui);
589         gui->plugin->config.drag = value;
590         gui->send_configure_change();
591         return 1;
592 }
593
594 CriKeyNewPoint::CriKeyNewPoint(CriKeyWindow *gui, CriKey *plugin, int x, int y)
595  : BC_GenericButton(x, y, 80, _("New"))
596 {
597         this->gui = gui;
598         this->plugin = plugin;
599 }
600 CriKeyNewPoint::~CriKeyNewPoint()
601 {
602 }
603 int CriKeyNewPoint::handle_event()
604 {
605         int k = plugin->new_point();
606         gui->point_list->update(k);
607         gui->send_configure_change();
608         return 1;
609 }
610
611 CriKeyDelPoint::CriKeyDelPoint(CriKeyWindow *gui, CriKey *plugin, int x, int y)
612  : BC_GenericButton(x, y, 80, C_("Del"))
613 {
614         this->gui = gui;
615         this->plugin = plugin;
616 }
617 CriKeyDelPoint::~CriKeyDelPoint()
618 {
619 }
620 int CriKeyDelPoint::handle_event()
621 {
622         int hot_point = gui->point_list->get_selection_number(0, 0);
623         CriKeyPoints &points = plugin->config.points;
624         if( hot_point >= 0 && hot_point < points.size() ) {
625                 plugin->config.del_point(hot_point);
626                 if( !points.size() ) plugin->new_point();
627                 int sz = points.size();
628                 if( hot_point >= sz && hot_point > 0 ) --hot_point;
629                 gui->point_list->update(hot_point);
630                 gui->send_configure_change();
631         }
632         return 1;
633 }
634
635 CriKeyReset::CriKeyReset(CriKeyWindow *gui, CriKey *plugin, int x, int y)
636  : BC_GenericButton(x, y, _("Reset"))
637 {
638         this->gui = gui;
639         this->plugin = plugin;
640 }
641 CriKeyReset::~CriKeyReset()
642 {
643 }
644 int CriKeyReset::handle_event()
645 {
646         CriKeyPoints &points = plugin->config.points;
647         points.remove_all_objects();
648         plugin->new_point();
649         gui->point_list->update(0);
650         gui->send_configure_change();
651         return 1;
652 }
653