r1014: Enable horizontal scrolling with the mouse wheel by pressing Ctrl.
[cinelerra_cv/ct.git] / cinelerra / manualgoto.C
blob88d1a33f1d1593df19d92987aaae0475bd452100
1 #include "awindow.h"
2 #include "awindowgui.h"
3 #include "manualgoto.h"
4 #include "edl.h"
5 #include "fonts.h"
6 #include "language.h"
7 #include "localsession.h"
8 #include "mainsession.h"
9 #include "mwindow.h"
10 #include "mwindowgui.h"
11 #include "vwindow.h"
12 #include "vwindowgui.h"
13 #include "keys.h"
14 #include "maincursor.h"
15 #include "cwindow.h"
16 #include "mwindowgui.h"
17 #include "edlsession.h"
18 #include "tracks.h"
20 ManualGoto::ManualGoto(MWindow *mwindow, BC_WindowBase *masterwindow)
21  : Thread()
23         this->mwindow = mwindow;
24         this->masterwindow = masterwindow;
25         gotowindow = 0;
26         done = 0;
29 ManualGoto::~ManualGoto()
31         done = 1;
32         gotowindow->set_done(1);
33         Thread::join();
34         if (gotowindow)
35                 delete gotowindow;
38 void ManualGoto::open_window()
41         double position;
42         if ((masterwindow == (BC_WindowBase *)mwindow->cwindow->gui)||
43            (masterwindow == (BC_WindowBase *)mwindow->gui->mbuttons))
44         {
45         
46                 position = mwindow->edl->local_session->get_selectionstart(1);
47                 position += mwindow->edl->session->get_frame_offset() / 
48                                                  mwindow->edl->session->frame_rate;;
49         }
50         else
51                 if (mwindow->vwindow->get_edl())
52                         position = mwindow->vwindow->get_edl()->local_session->get_selectionstart(1);
53                 else
54                         return;
55         if (!gotowindow)
56         {
57                 gotowindow = new ManualGotoWindow(mwindow, this);
58                 gotowindow->create_objects();
59                 gotowindow->reset_data(position);
60                 Thread::start();
61         } else
62                 gotowindow->reset_data(position);
65 void ManualGoto::run()
67         int result = 1;
68         while (!done) 
69         {
70                 result = gotowindow->run_window();
71                 gotowindow->lock_window();
72                 gotowindow->hide_window();              
73                 gotowindow->unlock_window();
75                 if (!done && result == 0) // ok button or return pressed
76                 {
77                         double new_position = gotowindow->get_entered_position_sec();
78                         char modifier = gotowindow->signtitle->get_text()[0];
79                         if ((masterwindow == (BC_WindowBase *)mwindow->cwindow->gui)||
80                            (masterwindow == (BC_WindowBase *)mwindow->gui->mbuttons))
81                         
82                         {
83                                 // mwindow/cwindow update
84                                 
85                                 double current_position = mwindow->edl->local_session->get_selectionstart(1);
86                                 switch (modifier)
87                                 {
88                                         case '+': 
89                                                 new_position += current_position;
90                                                 break;
91                                         case '-':
92                                                 new_position = current_position - new_position;
93                                                 break;
94                                         default:
95                                                 break;
96                                 }               
97                                 new_position = mwindow->edl->align_to_frame(new_position, 1);
98                                 new_position -= mwindow->edl->session->get_frame_offset() / mwindow->edl->session->frame_rate;;
99                                 if (new_position < 0) 
100                                         new_position = 0;
101                                 if (current_position != new_position)
102                                 {
103                                         mwindow->edl->local_session->set_selectionstart(new_position);
104                                         mwindow->edl->local_session->set_selectionend(new_position);
105                                         mwindow->gui->lock_window();
106                                         mwindow->find_cursor();
107                                         mwindow->gui->update(1, 1, 1, 1, 1, 1, 0);      
108                                         mwindow->gui->unlock_window();
109                                         mwindow->cwindow->update(1, 0, 0, 0, 0);                        
110                                 }
111                         } else
112                         if ((masterwindow == (BC_WindowBase *)mwindow->vwindow->gui) &&
113                             mwindow->vwindow->get_edl())
114                         {
115                                 // vwindow update
116                                 VWindow *vwindow = mwindow->vwindow;
117                                 double current_position = vwindow->get_edl()->local_session->get_selectionstart(1);
118                                 switch (modifier)
119                                 {
120                                         case '+': 
121                                                 new_position += current_position;
122                                                 break;
123                                         case '-':
124                                                 new_position = current_position - new_position;
125                                                 break;
126                                         default:
127                                                 break;
128                                 }
129                                 if (new_position > vwindow->get_edl()->tracks->total_length())
130                                         new_position = vwindow->get_edl()->tracks->total_length();
131                                 if (new_position < 0)
132                                         new_position = 0;
133                                 new_position = vwindow->get_edl()->align_to_frame(new_position, 1);
134                                 if (current_position != new_position)
135                                 {
136                                         vwindow->get_edl()->local_session->set_selectionstart(new_position);
137                                         vwindow->get_edl()->local_session->set_selectionend(new_position);
138                                         vwindow->gui->lock_window();
139                                         vwindow->update_position(CHANGE_NONE, 0, 1);                    
140                                         vwindow->gui->unlock_window();
141                                 }
142                         }
143                 }               
144         }
149 ManualGotoWindow::ManualGotoWindow(MWindow *mwindow, ManualGoto *thread)
150  : BC_Window(PROGRAM_NAME ": Goto position", 
151         mwindow->gui->get_abs_cursor_x(1) - 250 / 2,
152         mwindow->gui->get_abs_cursor_y(1) - 80 / 2,
153         250, 
154         80,
155         250,
156         80,
157         0,
158         0,
159         1)
161         this->mwindow = mwindow;
162         this->thread = thread;
165 ManualGotoWindow::~ManualGotoWindow()
169 void ManualGotoWindow::reset_data(double position)
171         lock_window();
172         reposition_window(
173                         mwindow->gui->get_abs_cursor_x(1) - 250 / 2,
174                         mwindow->gui->get_abs_cursor_y(1) - 80 / 2);
175         set_entered_position_sec(position);
176         signtitle->update("=");
177         activate();
178         show_window();
179         unlock_window();
182 double ManualGotoWindow::get_entered_position_sec()
184         int64_t hh = atoi(boxhours->get_text());
185         int64_t mm = atoi(boxminutes->get_text());
186         int64_t ss = atoi(boxseconds->get_text());
187         int64_t ms = atoi(boxmsec->get_text());
188         
189         double seconds = ((((hh * 60) + mm) * 60) + ss) + (1.0 * ms) / 1000;
190         return seconds;
193 void ManualGotoWindow::set_entered_position_sec(double position)
195 // Lifted from units.C
196         int hour, minute, second, thousandths;
198         position = fabs(position);
199         hour = (int)(position / 3600);
200         minute = (int)(position / 60 - hour * 60);
201         second = (int)position - (int64_t)hour * 3600 - (int64_t)minute * 60;
202         thousandths = (int)(position * 1000) % 1000;
203                 
204         boxhours->reshape_update(hour);
205         boxminutes->reshape_update(minute);
206         boxseconds->reshape_update(second);
207         boxmsec->reshape_update(thousandths);
210 int ManualGotoWindow::activate()
211 {       
212         boxhours->reshape_update(-1);
213         boxminutes->reshape_update(-1);
214         boxseconds->reshape_update(-1);
215         boxmsec->reshape_update(-1);
216         int result = BC_Window::activate();
217         boxminutes->deactivate();
218         boxseconds->deactivate();
219         boxmsec->deactivate();
220         boxhours->activate();
221         return result;  
222 }       
223 void ManualGotoWindow::create_objects()
225         int x = 76, y = 5;
226         int x1 = x;
227         int boxwidth = 26;
229         BC_Title *title;
230         add_subwindow(title = new BC_Title(x1 - 2, y, _("hour  min     sec     msec"), SMALLFONT));
231         y += title->get_h() + 3;
233         add_subwindow(signtitle = new BC_Title(x1 - 17, y, "=", LARGEFONT));
234         add_subwindow(boxhours = new ManualGotoNumber(this, x1, y, 16, 0, 9, 1));
235         x1 += boxhours->get_w() + 4;
236         add_subwindow(boxminutes = new ManualGotoNumber(this, x1, y, 26, 0, 59, 2));
237         x1 += boxminutes->get_w() + 4;
238         add_subwindow(boxseconds = new ManualGotoNumber(this, x1, y, 26, 0, 59, 2));
239         x1 += boxseconds->get_w() + 4;
240         add_subwindow(boxmsec = new ManualGotoNumber(this, x1, y, 34, 0, 999, 3));
241         y += boxhours->get_h() + 10;
243         add_subwindow(new BC_OKButton(this));
244         add_subwindow(new BC_CancelButton(this));
251 ManualGotoNumber::ManualGotoNumber(ManualGotoWindow *window, int x, int y, int w, int min_num, int max_num, int chars)
252  : BC_TextBox(x, y, w, 1, "0")
254         this->window = window;
255         this->min_num = min_num;
256         this->max_num = max_num;
257         this->chars = chars;
260 int ManualGotoNumber::handle_event()
262         return 1;
265 int ManualGotoNumber::deactivate()
267         reshape_update(-1);
268         return BC_TextBox::deactivate();
271 int ManualGotoNumber::activate()
273         int retval = BC_TextBox::activate();
274         select_whole_text(1);
275         return retval;
279 void ManualGotoNumber::reshape_update(int64_t number)
281         char format_text[10];
282         char text[BCTEXTLEN];
283         if (number < 0)
284                 number = atoll(get_text());
285         if (number > max_num) number = max_num;
286         if (number < min_num) number = min_num;
287         sprintf(format_text, "%%0%dlli", chars);
288         sprintf(text, format_text, number);
289         update(text);
290         select_whole_text(-1);
293 int ManualGotoNumber::keypress_event()
295         int in_textlen = strlen(get_text());
296         int key = get_keypress();
298         if (key == '+') 
299         {
300                 window->signtitle->update("+");
301                 return 1;
302         }
303         if (key == '-')
304         {
305                 window->signtitle->update("-");
306                 return 1;
307         }
308         if (key == '=') 
309         {
310                 window->signtitle->update("=");
311                 return 1;
312         }
313         
314         int ok_key = 0;
315         if ((key >= '0' && key <='9') ||
316             (key == ESC) ||  (key == RETURN) ||  
317             (key == TAB) ||  (key == LEFTTAB) ||  
318             (key == '.') ||  
319             (key == LEFT) || (key == RIGHT) ||  
320             (key == UP) ||   (key == DOWN) ||  
321             (key == PGUP) || (key == PGDN) ||  
322             (key == END) ||  (key == HOME) ||
323             (key == BACKSPACE) || (key == DELETE) ||
324             (ctrl_down() && (key == 'v' || key == 'V' || key == 'c' || key == 'C' || key == 'x' || key == 'X')))
325             ok_key = 1;  
327         if (in_textlen >= chars && key >= '0' && key <= '9' && !select_whole_text(0))
328                 ok_key = 0;
329         
330         if (!ok_key) return 1;
333 // treat dot as tab - for use from numerical keypad
334         if (key == '.') 
335         { 
336                 cycle_textboxes(1); 
337                 return 1; 
338         };
339         
340         int result = BC_TextBox::keypress_event();
341         int out_textlen = strlen(get_text());
342         // automatic cycle when we enter two numbers
343         if (key != TAB && out_textlen == chars && get_ibeam_letter() == chars) 
344                 cycle_textboxes(1);
345         return result;