r499: This commit was manufactured by cvs2svn to create tag 'r1_2_1-last'.
[cinelerra_cv/mob.git] / hvirtual / cinelerra / canvas.C
blob0a1bba6f7d7cc7d62380825814ba98360f91e174
1 #include "canvas.h"
2 #include "clip.h"
3 #include "edl.h"
4 #include "edlsession.h"
5 #include "language.h"
6 #include "vframe.h"
10 Canvas::Canvas(BC_WindowBase *subwindow, 
11         int x, 
12         int y, 
13         int w, 
14         int h,
15         int output_w,
16         int output_h,
17         int use_scrollbars,
18         int use_cwindow,
19         int use_rwindow,
20         int use_vwindow)
22         reset();
23         this->subwindow = subwindow;
24         this->x = x;
25         this->y = y;
26         this->w = w;
27         this->h = h;
28         this->output_w = output_w;
29         this->output_h = output_h;
30         this->use_scrollbars = use_scrollbars;
31         this->use_cwindow = use_cwindow;
32         this->use_rwindow = use_rwindow;
33         this->use_vwindow = use_vwindow;
36 Canvas::~Canvas()
38         if(refresh_frame) delete refresh_frame;
39         delete canvas_menu;
40         if(yscroll) delete yscroll;
41         if(xscroll) delete xscroll;
44 void Canvas::reset()
46         use_scrollbars = 0;
47         output_w = 0;
48         output_h = 0;
49     xscroll = 0;
50     yscroll = 0;
51         refresh_frame = 0;
54 // Get dimensions given a zoom
55 void Canvas::calculate_sizes(float aspect_ratio, 
56         int output_w, 
57         int output_h, 
58         float zoom, 
59         int &w, 
60         int &h)
62 // Horizontal stretch
63         if((float)output_w / output_h <= aspect_ratio)
64         {
65                 w = (int)((float)output_h * aspect_ratio * zoom);
66                 h = (int)((float)output_h * zoom);
67         }
68         else
69 // Vertical stretch
70         {
71                 h = (int)((float)output_w / aspect_ratio * zoom);
72                 w = (int)((float)output_w * zoom);
73         }
76 float Canvas::get_x_offset(EDL *edl, 
77         int single_channel, 
78         float zoom_x, 
79         float conformed_w,
80         float conformed_h)
82         if(use_scrollbars)
83         {
84                 if(xscroll) 
85                 {
86 // If the projection is smaller than the canvas, this forces it in the center.
87 //                      if(conformed_w < w_visible)
88 //                              return -(float)(w_visible - conformed_w) / 2;
90                         return (float)get_xscroll();
91                 }
92                 else
93                         return ((float)-canvas->get_w() / zoom_x + 
94                                 edl->calculate_output_w(single_channel)) / 2;
95         }
96         else
97         {
98                 int out_w, out_h;
99                 int canvas_w = canvas->get_w();
100                 int canvas_h = canvas->get_h();
101                 out_w = canvas_w;
102                 out_h = canvas_h;
103                 
104                 if((float)out_w / out_h > conformed_w / conformed_h)
105                 {
106                         out_w = (int)(out_h * conformed_w / conformed_h + 0.5);
107                 }
108                 
109                 if(out_w < canvas_w)
110                         return -(canvas_w - out_w) / 2 / zoom_x;
111         }
113         return 0;
116 float Canvas::get_y_offset(EDL *edl, 
117         int single_channel, 
118         float zoom_y, 
119         float conformed_w,
120         float conformed_h)
122         if(use_scrollbars)
123         {
124                 if(yscroll)
125                 {
126 // If the projection is smaller than the canvas, this forces it in the center.
127 //                      if(conformed_h < h_visible)
128 //                              return -(float)(h_visible - conformed_h) / 2;
130                         return (float)get_yscroll();
131                 }
132                 else
133                         return ((float)-canvas->get_h() / zoom_y + 
134                                 edl->calculate_output_h(single_channel)) / 2;
135         }
136         else
137         {
138                 int out_w, out_h;
139                 int canvas_w = canvas->get_w();
140                 int canvas_h = canvas->get_h();
141                 out_w = canvas_w;
142                 out_h = canvas_h;
144                 if((float)out_w / out_h <= conformed_w / conformed_h)
145                 {
146                         out_h = (int)((float)out_w / (conformed_w / conformed_h) + 0.5);
147                 }
149 //printf("Canvas::get_y_offset 1 %d %d %f\n", out_h, canvas_h, -((float)canvas_h - out_h) / 2);
150                 if(out_h < canvas_h)
151                         return -((float)canvas_h - out_h) / 2 / zoom_y;
152         }
154         return 0;
157 // This may not be used anymore
158 void Canvas::check_boundaries(EDL *edl, int &x, int &y, float &zoom)
160         if(x + w_visible > w_needed) x = w_needed - w_visible;
161         if(y + h_visible > h_needed) y = h_needed - h_visible;
163         if(x < 0) x = 0;
164         if(y < 0) y = 0;
167 void Canvas::update_scrollbars()
169         if(use_scrollbars)
170         {
171                 if(xscroll) xscroll->update_length(w_needed, get_xscroll(), w_visible);
172                 if(yscroll) yscroll->update_length(h_needed, get_yscroll(), h_visible);
173         }
176 void Canvas::get_zooms(EDL *edl, 
177         int single_channel, 
178         float &zoom_x, 
179         float &zoom_y,
180         float &conformed_w,
181         float &conformed_h)
183         edl->calculate_conformed_dimensions(single_channel, 
184                 conformed_w, 
185                 conformed_h);
187         if(use_scrollbars)
188         {
189                 zoom_x = get_zoom() * 
190                         conformed_w / 
191                         edl->calculate_output_w(single_channel);
192                 zoom_y = get_zoom() * 
193                         conformed_h / 
194                         edl->calculate_output_h(single_channel);
195         }
196         else
197         {
198                 int out_w, out_h;
199                 int canvas_w = canvas->get_w();
200                 int canvas_h = canvas->get_h();
201         
202                 out_w = canvas_w;
203                 out_h = canvas_h;
205                 if((float)out_w / out_h > conformed_w / conformed_h)
206                 {
207                         out_w = (int)((float)out_h * conformed_w / conformed_h + 0.5);
208                 }
209                 else
210                 {
211                         out_h = (int)((float)out_w / (conformed_w / conformed_h) + 0.5);
212                 }
214                 zoom_x = (float)out_w / edl->calculate_output_w(single_channel);
215                 zoom_y = (float)out_h / edl->calculate_output_h(single_channel);
216 //printf("get zooms 2 %d %d %f %f\n", canvas_w, canvas_h, conformed_w, conformed_h);
217         }
220 // Convert a coordinate on the canvas to a coordinate on the output
221 void Canvas::canvas_to_output(EDL *edl, int single_channel, float &x, float &y)
223         float zoom_x, zoom_y, conformed_w, conformed_h;
224         get_zooms(edl, single_channel, zoom_x, zoom_y, conformed_w, conformed_h);
226 //printf("Canvas::canvas_to_output y=%f zoom_y=%f y_offset=%f\n", 
227 //      y, zoom_y, get_y_offset(edl, single_channel, zoom_y, conformed_w, conformed_h));
229         x = (float)x / zoom_x + get_x_offset(edl, single_channel, zoom_x, conformed_w, conformed_h);
230         y = (float)y / zoom_y + get_y_offset(edl, single_channel, zoom_y, conformed_w, conformed_h);
233 void Canvas::output_to_canvas(EDL *edl, int single_channel, float &x, float &y)
235         float zoom_x, zoom_y, conformed_w, conformed_h;
236         get_zooms(edl, single_channel, zoom_x, zoom_y, conformed_w, conformed_h);
238 //printf("Canvas::output_to_canvas x=%f zoom_x=%f x_offset=%f\n", x, zoom_x, get_x_offset(edl, single_channel, zoom_x, conformed_w));
240         x = (float)zoom_x * (x - get_x_offset(edl, single_channel, zoom_x, conformed_w, conformed_h));
241         y = (float)zoom_y * (y - get_y_offset(edl, single_channel, zoom_y, conformed_w, conformed_h));
246 void Canvas::get_transfers(EDL *edl, 
247         int &in_x, 
248         int &in_y, 
249         int &in_w, 
250         int &in_h,
251         int &out_x, 
252         int &out_y, 
253         int &out_w, 
254         int &out_h,
255         int canvas_w,
256         int canvas_h)
258 // printf("Canvas::get_transfers %d %d\n", canvas_w, 
259 //              canvas_h);
260         if(canvas_w < 0) canvas_w = canvas->get_w();
261         if(canvas_h < 0) canvas_h = canvas->get_h();
263         if(use_scrollbars)
264         {
265                 float in_x1, in_y1, in_x2, in_y2;
266                 float out_x1, out_y1, out_x2, out_y2;
267                 float zoom_x, zoom_y, conformed_w, conformed_h;
269                 get_zooms(edl, 0, zoom_x, zoom_y, conformed_w, conformed_h);
270                 out_x1 = 0;
271                 out_y1 = 0;
272                 out_x2 = canvas_w;
273                 out_y2 = canvas_h;
274                 in_x1 = 0;
275                 in_y1 = 0;
276                 in_x2 = canvas_w;
277                 in_y2 = canvas_h;
279                 canvas_to_output(edl, 0, in_x1, in_y1);
280                 canvas_to_output(edl, 0, in_x2, in_y2);
282 //printf("Canvas::get_transfers 1 %.0f %.0f %.0f %.0f -> %.0f %.0f %.0f %.0f\n",
283 //in_x1, in_y1, in_x2, in_y2, out_x1, out_y1, out_x2, out_y2);
285                 if(in_x1 < 0)
286                 {
287                         out_x1 += -in_x1 * zoom_x;
288                         in_x1 = 0;
289                 }
291                 if(in_y1 < 0)
292                 {
293                         out_y1 += -in_y1 * zoom_y;
294                         in_y1 = 0;
295                 }
297                 int output_w = get_output_w(edl);
298                 int output_h = get_output_h(edl);
300                 if(in_x2 > output_w)
301                 {
302                         out_x2 -= (in_x2 - output_w) * zoom_x;
303                         in_x2 = output_w;
304                 }
306                 if(in_y2 > output_h)
307                 {
308                         out_y2 -= (in_y2 - output_h) * zoom_y;
309                         in_y2 = output_h;
310                 }
311 // printf("Canvas::get_transfers 2 %.0f %.0f %.0f %.0f -> %.0f %.0f %.0f %.0f\n",
312 //                      in_x1, in_y1, in_x2, in_y2, out_x1, out_y1, out_x2, out_y2);
314                 in_x = (int)in_x1;
315                 in_y = (int)in_y1;
316                 in_w = (int)(in_x2 - in_x1);
317                 in_h = (int)(in_y2 - in_y1);
318                 out_x = (int)out_x1;
319                 out_y = (int)out_y1;
320                 out_w = (int)(out_x2 - out_x1);
321                 out_h = (int)(out_y2 - out_y1);
323 // Center on canvas
324 //              if(!scrollbars_exist())
325 //              {
326 //                      out_x = canvas_w / 2 - out_w / 2;
327 //                      out_y = canvas_h / 2 - out_h / 2;
328 //              }
330 // printf("Canvas::get_transfers 2 %d %d %d %d -> %d %d %d %d\n",in_x, 
331 //                      in_y, 
332 //                      in_w, 
333 //                      in_h,
334 //                      out_x, 
335 //                      out_y, 
336 //                      out_w, 
337 //                      out_h);
338         }
339         else
340         {
341                 out_x = 0;
342                 out_y = 0;
343                 out_w = canvas_w;
344                 out_h = canvas_h;
346                 if(edl)
347                 {
348                         if((float)out_w / out_h > edl->get_aspect_ratio())
349                         {
350                                 out_w = (int)(out_h * edl->get_aspect_ratio() + 0.5);
351                                 out_x = canvas_w / 2 - out_w / 2;
352                         }
353                         else
354                         {
355                                 out_h = (int)(out_w / edl->get_aspect_ratio() + 0.5);
356                                 out_y = canvas_h / 2 - out_h / 2;
357                         }
358                         in_x = 0;
359                         in_y = 0;
360                         in_w = get_output_w(edl);
361                         in_h = get_output_h(edl);
362                 }
363                 else
364                 {
365                         in_x = 0;
366                         in_y = 0;
367                         in_w = this->output_w;
368                         in_h = this->output_h;
369                 }
370         }
372         in_x = MAX(0, in_x);
373         in_y = MAX(0, in_y);
374         in_w = MAX(0, in_w);
375         in_h = MAX(0, in_h);
376         out_x = MAX(0, out_x);
377         out_y = MAX(0, out_y);
378         out_w = MAX(0, out_w);
379         out_h = MAX(0, out_h);
382 int Canvas::scrollbars_exist()
384         return(use_scrollbars && (xscroll || yscroll));
387 int Canvas::get_output_w(EDL *edl)
389         if(use_scrollbars)
390                 return edl->calculate_output_w(0);
391         else
392                 return edl->session->output_w;
395 int Canvas::get_output_h(EDL *edl)
397         if(edl)
398         {
399                 if(use_scrollbars)
400                         return edl->calculate_output_h(0);
401                 else
402                         return edl->session->output_h;
403         }
408 void Canvas::get_scrollbars(EDL *edl, 
409         int &canvas_x, 
410         int &canvas_y, 
411         int &canvas_w, 
412         int &canvas_h)
414         int need_xscroll = 0;
415         int need_yscroll = 0;
416 //      int done = 0;
417         float zoom_x, zoom_y, conformed_w, conformed_h;
419         if(edl)
420         {
421                 w_needed = edl->calculate_output_w(0);
422                 h_needed = edl->calculate_output_h(0);
423                 w_visible = w_needed;
424                 h_visible = h_needed;
425         }
426 //printf("Canvas::get_scrollbars 1 %d %d\n", get_xscroll(), get_yscroll());
428         if(use_scrollbars)
429         {
430                 w_needed = edl->calculate_output_w(0);
431                 h_needed = edl->calculate_output_h(0);
432                 get_zooms(edl, 0, zoom_x, zoom_y, conformed_w, conformed_h);
433 //printf("Canvas::get_scrollbars 2 %d %d\n", get_xscroll(), get_yscroll());
435 //              while(!done)
436 //              {
437                         w_visible = (int)(canvas_w / zoom_x);
438                         h_visible = (int)(canvas_h / zoom_y);
439 //                      done = 1;
441 //                      if(w_needed > w_visible)
442                         if(1)
443                         {
444                                 if(!need_xscroll)
445                                 {
446                                         need_xscroll = 1;
447                                         canvas_h -= BC_ScrollBar::get_span(SCROLL_HORIZ);
448 //                                      done = 0;
449                                 }
450                         }
451                         else
452                                 need_xscroll = 0;
454 //                      if(h_needed > h_visible)
455                         if(1)
456                         {
457                                 if(!need_yscroll)
458                                 {
459                                         need_yscroll = 1;
460                                         canvas_w -= BC_ScrollBar::get_span(SCROLL_VERT);
461 //                                      done = 0;
462                                 }
463                         }
464                         else
465                                 need_yscroll = 0;
466 //              }
467 //printf("Canvas::get_scrollbars %d %d %d %d %d %d\n", canvas_w, canvas_h, w_needed, h_needed, w_visible, h_visible);
468 //printf("Canvas::get_scrollbars 3 %d %d\n", get_xscroll(), get_yscroll());
470                 w_visible = (int)(canvas_w / zoom_x);
471                 h_visible = (int)(canvas_h / zoom_y);
472         }
474         if(need_xscroll)
475         {
476                 if(!xscroll)
477                         subwindow->add_subwindow(xscroll = new CanvasXScroll(edl, 
478                                 this, 
479                 canvas_x,
480                 canvas_y + canvas_h,
481                                 w_needed,
482                                 get_xscroll(),
483                                 w_visible,
484                                 canvas_w));
485                 else
486                         xscroll->reposition_window(canvas_x, canvas_y + canvas_h, canvas_w);
488                 if(xscroll->get_length() != w_needed ||
489                         xscroll->get_handlelength() != w_visible)
490                         xscroll->update_length(w_needed, get_xscroll(), w_visible);
491         }
492         else
493         {
494                 if(xscroll) delete xscroll;
495                 xscroll = 0;
496         }
497 //printf("Canvas::get_scrollbars 4 %d %d\n", get_xscroll(), get_yscroll());
499         if(need_yscroll)
500         {
501                 if(!yscroll)
502                         subwindow->add_subwindow(yscroll = new CanvasYScroll(edl, 
503                                 this,
504                 canvas_x + canvas_w,
505                 canvas_y,
506                                 h_needed,
507                                 get_yscroll(),
508                                 h_visible,
509                                 canvas_h));
510                 else
511                         yscroll->reposition_window(canvas_x + canvas_w, canvas_y, canvas_h);
513                 if(yscroll->get_length() != edl->calculate_output_h(0) ||
514                         yscroll->get_handlelength() != h_visible)
515                         yscroll->update_length(h_needed, get_yscroll(), h_visible);
516         }
517         else
518         {
519                 if(yscroll) delete yscroll;
520                 yscroll = 0;
521         }
522 //printf("Canvas::get_scrollbars 5 %d %d\n", get_xscroll(), get_yscroll());
525 void Canvas::reposition_window(EDL *edl, int x, int y, int w, int h)
527         this->x = x;
528         this->y = y;
529         this->w = w;
530         this->h = h;
531         int view_x = x, view_y = y, view_w = w, view_h = h;
532 //printf("Canvas::reposition_window 1\n");
533         get_scrollbars(edl, view_x, view_y, view_w, view_h);
534 //printf("Canvas::reposition_window %d %d %d %d\n", view_x, view_y, view_w, view_h);
535         canvas->reposition_window(view_x, view_y, view_w, view_h);
536         draw_refresh();
537 //printf("Canvas::reposition_window 2\n");
540 void Canvas::set_cursor(int cursor)
542         canvas->set_cursor(cursor);
545 int Canvas::get_cursor_x()
547         return canvas->get_cursor_x();
550 int Canvas::get_cursor_y()
552         return canvas->get_cursor_y();
555 int Canvas::get_buttonpress()
557         return canvas->get_buttonpress();
561 int Canvas::create_objects(EDL *edl)
563         int view_x = x, view_y = y, view_w = w, view_h = h;
564         get_scrollbars(edl, view_x, view_y, view_w, view_h);
566         subwindow->add_subwindow(canvas = new CanvasOutput(edl, 
567                 this, 
568                 view_x, 
569                 view_y, 
570                 view_w, 
571                 view_h));
573         subwindow->add_subwindow(canvas_menu = new CanvasPopup(this));
574         canvas_menu->create_objects();
576         return 0;
579 int Canvas::button_press_event()
581         int result = 0;
583         if(canvas->get_buttonpress() == 3)
584         {
585                 canvas_menu->activate_menu();
586                 result = 1;
587         }
588         
589         return result;
595 CanvasOutput::CanvasOutput(EDL *edl, 
596         Canvas *canvas,
597     int x,
598     int y,
599     int w,
600     int h)
601  : BC_SubWindow(x, y, w, h, BC_WindowBase::get_resources()->bg_color)
603         this->canvas = canvas;
604         cursor_inside = 0;
607 CanvasOutput::~CanvasOutput()
611 int CanvasOutput::handle_event()
613         return 1;
616 int CanvasOutput::cursor_leave_event()
618         int result = 0;
619         if(cursor_inside) result = canvas->cursor_leave_event();
620         cursor_inside = 0;
621         return result;
624 int CanvasOutput::cursor_enter_event()
626         int result = 0;
627         if(is_event_win() && BC_WindowBase::cursor_inside())
628         {
629                 cursor_inside = 1;
630                 result = canvas->cursor_enter_event();
631         }
632         return result;
635 int CanvasOutput::button_press_event()
637         if(is_event_win() && BC_WindowBase::cursor_inside())
638         {
639                 return canvas->button_press_event();
640         }
641         return 0;
644 int CanvasOutput::button_release_event()
646         return canvas->button_release_event();
649 int CanvasOutput::cursor_motion_event()
651         return canvas->cursor_motion_event();
656 CanvasXScroll::CanvasXScroll(EDL *edl, 
657         Canvas *canvas, 
658     int x, 
659     int y, 
660         int length, 
661         int position, 
662         int handle_length,
663     int pixels)
664  : BC_ScrollBar(x, 
665                 y, 
666                 SCROLL_HORIZ, 
667                 pixels, 
668                 length, 
669                 position, 
670                 handle_length)
672         this->canvas = canvas;
675 CanvasXScroll::~CanvasXScroll()
679 int CanvasXScroll::handle_event()
681 //printf("CanvasXScroll::handle_event %d %d %d\n", get_length(), get_value(), get_handlelength());
682         canvas->update_zoom(get_value(), canvas->get_yscroll(), canvas->get_zoom());
683         canvas->draw_refresh();
684         return 1;
692 CanvasYScroll::CanvasYScroll(EDL *edl, 
693         Canvas *canvas, 
694     int x, 
695     int y, 
696         int length, 
697         int position, 
698         int handle_length,
699     int pixels)
700  : BC_ScrollBar(x, 
701                 y, 
702                 SCROLL_VERT, 
703                 pixels, 
704                 length, 
705                 position, 
706                 handle_length)
708         this->canvas = canvas;
711 CanvasYScroll::~CanvasYScroll()
715 int CanvasYScroll::handle_event()
717 //printf("CanvasYScroll::handle_event %d %d\n", get_value(), get_length());
718         canvas->update_zoom(canvas->get_xscroll(), get_value(), canvas->get_zoom());
719         canvas->draw_refresh();
720         return 1;
726 CanvasPopup::CanvasPopup(Canvas *canvas)
727  : BC_PopupMenu(0, 
728                 0, 
729                 0, 
730                 "", 
731                 0)
733         this->canvas = canvas;
736 CanvasPopup::~CanvasPopup()
740 void CanvasPopup::create_objects()
742         add_item(new CanvasPopupSize(canvas, _("Zoom 25%"), 0.25));
743         add_item(new CanvasPopupSize(canvas, _("Zoom 50%"), 0.5));
744         add_item(new CanvasPopupSize(canvas, _("Zoom 100%"), 1.0));
745         add_item(new CanvasPopupSize(canvas, _("Zoom 200%"), 2.0));
746         if(canvas->use_cwindow)
747         {
748                 add_item(new CanvasPopupResetCamera(canvas));
749                 add_item(new CanvasPopupResetProjector(canvas));
750                 add_item(toggle_controls = new CanvasToggleControls(canvas));
751         }
752         if(canvas->use_rwindow)
753         {
754                 add_item(new CanvasPopupResetTranslation(canvas));
755         }
756         if(canvas->use_vwindow)
757         {
758                 add_item(new CanvasPopupRemoveSource(canvas));
759         }
764 CanvasPopupSize::CanvasPopupSize(Canvas *canvas, char *text, float percentage)
765  : BC_MenuItem(text)
767         this->canvas = canvas;
768         this->percentage = percentage;
770 CanvasPopupSize::~CanvasPopupSize()
773 int CanvasPopupSize::handle_event()
775         canvas->zoom_resize_window(percentage);
776         return 1;
781 CanvasPopupResetCamera::CanvasPopupResetCamera(Canvas *canvas)
782  : BC_MenuItem(_("Reset camera"))
784         this->canvas = canvas;
786 int CanvasPopupResetCamera::handle_event()
788         canvas->reset_camera();
789         return 1;
794 CanvasPopupResetProjector::CanvasPopupResetProjector(Canvas *canvas)
795  : BC_MenuItem(_("Reset projector"))
797         this->canvas = canvas;
799 int CanvasPopupResetProjector::handle_event()
801         canvas->reset_projector();
802         return 1;
807 CanvasPopupResetTranslation::CanvasPopupResetTranslation(Canvas *canvas)
808  : BC_MenuItem(_("Reset translation"))
810         this->canvas = canvas;
812 int CanvasPopupResetTranslation::handle_event()
814         canvas->reset_translation();
815         return 1;
820 CanvasToggleControls::CanvasToggleControls(Canvas *canvas)
821  : BC_MenuItem(calculate_text(canvas->get_cwindow_controls()))
823         this->canvas = canvas;
825 int CanvasToggleControls::handle_event()
827         canvas->toggle_controls();
828         set_text(calculate_text(canvas->get_cwindow_controls()));
829         return 1;
832 char* CanvasToggleControls::calculate_text(int cwindow_controls)
834         if(!cwindow_controls) 
835                 return _("Show controls");
836         else
837                 return _("Hide controls");
843 CanvasPopupRemoveSource::CanvasPopupRemoveSource(Canvas *canvas)
844  : BC_MenuItem(_("Close source"))
846         this->canvas = canvas;
848 int CanvasPopupRemoveSource::handle_event()
850         canvas->close_source();
851         return 1;