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"
43 const char *SketcherCurve::types[] = {
48 const char *SketcherCurve::pens[] = {
55 SketcherCurveTypeItem::SketcherCurveTypeItem(int ty)
56 : BC_MenuItem(_(cv_type[ty]))
60 int SketcherCurveTypeItem::handle_event()
62 SketcherCurveType *popup = (SketcherCurveType*)get_popup_menu();
64 SketcherWindow *gui = popup->gui;
65 SketcherConfig &config = gui->plugin->config;
66 int ci = config.cv_selected;
67 if( ci >= 0 && ci < config.curves.size() ) {
68 SketcherCurve *cv = config.curves[ci];
70 gui->curve_list->update(ci);
71 gui->send_configure_change();
76 SketcherCurveType::SketcherCurveType(SketcherWindow *gui, int x, int y, int ty)
77 : BC_PopupMenu(x,y,64,_(cv_type[ty]))
81 void SketcherCurveType::create_objects()
83 int n = sizeof(cv_type)/sizeof(cv_type[0]);
84 for( int ty=0; ty<n; ++ty )
85 add_item(new SketcherCurveTypeItem(ty));
87 void SketcherCurveType::update(int ty)
89 set_text(_(cv_type[ty]));
93 SketcherCurvePenItem::SketcherCurvePenItem(int pen)
94 : BC_MenuItem(_(cv_pen[pen]))
98 int SketcherCurvePenItem::handle_event()
100 SketcherCurvePen *popup = (SketcherCurvePen*)get_popup_menu();
102 SketcherWindow *gui = popup->gui;
103 SketcherConfig &config = gui->plugin->config;
104 int ci = config.cv_selected;
105 if( ci >= 0 && ci < config.curves.size() ) {
106 SketcherCurve *cv = config.curves[ci];
108 gui->curve_list->update(ci);
109 gui->send_configure_change();
114 SketcherCurvePen::SketcherCurvePen(SketcherWindow *gui, int x, int y, int pen)
115 : BC_PopupMenu(x,y,72,_(cv_pen[pen]))
119 void SketcherCurvePen::create_objects()
121 int n = sizeof(cv_pen)/sizeof(cv_pen[0]);
122 for( int pen=0; pen<n; ++pen )
123 add_item(new SketcherCurvePenItem(pen));
125 void SketcherCurvePen::update(int pen)
127 set_text(_(cv_pen[pen]));
131 SketcherCurveColor::SketcherCurveColor(SketcherWindow *gui, int x, int y, int w)
132 : BC_Button(x, y, w, vframes)
136 for( int i=0; i<3; ++i ) {
137 vframes[i] = new VFrame(w, w, BC_RGBA8888);
138 vframes[i]->clear_frame();
142 SketcherCurveColor::~SketcherCurveColor()
144 for( int i=0; i<3; ++i )
148 void SketcherCurveColor::set_color(int color)
151 int r = (color>>16) & 0xff;
152 int g = (color>>8) & 0xff;
153 int b = (color>>0) & 0xff;
154 for( int i=0; i<3; ++i ) {
155 VFrame *vframe = vframes[i];
156 int ww = vframe->get_w(), hh = vframe->get_h();
157 int cx = (ww+1)/2, cy = hh/2;
158 double cc = (cx*cx + cy*cy) / 4.;
159 uint8_t *bp = vframe->get_data(), *dp = bp;
160 uint8_t *ep = dp + vframe->get_data_size();
161 int rr = r, gg = g, bb = b;
162 int bpl = vframe->get_bytes_per_line();
167 if( (rr+=48) > 0xff ) rr = 0xff;
168 if( (gg+=48) > 0xff ) gg = 0xff;
169 if( (bb+=48) > 0xff ) bb = 0xff;
172 if( (rr-=48) < 0x00 ) rr = 0x00;
173 if( (gg-=48) < 0x00 ) gg = 0x00;
174 if( (bb-=48) < 0x00 ) bb = 0x00;
178 int yy = (dp-bp) / bpl, xx = ((dp-bp) % bpl) >> 2;
179 int dy = cy - yy, dx = cx - xx;
180 double s = dx*dx + dy*dy - cc;
181 double ss = s < 0 ? 1 : s >= cc ? 0 : 1 - s/cc;
183 *dp++ = rr; *dp++ = gg; *dp++ = bb; *dp++ = aa;
189 void SketcherCurveColor::update_gui(int color)
195 int SketcherCurveColor::handle_event()
197 gui->start_color_thread(this);
201 SketcherCurveColorPicker::SketcherCurveColorPicker(SketcherWindow *gui, SketcherCurveColor *color_button)
202 : ColorPicker(0, _("Color"))
205 this->color_button = color_button;
207 color_update = new SketcherCurveColorThread(this);
210 SketcherCurveColorPicker::~SketcherCurveColorPicker()
215 void SketcherCurveColorPicker::start(int color)
217 start_window(color, 0, 1);
218 color_update->start();
221 void SketcherCurveColorPicker::handle_done_event(int result)
223 color_update->stop();
224 gui->lock_window("SketcherCurveColorPicker::handle_done_event");
225 if( result ) color = orig_color;
226 color_button->update_gui(color);
227 gui->unlock_window();
228 SketcherConfig &config = gui->plugin->config;
229 int ci = config.cv_selected;
230 if( ci >= 0 && ci < config.curves.size() ) {
231 SketcherCurve *cv = config.curves[ci];
233 gui->curve_list->update(ci);
234 gui->send_configure_change();
238 int SketcherCurveColorPicker::handle_new_color(int color, int alpha)
241 color_update->update_lock->unlock();
245 void SketcherCurveColorPicker::update_gui()
247 gui->lock_window("SketcherCurveColorPicker::update_gui");
248 color_button->update_gui(color);
249 SketcherConfig &config = gui->plugin->config;
250 int ci = config.cv_selected;
252 SketcherCurve *cv = config.curves[ci];
254 gui->curve_list->update(ci);
255 gui->send_configure_change();
257 gui->unlock_window();
260 SketcherCurveColorThread::SketcherCurveColorThread(SketcherCurveColorPicker *color_picker)
263 this->color_picker = color_picker;
264 this->update_lock = new Condition(0,"SketcherCurveColorThread::update_lock");
268 SketcherCurveColorThread::~SketcherCurveColorThread()
274 void SketcherCurveColorThread::start()
282 void SketcherCurveColorThread::stop()
286 update_lock->unlock();
291 void SketcherCurveColorThread::run()
294 update_lock->lock("SketcherCurveColorThread::run");
296 color_picker->update_gui();
301 SketcherNum::SketcherNum(SketcherWindow *gui, int x, int y, int output,
303 : BC_TumbleTextBox(gui, output, mn, mx, x, y, 64)
309 SketcherNum::~SketcherNum()
313 int SketcherPointX::handle_event()
315 if( !SketcherNum::handle_event() ) return 0;
316 SketcherConfig &config = gui->plugin->config;
317 int ci = config.cv_selected;
318 if( ci >= 0 && ci < config.curves.size() ) {
319 SketcherCurve *cv = config.curves[ci];
320 SketcherPointList *point_list = gui->point_list;
321 int hot_point = point_list->get_selection_number(0, 0);
322 SketcherPoints &points = cv->points;
323 if( hot_point >= 0 && hot_point < points.size() ) {
324 int v = atoi(get_text());
325 points[hot_point]->x = v;
326 point_list->set_point(hot_point, PT_X, v);
327 point_list->update_list(hot_point);
328 gui->send_configure_change();
333 int SketcherPointY::handle_event()
335 if( !SketcherNum::handle_event() ) return 0;
336 SketcherConfig &config = gui->plugin->config;
337 int ci = config.cv_selected;
338 if( ci >= 0 && ci < config.curves.size() ) {
339 SketcherCurve *cv = config.curves[ci];
340 SketcherPointList *point_list = gui->point_list;
341 int hot_point = point_list->get_selection_number(0, 0);
342 SketcherPoints &points = cv->points;
343 if( hot_point >= 0 && hot_point < points.size() ) {
344 int v = atoi(get_text());
345 points[hot_point]->y = v;
346 point_list->set_point(hot_point, PT_Y, v);
347 point_list->update_list(hot_point);
348 gui->send_configure_change();
354 int SketcherCurveRadius::handle_event()
356 if( !SketcherNum::handle_event() ) return 0;
357 SketcherConfig &config = gui->plugin->config;
358 int ci = config.cv_selected;
359 if( ci >= 0 && ci < config.curves.size() ) {
360 SketcherCurve *cv = config.curves[ci];
361 int v = atoi(get_text());
363 gui->curve_list->update(ci);
364 gui->send_configure_change();
370 SketcherWindow::SketcherWindow(Sketcher *plugin)
371 : PluginClientWindow(plugin, 380, 580, 380, 580, 0)
373 this->plugin = plugin;
374 this->title_type = 0; this->curve_type = 0;
375 this->title_pen = 0; this->curve_pen = 0;
376 this->title_color = 0; this->curve_color = 0;
377 this->color_picker = 0; this->new_points = 0;
378 this->new_curve = 0; this->del_curve = 0;
379 this->curve_up = 0; this->curve_dn = 0;
380 this->title_x = 0; this->point_x = 0;
381 this->title_y = 0; this->point_y = 0;
382 this->new_point = 0; this->del_point = 0;
383 this->point_up = 0; this->point_dn = 0;
384 this->drag = 0; this->dragging = 0;
385 this->last_x = 0; this->last_y = 0;
386 this->point_list = 0; this->pending_config = 0;
389 SketcherWindow::~SketcherWindow()
397 void SketcherWindow::create_objects()
399 int x = 10, y = 10, x1, y1;
400 int margin = plugin->get_theme()->widget_border;
402 int ci = plugin->config.cv_selected;
403 if( ci < 0 || ci >= plugin->config.curves.size() )
404 ci = plugin->new_curve(0, 1, 0, BLACK);
405 SketcherCurve *cv = plugin->config.curves[ci];
406 add_subwindow(reset_curves = new SketcherResetCurves(this, plugin, x1=x, y+3));
407 x1 += reset_curves->get_w() + 2*margin;
408 const char *curve_text = _("Curve");
409 add_subwindow(title_radius = new BC_Title(x1, y, _("Width:")));
410 x1 += title_radius->get_w() + margin;
411 curve_radius = new SketcherCurveRadius(this, x1, y, cv->radius);
412 curve_radius->create_objects();
413 y += reset_curves->get_h() + 2*margin;
414 x1 = get_w()-x - BC_Title::calculate_w(this, curve_text, LARGEFONT);
415 y1 = y-margin - BC_Title::calculate_h(this, curve_text, LARGEFONT);
416 add_subwindow(title = new BC_Title(x1, y1, curve_text, LARGEFONT,
417 get_resources()->menu_highlighted_fontcolor));
418 add_subwindow(curve_list = new SketcherCurveList(this, plugin, x, y));
419 y += curve_list->get_h() + margin;
420 add_subwindow(title_type = new BC_Title(x, y, _("Type:")));
421 x1 = x + title_type->get_w() + margin;
422 add_subwindow(curve_type = new SketcherCurveType(this, x1, y, cv->ty));
423 curve_type->create_objects();
424 x1 += curve_type->get_w() + margin;
425 add_subwindow(new_curve = new SketcherNewCurve(this, plugin, x1, y));
426 x1 += new_curve->get_w() + margin;
427 add_subwindow(curve_up = new SketcherCurveUp(this, x1, y));
428 x1 += curve_up->get_w() + 2*margin;
429 add_subwindow(title_color = new BC_Title(x1, y, _("Color:")));
430 y += curve_type->get_h() + margin;
432 add_subwindow(title_pen = new BC_Title(x, y, _("Pen:")));
433 x1 = x + title_pen->get_w() + margin;
434 add_subwindow(curve_pen = new SketcherCurvePen(this, x1, y, cv->pen));
435 curve_pen->create_objects();
436 x1 += curve_pen->get_w() + margin;
437 add_subwindow(del_curve = new SketcherDelCurve(this, plugin, x1, y));
438 x1 += del_curve->get_w() + margin;
439 add_subwindow(curve_dn = new SketcherCurveDn(this, x1, y));
440 x1 += curve_dn->get_w() + 2*margin;
441 add_subwindow(curve_color = new SketcherCurveColor(this, x1, y, COLOR_W));
442 curve_color->create_objects();
443 curve_color->set_color(cv->color);
444 curve_color->draw_face();
445 y += COLOR_H + margin;
446 curve_list->update(ci);
449 add_subwindow(bar = new BC_Bar(x, y, get_w()-2*x));
450 y += bar->get_h() + 2*margin;
452 int pi = plugin->config.pt_selected;
453 SketcherPoint *pt = pi >= 0 && pi < cv->points.size() ? cv->points[pi] : 0;
454 add_subwindow(reset_points = new SketcherResetPoints(this, plugin, x1=x, y+3));
455 x1 += reset_points->get_w() + 2*margin;
456 add_subwindow(drag = new SketcherDrag(this, x1, y));
457 y += drag->get_h() + margin;
458 if( plugin->config.drag ) {
459 if( !grab(plugin->server->mwindow->cwindow->gui) )
460 eprintf("drag enabled, but compositor already grabbed\n");
462 const char *point_text = _("Point");
463 x1 = get_w()-x - BC_Title::calculate_w(this, point_text, LARGEFONT);
464 y1 = y-margin - BC_Title::calculate_h(this, point_text, LARGEFONT);
465 add_subwindow(title = new BC_Title(x1, y1, point_text, LARGEFONT,
466 get_resources()->menu_highlighted_fontcolor));
467 add_subwindow(point_list = new SketcherPointList(this, plugin, x, y));
469 y += point_list->get_h() + margin;
470 add_subwindow(title_x = new BC_Title(x, y, _("X:")));
471 x1 = x + title_x->get_w() + margin;
472 point_x = new SketcherPointX(this, x1, y, !pt ? 0.f : pt->x);
473 point_x->create_objects();
474 x1 += point_x->get_w() + 2*margin;
475 add_subwindow(new_point = new SketcherNewPoint(this, plugin, x1, y));
476 x1 += new_point->get_w() + margin;
477 add_subwindow(point_up = new SketcherPointUp(this, x1, y));
478 y += point_x->get_h() + margin;
479 add_subwindow(title_y = new BC_Title(x, y, _("Y:")));
480 x1 = x + title_y->get_w() + margin;
481 point_y = new SketcherPointY(this, x1, y, !pt ? 0.f : pt->y);
482 point_y->create_objects();
483 x1 += point_y->get_w() + 2*margin;
484 add_subwindow(del_point = new SketcherDelPoint(this, plugin, x1, y));
485 x1 += del_point->get_w() + margin;
486 add_subwindow(point_dn = new SketcherPointDn(this, x1, y));
487 y += point_y->get_h() + margin + 10;
488 point_list->update(pi);
490 add_subwindow(notes0 = new BC_Title(x, y,
496 add_subwindow(notes1 = new BC_Title(x+80, y,
501 "deletes point\n")));
502 add_subwindow(notes2 = new BC_Title(x+200, y,
504 "append new points\n"
511 void SketcherWindow::send_configure_change()
514 plugin->send_configure_change();
517 int SketcherWindow::grab_event(XEvent *event)
519 int ret = do_grab_event(event);
520 if( pending_config && !grab_event_count() )
521 send_configure_change();
525 int SketcherWindow::do_grab_event(XEvent *event)
527 switch( event->type ) {
528 case ButtonPress: break;
529 case ButtonRelease: break;
530 case MotionNotify: break;
532 if( keysym_lookup(event) > 0 ) {
533 switch( get_keysym() ) {
535 return (event->xkey.state & ShiftMask) ?
536 del_curve->handle_event() :
537 del_point->handle_event() ;
544 MWindow *mwindow = plugin->server->mwindow;
545 CWindowGUI *cwindow_gui = mwindow->cwindow->gui;
546 CWindowCanvas *canvas = cwindow_gui->canvas;
547 int cx, cy; cwindow_gui->get_relative_cursor(cx, cy);
548 cx -= mwindow->theme->ccanvas_x;
549 cy -= mwindow->theme->ccanvas_y;
552 if( cx < 0 || cx >= mwindow->theme->ccanvas_w ||
553 cy < 0 || cy >= mwindow->theme->ccanvas_h )
557 switch( event->type ) {
559 if( dragging ) return 0;
560 dragging = event->xbutton.state & Mod1Mask ? -1 : 1; // alt_down
564 if( !dragging ) return 0;
571 int ci = plugin->config.cv_selected;
572 if( ci < 0 || ci >= plugin->config.curves.size() )
575 float cursor_x = cx, cursor_y = cy;
576 canvas->canvas_to_output(mwindow->edl, 0, cursor_x, cursor_y);
577 int64_t position = plugin->get_source_position();
578 float projector_x, projector_y, projector_z;
579 Track *track = plugin->server->plugin->track;
580 int track_w = track->track_w, track_h = track->track_h;
581 track->automation->get_projector(
582 &projector_x, &projector_y, &projector_z,
583 position, PLAY_FORWARD);
584 projector_x += mwindow->edl->session->output_w / 2;
585 projector_y += mwindow->edl->session->output_h / 2;
586 float output_x = (cursor_x - projector_x) / projector_z + track_w / 2;
587 float output_y = (cursor_y - projector_y) / projector_z + track_h / 2;
588 SketcherCurve *cv = plugin->config.curves[ci];
589 SketcherPoints &points = cv->points;
590 int state = event->xmotion.state;
592 switch( event->type ) {
594 if( dragging < 0 ) break;
596 int button_no = event->xbutton.button;
597 if( button_no == LEFT_BUTTON ) {
598 // create new point string
599 if( (state & ShiftMask) ) {
601 hot_point = plugin->new_point(cv, output_x, output_y);
602 point_list->update(hot_point);
606 int sz = points.size();
607 int last_point = hot_point;
609 SketcherPoint *pt = points[hot_point=0];
610 double dist = DISTANCE(output_x,output_y, pt->x,pt->y);
611 for( int i=1; i<sz; ++i ) {
613 double d = DISTANCE(output_x,output_y, pt->x,pt->y);
614 if( d >= dist ) continue;
615 dist = d; hot_point = i;
617 pt = points[hot_point];
618 float px = (pt->x - track_w / 2) * projector_z + projector_x;
619 float py = (pt->y - track_h / 2) * projector_z + projector_y;
620 dist = DISTANCE(px, py, cursor_x,cursor_y);
621 if( dist >= HANDLE_W ) hot_point = -1;
623 if( hot_point != last_point ) {
624 SketcherPoint *pt = 0;
625 if( hot_point >= 0 && hot_point < sz ) {
626 pt = points[hot_point];
627 point_list->set_point(hot_point, PT_X, pt->x = output_x);
628 point_list->set_point(hot_point, PT_Y, pt->y = output_y);
630 point_list->update_list(hot_point);
631 point_x->update(pt ? pt->x : 0.f);
632 point_y->update(pt ? pt->y : 0.f);
636 else if( button_no == MIDDLE_BUTTON ) {
637 if( (state & ShiftMask) ) {
638 int ci = plugin->new_curve(cv->ty, cv->radius, cv->pen, cv->color);
639 curve_list->update(ci);
640 point_list->update(-1);
644 if( ty >= TYP_SZ ) ty = 0;
646 curve_type->update(ty);
647 curve_list->update(ci);
652 int hot_point = point_list->get_selection_number(0, 0);
654 SketcherCurves &curves = plugin->config.curves;
655 int dx = round(output_x - last_x);
656 int dy = round(output_y - last_y);
657 int mnc = (state & ShiftMask) || ci<0 ? 0 : ci;
658 int mxc = (state & ShiftMask) ? curves.size() : ci+1;
659 for( int i=mnc; i<mxc; ++i ) {
660 SketcherCurve *crv = plugin->config.curves[i];
661 int pts = crv->points.size();
662 for( int k=0; k<pts; ++k ) {
663 SketcherPoint *pt = crv->points[k];
664 pt->x += dx; pt->y += dy;
667 SketcherPoint *pt = hot_point >= 0 && hot_point < points.size() ?
668 points[hot_point] : 0;
669 point_x->update(pt ? pt->x : 0.f);
670 point_y->update(pt ? pt->y : 0.f);
671 point_list->update(hot_point);
674 if( (state & Button1Mask) ) {
675 SketcherPoint *pt = hot_point >= 0 && hot_point < points.size() ?
676 points[hot_point] : 0;
677 if( pt && pt->x == output_x && pt->y == output_y ) break;
680 float frac_w = DISTANCE(pt->x, pt->y, output_x, output_y) / get_w();
681 if( frac_w < 0.01 ) break; // 1 percent w
683 if( (state & ShiftMask) ) {
685 hot_point = plugin->new_point(cv, output_x, output_y);
686 point_list->update(hot_point);
690 point_list->set_point(hot_point, PT_X, pt->x = output_x);
691 point_list->set_point(hot_point, PT_Y, pt->y = output_y);
692 point_list->update_list(hot_point);
693 point_x->update(pt->x);
694 point_y->update(pt->y);
698 case ButtonRelease: {
704 last_x = output_x; last_y = output_y;
709 int SketcherWindow::keypress_event()
711 int key = get_keypress();
713 case DELETE: return shift_down() ?
714 del_curve->handle_event() :
715 del_point->handle_event() ;
720 void SketcherWindow::done_event(int result)
722 ungrab(client->server->mwindow->cwindow->gui);
725 void SketcherWindow::start_color_thread(SketcherCurveColor *color_button)
729 color_picker = new SketcherCurveColorPicker(this, color_button);
730 int color = BLACK, ci = plugin->config.cv_selected;
731 if( ci >= 0 && ci < plugin->config.curves.size() ) {
732 SketcherCurve *cv = plugin->config.curves[ci];
735 color_picker->start(color);
736 lock_window("SketcherWindow::start_color_thread");
740 SketcherCurveList::SketcherCurveList(SketcherWindow *gui, Sketcher *plugin, int x, int y)
741 : BC_ListBox(x, y, 360, 130, LISTBOX_TEXT)
744 this->plugin = plugin;
745 titles[CV_ID] = _("id"); widths[CV_ID] = 64;
746 titles[CV_TY] = _("type"); widths[CV_TY] = 64;
747 titles[CV_RAD] = _("radius"); widths[CV_RAD] = 64;
748 titles[CV_PEN] = _("pen"); widths[CV_PEN] = 64;
749 titles[CV_CLR] = _("color"); widths[CV_CLR] = 64;
751 SketcherCurveList::~SketcherCurveList()
755 void SketcherCurveList::clear()
757 for( int i=CV_SZ; --i>=0; )
758 cols[i].remove_all_objects();
761 int SketcherCurveList::column_resize_event()
763 for( int i=CV_SZ; --i>=0; )
764 widths[i] = get_column_width(i);
768 int SketcherCurveList::handle_event()
770 int ci = get_selection_number(0, 0);
772 gui->point_list->update(0);
773 gui->send_configure_change();
777 int SketcherCurveList::selection_changed()
783 void SketcherCurveList::set_selected(int k)
786 if( k >= 0 && k < plugin->config.curves.size() ) {
787 SketcherCurve *cv = plugin->config.curves[k];
788 gui->curve_type->update(cv->ty);
789 gui->curve_radius->update(cv->radius);
790 gui->curve_pen->update(cv->pen);
791 gui->curve_color->update_gui(cv->color);
794 plugin->config.cv_selected = ci;
795 update_selection(&cols[0], ci);
799 void SketcherCurveList::update_list(int k)
801 int xpos = get_xposition(), ypos = get_yposition();
802 if( k < 0 ) k = get_selection_number(0, 0);
803 update_selection(&cols[0], k);
804 BC_ListBox::update(&cols[0], &titles[0],&widths[0],CV_SZ, xpos,ypos,k);
808 void SketcherCurveList::update(int k)
811 SketcherCurves &curves = plugin->config.curves;
812 int sz = curves.size();
813 for( int i=0; i<sz; ++i ) {
814 SketcherCurve *cv = curves[i];
815 char itxt[BCSTRLEN]; sprintf(itxt,"%d", cv->id);
816 char ttxt[BCSTRLEN]; sprintf(ttxt,"%s", cv_type[cv->ty]);
817 char rtxt[BCSTRLEN]; sprintf(rtxt,"%d", cv->radius);
818 char ptxt[BCSTRLEN]; sprintf(ptxt,"%s", cv_pen[cv->pen]);
819 int color = cv->color;
820 int r = (color>>16)&0xff, g = (color>>8)&0xff, b = (color>>0)&0xff;
821 char ctxt[BCSTRLEN]; sprintf(ctxt,"#%02x%02x%02x", r, g, b);
822 add_curve(itxt, ttxt, rtxt, ptxt, ctxt);
827 void SketcherCurveList::add_curve(const char *id, const char *type,
828 const char *radius, const char *pen, const char *color)
830 cols[CV_ID].append(new BC_ListBoxItem(id));
831 cols[CV_TY].append(new BC_ListBoxItem(type));
832 cols[CV_RAD].append(new BC_ListBoxItem(radius));
833 cols[CV_PEN].append(new BC_ListBoxItem(pen));
834 cols[CV_CLR].append(new BC_ListBoxItem(color));
837 SketcherNewCurve::SketcherNewCurve(SketcherWindow *gui, Sketcher *plugin, int x, int y)
838 : BC_GenericButton(x, y, 64, _("New"))
841 this->plugin = plugin;
843 SketcherNewCurve::~SketcherNewCurve()
846 int SketcherNewCurve::handle_event()
848 int ty = 1, pen = 0, color = 0, radius = 1;
849 int ci = plugin->config.cv_selected;
850 if( ci >= 0 && ci < plugin->config.curves.size() ) {
851 SketcherCurve *cv = plugin->config.curves[ci];
852 ty = cv->ty; pen = cv->pen;
853 color = cv->color; radius = cv->radius;
855 int k = plugin->new_curve(ty, radius, pen, color);
856 gui->curve_list->update(k);
857 gui->point_list->update(-1);
858 gui->send_configure_change();
862 SketcherDelCurve::SketcherDelCurve(SketcherWindow *gui, Sketcher *plugin, int x, int y)
863 : BC_GenericButton(x, y, 64, C_("Del"))
866 this->plugin = plugin;
868 SketcherDelCurve::~SketcherDelCurve()
871 int SketcherDelCurve::handle_event()
873 int hot_curve = gui->curve_list->get_selection_number(0, 0);
874 SketcherCurves &curves = plugin->config.curves;
875 if( hot_curve >= 0 && hot_curve < curves.size() ) {
876 curves.remove_object_number(hot_curve);
877 if( --hot_curve < 0 )
878 hot_curve = plugin->new_curve(0, 1, 0, BLACK);
879 gui->curve_list->update(hot_curve);
880 gui->point_list->update(-1);
881 gui->send_configure_change();
886 SketcherCurveUp::SketcherCurveUp(SketcherWindow *gui, int x, int y)
887 : BC_GenericButton(x, y, _("Up"))
891 SketcherCurveUp::~SketcherCurveUp()
895 int SketcherCurveUp::handle_event()
897 SketcherCurves &curves = gui->plugin->config.curves;
898 int hot_curve = gui->curve_list->get_selection_number(0, 0);
900 if( hot_curve > 0 && hot_curve < curves.size() ) {
901 SketcherCurve *&cv0 = curves[hot_curve];
902 SketcherCurve *&cv1 = curves[--hot_curve];
903 SketcherCurve *t = cv0; cv0 = cv1; cv1 = t;
904 gui->curve_list->update(hot_curve);
906 gui->send_configure_change();
910 SketcherCurveDn::SketcherCurveDn(SketcherWindow *gui, int x, int y)
911 : BC_GenericButton(x, y, _("Dn"))
915 SketcherCurveDn::~SketcherCurveDn()
919 int SketcherCurveDn::handle_event()
921 SketcherCurves &curves = gui->plugin->config.curves;
922 int hot_curve = gui->curve_list->get_selection_number(0, 0);
924 if( hot_curve >= 0 && hot_curve < curves.size()-1 ) {
925 SketcherCurve *&cv0 = curves[hot_curve];
926 SketcherCurve *&cv1 = curves[++hot_curve];
927 SketcherCurve *t = cv0; cv0 = cv1; cv1 = t;
928 gui->curve_list->update(hot_curve);
930 gui->send_configure_change();
935 SketcherPointList::SketcherPointList(SketcherWindow *gui, Sketcher *plugin, int x, int y)
936 : BC_ListBox(x, y, 360, 130, LISTBOX_TEXT)
939 this->plugin = plugin;
940 titles[PT_X] = _("X"); widths[PT_X] = 90;
941 titles[PT_Y] = _("Y"); widths[PT_Y] = 90;
942 titles[PT_ID] = _("ID"); widths[PT_ID] = 50;
944 SketcherPointList::~SketcherPointList()
948 void SketcherPointList::clear()
950 for( int i=PT_SZ; --i>=0; )
951 cols[i].remove_all_objects();
954 int SketcherPointList::column_resize_event()
956 for( int i=PT_SZ; --i>=0; )
957 widths[i] = get_column_width(i);
961 int SketcherPointList::handle_event()
963 int pi = get_selection_number(0, 0);
965 gui->send_configure_change();
969 int SketcherPointList::selection_changed()
975 void SketcherPointList::add_point(const char *id, const char *xp, const char *yp)
977 cols[PT_ID].append(new BC_ListBoxItem(id));
978 cols[PT_X].append(new BC_ListBoxItem(xp));
979 cols[PT_Y].append(new BC_ListBoxItem(yp));
982 void SketcherPointList::set_point(int i, int c, int v)
985 sprintf(stxt,"%d",v);
988 void SketcherPointList::set_point(int i, int c, const char *cp)
990 cols[c].get(i)->set_text(cp);
993 void SketcherPointList::set_selected(int k)
995 SketcherPoint *pt = 0;
996 int ci = plugin->config.cv_selected, pi = -1;
997 if( ci >= 0 && ci < plugin->config.curves.size() ) {
998 SketcherCurve *cv = plugin->config.curves[ci];
999 pt = k >= 0 && k < cv->points.size() ? cv->points[pi=k] : 0;
1001 gui->point_x->update(pt ? pt->x : 0.f);
1002 gui->point_y->update(pt ? pt->y : 0.f);
1003 plugin->config.pt_selected = pi;
1004 update_selection(&cols[0], pi);
1007 void SketcherPointList::update_list(int k)
1009 int xpos = get_xposition(), ypos = get_yposition();
1010 if( k < 0 ) k = get_selection_number(0, 0);
1011 update_selection(&cols[0], k);
1012 BC_ListBox::update(&cols[0], &titles[0],&widths[0],PT_SZ, xpos,ypos,k);
1015 void SketcherPointList::update(int k)
1018 int ci = plugin->config.cv_selected, sz = 0;
1019 if( ci >= 0 && ci < plugin->config.curves.size() ) {
1020 SketcherCurve *cv = plugin->config.curves[ci];
1021 SketcherPoints &points = cv->points;
1023 for( int i=0; i<sz; ++i ) {
1024 SketcherPoint *pt = points[i];
1025 char itxt[BCSTRLEN]; sprintf(itxt,"%d", pt->id);
1026 char xtxt[BCSTRLEN]; sprintf(xtxt,"%d", pt->x);
1027 char ytxt[BCSTRLEN]; sprintf(ytxt,"%d", pt->y);
1028 add_point(itxt, xtxt, ytxt);
1034 void SketcherWindow::update_gui()
1036 SketcherConfig &config = plugin->config;
1037 int ci = config.cv_selected;
1038 int pi = config.pt_selected;
1039 curve_list->update(ci);
1040 point_list->update(pi);
1041 SketcherCurve *cv = ci >= 0 ? config.curves[ci] : 0;
1042 curve_radius->update(cv ? cv->radius : 1);
1043 curve_type->update(cv ? cv->ty : TYP_OFF);
1044 curve_pen->update(cv ? cv->pen : PEN_SQUARE);
1045 curve_color->set_color(cv ? cv->color : BLACK);
1046 SketcherPoint *pt = pi >= 0 ? cv->points[pi] : 0;
1047 point_x->update(pt ? pt->x : 0);
1048 point_y->update(pt ? pt->y : 0);
1049 drag->update(plugin->config.drag);
1053 SketcherPointUp::SketcherPointUp(SketcherWindow *gui, int x, int y)
1054 : BC_GenericButton(x, y, _("Up"))
1058 SketcherPointUp::~SketcherPointUp()
1062 int SketcherPointUp::handle_event()
1064 SketcherConfig &config = gui->plugin->config;
1065 int ci = config.cv_selected;
1066 if( ci < 0 || ci >= config.curves.size() )
1068 SketcherCurve *cv = config.curves[ci];
1069 SketcherPoints &points = cv->points;
1070 int sz = points.size();
1071 int hot_point = gui->point_list->get_selection_number(0, 0);
1073 if( sz > 1 && hot_point > 0 ) {
1074 SketcherPoint *&pt0 = points[hot_point];
1075 SketcherPoint *&pt1 = points[--hot_point];
1076 SketcherPoint *t = pt0; pt0 = pt1; pt1 = t;
1077 gui->point_list->update(hot_point);
1079 gui->send_configure_change();
1083 SketcherPointDn::SketcherPointDn(SketcherWindow *gui, int x, int y)
1084 : BC_GenericButton(x, y, _("Dn"))
1088 SketcherPointDn::~SketcherPointDn()
1092 int SketcherPointDn::handle_event()
1094 SketcherConfig &config = gui->plugin->config;
1095 int ci = config.cv_selected;
1096 if( ci < 0 || ci >= config.curves.size() )
1098 SketcherCurve *cv = config.curves[ci];
1099 SketcherPoints &points = cv->points;
1100 int sz = points.size();
1101 int hot_point = gui->point_list->get_selection_number(0, 0);
1102 if( sz > 1 && hot_point < sz-1 ) {
1103 SketcherPoint *&pt0 = points[hot_point];
1104 SketcherPoint *&pt1 = points[++hot_point];
1105 SketcherPoint *t = pt0; pt0 = pt1; pt1 = t;
1106 gui->point_list->update(hot_point);
1108 gui->send_configure_change();
1112 SketcherDrag::SketcherDrag(SketcherWindow *gui, int x, int y)
1113 : BC_CheckBox(x, y, gui->plugin->config.drag, _("Drag"))
1117 int SketcherDrag::handle_event()
1119 CWindowGUI *cwindow_gui = gui->plugin->server->mwindow->cwindow->gui;
1120 int value = get_value();
1122 if( !gui->grab(cwindow_gui) ) {
1128 gui->ungrab(cwindow_gui);
1129 gui->plugin->config.drag = value;
1130 gui->send_configure_change();
1134 SketcherNewPoint::SketcherNewPoint(SketcherWindow *gui, Sketcher *plugin, int x, int y)
1135 : BC_GenericButton(x, y, 64, _("New"))
1138 this->plugin = plugin;
1140 SketcherNewPoint::~SketcherNewPoint()
1143 int SketcherNewPoint::handle_event()
1145 int k = plugin->new_point();
1146 gui->point_list->update(k);
1147 gui->send_configure_change();
1151 SketcherDelPoint::SketcherDelPoint(SketcherWindow *gui, Sketcher *plugin, int x, int y)
1152 : BC_GenericButton(x, y, 64, C_("Del"))
1155 this->plugin = plugin;
1157 SketcherDelPoint::~SketcherDelPoint()
1160 int SketcherDelPoint::handle_event()
1162 SketcherConfig &config = gui->plugin->config;
1163 int ci = config.cv_selected;
1164 if( ci >= 0 && ci < config.curves.size() ) {
1165 SketcherCurve *cv = config.curves[ci];
1166 SketcherPoints &points = cv->points;
1167 int hot_point = gui->point_list->get_selection_number(0, 0);
1168 if( hot_point >= 0 && hot_point < points.size() ) {
1169 points.remove_object_number(hot_point);
1170 gui->point_list->update(--hot_point);
1171 gui->send_configure_change();
1177 SketcherResetCurves::SketcherResetCurves(SketcherWindow *gui, Sketcher *plugin, int x, int y)
1178 : BC_GenericButton(x, y, _("Reset"))
1181 this->plugin = plugin;
1183 SketcherResetCurves::~SketcherResetCurves()
1186 int SketcherResetCurves::handle_event()
1188 SketcherConfig &config = plugin->config;
1189 config.curves.remove_all_objects();
1190 int ci = plugin->new_curve(0, 1, 0, BLACK);
1191 gui->curve_list->update(ci);
1192 gui->point_list->update(-1);
1193 gui->send_configure_change();
1197 SketcherResetPoints::SketcherResetPoints(SketcherWindow *gui, Sketcher *plugin, int x, int y)
1198 : BC_GenericButton(x, y, _("Reset"))
1201 this->plugin = plugin;
1203 SketcherResetPoints::~SketcherResetPoints()
1206 int SketcherResetPoints::handle_event()
1208 SketcherConfig &config = gui->plugin->config;
1209 int ci = config.cv_selected;
1210 if( ci >= 0 && ci < config.curves.size() ) {
1211 SketcherCurve *cv = config.curves[ci];
1212 cv->points.remove_all_objects();
1213 gui->point_list->update(-1);
1214 gui->send_configure_change();