Credit Andrew - fix vorbis audio which was scratchy and ensure aging plugin does...
[goodguy/cinelerra.git] / cinelerra-5.1 / guicast / bcdragbox.C
1 /*
2  * CINELERRA
3  * Copyright (C) 2020 William Morrow
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License as published
7  * by 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, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public
16  * License along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
18  * USA
19  */
20
21
22 #include "bcdragbox.h"
23 #include "bcmenuitem.h"
24 #include "bctimer.h"
25 #include "bcwindowbase.h"
26 #include "colors.h"
27
28 BC_DragBox::BC_DragBox(BC_WindowBase *parent)
29  : Thread(1, 0, 0)
30 {
31         this->parent = parent;
32         popup = 0;
33         done = -1;
34 }
35 BC_DragBox::~BC_DragBox()
36 {
37         if( running() ) {
38                 done = 1;
39                 cancel();
40         }
41         join();
42         delete popup;
43 }
44
45 void BC_DragBox::start_drag()
46 {
47         popup = new BC_DragBoxPopup(this);
48         popup->lock_window("BC_DragBox::start");
49         for( int i=0; i<4; ++i )
50                 edge[i] = new BC_Popup(parent, 0,0, 1,1, ORANGE, 1);
51         parent->grab_buttons();
52         parent->grab_cursor();
53         popup->grab(parent);
54         popup->create_objects();
55         popup->show_window();
56         popup->unlock_window();
57         done = 0;
58         Thread::start();
59 }
60
61 void BC_DragBox::run()
62 {
63         popup->lock_window("BC_DragBox::run 0");
64         while( !done ) {
65                 popup->update();
66                 popup->unlock_window();
67                 enable_cancel();
68                 Timer::delay(200);
69                 disable_cancel();
70                 popup->lock_window("BC_DragBox::run 1");
71         }
72         int x0 = popup->lx0, y0 = popup->ly0;
73         int x1 = popup->lx1, y1 = popup->ly1;
74         parent->ungrab_cursor();
75         parent->ungrab_buttons();
76         popup->ungrab(parent);
77         for( int i=0; i<4; ++i ) delete edge[i];
78         popup->unlock_window();
79         delete popup;  popup = 0;
80         handle_done_event(x0, y0, x1, y1);
81 }
82
83 BC_DragBoxPopup::BC_DragBoxPopup(BC_DragBox *grab_thread)
84  : BC_Popup(grab_thread->parent, 0,0, 16,16, -1,1)
85 {
86         this->grab_thread = grab_thread;
87         dragging = -1;
88         grab_color = ORANGE;
89         x0 = y0 = x1 = y1 = -1;
90         lx0 = ly0 = lx1 = ly1 = -1;
91 }
92
93 BC_DragBoxPopup::~BC_DragBoxPopup()
94 {
95 }
96
97 int BC_DragBoxPopup::grab_event(XEvent *event)
98 {
99         int cur_drag = dragging;
100         switch( event->type ) {
101         case ButtonPress: {
102                 if( cur_drag > 0 ) return 1;
103                 int x0 = event->xbutton.x_root;
104                 int y0 = event->xbutton.y_root;
105                 if( !cur_drag ) {
106                         draw_selection(-1);
107                         if( event->xbutton.button == RIGHT_BUTTON ) break;
108                         if( x0>=get_x() && x0<get_x()+get_w() &&
109                             y0>=get_y() && y0<get_y()+get_h() ) break;
110                 }
111                 this->x0 = this->x1 = x0;
112                 this->y0 = this->y1 = y0;
113                 draw_selection(1);
114                 dragging = 1;
115                 return 1; }
116         case ButtonRelease:
117                 dragging = 0;
118         case MotionNotify:
119                 if( cur_drag > 0 ) {
120                         this->x1 = event->xbutton.x_root;
121                         this->y1 = event->xbutton.y_root;
122                         draw_selection(0);
123                 }
124                 return 1;
125         default:
126                 return 0;
127         }
128
129         hide_window();
130         sync_display();
131         grab_thread->done = 1;
132         return 1;
133 }
134
135 void BC_DragBoxPopup::update()
136 {
137         set_color(grab_color ^= GREEN);
138         draw_box(0,0, get_w(),get_h());
139         flash(1);
140 }
141
142 void BC_DragBoxPopup::draw_selection(int show)
143 {
144         if( show < 0 ) {
145                 for( int i=0; i<4; ++i ) hide_window(0);
146                 flush();
147                 return;
148         }
149
150         int nx0 = x0 < x1 ? x0 : x1;
151         int nx1 = x0 < x1 ? x1 : x0;
152         int ny0 = y0 < y1 ? y0 : y1;
153         int ny1 = y0 < y1 ? y1 : y0;
154         lx0 = nx0;  lx1 = nx1;
155         ly0 = ny0;  ly1 = ny1;
156
157         --nx0;  --ny0;
158         BC_Popup **edge = grab_thread->edge;
159         edge[0]->reposition_window(nx0,ny0, nx1-nx0, 1);
160         edge[1]->reposition_window(nx1,ny0, 1, ny1-ny0);
161         edge[2]->reposition_window(nx0,ny1, nx1-nx0, 1);
162         edge[3]->reposition_window(nx0,ny0, 1, ny1-ny0);
163
164         if( show > 0 ) {
165                 for( int i=0; i<4; ++i ) edge[i]->show_window(0);
166         }
167         flush();
168 }
169