3 * Copyright (C) 2014 Adam Williams <broadcast at earthling dot net>
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.
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.
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
21 #include "automation.h"
22 #include "bcdisplayinfo.h"
25 #include "sketcherwindow.h"
28 #include "cwindowgui.h"
30 #include "edlsession.h"
33 #include "mainerror.h"
36 #include "pluginserver.h"
40 #define AltMask Mod1Mask
45 const char *SketcherPoint::types[] = {
50 const char *SketcherCurve::pens[] = {
59 SketcherCurvePenItem::SketcherCurvePenItem(int pen)
60 : BC_MenuItem(_(SketcherCurve::pens[pen]))
64 int SketcherCurvePenItem::handle_event()
66 SketcherCurvePen *popup = (SketcherCurvePen*)get_popup_menu();
68 SketcherWindow *gui = popup->gui;
69 SketcherConfig &config = gui->plugin->config;
70 int ci = config.cv_selected;
71 if( ci >= 0 && ci < config.curves.size() ) {
72 SketcherCurve *cv = config.curves[ci];
74 gui->curve_list->update(ci);
75 gui->send_configure_change();
80 SketcherCurvePen::SketcherCurvePen(SketcherWindow *gui, int x, int y, int pen)
81 : BC_PopupMenu(x,y,72,_(cv_pen[pen]))
85 void SketcherCurvePen::create_objects()
87 int n = sizeof(cv_pen)/sizeof(cv_pen[0]);
88 for( int pen=0; pen<n; ++pen )
89 add_item(new SketcherCurvePenItem(pen));
91 void SketcherCurvePen::update(int pen)
93 set_text(_(cv_pen[pen]));
97 SketcherCurveColor::SketcherCurveColor(SketcherWindow *gui, int x, int y, int w, int h)
98 : BC_Button(x, y, w, vframes)
101 this->color = CV_COLOR;
102 for( int i=0; i<3; ++i ) {
103 vframes[i] = new VFrame(w, h, BC_RGB888);
104 vframes[i]->clear_frame();
108 SketcherCurveColor::~SketcherCurveColor()
110 for( int i=0; i<3; ++i )
114 void SketcherCurveColor::set_color(int color)
117 int r = (color>>16) & 0xff;
118 int g = (color>>8) & 0xff;
119 int b = (color>>0) & 0xff;
120 for( int i=0; i<3; ++i ) {
121 VFrame *vframe = vframes[i];
122 int ww = vframe->get_w(), hh = vframe->get_h();
123 uint8_t **rows = vframe->get_rows();
124 int rr = r, gg = g, bb = b;
129 if( (rr+=48) > 0xff ) rr = 0xff;
130 if( (gg+=48) > 0xff ) gg = 0xff;
131 if( (bb+=48) > 0xff ) bb = 0xff;
134 if( (rr-=48) < 0x00 ) rr = 0x00;
135 if( (gg-=48) < 0x00 ) gg = 0x00;
136 if( (bb-=48) < 0x00 ) bb = 0x00;
139 for( int y=0; y<hh; ++y ) {
140 uint8_t *rp = rows[y];
141 for( int x=0; x<ww; ++x ) {
142 *rp++ = rr; *rp++ = gg; *rp++ = bb;
149 void SketcherCurveColor::update_gui(int color)
155 int SketcherCurveColor::handle_event()
157 gui->start_color_thread(this);
161 SketcherCurveColorPicker::SketcherCurveColorPicker(SketcherWindow *gui, SketcherCurveColor *color_button)
162 : ColorPicker(0, _("Color"))
165 this->color_button = color_button;
167 color_update = new SketcherCurveColorThread(this);
170 SketcherCurveColorPicker::~SketcherCurveColorPicker()
175 void SketcherCurveColorPicker::start(int color)
177 start_window(color, 0, 1);
178 color_update->start();
181 void SketcherCurveColorPicker::handle_done_event(int result)
183 color_update->stop();
184 gui->lock_window("SketcherCurveColorPicker::handle_done_event");
185 if( result ) color = orig_color;
186 color_button->update_gui(color);
187 gui->unlock_window();
188 SketcherConfig &config = gui->plugin->config;
189 int ci = config.cv_selected;
190 if( ci >= 0 && ci < config.curves.size() ) {
191 SketcherCurve *cv = config.curves[ci];
193 gui->curve_list->update(ci);
194 gui->send_configure_change();
198 int SketcherCurveColorPicker::handle_new_color(int color, int alpha)
201 color_update->update_lock->unlock();
205 void SketcherCurveColorPicker::update_gui()
207 gui->lock_window("SketcherCurveColorPicker::update_gui");
208 color_button->update_gui(color);
209 SketcherConfig &config = gui->plugin->config;
210 int ci = config.cv_selected;
212 SketcherCurve *cv = config.curves[ci];
214 gui->curve_list->update(ci);
215 gui->send_configure_change();
217 gui->unlock_window();
220 SketcherCurveColorThread::SketcherCurveColorThread(SketcherCurveColorPicker *color_picker)
223 this->color_picker = color_picker;
224 this->update_lock = new Condition(0,"SketcherCurveColorThread::update_lock");
228 SketcherCurveColorThread::~SketcherCurveColorThread()
234 void SketcherCurveColorThread::start()
242 void SketcherCurveColorThread::stop()
246 update_lock->unlock();
251 void SketcherCurveColorThread::run()
254 update_lock->lock("SketcherCurveColorThread::run");
256 color_picker->update_gui();
261 SketcherNum::SketcherNum(SketcherWindow *gui, int x, int y, int output,
263 : BC_TumbleTextBox(gui, output, mn, mx, x, y, 64)
269 SketcherNum::~SketcherNum()
273 int SketcherPointX::handle_event()
275 if( !SketcherNum::handle_event() ) return 0;
276 SketcherConfig &config = gui->plugin->config;
277 int ci = config.cv_selected;
278 if( ci >= 0 && ci < config.curves.size() ) {
279 SketcherCurve *cv = config.curves[ci];
280 SketcherPointList *point_list = gui->point_list;
281 int pi = config.pt_selected;
282 SketcherPoints &points = cv->points;
283 if( pi >= 0 && pi < points.size() ) {
284 int v = atoi(get_text());
286 point_list->set_point(pi, PT_X, v);
287 point_list->update_list(pi);
288 gui->send_configure_change();
293 int SketcherPointY::handle_event()
295 if( !SketcherNum::handle_event() ) return 0;
296 SketcherConfig &config = gui->plugin->config;
297 int ci = config.cv_selected;
298 if( ci >= 0 && ci < config.curves.size() ) {
299 SketcherCurve *cv = config.curves[ci];
300 SketcherPointList *point_list = gui->point_list;
301 int pi = config.pt_selected;
302 SketcherPoints &points = cv->points;
303 if( pi >= 0 && pi < points.size() ) {
304 int v = atoi(get_text());
306 point_list->set_point(pi, PT_Y, v);
307 point_list->update_list(pi);
308 gui->send_configure_change();
314 int SketcherCurveRadius::handle_event()
316 if( !SketcherNum::handle_event() ) return 0;
317 SketcherConfig &config = gui->plugin->config;
318 int ci = config.cv_selected;
319 if( ci >= 0 && ci < config.curves.size() ) {
320 SketcherCurve *cv = config.curves[ci];
321 int v = atoi(get_text());
323 gui->curve_list->update(ci);
324 gui->send_configure_change();
330 SketcherWindow::SketcherWindow(Sketcher *plugin)
331 : PluginClientWindow(plugin, 380, 580, 380, 580, 0)
333 this->plugin = plugin;
334 this->title_pen = 0; this->curve_pen = 0;
335 this->title_color = 0; this->curve_color = 0;
336 this->color_picker = 0; this->new_points = 0;
337 this->new_curve = 0; this->del_curve = 0;
338 this->curve_up = 0; this->curve_dn = 0;
339 this->title_x = 0; this->point_x = 0;
340 this->title_y = 0; this->point_y = 0;
341 this->new_point = 0; this->del_point = 0;
342 this->point_up = 0; this->point_dn = 0;
343 this->drag = 0; this->dragging = 0;
344 this->last_x = 0; this->last_y = 0;
345 this->point_list = 0; this->pending_config = 0;
348 SketcherWindow::~SketcherWindow()
356 void SketcherWindow::create_objects()
358 int x = 10, y = 10, dy = 0, x1, y1;
359 int margin = plugin->get_theme()->widget_border;
361 int ci = plugin->config.cv_selected;
362 if( ci < 0 || ci >= plugin->config.curves.size() )
363 ci = plugin->new_curve();
364 SketcherCurve *cv = plugin->config.curves[ci];
366 reset_curves = new SketcherResetCurves(this, plugin, x1=x, y+3);
367 add_subwindow(reset_curves); dy = bmax(dy,reset_curves->get_h());
368 x1 += reset_curves->get_w() + 2*margin;
369 const char *curve_text = _("Curve");
370 title_radius = new BC_Title(x1, y, _("Width:"));
371 add_subwindow(title_radius); dy = bmax(dy,title_radius->get_h());
372 x1 += title_radius->get_w() + margin;
373 curve_radius = new SketcherCurveRadius(this, x1, y, cv->radius);
374 curve_radius->create_objects();
375 y += dy + 2*margin; dy = 0;
377 x1 = get_w()-x - BC_Title::calculate_w(this, curve_text, LARGEFONT);
378 y1 = y-margin - BC_Title::calculate_h(this, curve_text, LARGEFONT);
379 title = new BC_Title(x1, y1, curve_text, LARGEFONT,
380 get_resources()->menu_highlighted_fontcolor);
381 add_subwindow(title); dy = bmax(dy,title->get_h());
382 curve_list = new SketcherCurveList(this, plugin, x, y);
383 add_subwindow(curve_list); dy = bmax(dy,curve_list->get_h());
384 y += dy + margin; dy = 0;
386 new_curve = new SketcherNewCurve(this, plugin, x1=x, y);
387 add_subwindow(new_curve); dy = bmax(dy,new_curve->get_h());
388 x1 += new_curve->get_w() + margin;
389 curve_up = new SketcherCurveUp(this, x1, y);
390 add_subwindow(curve_up); dy = bmax(dy,curve_up->get_h());
391 x1 += curve_up->get_w() + 4*margin;
392 title_pen = new BC_Title(x1+30, y, _("Pen:"));
393 add_subwindow(title_pen); dy = bmax(dy,title_pen->get_h());
394 int x2 = (get_w()+x1)/2;
395 title_color = new BC_Title(x2+10, y, _("Color:"));
396 add_subwindow(title_color); dy = bmax(dy,title_color->get_h());
397 y += dy + margin; dy = 0;
399 del_curve = new SketcherDelCurve(this, plugin, x1=x, y);
400 add_subwindow(del_curve); dy = bmax(dy,del_curve->get_h());
401 x1 += del_curve->get_w() + margin;
402 curve_dn = new SketcherCurveDn(this, x1, y);
403 add_subwindow(curve_dn); dy = bmax(dy,curve_dn->get_h());
404 x1 += curve_dn->get_w() + 4*margin;
405 curve_pen = new SketcherCurvePen(this, x1, y, cv->pen);
406 add_subwindow(curve_pen); dy = bmax(dy,curve_pen->get_h());
407 curve_pen->create_objects();
408 curve_color = new SketcherCurveColor(this, x2+20, y, COLOR_W, COLOR_H);
409 add_subwindow(curve_color); dy = bmax(dy,curve_color->get_h());
410 curve_color->set_color(cv->color);
411 curve_color->draw_face();
412 y += dy + margin; dy = 0;
413 curve_list->update(ci);
416 bar = new BC_Bar(x, y, get_w()-2*x);
417 add_subwindow(bar); dy = bmax(dy,bar->get_h());
420 int pi = plugin->config.pt_selected;
421 SketcherPoint *pt = pi >= 0 && pi < cv->points.size() ? cv->points[pi] : 0;
422 reset_points = new SketcherResetPoints(this, plugin, x1=x, y+3);
423 add_subwindow(reset_points); dy = bmax(dy,reset_points->get_h());
424 x1 += reset_points->get_w() + 2*margin;
425 if( plugin->config.drag ) {
426 if( !grab(plugin->server->mwindow->cwindow->gui) ) {
427 eprintf("drag enabled, but compositor already grabbed\n");
428 plugin->config.drag = 0;
431 drag = new SketcherDrag(this, x1, y);
432 add_subwindow(drag); dy = bmax(dy,drag->get_h());
433 x1 += drag->get_w() + 2*margin;
434 int pty = pt ? pt->pty : PTY_LINE;
435 point_type = new SketcherPointType(this, x1, y, pty);
436 add_subwindow(point_type); dy = bmax(dy,point_type->get_h());
437 point_type->create_objects();
438 y += dy + margin; dy = 0;
440 const char *point_text = _("Point");
441 x1 = get_w()-x - BC_Title::calculate_w(this, point_text, LARGEFONT);
442 y1 = y-margin - BC_Title::calculate_h(this, point_text, LARGEFONT);
443 add_subwindow(title = new BC_Title(x1, y1, point_text, LARGEFONT,
444 get_resources()->menu_highlighted_fontcolor));
445 point_list = new SketcherPointList(this, plugin, x, y);
446 add_subwindow(point_list); dy = bmax(dy,point_list->get_h());
447 y += dy + margin; dy = 0;
449 new_point = new SketcherNewPoint(this, plugin, x1=x, y);
450 add_subwindow(new_point); dy = bmax(dy,new_point->get_h());
451 x1 += new_point->get_w() + margin;
452 point_up = new SketcherPointUp(this, x1, y);
453 add_subwindow(point_up); dy = bmax(dy,point_up->get_h());
454 x1 += point_up->get_w() + 2*margin;
455 title_x = new BC_Title(x1, y, _("X:"));
456 add_subwindow(title_x); dy = bmax(dy,title_x->get_h());
457 x1 += title_x->get_w() + margin;
458 point_x = new SketcherPointX(this, x1, y, !pt ? 0.f : pt->x);
459 point_x->create_objects(); dy = bmax(dy, point_x->get_h());
460 y += dy + margin; dy = 0;
462 del_point = new SketcherDelPoint(this, plugin, x1=x, y);
463 add_subwindow(del_point); dy = bmax(dy,del_point->get_h());
464 x1 += del_point->get_w() + margin;
465 point_dn = new SketcherPointDn(this, x1, y);
466 add_subwindow(point_dn); dy = bmax(dy,point_dn->get_h());
467 x1 += point_dn->get_w() + 2*margin;
468 title_y = new BC_Title(x1, y, _("Y:"));
469 add_subwindow(title_y); dy = bmax(dy,title_y->get_h());
470 x1 += title_y->get_w() + margin;
471 point_y = new SketcherPointY(this, x1, y, !pt ? 0.f : pt->y);
472 point_y->create_objects(); dy = bmax(dy, point_y->get_h());
473 y += dy + margin + 5;
474 point_list->update(pi);
476 add_subwindow(notes0 = new BC_Title(x, y,
483 add_subwindow(notes1 = new BC_Title(x+80, y,
489 "deletes point\n")));
490 add_subwindow(notes2 = new BC_Title(x+200, y,
496 "deletes curve\n")));
500 void SketcherWindow::send_configure_change()
503 plugin->send_configure_change();
506 int SketcherWindow::grab_event(XEvent *event)
508 int ret = do_grab_event(event);
509 if( pending_config && !grab_event_count() )
510 send_configure_change();
514 int SketcherWindow::do_grab_event(XEvent *event)
516 switch( event->type ) {
517 case ButtonPress: break;
518 case ButtonRelease: break;
519 case MotionNotify: break;
521 if( keysym_lookup(event) > 0 ) {
522 switch( get_keysym() ) {
525 return (event->xkey.state & ShiftMask) ?
526 del_curve->handle_event() :
527 del_point->handle_event() ;
534 MWindow *mwindow = plugin->server->mwindow;
535 CWindowGUI *cwindow_gui = mwindow->cwindow->gui;
536 CWindowCanvas *canvas = cwindow_gui->canvas;
537 int cx, cy; cwindow_gui->get_relative_cursor(cx, cy);
538 cx -= mwindow->theme->ccanvas_x;
539 cy -= mwindow->theme->ccanvas_y;
542 if( cx < 0 || cx >= mwindow->theme->ccanvas_w ||
543 cy < 0 || cy >= mwindow->theme->ccanvas_h )
547 switch( event->type ) {
549 if( dragging ) return 0;
554 if( !dragging ) return 0;
560 SketcherConfig &config = plugin->config;
561 int ci = config.cv_selected;
562 if( ci < 0 || ci >= plugin->config.curves.size() )
564 SketcherCurves &curves = config.curves;
565 SketcherCurve *cv = curves[ci];
566 int pi = config.pt_selected;
568 float cursor_x = cx, cursor_y = cy;
569 canvas->canvas_to_output(mwindow->edl, 0, cursor_x, cursor_y);
570 int64_t position = plugin->get_source_position();
571 float projector_x, projector_y, projector_z;
572 Track *track = plugin->server->plugin->track;
573 int track_w = track->track_w, track_h = track->track_h;
574 track->automation->get_projector(
575 &projector_x, &projector_y, &projector_z,
576 position, PLAY_FORWARD);
577 projector_x += mwindow->edl->session->output_w / 2;
578 projector_y += mwindow->edl->session->output_h / 2;
579 float output_x = (cursor_x - projector_x) / projector_z + track_w / 2;
580 float output_y = (cursor_y - projector_y) / projector_z + track_h / 2;
581 SketcherPoints &points = cv->points;
582 int state = event->xmotion.state;
584 switch( event->type ) {
586 int button_no = event->xbutton.button;
587 switch( button_no ) {
589 if( (state & ShiftMask) ) { // create new point/string
591 pi = plugin->new_point(cv, PTY_LINE, output_x, output_y, pi+1);
592 point_list->update(pi);
595 if( (state & AltMask) ) { // create new curve
596 ci = plugin->new_curve(cv->pen, cv->radius, cv->color);
597 curve_list->update(ci);
598 point_list->update(-1);
601 SketcherPoint *pt = 0; // select point
602 int last_point = pi; pi = -1;
603 int n = points.size();
604 double dist = DBL_MAX;
605 for( int i=0; i<n; ++i ) {
606 SketcherPoint *p = points[i];
607 double d = DISTANCE(output_x,output_y, p->x,p->y);
608 if( d < dist ) { dist = d; pi = i; pt = p; }
611 float px = (pt->x - track_w / 2) * projector_z + projector_x;
612 float py = (pt->y - track_h / 2) * projector_z + projector_y;
613 float pix = DISTANCE(px, py, cursor_x,cursor_y);
614 if( pix >= HANDLE_W ) { pi = -1; pt = 0; }
616 if( pi != last_point )
617 point_list->set_selected(pi);
620 if( (state & ShiftMask) ) { // create new curve point
622 pi = plugin->new_point(cv, PTY_CURVE,
623 output_x, output_y, pi+1);
624 point_list->update(pi);
627 SketcherPoint *pt = 0; // select point
628 double dist = DBL_MAX;
630 for( int i=0; i<curves.size(); ++i ) {
631 SketcherCurve *crv = curves[i];
632 int pts = crv->points.size();
633 for( int k=0; k<pts; ++k ) {
634 SketcherPoint *p = crv->points[k];
635 double d = DISTANCE(output_x,output_y, p->x,p->y);
644 float px = (pt->x - track_w / 2) * projector_z + projector_x;
645 float py = (pt->y - track_h / 2) * projector_z + projector_y;
646 float pix = DISTANCE(px, py, cursor_x,cursor_y);
647 if( pix >= HANDLE_W ) { pi = -1; pt = 0; }
650 curve_list->update(ci);
651 point_list->update(pi);
657 if( (state & ShiftMask) ) { // string of points
658 if( (state & (Button1Mask|Button3Mask)) ) {
659 if( pi < 0 ) pi = points.size()-1;
661 SketcherPoint *pt = pi >= 0 && pi < points.size() ? points[pi] : 0;
662 float frac_w = DISTANCE(pt->x, pt->y, output_x, output_y) / get_w();
663 if( frac_w < 0.01 ) break; // 1 percent w
666 int pty = (state & Button1Mask) ? PTY_LINE : PTY_CURVE;
667 pi = plugin->new_point(cv, pty, output_x, output_y, pi+1);
668 point_list->update(pi);
672 if( (state & Button1Mask) ) {
673 if( (state & ControlMask) ) { // drag selected point
674 SketcherPoint *pt = pi >= 0 && pi < points.size() ? points[pi] : 0;
676 point_list->set_point(pi, PT_X, pt->x = output_x);
677 point_list->set_point(pi, PT_Y, pt->y = output_y);
678 point_list->update_list(pi);
679 point_x->update(pt->x);
680 point_y->update(pt->y);
685 if( (state & Button3Mask) ) {
686 if( (state & (ControlMask | AltMask)) ) { // drag selected curve(s)
687 SketcherCurves &curves = plugin->config.curves;
688 int dx = round(output_x - last_x);
689 int dy = round(output_y - last_y);
690 int mnc = (state & AltMask) || ci<0 ? 0 : ci;
691 int mxc = (state & AltMask) ? curves.size() : ci+1;
692 for( int i=mnc; i<mxc; ++i ) {
693 SketcherCurve *crv = plugin->config.curves[i];
694 int pts = crv->points.size();
695 for( int k=0; k<pts; ++k ) {
696 SketcherPoint *pt = crv->points[k];
697 pt->x += dx; pt->y += dy;
700 SketcherPoint *pt = pi >= 0 && pi < points.size() ?
702 point_x->update(pt ? pt->x : 0.f);
703 point_y->update(pt ? pt->y : 0.f);
704 point_list->update(pi);
709 case ButtonRelease: {
715 last_x = output_x; last_y = output_y;
720 int SketcherWindow::keypress_event()
722 int key = get_keypress();
724 case DELETE: return shift_down() ?
725 del_curve->handle_event() :
726 del_point->handle_event() ;
731 void SketcherWindow::done_event(int result)
733 ungrab(client->server->mwindow->cwindow->gui);
736 void SketcherWindow::start_color_thread(SketcherCurveColor *color_button)
740 color_picker = new SketcherCurveColorPicker(this, color_button);
741 int color = CV_COLOR, ci = plugin->config.cv_selected;
742 if( ci >= 0 && ci < plugin->config.curves.size() ) {
743 SketcherCurve *cv = plugin->config.curves[ci];
746 color_picker->start(color);
747 lock_window("SketcherWindow::start_color_thread");
751 SketcherCurveList::SketcherCurveList(SketcherWindow *gui, Sketcher *plugin, int x, int y)
752 : BC_ListBox(x, y, 360, 130, LISTBOX_TEXT)
755 this->plugin = plugin;
756 titles[CV_ID] = _("id"); widths[CV_ID] = 64;
757 titles[CV_RAD] = _("radius"); widths[CV_RAD] = 64;
758 titles[CV_PEN] = _("pen"); widths[CV_PEN] = 64;
759 titles[CV_CLR] = _("color"); widths[CV_CLR] = 64;
761 SketcherCurveList::~SketcherCurveList()
765 void SketcherCurveList::clear()
767 for( int i=CV_SZ; --i>=0; )
768 cols[i].remove_all_objects();
771 int SketcherCurveList::column_resize_event()
773 for( int i=CV_SZ; --i>=0; )
774 widths[i] = get_column_width(i);
778 int SketcherCurveList::handle_event()
780 int ci = get_selection_number(0, 0);
782 gui->point_list->update(0);
783 gui->send_configure_change();
787 int SketcherCurveList::selection_changed()
793 void SketcherCurveList::set_curve(int i, int c, const char *cp)
795 cols[c].get(i)->set_text(cp);
798 void SketcherCurveList::set_selected(int k)
801 if( k >= 0 && k < plugin->config.curves.size() ) {
802 SketcherCurve *cv = plugin->config.curves[k];
803 gui->curve_radius->update(cv->radius);
804 gui->curve_pen->update(cv->pen);
805 gui->curve_color->update_gui(cv->color);
808 plugin->config.cv_selected = ci;
812 void SketcherCurveList::update_list(int k)
814 int xpos = get_xposition(), ypos = get_yposition();
815 if( k >= 0 ) update_selection(&cols[0], k);
816 BC_ListBox::update(&cols[0], &titles[0],&widths[0],CV_SZ, xpos,ypos,k);
820 void SketcherCurveList::update(int k)
823 SketcherCurves &curves = plugin->config.curves;
824 int sz = curves.size();
825 for( int i=0; i<sz; ++i ) {
826 SketcherCurve *cv = curves[i];
827 char itxt[BCSTRLEN]; sprintf(itxt,"%d", cv->id);
828 char ptxt[BCSTRLEN]; sprintf(ptxt,"%s", cv_pen[cv->pen]);
829 char rtxt[BCSTRLEN]; sprintf(rtxt,"%d", cv->radius);
830 int color = cv->color;
831 int r = (color>>16)&0xff, g = (color>>8)&0xff, b = (color>>0)&0xff;
832 char ctxt[BCSTRLEN]; sprintf(ctxt,"#%02x%02x%02x", r, g, b);
833 add_curve(itxt, ptxt, rtxt, ctxt);
838 void SketcherCurveList::add_curve(const char *id, const char *pen,
839 const char *radius, const char *color)
841 cols[CV_ID].append(new BC_ListBoxItem(id));
842 cols[CV_RAD].append(new BC_ListBoxItem(radius));
843 cols[CV_PEN].append(new BC_ListBoxItem(pen));
844 cols[CV_CLR].append(new BC_ListBoxItem(color));
847 SketcherNewCurve::SketcherNewCurve(SketcherWindow *gui, Sketcher *plugin, int x, int y)
848 : BC_GenericButton(x, y, 64, _("New"))
851 this->plugin = plugin;
853 SketcherNewCurve::~SketcherNewCurve()
856 int SketcherNewCurve::handle_event()
858 int pen = PTY_LINE, radius = 1, color = CV_COLOR;
859 int ci = plugin->config.cv_selected;
860 if( ci >= 0 && ci < plugin->config.curves.size() ) {
861 SketcherCurve *cv = plugin->config.curves[ci];
862 pen = cv->pen; radius = cv->radius; color = cv->color;
864 ci = plugin->new_curve(pen, radius, color);
865 gui->curve_list->update(ci);
866 gui->point_list->update(-1);
867 gui->send_configure_change();
871 SketcherDelCurve::SketcherDelCurve(SketcherWindow *gui, Sketcher *plugin, int x, int y)
872 : BC_GenericButton(x, y, 64, C_("Del"))
875 this->plugin = plugin;
877 SketcherDelCurve::~SketcherDelCurve()
880 int SketcherDelCurve::handle_event()
882 SketcherConfig &config = plugin->config;
883 int ci = config.cv_selected;
884 SketcherCurves &curves = config.curves;
885 if( ci >= 0 && ci < curves.size() ) {
886 curves.remove_object_number(ci--);
889 ci = plugin->new_curve();
890 gui->curve_list->update(ci);
891 gui->point_list->update(-1);
892 gui->send_configure_change();
897 SketcherCurveUp::SketcherCurveUp(SketcherWindow *gui, int x, int y)
898 : BC_GenericButton(x, y, _("Up"))
902 SketcherCurveUp::~SketcherCurveUp()
906 int SketcherCurveUp::handle_event()
908 SketcherConfig &config = gui->plugin->config;
909 int ci = config.cv_selected;
910 SketcherCurves &curves = config.curves;
911 if( ci > 0 && ci < curves.size() ) {
912 SketcherCurve *&cv0 = curves[ci];
913 SketcherCurve *&cv1 = curves[--ci];
914 SketcherCurve *t = cv0; cv0 = cv1; cv1 = t;
915 gui->curve_list->update(ci);
917 gui->send_configure_change();
921 SketcherCurveDn::SketcherCurveDn(SketcherWindow *gui, int x, int y)
922 : BC_GenericButton(x, y, _("Dn"))
926 SketcherCurveDn::~SketcherCurveDn()
930 int SketcherCurveDn::handle_event()
932 SketcherConfig &config = gui->plugin->config;
933 int ci = config.cv_selected;
934 SketcherCurves &curves = config.curves;
935 if( ci >= 0 && ci < curves.size()-1 ) {
936 SketcherCurve *&cv0 = curves[ci];
937 SketcherCurve *&cv1 = curves[++ci];
938 SketcherCurve *t = cv0; cv0 = cv1; cv1 = t;
939 gui->curve_list->update(ci);
941 gui->send_configure_change();
946 SketcherPointTypeItem::SketcherPointTypeItem(int pty)
947 : BC_MenuItem(_(pt_type[pty]))
951 int SketcherPointTypeItem::handle_event()
953 SketcherPointType *popup = (SketcherPointType*)get_popup_menu();
955 SketcherWindow *gui = popup->gui;
956 SketcherConfig &config = gui->plugin->config;
957 SketcherCurves &curves = config.curves;
958 int ci = config.cv_selected;
959 if( ci < 0 || ci >= curves.size() )
961 SketcherCurve *cv = curves[ci];
962 SketcherPoints &points = cv->points;
963 int pi = config.pt_selected;
965 ArrayList<int> selected;
966 for( int v,i=0; (v=gui->point_list->get_selection_number(0, i))>=0; ++i )
969 for( int i=selected.size(); --i>=0; ) {
971 if( k < 0 || k >= points.size() ) continue;
972 SketcherPoint *pt = cv->points[k];
974 gui->point_list->set_point(k, PT_TY, _(pt_type[pty]));
977 gui->point_list->update_list(pi);
978 gui->send_configure_change();
982 SketcherPointType::SketcherPointType(SketcherWindow *gui, int x, int y, int pty)
983 : BC_PopupMenu(x,y,64,_(pt_type[pty]))
987 void SketcherPointType::create_objects()
989 for( int pty=0; pty<PT_SZ; ++pty )
990 add_item(new SketcherPointTypeItem(pty));
992 void SketcherPointType::update(int pty)
994 set_text(_(pt_type[pty]));
998 SketcherPointList::SketcherPointList(SketcherWindow *gui, Sketcher *plugin, int x, int y)
999 : BC_ListBox(x, y, 360, 130, LISTBOX_TEXT)
1002 this->plugin = plugin;
1003 titles[PT_ID] = _("ID"); widths[PT_ID] = 50;
1004 titles[PT_TY] = _("Type"); widths[PT_TY] = 80;
1005 titles[PT_X] = _("X"); widths[PT_X] = 90;
1006 titles[PT_Y] = _("Y"); widths[PT_Y] = 90;
1007 set_selection_mode(LISTBOX_MULTIPLE);
1009 SketcherPointList::~SketcherPointList()
1013 void SketcherPointList::clear()
1015 for( int i=PT_SZ; --i>=0; )
1016 cols[i].remove_all_objects();
1019 int SketcherPointList::column_resize_event()
1021 for( int i=PT_SZ; --i>=0; )
1022 widths[i] = get_column_width(i);
1026 int SketcherPointList::handle_event()
1028 int pi = get_selection_number(0, 0);
1029 if( get_selection_number(0, 1) >= 0 ) pi = -1;
1031 gui->send_configure_change();
1035 int SketcherPointList::selection_changed()
1041 void SketcherPointList::add_point(const char *id, const char *ty, const char *xp, const char *yp)
1043 cols[PT_ID].append(new BC_ListBoxItem(id));
1044 cols[PT_TY].append(new BC_ListBoxItem(ty));
1045 cols[PT_X].append(new BC_ListBoxItem(xp));
1046 cols[PT_Y].append(new BC_ListBoxItem(yp));
1049 void SketcherPointList::set_point(int i, int c, int v)
1051 char stxt[BCSTRLEN];
1052 sprintf(stxt,"%d",v);
1053 set_point(i,c,stxt);
1055 void SketcherPointList::set_point(int i, int c, const char *cp)
1057 cols[c].get(i)->set_text(cp);
1060 void SketcherPointList::set_selected(int k)
1062 SketcherPoint *pt = 0;
1063 int ci = plugin->config.cv_selected, pi = -1;
1064 if( ci >= 0 && ci < plugin->config.curves.size() ) {
1065 SketcherCurve *cv = plugin->config.curves[ci];
1066 pt = k >= 0 && k < cv->points.size() ? cv->points[pi=k] : 0;
1068 gui->point_type->update(pt ? pt->pty : PTY_OFF);
1069 gui->point_x->update(pt ? pt->x : 0.f);
1070 gui->point_y->update(pt ? pt->y : 0.f);
1071 plugin->config.pt_selected = pi;
1074 void SketcherPointList::update_list(int k)
1076 int xpos = get_xposition(), ypos = get_yposition();
1077 if( k >= 0 ) update_selection(&cols[0], k);
1078 BC_ListBox::update(&cols[0], &titles[0],&widths[0],PT_SZ, xpos,ypos,k);
1081 void SketcherPointList::update(int k)
1084 int ci = plugin->config.cv_selected, sz = 0;
1085 if( ci >= 0 && ci < plugin->config.curves.size() ) {
1086 SketcherCurve *cv = plugin->config.curves[ci];
1087 SketcherPoints &points = cv->points;
1089 for( int i=0; i<sz; ++i ) {
1090 SketcherPoint *pt = points[i];
1091 char itxt[BCSTRLEN]; sprintf(itxt,"%d", pt->id);
1092 char ttxt[BCSTRLEN]; sprintf(ttxt,"%s", _(pt_type[pt->pty]));
1093 char xtxt[BCSTRLEN]; sprintf(xtxt,"%d", pt->x);
1094 char ytxt[BCSTRLEN]; sprintf(ytxt,"%d", pt->y);
1095 add_point(itxt, ttxt, xtxt, ytxt);
1101 void SketcherWindow::update_gui()
1103 SketcherConfig &config = plugin->config;
1104 int ci = config.cv_selected;
1105 int pi = config.pt_selected;
1106 curve_list->update(ci);
1107 point_list->update(pi);
1108 SketcherCurve *cv = ci >= 0 ? config.curves[ci] : 0;
1109 curve_radius->update(cv ? cv->radius : 1);
1110 curve_pen->update(cv ? cv->pen : PEN_SQUARE);
1111 curve_color->set_color(cv ? cv->color : CV_COLOR);
1112 SketcherPoint *pt = pi >= 0 ? cv->points[pi] : 0;
1113 point_x->update(pt ? pt->x : 0);
1114 point_y->update(pt ? pt->y : 0);
1115 drag->update(plugin->config.drag);
1119 SketcherPointUp::SketcherPointUp(SketcherWindow *gui, int x, int y)
1120 : BC_GenericButton(x, y, _("Up"))
1124 SketcherPointUp::~SketcherPointUp()
1128 int SketcherPointUp::handle_event()
1130 SketcherConfig &config = gui->plugin->config;
1131 int ci = config.cv_selected;
1132 if( ci < 0 || ci >= config.curves.size() )
1134 SketcherCurve *cv = config.curves[ci];
1135 SketcherPoints &points = cv->points;
1136 if( points.size() < 2 )
1138 int pi = config.pt_selected;
1140 ArrayList<int> selected;
1141 for( int v,i=0; (v=gui->point_list->get_selection_number(0, i))>=0; ++i )
1144 for( int i=0; i<selected.size(); ++i ) {
1145 int k = selected[i];
1146 if( k <= 0 ) continue;
1148 SketcherPoint *&pt0 = points[k];
1149 SketcherPoint *&pt1 = points[--k];
1150 SketcherPoint *t = pt0; pt0 = pt1; pt1 = t;
1152 gui->point_list->update(pi);
1153 gui->send_configure_change();
1157 SketcherPointDn::SketcherPointDn(SketcherWindow *gui, int x, int y)
1158 : BC_GenericButton(x, y, _("Dn"))
1162 SketcherPointDn::~SketcherPointDn()
1166 int SketcherPointDn::handle_event()
1168 SketcherConfig &config = gui->plugin->config;
1169 int ci = config.cv_selected;
1170 if( ci < 0 || ci >= config.curves.size() )
1172 SketcherCurve *cv = config.curves[ci];
1173 SketcherPoints &points = cv->points;
1174 int sz1 = points.size()-1;
1177 int pi = config.pt_selected;
1179 ArrayList<int> selected;
1180 for( int v,i=0; (v=gui->point_list->get_selection_number(0, i))>=0; ++i )
1183 for( int i=selected.size(); --i>=0; ) {
1184 int k = selected[i];
1185 if( k >= sz1 ) continue;
1187 SketcherPoint *&pt0 = points[k];
1188 SketcherPoint *&pt1 = points[++k];
1189 SketcherPoint *t = pt0; pt0 = pt1; pt1 = t;
1191 gui->point_list->update(pi);
1192 gui->send_configure_change();
1196 SketcherDrag::SketcherDrag(SketcherWindow *gui, int x, int y)
1197 : BC_CheckBox(x, y, gui->plugin->config.drag, _("Drag"))
1201 int SketcherDrag::handle_event()
1203 CWindowGUI *cwindow_gui = gui->plugin->server->mwindow->cwindow->gui;
1204 int value = get_value();
1206 if( !gui->grab(cwindow_gui) ) {
1212 gui->ungrab(cwindow_gui);
1213 gui->plugin->config.drag = value;
1214 gui->send_configure_change();
1218 SketcherNewPoint::SketcherNewPoint(SketcherWindow *gui, Sketcher *plugin, int x, int y)
1219 : BC_GenericButton(x, y, 64, _("New"))
1222 this->plugin = plugin;
1224 SketcherNewPoint::~SketcherNewPoint()
1227 int SketcherNewPoint::handle_event()
1229 int pi = plugin->config.pt_selected;
1230 int k = plugin->new_point(pi+1);
1231 gui->point_list->update(k);
1232 gui->send_configure_change();
1236 SketcherDelPoint::SketcherDelPoint(SketcherWindow *gui, Sketcher *plugin, int x, int y)
1237 : BC_GenericButton(x, y, 64, C_("Del"))
1240 this->plugin = plugin;
1242 SketcherDelPoint::~SketcherDelPoint()
1245 int SketcherDelPoint::handle_event()
1247 SketcherConfig &config = gui->plugin->config;
1248 SketcherCurves &curves = config.curves;
1249 int ci = config.cv_selected;
1250 if( ci < 0 || ci >= curves.size() )
1252 SketcherCurve *cv = curves[ci];
1253 SketcherPoints &points = cv->points;
1254 int pi = config.pt_selected;
1256 ArrayList<int> selected;
1257 for( int v,i=0; (v=gui->point_list->get_selection_number(0, i))>=0; ++i )
1260 for( int i=selected.size(); --i>=0; ) {
1261 int k = selected[i];
1262 if( k < 0 || k >= points.size() ) continue;
1263 points.remove_object_number(k);
1264 if( k == pi && --pi < 0 && points.size() > 0 ) pi = 0;
1266 gui->point_list->update(pi);
1267 gui->send_configure_change();
1271 SketcherResetCurves::SketcherResetCurves(SketcherWindow *gui, Sketcher *plugin, int x, int y)
1272 : BC_GenericButton(x, y, _("Reset"))
1275 this->plugin = plugin;
1277 SketcherResetCurves::~SketcherResetCurves()
1280 int SketcherResetCurves::handle_event()
1282 SketcherConfig &config = plugin->config;
1283 config.curves.remove_all_objects();
1284 int ci = plugin->new_curve();
1285 gui->curve_list->update(ci);
1286 gui->point_list->update(-1);
1287 gui->send_configure_change();
1291 SketcherResetPoints::SketcherResetPoints(SketcherWindow *gui, Sketcher *plugin, int x, int y)
1292 : BC_GenericButton(x, y, _("Reset"))
1295 this->plugin = plugin;
1297 SketcherResetPoints::~SketcherResetPoints()
1300 int SketcherResetPoints::handle_event()
1302 SketcherConfig &config = gui->plugin->config;
1303 int ci = config.cv_selected;
1304 if( ci >= 0 && ci < config.curves.size() ) {
1305 SketcherCurve *cv = config.curves[ci];
1306 cv->points.remove_all_objects();
1307 gui->point_list->update(-1);
1308 gui->send_configure_change();