Merge CV, ver=5.1; ops/methods from HV, and interface from CV where possible
[goodguy/history.git] / cinelerra-5.1 / cinelerra / zoompanel.C
diff --git a/cinelerra-5.1/cinelerra/zoompanel.C b/cinelerra-5.1/cinelerra/zoompanel.C
new file mode 100644 (file)
index 0000000..c272b12
--- /dev/null
@@ -0,0 +1,393 @@
+
+/*
+ * CINELERRA
+ * Copyright (C) 1997-2014 Adam Williams <broadcast at earthling dot net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include "bcsignals.h"
+#include "clip.h"
+#include "edl.h"
+#include "edlsession.h"
+#include "mwindow.h"
+#include "mwindowgui.h"
+#include "theme.h"
+#include "trackcanvas.h"
+#include "units.h"
+#include "vframe.h"
+#include "zoompanel.h"
+
+
+ZoomHash::ZoomHash(double value, const char *text)
+{
+       this->value = value;
+       this->text = new char[strlen(text) + 1];
+       strcpy(this->text, text);
+}
+
+ZoomHash::~ZoomHash()
+{
+       delete [] text;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ZoomPanel::ZoomPanel(MWindow *mwindow,
+       BC_WindowBase *subwindow,
+       double value,
+       int x,
+       int y,
+       int w,
+       double min,
+       double max,
+       int zoom_type)
+{
+       this->mwindow = mwindow;
+       this->subwindow = subwindow;
+       this->x = x;
+       this->y = y;
+       this->w = w;
+       this->value = value;
+       this->min = min;
+       this->max = max;
+       this->zoom_type = zoom_type;
+       this->menu_images = 0;
+       this->tumbler_images = 0;
+       this->user_table = 0;
+       this->user_size = 0;
+}
+
+ZoomPanel::ZoomPanel(MWindow *mwindow,
+       BC_WindowBase *subwindow,
+       double value,
+       int x,
+       int y,
+       int w,
+       double *user_table,
+       int user_size,
+       int zoom_type)
+{
+       this->mwindow = mwindow;
+       this->subwindow = subwindow;
+       this->x = x;
+       this->y = y;
+       this->w = w;
+       this->value = value;
+       this->min = min;
+       this->max = max;
+       this->zoom_type = zoom_type;
+       this->menu_images = 0;
+       this->tumbler_images = 0;
+       this->user_table = user_table;
+       this->user_size = user_size;
+}
+
+ZoomPanel::~ZoomPanel()
+{
+       delete zoom_text;
+       delete zoom_tumbler;
+       zoom_table.remove_all_objects();
+}
+
+void ZoomPanel::calculate_menu()
+{
+       if(user_size)
+       {
+               for(int i = 0; i < user_size; i++)
+               {
+                       zoom_text->add_item(new BC_MenuItem(value_to_text(user_table[i], 0)));
+                       zoom_table.append(new ZoomHash(user_table[i], value_to_text(user_table[i], 0)));
+               }
+       }
+       else
+       {
+               for(double zoom = min; zoom <= max; zoom *= 2)
+               {
+                       zoom_text->add_item(new BC_MenuItem(value_to_text(zoom, 0)));
+                       zoom_table.append(new ZoomHash(zoom, value_to_text(zoom, 0)));
+               }
+       }
+}
+
+int ZoomPanel::calculate_w(int menu_w)
+{
+       return BC_PopupMenu::calculate_w(menu_w) + BC_Tumbler::calculate_w();
+}
+
+void ZoomPanel::update_menu()
+{
+       while(zoom_text->total_items())
+       {
+               zoom_text->remove_item(0);
+       }
+
+       zoom_table.remove_all_objects();
+       calculate_menu();
+}
+
+void ZoomPanel::set_menu_images(VFrame **data)
+{
+       this->menu_images = data;
+}
+
+void ZoomPanel::set_tumbler_images(VFrame **data)
+{
+       this->tumbler_images = data;
+}
+
+void ZoomPanel::create_objects()
+{
+       subwindow->add_subwindow(zoom_text = new ZoomPopup(mwindow,
+               this,
+               x,
+               y));
+       x += zoom_text->get_w();
+       subwindow->add_subwindow(zoom_tumbler = new ZoomTumbler(mwindow,
+               this,
+               x,
+               y));
+       calculate_menu();
+}
+
+void ZoomPanel::reposition_window(int x, int y)
+{
+       zoom_text->reposition_window(x, y);
+       x += zoom_text->get_w();
+       zoom_tumbler->reposition_window(x, y);
+}
+
+
+int ZoomPanel::get_w()
+{
+       return zoom_text->get_w() + zoom_tumbler->get_w();
+}
+
+double ZoomPanel::get_value()
+{
+       return value;
+}
+
+char* ZoomPanel::get_text()
+{
+       return zoom_text->get_text();
+}
+
+void ZoomPanel::set_text(const char *text)
+{
+       zoom_text->set_text(text);
+}
+
+void ZoomPanel::update(double value)
+{
+       this->value = value;
+       zoom_text->set_text(value_to_text(value));
+}
+
+void ZoomPanel::update(const char *value)
+{
+       zoom_text->set_text(value);
+}
+
+
+char* ZoomPanel::value_to_text(double value, int use_table)
+{
+       if(use_table)
+       {
+               for(int i = 0; i < zoom_table.total; i++)
+               {
+//printf("ZoomPanel::value_to_text %p\n", zoom_table.values[i]);
+                       if(EQUIV(zoom_table.values[i]->value, value))
+                               return zoom_table.values[i]->text;
+               }
+//printf("ZoomPanel::value_to_text: should never get here\n");
+               return zoom_table.values[0]->text;
+       }
+
+       switch(zoom_type)
+       {
+               case ZOOM_PERCENTAGE:
+                       sprintf(string, "%d%%", (int)(value * 100));
+                       break;
+
+               case ZOOM_FLOAT:
+                       sprintf(string, "%.1f", value);
+                       break;
+
+               case ZOOM_LONG:
+                       sprintf(string, "%ld", (long)value);
+                       break;
+
+               case ZOOM_TIME:
+               {
+//                     sprintf(string, "%ld", (long)value);
+                       double total_seconds = (double)(mwindow->theme->mcanvas_w -
+                                       mwindow->theme->patchbay_w -
+                                       BC_ScrollBar::get_span(SCROLL_VERT)) *
+                               value /
+                               mwindow->edl->session->sample_rate;
+                       Units::totext(string,
+                               total_seconds,
+                               mwindow->edl->session->time_format,
+                               mwindow->edl->session->sample_rate,
+                               mwindow->edl->session->frame_rate,
+                               mwindow->edl->session->frames_per_foot);
+                       break;
+               }
+       }
+       return string;
+}
+
+double ZoomPanel::text_to_zoom(char *text, int use_table)
+{
+       if(use_table) {
+               for(int i = 0; i < zoom_table.total; i++) {
+                       if(!strcasecmp(text, zoom_table.values[i]->text))
+                               return zoom_table.values[i]->value;
+               }
+               return zoom_table.values[0]->value;
+       }
+
+       double result = 1.;
+       switch(zoom_type) {
+               case ZOOM_PERCENTAGE:
+                       result = atof(text) / 100;
+                       break;
+               case ZOOM_FLOAT:
+               case ZOOM_LONG:
+//             case ZOOM_TIME:
+                       result = atof(text);
+                       break;
+               case ZOOM_TIME: {
+                       double total_samples = Units::fromtext(text,
+                               mwindow->edl->session->sample_rate,
+                               mwindow->edl->session->time_format,
+                               mwindow->edl->session->frame_rate,
+                               mwindow->edl->session->frames_per_foot);
+                       total_samples /= mwindow->theme->mcanvas_w -
+                               mwindow->theme->patchbay_w -
+                               BC_ScrollBar::get_span(SCROLL_VERT);
+                       double difference = fabs(total_samples - result);
+                       while(fabs(result - total_samples) <= difference) {
+                               difference = fabs(result - total_samples);
+                               result *= 2;
+                       }
+                       break;
+               }
+       }
+       return result;
+}
+
+
+
+
+
+
+
+ZoomPopup::ZoomPopup(MWindow *mwindow, ZoomPanel *panel, int x, int y)
+ : BC_PopupMenu(x,
+               y,
+               panel->w,
+               panel->value_to_text(panel->value, 0),
+               1,
+               panel->menu_images)
+{
+       this->mwindow = mwindow;
+       this->panel = panel;
+}
+
+ZoomPopup::~ZoomPopup()
+{
+}
+
+int ZoomPopup::handle_event()
+{
+       panel->value = panel->text_to_zoom(get_text());
+       panel->handle_event();
+       return 1;
+}
+
+
+
+ZoomTumbler::ZoomTumbler(MWindow *mwindow, ZoomPanel *panel, int x, int y)
+ : BC_Tumbler(x,
+       y,
+       panel->tumbler_images)
+{
+       this->mwindow = mwindow;
+       this->panel = panel;
+}
+
+ZoomTumbler::~ZoomTumbler()
+{
+}
+
+int ZoomTumbler::handle_up_event()
+{
+       if(panel->user_table)
+       {
+               int current_index = 0;
+               for(current_index = 0; current_index < panel->user_size; current_index++)
+                       if(EQUIV(panel->user_table[current_index], panel->value)) break;
+               current_index++;
+               CLAMP(current_index, 0, panel->user_size - 1);
+               panel->value = panel->user_table[current_index];
+       }
+       else
+       {
+               panel->value *= 2;
+               RECLIP(panel->value, panel->min, panel->max);
+       }
+
+       panel->zoom_text->set_text(panel->value_to_text(panel->value));
+       panel->handle_event();
+       return 1;
+}
+
+int ZoomTumbler::handle_down_event()
+{
+       if(panel->user_table)
+       {
+               int current_index = 0;
+               for(current_index = 0; current_index < panel->user_size; current_index++)
+                       if(EQUIV(panel->user_table[current_index], panel->value)) break;
+               current_index--;
+               CLAMP(current_index, 0, panel->user_size - 1);
+               panel->value = panel->user_table[current_index];
+       }
+       else
+       {
+               panel->value /= 2;
+               RECLIP(panel->value, panel->min, panel->max);
+       }
+       panel->zoom_text->set_text(panel->value_to_text(panel->value));
+       panel->handle_event();
+       return 1;
+}