--- /dev/null
+/* Copyright 2009-2010 Yorba Foundation
+ *
+ * This software is licensed under the GNU Lesser General Public License
+ * (version 2.1 or later). See the COPYING file in this distribution.
+ */
+
+using Logging;
+
+class TrackViewConcrete : TrackView, Gtk.Fixed {
+ Model.Track track;
+ TimeLine timeline;
+ TransportDelegate transport_delegate;
+
+ const int clip_height = 64;
+ const int TrackHeight = clip_height + TimeLine.BORDER * 2;
+
+ public TrackViewConcrete(TransportDelegate transport_delegate,
+ Model.Track track, TimeLine timeline) {
+ this.track = track;
+ this.timeline = timeline;
+ this.transport_delegate = transport_delegate;
+
+ track.clip_added.connect(on_clip_added);
+ track.clip_removed.connect(on_clip_removed);
+ }
+
+ override void size_request(out Gtk.Requisition requisition) {
+ base.size_request(out requisition);
+ requisition.height = TrackHeight;
+ requisition.width += TimeLine.BORDER; // right margin
+ }
+
+ void on_clip_moved(ClipView clip) {
+ emit(this, Facility.SIGNAL_HANDLERS, Level.INFO, "on_clip_moved");
+ set_clip_pos(clip);
+ }
+
+ void on_clip_deleted(Model.Clip clip) {
+ emit(this, Facility.SIGNAL_HANDLERS, Level.INFO, "on_clip_deleted");
+ track.delete_clip(clip);
+ clear_drag();
+ }
+
+ void on_clip_added(Model.Track t, Model.Clip clip, bool select) {
+ emit(this, Facility.SIGNAL_HANDLERS, Level.INFO, "on_clip_added");
+ ClipView view = new ClipView(transport_delegate, clip, timeline.provider, clip_height);
+ view.clip_moved.connect(on_clip_moved);
+ view.clip_deleted.connect(on_clip_deleted);
+ view.move_begin.connect(on_move_begin);
+ view.trim_begin.connect(on_trim_begin);
+
+ put(view, timeline.provider.time_to_xpos(clip.start), TimeLine.BORDER);
+ view.show();
+
+ timeline.track_changed();
+ clip_view_added(view);
+ if (select) {
+ view.selection_request(view, false);
+ }
+ }
+
+ // TODO: This method should not be public. When linking/grouping is done, this method
+ // should become private. See Timeline.on_clip_view_move_begin for more information.
+ public void move_to_top(ClipView clip_view) {
+ /*
+ * We remove the ClipView from the Fixed object and add it again to make
+ * sure that when we draw it, it is displayed above every other clip while
+ * dragging.
+ */
+ remove(clip_view);
+ put(clip_view,
+ timeline.provider.time_to_xpos(clip_view.clip.start),
+ TimeLine.BORDER);
+ clip_view.show();
+ }
+
+ void on_trim_begin(ClipView clip_view) {
+ emit(this, Facility.SIGNAL_HANDLERS, Level.INFO, "on_trim_begin");
+ move_to_top(clip_view);
+ }
+
+ void on_move_begin(ClipView clip_view, bool do_copy) {
+ emit(this, Facility.SIGNAL_HANDLERS, Level.INFO, "on_move_begin");
+ move_to_top(clip_view);
+ }
+
+ void set_clip_pos(ClipView view) {
+ move(view, timeline.provider.time_to_xpos(view.clip.start), TimeLine.BORDER);
+ queue_draw();
+ }
+
+ public void resize() {
+ foreach (Gtk.Widget w in get_children()) {
+ ClipView view = w as ClipView;
+ if (view != null) {
+ view.on_clip_moved(view.clip);
+ }
+ }
+ }
+
+ void on_clip_removed(Model.Clip clip) {
+ emit(this, Facility.SIGNAL_HANDLERS, Level.INFO, "on_clip_removed");
+ foreach (Gtk.Widget w in get_children()) {
+ ClipView view = w as ClipView;
+ if (view.clip == clip) {
+ view.clip_moved.disconnect(on_clip_moved);
+ remove(view);
+ timeline.track_changed();
+ return;
+ }
+ }
+ }
+
+/*
+ void unselect_gap() {
+ if (timeline.gap_view != null) {
+ TrackView parent = timeline.gap_view.parent as TrackView;
+ parent.remove(timeline.gap_view);
+ timeline.gap_view = null;
+ }
+ }
+*/
+
+ override bool button_press_event(Gdk.EventButton e) {
+ if (e.type != Gdk.EventType.BUTTON_PRESS &&
+ e.type != Gdk.EventType.2BUTTON_PRESS &&
+ e.type != Gdk.EventType.3BUTTON_PRESS)
+ return false;
+
+ if (e.button == 1 ||
+ e.button == 3) {
+/*
+ int x = (int) e.x;
+ int64 time = timeline.provider.xpos_to_time(x);
+ Model.Gap g;
+ track.find_containing_gap(time, out g);
+ if (g.end > g.start) {
+ int64 length = g.end - g.start;
+ int width = timeline.provider.time_to_xpos(g.start + length) -
+ timeline.provider.time_to_xpos(g.start);
+
+ timeline.gap_view = new GapView(g.start, length,
+ width, clip_height);
+ timeline.gap_view.removed += on_gap_view_removed;
+ timeline.gap_view.unselected += on_gap_view_unselected;
+ put(timeline.gap_view, timeline.provider.time_to_xpos(g.start), TimeLine.BORDER);
+ timeline.gap_view.show();
+ }
+*/
+ timeline.deselect_all_clips();
+ /*
+ track.set_selected(true);
+ */
+ }
+ return false;
+ }
+
+/*
+ void on_gap_view_removed(GapView gap_view) {
+ emit(this, Facility.SIGNAL_HANDLERS, Level.INFO, "on_gap_view_removed");
+ track.delete_gap(gap_view.gap);
+ }
+
+ void on_gap_view_unselected(GapView gap_view) {
+ emit(this, Facility.SIGNAL_HANDLERS, Level.INFO, "on_gap_view_unselected");
+ unselect_gap();
+ }
+*/
+ void clear_drag() {
+ window.set_cursor(null);
+ queue_draw();
+ }
+
+ public Model.Track get_track() {
+ return track;
+ }
+
+ public int get_track_height() {
+ return TrackHeight;
+ }
+
+ public Gtk.Widget? find_child(double x, double y) {
+ foreach (Gtk.Widget w in get_children()) {
+ if (w.allocation.x <= x && x < w.allocation.x + w.allocation.width) {
+ return w;
+ }
+ }
+ return null;
+ }
+
+ public void select_all() {
+ foreach (Gtk.Widget child in get_children()) {
+ ClipView? clip_view = child as ClipView;
+ if (clip_view != null) {
+ clip_view.select();
+ }
+ }
+ }
+}