add dragcheckbox, fix transition plugin title, sams opencv icons, drop libipp in...
[goodguy/history.git] / cinelerra-5.1 / cinelerra / dragcheckbox.C
diff --git a/cinelerra-5.1/cinelerra/dragcheckbox.C b/cinelerra-5.1/cinelerra/dragcheckbox.C
new file mode 100644 (file)
index 0000000..559851e
--- /dev/null
@@ -0,0 +1,276 @@
+#include "automation.h"
+#include "bctoggle.h"
+#include "canvas.h"
+#include "cwindow.h"
+#include "cwindowgui.h"
+#include "dragcheckbox.h"
+#include "edl.h"
+#include "edlsession.h"
+#include "mwindow.h"
+#include "theme.h"
+#include "track.h"
+#include "vframe.h"
+
+DragCheckBox::DragCheckBox(MWindow *mwindow,
+       int x, int y, const char *text, int *value,
+       float drag_x, float drag_y, float drag_w, float drag_h)
+ : BC_CheckBox(x, y, value, text)
+{
+       this->mwindow = mwindow;
+       this->drag_x = drag_x;  this->drag_y = drag_y;
+       this->drag_w = drag_w;  this->drag_h = drag_h;
+       drag_dx = drag_dy = 0;
+       grabbed = 0;
+       dragging = 0;
+       pending = 0;
+}
+
+DragCheckBox::~DragCheckBox()
+{
+       drag_deactivate();
+}
+
+void DragCheckBox::create_objects()
+{
+       if( !drag_w ) drag_w = get_drag_track()->track_w;
+       if( !drag_h ) drag_h = get_drag_track()->track_h;
+       if( get_value() )
+               drag_activate();
+}
+
+int DragCheckBox::handle_event()
+{
+       int ret = BC_CheckBox::handle_event();
+       if( get_value() ) {
+               if( drag_activate() ) {
+                       update(*value=0);
+                       flicker(10,50);
+               }
+       }
+       else
+               drag_deactivate();
+       return ret;
+}
+
+int DragCheckBox::drag_activate()
+{
+       int ret = 0;
+       if( !grabbed && !(grabbed = grab(mwindow->cwindow->gui)) ) {
+               ret = 1;
+       }
+       pending = 0;
+       dragging = 0;
+       return ret;
+}
+
+void DragCheckBox::drag_deactivate()
+{
+       if( grabbed ) {
+               ungrab(mwindow->cwindow->gui);
+               grabbed = 0;
+       }
+       pending = 0;
+       dragging = 0;
+}
+
+int DragCheckBox::check_pending()
+{
+       if( pending && !grab_event_count() ) {
+               pending = 0;
+               update_gui();
+       }
+       return 0;
+}
+
+int DragCheckBox::grab_event(XEvent *event)
+{
+       switch( event->type ) {
+       case ButtonPress: break;
+       case ButtonRelease: break;
+       case MotionNotify: break;
+       default:
+               return check_pending();
+       }
+
+       CWindowGUI *cwindow_gui = mwindow->cwindow->gui;
+       CWindowCanvas *canvas = cwindow_gui->canvas;
+       int cx, cy;  cwindow_gui->get_relative_cursor(cx, cy);
+       cx -= mwindow->theme->ccanvas_x;
+       cy -= mwindow->theme->ccanvas_y;
+
+       if( !dragging ) {
+               if( cx < 0 || cx >= mwindow->theme->ccanvas_w ||
+                   cy < 0 || cy >= mwindow->theme->ccanvas_h )
+                       return check_pending();
+       }
+
+       switch( event->type ) {
+       case ButtonPress:
+               if( !dragging ) break;
+               return 1;
+       case ButtonRelease:
+               if( !dragging ) return check_pending();
+               dragging = 0;
+               return 1;
+       case MotionNotify:
+               if( !dragging ) return check_pending();
+               break;
+       default:
+               return check_pending();
+       }
+
+       Track *track = get_drag_track();
+       if( !track ) return 0;
+       if( !drag_w ) drag_w = track->track_w;
+       if( !drag_h ) drag_h = track->track_h;
+
+       int64_t position = get_drag_position();
+
+       float cursor_x = cx, cursor_y = cy;
+       canvas->canvas_to_output(mwindow->edl, 0, cursor_x, cursor_y);
+       float projector_x, projector_y, projector_z;
+       int track_w = track->track_w, track_h = track->track_h;
+       track->automation->get_projector(
+               &projector_x, &projector_y, &projector_z,
+               position, PLAY_FORWARD);
+       projector_x += mwindow->edl->session->output_w / 2;
+       projector_y += mwindow->edl->session->output_h / 2;
+       cursor_x = (cursor_x - projector_x) / projector_z + track_w / 2;
+       cursor_y = (cursor_y - projector_y) / projector_z + track_h / 2;
+       float r = MIN(track_w, track_h)/100.f + 2;
+       float x0 = drag_x, x1 = drag_x+(drag_w+1)/2, x2 = drag_x+drag_w;
+       float y0 = drag_y, y1 = drag_y+(drag_h+1)/2, y2 = drag_y+drag_h;
+       if( !dragging ) {  // clockwise
+                    if( fabs(drag_dx = cursor_x-x0) < r &&  // x0,y0
+                        fabs(drag_dy = cursor_y-y0) < r ) dragging = 1;
+               else if( fabs(drag_dx = cursor_x-x1) < r &&  // x1,y0
+                        fabs(drag_dy = cursor_y-y0) < r ) dragging = 2;
+               else if( fabs(drag_dx = cursor_x-x2) < r &&  // x2,y0
+                        fabs(drag_dy = cursor_y-y0) < r ) dragging = 3;
+               else if( fabs(drag_dx = cursor_x-x2) < r &&  // x2,y1
+                        fabs(drag_dy = cursor_y-y1) < r ) dragging = 4;
+               else if( fabs(drag_dx = cursor_x-x2) < r &&  // x2,y2
+                        fabs(drag_dy = cursor_y-y2) < r ) dragging = 5;
+               else if( fabs(drag_dx = cursor_x-x1) < r &&  // x1,y2
+                        fabs(drag_dy = cursor_y-y2) < r ) dragging = 6;
+               else if( fabs(drag_dx = cursor_x-x0) < r &&  // x0,y2
+                        fabs(drag_dy = cursor_y-y2) < r ) dragging = 7;
+               else if( fabs(drag_dx = cursor_x-x0) < r &&  // x0,y1
+                        fabs(drag_dy = cursor_y-y1) < r ) dragging = 8;
+               else if( fabs(drag_dx = cursor_x-x1) < r &&  // x1,y1
+                        fabs(drag_dy = cursor_y-y1) < r ) dragging = 9;
+                       return 0;
+       }
+       int cur_x = cursor_x - drag_dx;
+       int cur_y = cursor_y - drag_dy;
+       switch( dragging ) {
+       case 1: { // x0,y0
+               float dx = cur_x - x0;
+               float dy = cur_y - y0;
+               if( !dx && !dy ) return 1;
+               if( (drag_w-=dx) < 1 ) drag_w = 1;
+               if( (drag_h-=dy) < 1 ) drag_h = 1;
+               drag_x = cur_x;   drag_y = cur_y;
+               break; }
+       case 2: { // x1,y0
+               float dy = cur_y - y0;
+               if( !dy ) return 1;
+               drag_y = cur_y;
+               if( (drag_h-=dy) < 1 ) drag_h = 1;
+               break; }
+       case 3: { // x2,y0
+               float dx = cur_x - x2;
+               float dy = cur_y - y0;
+               if( (drag_w+=dx) < 1 ) drag_w = 1;
+               if( (drag_h-=dy) < 1 ) drag_h = 1;
+               drag_y = cur_y;
+               break; }
+       case 4: { // x2,y1
+               float dx = cur_x - x2;
+               if( !dx ) return 1;
+               if( (drag_w+=dx) < 1 ) drag_w = 1;
+               break; }
+       case 5: { // x2,y2
+               float dx = cur_x - x2;
+               float dy = cur_y - y2;
+               if( (drag_w+=dx) < 1 ) drag_w = 1;
+                if( (drag_h+=dy) < 1 ) drag_h = 1;
+               break; }
+       case 6: { // x1,y2
+               float dy = cur_y - y2;
+               if( !dy ) return 1;
+               if( (drag_h+=dy) < 1 ) drag_h = 1;
+               break; }
+       case 7: { // x0,y2
+               float dx = cur_x - x0;
+               float dy = cur_y - y2;
+               if( (drag_w-=dx) < 1 ) drag_w = 1;
+               if( (drag_h+=dy) < 1 ) drag_h = 1;
+               drag_x = cur_x;
+               break; }
+       case 8: { // x0,y1
+               float dx = cur_x - x0;
+               if( !dx ) return 1;
+               if( (drag_w-=dx) < 1 ) drag_w = 1;
+               drag_x = cur_x;
+               break; }
+       case 9: { // x1,y1
+               float dx = cur_x - x1;
+               float dy = cur_y - y1;
+               if( !dx && !dy ) return 1;
+               drag_x += dx;
+               drag_y += dy;
+               }
+       }
+       if( grab_event_count() )
+               pending = 1;
+       else if( dragging ) {
+               pending = 0;
+               update_gui();
+       }
+       return 1;
+}
+
+void DragCheckBox::draw_boundary(VFrame *out,
+       int x, int y, int w, int h)
+{
+       int iw = out->get_w(), ih = out->get_h();
+       int mr = MIN(iw, ih)/200 + 2, rr = 2*mr;
+       int r2 = (rr+1)/2;
+       int x0 = x-r2, x1 = x+(w+1)/2, x2 = x+w+r2;
+       int y0 = y-r2, y1 = y+(h+1)/2, y2 = y+h+r2;
+       int st = 1;
+       for( int r=2; r<mr; r<<=1 ) st = r;
+       out->set_stiple(st);
+
+       for( int r=mr/2; --r>=0; ) { // bbox
+               int lft = x+r, rgt = x+w-1-r;
+               int top = y+r, bot = y+h-1-r;
+               out->draw_line(lft,top, rgt,top);
+               out->draw_line(rgt,top, rgt,bot);
+               out->draw_line(rgt,bot, lft,bot);
+               out->draw_line(lft,bot, lft,top);
+       }
+
+       for( int r=mr; r<rr; ++r ) { // center
+               out->draw_smooth(x1-r,y1, x1-r,y1+r, x1,y1+r);
+               out->draw_smooth(x1,y1+r, x1+r,y1+r, x1+r,y1);
+               out->draw_smooth(x1+r,y1, x1+r,y1-r, x1,y1-r);
+               out->draw_smooth(x1,y1-r, x1-r,y1-r, x1-r,y1);
+       }
+
+       for( int r=rr; --r>=0; ) { // edge arrows
+               out->draw_line(x1-r,y0+r, x1+r,y0+r);
+               out->draw_line(x2-r,y1-r, x2-r,y1+r);
+               out->draw_line(x1-r,y2-r, x1+r,y2-r);
+               out->draw_line(x0+r,y1+r, x0+r,y1-r);
+       }
+       x0 += r2;  y0 += r2;  x2 -= r2;  y2 -= r2;
+       for( int r=2*mr; --r>=0; ) { // corner arrows
+               out->draw_line(x0,y0+r, x0+r,y0);
+               out->draw_line(x2,y0+r, x2-r,y0);
+               out->draw_line(x2,y2-r, x2-r,y2);
+               out->draw_line(x0,y2-r, x0+r,y2);
+       }
+}
+