rework keyframe hide popup, keyframe auto render, textbox set_selection wide text
[goodguy/history.git] / cinelerra-5.1 / cinelerra / scale.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
5  * 
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  * 
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  * 
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  * 
20  */
21
22 #include "bchash.h"
23 #include "mainundo.h"
24 #include "mwindow.h"
25 #include "scale.h"
26 #include "mainsession.h"
27 #include "tracks.h"
28 #include "videowindow.h"
29
30 #include <libintl.h>
31 #define _(String) gettext(String)
32 #define gettext_noop(String) String
33 #define N_(String) gettext_noop (String)
34
35 Scale::Scale(MWindow *mwindow)
36  : BC_MenuItem(_("Resize..."))
37
38         this->mwindow = mwindow; 
39         thread = new ScaleThread(mwindow);
40 }
41
42 Scale::~Scale() 
43 {
44         delete thread;
45 }
46
47 int Scale::handle_event()
48 {
49         thread->start();
50 }
51
52 ScaleThread::ScaleThread(MWindow *mwindow)
53  : Thread()
54
55         this->mwindow = mwindow; 
56         already_running = 0;
57 }
58
59 ScaleThread::~ScaleThread() {}
60
61 void ScaleThread::run()
62 {
63         if(already_running) return;
64         already_running = 1;
65         constrain_ratio = mwindow->defaults->get("SCALECONSTRAIN", 0);
66         scale_data = mwindow->defaults->get("SCALEDATA", 0);
67         auto_aspect = mwindow->defaults->get("AUDIOASPECT", 0);
68         offsets[0] = offsets[1] = offsets[2] = offsets[3] = 0;
69
70         orig_dimension[0] = dimension[0] = mwindow->session->track_w;
71         orig_dimension[1] = dimension[1] = mwindow->session->track_h;
72         orig_dimension[2] = dimension[2] = mwindow->session->output_w;
73         orig_dimension[3] = dimension[3] = mwindow->session->output_h;
74         ratio[0] = ratio[1] = ratio[2] = ratio[3] = 1;
75         aspect_w = mwindow->session->aspect_w;
76         aspect_h = mwindow->session->aspect_h;
77
78         window = new ScaleWindow(this);
79         window->create_objects();
80         int result = window->run_window();
81         if(!result)
82         {
83                 int dummy_offsets[4];
84                 dummy_offsets[0] = dummy_offsets[1] = dummy_offsets[2] = dummy_offsets[3] = 0;
85 // Fake the offsets if data is scaled.
86
87 // fix tracks
88                 //mwindow->stop_playback(1);
89 // save the before undo
90                 mwindow->undo->update_undo_edits(_("Resize"), 0);
91                 mwindow->tracks->scale_video(dimension, scale_data ? dummy_offsets : offsets, scale_data);
92                 mwindow->session->track_w = dimension[0];
93                 mwindow->session->track_h = dimension[1];
94                 mwindow->session->output_w = dimension[2];
95                 mwindow->session->output_h = dimension[3];
96                 mwindow->session->aspect_w = aspect_w;
97                 mwindow->session->aspect_h = aspect_h;
98                 mwindow->video_window->resize_window();
99                 mwindow->draw();
100                 mwindow->undo->update_undo_edits();
101                 mwindow->session->changes_made = 1;
102                 mwindow->defaults->update("ASPECTW", aspect_w);
103                 mwindow->defaults->update("ASPECTH", aspect_h);
104                 mwindow->defaults->update("AUTOASPECT", auto_aspect);
105         }
106         delete window;
107
108         mwindow->defaults->update("SCALECONSTRAIN", constrain_ratio);
109         mwindow->defaults->update("SCALEDATA", scale_data);
110         already_running = 0;
111 }
112
113 int ScaleThread::update_window(int offset_updated)
114 {
115         int pair_start = 0;
116         int i, result, modified_item, dimension_modified = 0, ratio_modified = 0;
117
118         for(i = 0, result = 0; i < 4 && !result; i++)
119         {
120                 if(i == 2) pair_start = 2;
121                 if(dimension[i] < 0)
122                 {
123                         dimension[i] *= -1;
124                         result = 1;
125                         modified_item = i;
126                         dimension_modified = 1;
127                 }
128                 if(ratio[i] < 0)
129                 {
130                         ratio[i] *= -1;
131                         result = 1;
132                         modified_item = i;
133                         ratio_modified = 1;
134                 }
135         }
136
137         if(result)
138         {
139                 if(dimension_modified)
140                         ratio[modified_item] = (float)dimension[modified_item] / orig_dimension[modified_item];
141
142                 if(ratio_modified && !constrain_ratio)
143                 {
144                         dimension[modified_item] = (int)(orig_dimension[modified_item] * ratio[modified_item]);
145                         window->dimension[modified_item]->update((long)dimension[modified_item]);
146                 }
147
148                 for(i = pair_start; i < pair_start + 2 && constrain_ratio; i++)
149                 {
150                         if(dimension_modified ||
151                                 (i != modified_item && ratio_modified))
152                         {
153                                 ratio[i] = ratio[modified_item];
154                                 window->ratio[i]->update(ratio[i]);
155                         }
156
157                         if(ratio_modified ||
158                                 (i != modified_item && dimension_modified))
159                         {
160                                 dimension[i] = (int)(orig_dimension[i] * ratio[modified_item]);
161                                 window->dimension[i]->update((long)dimension[i]);
162                         }
163                 }
164         }
165
166 //      window->position1->draw();
167 //      window->position2->draw();
168 //printf("%d\n", offsets[0]);
169 //      if(!offset_updated)
170 //      {
171 //              window->offsets[0]->update(offsets[0]);
172 //              window->offsets[1]->update(offsets[1]);
173 //              window->offsets[2]->update(offsets[2]);
174 //              window->offsets[3]->update(offsets[3]);
175 //      }
176         
177         update_aspect(window);
178         return 0;
179 }
180
181 int ScaleThread::update_aspect(ScaleWindow *window)
182 {
183         if(auto_aspect)
184         {
185                 char string[1024];
186                 mwindow->create_aspect_ratio(aspect_w, aspect_h, dimension[2], dimension[3]);
187                 sprintf(string, "%.0f", aspect_w);
188                 window->aspect_w->update(string);
189                 sprintf(string, "%.0f", aspect_h);
190                 window->aspect_h->update(string);
191         }
192 }
193
194
195
196 ScaleWindow::ScaleWindow(ScaleThread *thread)
197  : BC_Window(_(PROGRAM_NAME ": Scale"), 370, 260, 0, 0)
198 { this->thread = thread; }
199
200 ScaleWindow::~ScaleWindow()
201 {
202 }
203
204 void ScaleWindow::create_objects()
205 {
206         int x = 10, y = 10;
207         add_subwindow(new BC_Title(x, y, _("New camera size:")));
208         add_subwindow(new BC_Title(x + 200, y, _("New projector size:")));
209         y += 30;
210         add_subwindow(new BC_Title(x, y, _("Width:")));
211         x += 70;
212         add_subwindow(dimension[0] = new ScaleSizeText(x, y, thread, &(thread->dimension[0])));
213         x += 110;
214         add_subwindow(new BC_Title(x, y, _("Width:")));
215         x += 70;
216         add_subwindow(dimension[2] = new ScaleSizeText(x, y, thread, &(thread->dimension[2])));
217
218         y += 30;
219         x = 10;
220         add_subwindow(new BC_Title(x, y, _("Height:")));
221         x += 70;
222         add_subwindow(dimension[1] = new ScaleSizeText(x, y, thread, &(thread->dimension[1])));
223         x += 110;
224         add_subwindow(new BC_Title(x, y, _("Height:")));
225         x += 70;
226         add_subwindow(dimension[3] = new ScaleSizeText(x, y, thread, &(thread->dimension[3])));
227
228         y += 30;
229         x = 10;
230         add_subwindow(new BC_Title(x, y, _("W Ratio:")));
231         x += 70;
232         add_subwindow(ratio[0] = new ScaleRatioText(x, y, thread, &(thread->ratio[0])));
233         x += 110;
234         add_subwindow(new BC_Title(x, y, _("W Ratio:")));
235         x += 70;
236         add_subwindow(ratio[2] = new ScaleRatioText(x, y, thread, &(thread->ratio[2])));
237
238         y += 30;
239         x = 10;
240         add_subwindow(new BC_Title(x, y, _("H Ratio:")));
241         x += 70;
242         add_subwindow(ratio[1] = new ScaleRatioText(x, y, thread, &(thread->ratio[1])));
243         x += 110;
244         add_subwindow(new BC_Title(x, y, _("H Ratio:")));
245         x += 70;
246         add_subwindow(ratio[3] = new ScaleRatioText(x, y, thread, &(thread->ratio[3])));
247
248 //      y += 30;
249 //      x = 10;
250 //      add_subwindow(new BC_Title(x, y, "X Offset:"));
251 //      x += 70;
252 //      add_subwindow(offsets[0] = new ScaleOffsetText(x, y, thread, &(thread->offsets[0])));
253 //      x += 110;
254 //      add_subwindow(new BC_Title(x, y, "X Offset:"));
255 //      x += 70;
256 //      add_subwindow(offsets[2] = new ScaleOffsetText(x, y, thread, &(thread->offsets[2])));
257 //
258 //      y += 30;
259 //      x = 10;
260 //      add_subwindow(new BC_Title(x, y, "Y Offset:"));
261 //      x += 70;
262 //      add_subwindow(offsets[1] = new ScaleOffsetText(x, y, thread, &(thread->offsets[1])));
263 //      x += 110;
264 //      add_subwindow(new BC_Title(x, y, "Y Offset:"));
265 //      x += 70;
266 //      add_subwindow(offsets[3] = new ScaleOffsetText(x, y, thread, &(thread->offsets[3])));
267
268         x = 10;
269         y += 30;
270         add_subwindow(new BC_Title(x, y, _("Aspect ratio:")));
271         x += 100;
272         char string[1024];
273         sprintf(string, "%.0f", thread->aspect_w);
274         add_subwindow(aspect_w = new ScaleAspectW(x, y, thread, &(thread->aspect_w), string));
275         x += 55;
276         add_subwindow(new BC_Title(x, y, _(":")));
277         x += 10;
278         sprintf(string, "%.0f", thread->aspect_h);
279         add_subwindow(aspect_h = new ScaleAspectH(x, y, thread, &(thread->aspect_h), string));
280         x += 60;
281         add_subwindow(new ScaleAspectAuto(x, y + 5, thread));
282
283         y += 30;
284 //      x = 40;
285 //      add_subwindow(new BC_Title(x, y, _("Camera position:")));
286 //      x += 200;
287 //      add_subwindow(new BC_Title(x, y, _("Projector position:")));
288
289 //      ScalePosition *position;
290 //      x = 60;
291 //      y += 25;
292 //      add_subwindow(position1 = new ScalePosition(x, y, thread, this, 
293 //              &(thread->orig_dimension[0]), &(thread->dimension[0]), &(thread->offsets[0])));
294 //      position1->draw();
295
296 //      x += 200;
297 //      add_subwindow(position2 = new ScalePosition(x, y, thread, this, 
298 //              &(thread->orig_dimension[2]), &(thread->dimension[2]), &(thread->offsets[2])));
299 //      position2->draw();
300
301 //      y += 110;
302         x = 10;
303         add_subwindow(new ScaleConstrain(x, y, thread));        
304         x += 200;
305         add_subwindow(new ScaleData(x, y, thread));     
306
307         y += 30;
308         x = 50;
309         add_subwindow(new BC_OKButton(x, y));
310         x += 200;
311         add_subwindow(new BC_CancelButton(x, y));
312 }
313
314 ScaleSizeText::ScaleSizeText(int x, int y, ScaleThread *thread, int *output)
315  : BC_TextBox(x, y, 100, 1, *output)
316
317         this->thread = thread; 
318         this->output = output; 
319 }
320 ScaleSizeText::~ScaleSizeText() {}
321 int ScaleSizeText::handle_event()
322 {
323         *output = atol(get_text());
324         *output /= 2;
325         *output *= 2;
326         if(*output <= 0) *output = 2;
327         if(*output > 10000) *output = 10000;
328         *output *= -1;
329         thread->update_window();
330 }
331
332 ScaleOffsetText::ScaleOffsetText(int x, int y, ScaleThread *thread, int *output)
333  : BC_TextBox(x, y, 100, 1, *output)
334 { this->thread = thread; this->output = output; }
335 ScaleOffsetText::~ScaleOffsetText() {}
336 int ScaleOffsetText::handle_event()
337 {
338         *output = atol(get_text());
339         //if(*output <= 0) *output = 0;
340         if(*output > 10000) *output = 10000;
341         if(*output < -10000) *output = -10000;
342         thread->update_window(1);
343 }
344
345 ScaleRatioText::ScaleRatioText(int x, int y, ScaleThread *thread, float *output)
346  : BC_TextBox(x, y, 100, 1, *output)
347 { this->thread = thread; this->output = output; }
348 ScaleRatioText::~ScaleRatioText() {}
349 int ScaleRatioText::handle_event()
350 {
351         *output = atof(get_text());
352         //if(*output <= 0) *output = 1;
353         if(*output > 10000) *output = 10000;
354         if(*output < -10000) *output = -10000;
355         *output *= -1;
356         thread->update_window();
357 }
358
359
360
361
362 ScaleConstrain::ScaleConstrain(int x, int y, ScaleThread *thread)
363  : BC_CheckBox(x, y, thread->constrain_ratio, _("Constrain ratio"))
364 { this->thread = thread; }
365 ScaleConstrain::~ScaleConstrain() {}
366 int ScaleConstrain::handle_event()
367 {
368         thread->constrain_ratio = get_value();
369 }
370
371 ScaleData::ScaleData(int x, int y, ScaleThread *thread)
372  : BC_CheckBox(x, y, thread->scale_data, _("Scale data"))
373 { this->thread = thread; }
374 ScaleData::~ScaleData() {}
375 int ScaleData::handle_event()
376 {
377         thread->scale_data = get_value();
378         thread->update_window();
379 }
380
381
382 ScaleAspectAuto::ScaleAspectAuto(int x, int y, ScaleThread *thread)
383  : BC_CheckBox(x, y, thread->auto_aspect, _("Auto"))
384 { this->thread = thread; }
385
386 ScaleAspectAuto::~ScaleAspectAuto()
387 {
388 }
389
390 int ScaleAspectAuto::handle_event()
391 {
392         thread->auto_aspect = get_value();
393         thread->update_aspect(thread->window);
394 }
395
396
397
398
399 ScaleAspectW::ScaleAspectW(int x, int y, ScaleThread *thread, float *output, char *string)
400  : BC_TextBox(x, y, 50, 1, string)
401 {
402         this->output = output;
403         this->thread = thread;
404 }
405 ScaleAspectW::~ScaleAspectW()
406 {
407 }
408
409 int ScaleAspectW::handle_event()
410 {
411         *output = atof(get_text());
412 }
413
414
415 ScaleAspectH::ScaleAspectH(int x, int y, ScaleThread *thread, float *output, char *string)
416  : BC_TextBox(x, y, 50, 1, string)
417 {
418         this->output = output;
419         this->thread = thread;
420 }
421 ScaleAspectH::~ScaleAspectH()
422 {
423 }
424
425 int ScaleAspectH::handle_event()
426 {
427         *output = atof(get_text());
428 }
429
430