#include <libgnomecanvasmm/item.h>
#include "pbd/error.h"
+#include "pbd/convert.h"
#include <gtkmm2ext/utils.h>
#include <gtkmm2ext/selector.h>
-#include <gtkmm2ext/stop_signal.h>
#include "ardour/session.h"
#include "ardour/utils.h"
#include "ardour/location.h"
#include "ardour_ui.h"
+#include "global_signals.h"
#include "gui_thread.h"
#include "public_editor.h"
#include "time_axis_view.h"
#include "rgb_macros.h"
#include "utils.h"
#include "streamview.h"
+#include "editor_drag.h"
#include "i18n.h"
using Gtkmm2ext::Keyboard;
const double trim_handle_size = 6.0; /* pixels */
-
-uint32_t TimeAxisView::hLargest = 0;
-uint32_t TimeAxisView::hLarge = 0;
-uint32_t TimeAxisView::hLarger = 0;
-uint32_t TimeAxisView::hNormal = 0;
-uint32_t TimeAxisView::hSmaller = 0;
-uint32_t TimeAxisView::hSmall = 0;
-bool TimeAxisView::need_size_info = true;
+uint32_t TimeAxisView::extra_height;
+uint32_t TimeAxisView::smaller_height;
int const TimeAxisView::_max_order = 512;
PBD::Signal1<void,TimeAxisView*> TimeAxisView::CatchDeletion;
_editor (ed),
_order (0)
{
- if (need_size_info) {
- compute_controls_size_info ();
- need_size_info = false;
+ if (extra_height == 0) {
+ compute_heights ();
}
+
_canvas_background = new Group (*ed.get_background_group (), 0.0, 0.0);
_canvas_display = new Group (*ed.get_trackview_group (), 0.0, 0.0);
_canvas_display->hide(); // reveal as needed
selection_group = new Group (*_canvas_display);
+ selection_group->set_data (X_("timeselection"), (void *) 1);
selection_group->hide();
_ghost_group = new Group (*_canvas_display);
control_parent = 0;
display_menu = 0;
- size_menu = 0;
_hidden = false;
in_destructor = false;
height = 0;
controls_table.show_all ();
controls_table.set_no_show_all ();
- resizer.set_size_request (10, 10);
+ resizer.set_size_request (10, 6);
resizer.set_name ("ResizeHandle");
resizer.signal_expose_event().connect (sigc::mem_fun (*this, &TimeAxisView::resizer_expose));
resizer.signal_button_press_event().connect (sigc::mem_fun (*this, &TimeAxisView::resizer_button_press));
resizer.signal_button_release_event().connect (sigc::mem_fun (*this, &TimeAxisView::resizer_button_release));
resizer.signal_motion_notify_event().connect (sigc::mem_fun (*this, &TimeAxisView::resizer_motion));
+
resizer.set_events (Gdk::BUTTON_PRESS_MASK|
Gdk::BUTTON_RELEASE_MASK|
Gdk::POINTER_MOTION_MASK|
HSeparator* separator = manage (new HSeparator());
controls_vbox.pack_start (controls_table, false, false);
- controls_vbox.pack_end (*separator, false, false);
- controls_vbox.pack_end (resizer_box, false, true);
+ controls_vbox.pack_end (resizer_box, false, false);
controls_vbox.show ();
//controls_ebox.set_name ("TimeAxisViewControlsBaseUnselected");
controls_ebox.signal_button_release_event().connect (sigc::mem_fun (*this, &TimeAxisView::controls_ebox_button_release));
controls_ebox.signal_scroll_event().connect (sigc::mem_fun (*this, &TimeAxisView::controls_ebox_scroll), true);
- controls_hbox.pack_start (controls_ebox,true,true);
+ controls_hbox.pack_start (controls_ebox, false, false);
controls_hbox.show ();
+ time_axis_vbox.pack_start (controls_hbox, true, true);
+ time_axis_vbox.pack_end (*separator, false, false);
+ time_axis_vbox.show();
+
ColorsChanged.connect (sigc::mem_fun (*this, &TimeAxisView::color_handler));
- GhostRegion::CatchDeletion.connect (*this, ui_bind (&TimeAxisView::erase_ghost, this, _1), gui_context());
+ GhostRegion::CatchDeletion.connect (*this, invalidator (*this), ui_bind (&TimeAxisView::erase_ghost, this, _1), gui_context());
}
TimeAxisView::~TimeAxisView()
delete (*i)->end_trim;
}
- for (list<SimpleLine*>::iterator i = feature_lines.begin(); i != feature_lines.end(); ++i) {
- delete (*i);
- }
-
delete selection_group;
selection_group = 0;
TimeAxisView::show_at (double y, int& nth, VBox *parent)
{
if (control_parent) {
- control_parent->reorder_child (controls_hbox, nth);
+ control_parent->reorder_child (time_axis_vbox, nth);
} else {
control_parent = parent;
- parent->pack_start (controls_hbox, false, false);
- parent->reorder_child (controls_hbox, nth);
+ parent->pack_start (time_axis_vbox, false, false);
+ parent->reorder_child (time_axis_vbox, nth);
}
_order = nth;
_canvas_display->raise_to_top ();
if (_marked_for_display) {
- controls_hbox.show ();
+ time_axis_vbox.show ();
controls_ebox.show ();
_canvas_background->show ();
}
/* now show children */
- cerr << name() << " has " << children.size() << " to show\n";
-
for (Children::iterator i = children.begin(); i != children.end(); ++i) {
if (canvas_item_visible ((*i)->_canvas_display)) {
++nth;
_effective_height += (*i)->show_at (y + _effective_height, nth, parent);
- cerr << "\tshowed " << (*i)->name() << " as " << nth << endl;
- } else {
- cerr << "\t" << (*i)->name() << " has an invisible canvas display\n";
- }
+ }
}
return _effective_height;
if (_marked_for_display) {
if (_y_position + _effective_height < _editor.get_trackview_group_vertical_offset () || _y_position > _editor.get_trackview_group_vertical_offset () + _canvas_display->get_canvas()->get_height()) {
_canvas_background->hide ();
- cerr << "Clip hides canvas display for " << name() << endl;
_canvas_display->hide ();
return;
}
- cerr << "Clip shows canvas display for " << name() << endl;
_canvas_background->show ();
_canvas_display->show ();
}
_canvas_background->hide ();
if (control_parent) {
- control_parent->remove (controls_hbox);
+ control_parent->remove (time_axis_vbox);
control_parent = 0;
}
void
TimeAxisView::step_height (bool bigger)
{
- static const uint32_t step = 20;
+ static const uint32_t step = 25;
if (bigger) {
- set_height (height + step);
+ if (height == preset_height(HeightSmall)) {
+ set_height (preset_height(HeightSmaller));
+ }
+ else if (height == preset_height(HeightSmaller)) {
+ set_height (preset_height(HeightNormal));
+ }
+ else {
+ set_height (height + step);
+ }
+
} else {
- if (height > step) {
- set_height (std::max (height - step, hSmall));
- } else if (height != hSmall) {
- set_height (hSmall);
+ if ( height == preset_height(HeightSmall)){
+ return;
+ }
+
+ if (height <= preset_height (HeightSmaller) && height > preset_height (HeightSmall)) {
+ set_height (preset_height(HeightSmall));
+ }
+ else if ( height <= preset_height (HeightNormal) && height > preset_height (HeightSmaller)){
+ set_height (preset_height(HeightSmaller));
}
+ else {
+ set_height (height - step);
+ }
}
}
}
void
-TimeAxisView::set_height(uint32_t h)
+TimeAxisView::set_height (Height h)
{
- controls_ebox.property_height_request () = h;
+ set_height (preset_height (h));
+}
+
+void
+TimeAxisView::set_height (uint32_t h)
+{
+ if (h < preset_height (HeightSmall)) {
+ h = preset_height (HeightSmall);
+ }
+
+ time_axis_vbox.property_height_request () = h;
height = h;
for (list<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) {
/* resize the selection rect */
show_selection (_editor.get_selection().time);
}
-
- reshow_feature_lines ();
}
bool
/* resize to show editable name display */
- if ((*i)->current_height() <= hSmaller) {
- (*i)->set_height (hSmaller);
+ if ((*i)->current_height() <= preset_height (HeightSmaller)) {
+ (*i)->set_height (HeightSmaller);
}
(*i)->name_entry.grab_focus();
display_menu->popup (1, when);
}
-gint
-TimeAxisView::size_click (GdkEventButton *ev)
-{
- conditionally_add_to_selection ();
- popup_size_menu (ev->time);
- return TRUE;
-}
-
-void
-TimeAxisView::popup_size_menu (guint32 when)
-{
- if (size_menu == 0) {
- build_size_menu ();
- }
- size_menu->popup (1, when);
-}
-
void
TimeAxisView::set_selected (bool yn)
{
if (_selected) {
controls_ebox.set_name (controls_base_selected_name);
- controls_hbox.set_name (controls_base_selected_name);
+ time_axis_vbox.set_name (controls_base_selected_name);
controls_vbox.set_name (controls_base_selected_name);
} else {
controls_ebox.set_name (controls_base_unselected_name);
- controls_hbox.set_name (controls_base_unselected_name);
+ time_axis_vbox.set_name (controls_base_unselected_name);
controls_vbox.set_name (controls_base_unselected_name);
hide_selection ();
resizer.queue_draw ();
}
-void
-TimeAxisView::build_size_menu ()
-{
- using namespace Menu_Helpers;
-
- size_menu = new Menu;
- size_menu->set_name ("ArdourContextMenu");
- MenuList& items = size_menu->items();
-
- items.push_back (MenuElem (_("Largest"), sigc::bind (sigc::mem_fun (*this, &TimeAxisView::set_heights), hLargest)));
- items.push_back (MenuElem (_("Large"), sigc::bind (sigc::mem_fun (*this, &TimeAxisView::set_heights), hLarge)));
- items.push_back (MenuElem (_("Larger"), sigc::bind (sigc::mem_fun (*this, &TimeAxisView::set_heights), hLarger)));
- items.push_back (MenuElem (_("Normal"), sigc::bind (sigc::mem_fun (*this, &TimeAxisView::set_heights), hNormal)));
- items.push_back (MenuElem (_("Smaller"), sigc::bind (sigc::mem_fun (*this, &TimeAxisView::set_heights),hSmaller)));
- items.push_back (MenuElem (_("Small"), sigc::bind (sigc::mem_fun (*this, &TimeAxisView::set_heights), hSmall)));
-}
-
void
TimeAxisView::build_display_menu ()
{
AnalysisFeatureList::const_iterator i;
list<ArdourCanvas::SimpleLine*>::iterator l;
-
- for (i = analysis_features.begin(), l = feature_lines.begin(); i != analysis_features.end() && l != feature_lines.end(); ++i, ++l) {
- (*l)->property_x1() = _editor.frame_to_pixel (*i);
- (*l)->property_x2() = _editor.frame_to_pixel (*i);
- }
}
void
rect->start_trim->property_x1() = x1;
rect->start_trim->property_y1() = 1.0;
rect->start_trim->property_x2() = x1 + trim_handle_size;
- rect->start_trim->property_y2() = 1.0 + trim_handle_size;
+ rect->start_trim->property_y2() = y2;
rect->end_trim->property_x1() = x2 - trim_handle_size;
rect->end_trim->property_y1() = 1.0;
rect->end_trim->property_x2() = x2;
- rect->end_trim->property_y2() = 1.0 + trim_handle_size;
+ rect->end_trim->property_y2() = y2;
rect->start_trim->show();
rect->end_trim->show();
rect = new SelectionRect;
rect->rect = new SimpleRect (*selection_group);
+ rect->rect->property_outline_what() = 0x0;
rect->rect->property_x1() = 0.0;
rect->rect->property_y1() = 0.0;
rect->rect->property_x2() = 0.0;
rect->rect->property_y2() = 0.0;
rect->rect->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_SelectionRect.get();
- rect->rect->property_outline_color_rgba() = ARDOUR_UI::config()->canvasvar_Selection.get();
rect->start_trim = new SimpleRect (*selection_group);
+ rect->start_trim->property_outline_what() = 0x0;
rect->start_trim->property_x1() = 0.0;
rect->start_trim->property_x2() = 0.0;
- rect->start_trim->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_Selection.get();
- rect->start_trim->property_outline_color_rgba() = ARDOUR_UI::config()->canvasvar_Selection.get();
-
+
rect->end_trim = new SimpleRect (*selection_group);
+ rect->end_trim->property_outline_what() = 0x0;
rect->end_trim->property_x1() = 0.0;
rect->end_trim->property_x2() = 0.0;
- rect->end_trim->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_Selection.get();
- rect->end_trim->property_outline_color_rgba() = ARDOUR_UI::config()->canvasvar_Selection.get();
free_selection_rects.push_front (rect);
}
}
+/** Get selectable things within a given range.
+ * @param start Start time in session frames.
+ * @param end End time in session frames.
+ * @param top Top y range, in trackview coordinates (ie 0 is the top of the track view)
+ * @param bot Bottom y range, in trackview coordinates (ie 0 is the top of the track view)
+ * @param result Filled in with selectable things.
+ */
void
-TimeAxisView::get_selectables (nframes_t /*start*/, nframes_t /*end*/, double /*top*/, double /*bot*/, list<Selectable*>& /*result*/)
+TimeAxisView::get_selectables (framepos_t /*start*/, framepos_t /*end*/, double /*top*/, double /*bot*/, list<Selectable*>& /*result*/)
{
return;
}
XMLNode&
TimeAxisView::get_state ()
{
+ /* XXX: is this method used? */
+
XMLNode* node = new XMLNode ("TAV-" + name());
char buf[32];
{
const XMLProperty *prop;
+ /* XXX: I think this might be vestigial */
if ((prop = node.property ("marked-for-display")) != 0) {
_marked_for_display = (prop->value() == "1");
}
+ if ((prop = node.property ("shown-editor")) != 0) {
+ _marked_for_display = string_is_affirmative (prop->value ());
+ }
+
if ((prop = node.property ("track-height")) != 0) {
if (prop->value() == "largest") {
- set_height (hLargest);
+ set_height (HeightLargest);
} else if (prop->value() == "large") {
- set_height (hLarge);
+ set_height (HeightLarge);
} else if (prop->value() == "larger") {
- set_height (hLarger);
+ set_height (HeightLarger);
} else if (prop->value() == "normal") {
- set_height (hNormal);
+ set_height (HeightNormal);
} else if (prop->value() == "smaller") {
- set_height (hSmaller);
+ set_height (HeightSmaller);
} else if (prop->value() == "small") {
- set_height (hSmall);
+ set_height (HeightSmall);
} else {
error << string_compose(_("unknown track height name \"%1\" in XML GUI information"), prop->value()) << endmsg;
- set_height (Normal);
+ set_height (HeightNormal);
}
} else if ((prop = node.property ("height")) != 0) {
} else {
- set_height (hNormal);
+ set_height (HeightNormal);
}
return 0;
}
void
-TimeAxisView::compute_controls_size_info ()
+TimeAxisView::compute_heights ()
{
Gtk::Window window (Gtk::WINDOW_TOPLEVEL);
Gtk::Table two_row_table (2, 8);
Gtk::Table one_row_table (1, 8);
Button* buttons[5];
const int border_width = 2;
- const int extra_height = (2 * border_width)
+ extra_height = (2 * border_width)
//+ 2 // 2 pixels for the hseparator between TimeAxisView control areas
- + 10; // resizer button (3 x 2 pixel elements + 2 x 2 pixel gaps)
+ + 6; // resizer button (3 x 2 pixel elements + 2 x 2 pixel gaps)
window.add (one_row_table);
one_row_table.show_all ();
Gtk::Requisition req(one_row_table.size_request ());
-
// height required to show 1 row of buttons
- hSmaller = req.height + extra_height;
-
- window.remove ();
- window.add (two_row_table);
-
- two_row_table.attach (*buttons[1], 5, 6, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND, 0, 0);
- two_row_table.attach (*buttons[2], 6, 7, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND, 0, 0);
- two_row_table.attach (*buttons[3], 7, 8, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND, 0, 0);
- two_row_table.attach (*buttons[4], 8, 9, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND, 0, 0);
-
- two_row_table.show_all ();
- req = two_row_table.size_request ();
-
- // height required to show all normal buttons
-
- hNormal = /*req.height*/ 48 + extra_height;
-
- // these heights are all just larger than normal. no more
- // elements are visible (yet).
-
- hLarger = hNormal + 50;
- hLarge = hNormal + 150;
- hLargest = hNormal + 250;
-
- // height required to show track name
-
- hSmall = 27;
+ smaller_height = req.height + extra_height;
}
void
return std::make_pair ( (TimeAxisView *) 0, 0);
}
-void
-TimeAxisView::show_feature_lines (const AnalysisFeatureList& pos)
-{
- analysis_features = pos;
- reshow_feature_lines ();
-}
-
-
-void
-TimeAxisView::hide_feature_lines ()
-{
- list<ArdourCanvas::SimpleLine*>::iterator l;
-
- for (l = feature_lines.begin(); l != feature_lines.end(); ++l) {
- (*l)->hide();
- }
-}
-
-void
-TimeAxisView::reshow_feature_lines ()
-{
- while (feature_lines.size()< analysis_features.size()) {
- ArdourCanvas::SimpleLine* l = new ArdourCanvas::SimpleLine (*_canvas_display);
- l->property_color_rgba() = (guint) ARDOUR_UI::config()->canvasvar_ZeroLine.get();
- feature_lines.push_back (l);
- }
-
- while (feature_lines.size() > analysis_features.size()) {
- ArdourCanvas::SimpleLine *line = feature_lines.back();
- feature_lines.pop_back ();
- delete line;
- }
-
- AnalysisFeatureList::const_iterator i;
- list<ArdourCanvas::SimpleLine*>::iterator l;
-
- for (i = analysis_features.begin(), l = feature_lines.begin(); i != analysis_features.end() && l != feature_lines.end(); ++i, ++l) {
- (*l)->property_x1() = _editor.frame_to_pixel (*i);
- (*l)->property_x2() = _editor.frame_to_pixel (*i);
- (*l)->property_y1() = 0;
- (*l)->property_y2() = current_height();
- (*l)->show ();
- }
-}
-
bool
TimeAxisView::resizer_button_press (GdkEventButton* event)
{
bool
TimeAxisView::resizer_button_release (GdkEventButton*)
{
+ _editor.stop_canvas_autoscroll ();
_resize_drag_start = -1;
return true;
}
bool
TimeAxisView::resizer_motion (GdkEventMotion* ev)
{
- if (_resize_drag_start < 0) {
- return true;
- }
-
- int32_t const delta = (int32_t) floor (ev->y_root - _resize_drag_start);
- _editor.add_to_idle_resize (this, delta);
- _resize_drag_start = ev->y_root;
+ if (_resize_drag_start >= 0) {
+ /* (ab)use the DragManager to do autoscrolling; adjust the event coordinates
+ into the world coordinate space that DragManager::motion_handler is expecting,
+ and then fake a DragManager motion event so that when maybe_autoscroll
+ asks DragManager for the current pointer position it will get the correct
+ answers.
+ */
+ int tx, ty;
+ resizer.translate_coordinates (*control_parent, ev->x, ev->y, tx, ty);
+ ev->y = ty - _editor.get_trackview_group_vertical_offset();
+ _editor.drags()->motion_handler ((GdkEvent *) ev, false);
+ _editor.maybe_autoscroll (false, true);
+
+ /* now do the actual TAV resize */
+ int32_t const delta = (int32_t) floor (ev->y_root - _resize_drag_start);
+ _editor.add_to_idle_resize (this, delta);
+ _resize_drag_start = ev->y_root;
+ }
return true;
}
win->draw_line (light, 1, 5, w - 1, 5);
win->draw_point (light, w - 1, 4);
- /* handle/line #3 */
-
- win->draw_line (dark, 0, 8, w - 2, 8);
- win->draw_point (dark, 0, 9);
- win->draw_line (light, 1, 9, w - 1, 9);
- win->draw_point (light, w - 1, 8);
+ /* use vertical resize mouse cursor */
+ win->set_cursor(Gdk::Cursor(Gdk::SB_V_DOUBLE_ARROW));
return true;
}
canvas_display()->show();
} else {
set_marked_for_display (false);
- canvas_display()->hide ();
+ hide ();
}
return true; // things changed
}
return false;
}
+
+uint32_t
+TimeAxisView::preset_height (Height h)
+{
+ switch (h) {
+ case HeightLargest:
+ return extra_height + 48 + 250;
+ case HeightLarger:
+ return extra_height + 48 + 150;
+ case HeightLarge:
+ return extra_height + 48 + 50;
+ case HeightNormal:
+ return extra_height + 48;
+ case HeightSmall:
+ return 27;
+ case HeightSmaller:
+ return smaller_height;
+ }
+
+ /* NOTREACHED */
+ return 0;
+}
+
+/** @return Child time axis views that are not hidden */
+TimeAxisView::Children
+TimeAxisView::get_child_list ()
+{
+ Children c;
+
+ for (Children::iterator i = children.begin(); i != children.end(); ++i) {
+ if (!(*i)->hidden()) {
+ c.push_back(*i);
+ }
+ }
+
+ return c;
+}
+
+