Initial commit
[fillmore] / src / fillmore / header_area.vala
diff --git a/src/fillmore/header_area.vala b/src/fillmore/header_area.vala
new file mode 100644 (file)
index 0000000..17bf8fd
--- /dev/null
@@ -0,0 +1,268 @@
+/* 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 TrackHeader : Gtk.EventBox {
+    protected weak Model.Track track;
+    protected weak HeaderArea header_area;
+    protected Gtk.Label track_label;
+    
+    public const int width = 100;
+    
+    public TrackHeader(Model.Track track, HeaderArea area, int height) {
+        this.track = track;
+        this.header_area = area;
+        
+        track.track_renamed.connect(on_track_renamed);
+        track.track_selection_changed.connect(on_track_selection_changed);
+        set_size_request(width, height);
+        modify_bg(Gtk.StateType.NORMAL, header_area.background_color);
+        modify_bg(Gtk.StateType.SELECTED, parse_color("#68a"));
+        
+        track_label = new Gtk.Label(track.display_name);
+        track_label.modify_fg(Gtk.StateType.NORMAL, parse_color("#fff"));
+    }
+    
+    void on_track_renamed() {
+        emit(this, Facility.SIGNAL_HANDLERS, Level.INFO, "on_track_renamed");
+        track_label.set_text(track.display_name);
+    }
+    
+    void on_track_selection_changed(Model.Track track) {
+        emit(this, Facility.SIGNAL_HANDLERS, Level.INFO, "on_track_selection_changed");
+        set_state(track.get_is_selected() ? Gtk.StateType.SELECTED : Gtk.StateType.NORMAL);
+    }
+    
+    public override bool button_press_event(Gdk.EventButton event) {
+        header_area.select(track);
+        return true;
+    }
+    
+    public Model.Track get_track() {
+        return track;
+    }
+}
+
+public class SliderBase : Gtk.HScrollbar {
+    Gdk.Pixbuf slider_image;
+    construct {
+        can_focus = true;
+        try {
+            slider_image = new Gdk.Pixbuf.from_file(
+                AppDirs.get_resources_dir().get_child("dot.png").get_path());
+        } catch (GLib.Error e) {
+            warning("Could not load resource for slider: %s", e.message);
+        }
+    }
+    
+    public override bool expose_event (Gdk.EventExpose event) {
+        Gdk.GC gc = style.fg_gc[(int) Gtk.StateType.NORMAL];
+        int radius = (slider_end - slider_start) / 2;
+        int center = allocation.x + slider_start + radius;
+        int height = allocation.y + allocation.height / 2;
+
+        event.window.draw_rectangle(gc, false,
+            allocation.x + radius, height - 2, allocation.width - 2 * radius, 1);
+
+        event.window.draw_pixbuf(gc, slider_image, 0, 0, center - radius, allocation.y + 2, 
+            slider_image.get_width(), slider_image.get_height(), Gdk.RgbDither.NORMAL, 0, 0);
+        return true;
+    }
+}
+
+class PanSlider : SliderBase {
+    construct {
+    }
+}
+
+public class VolumeSlider : SliderBase {
+    construct {
+    }
+}
+
+class AudioTrackHeader : TrackHeader {
+    public double panorama;
+    public double volume;
+    
+    public AudioTrackHeader(Model.AudioTrack track, HeaderArea header, int height) {
+        base(track, header, height);
+        
+        track_label.modify_font(Pango.FontDescription.from_string("Sans 10"));
+        track_label.set_padding(4, 2);
+        track_label.set_alignment(0,0);
+        
+        track.parameter_changed.connect(on_parameter_changed);
+        
+        volume = track.get_volume();
+        panorama = track.get_pan();
+        
+        Gtk.VBox vbox = new Gtk.VBox(false, 0);
+        vbox.pack_start(track_label, true, true, 0);
+        Hildon.Button volpan_button = new Hildon.Button(Hildon.SizeType.AUTO_HEIGHT | Hildon.SizeType.AUTO_WIDTH, Hildon.ButtonArrangement.HORIZONTAL);
+        //volpan_button.set_text("Vol", "");
+        volpan_button.set_image(new Gtk.Image.from_icon_name("statusarea_volumelevel4", Gtk.IconSize.BUTTON));
+        volpan_button.set_image_position(Gtk.PositionType.LEFT);
+        volpan_button.clicked.connect(do_volpan_popup);
+        vbox.add(volpan_button);
+        
+        //View.AudioMeter meter = new View.AudioMeter(track);
+        //vbox.add(meter);        
+        //vbox.add(volume_box);
+        //vbox.add(pan_box);
+        add(vbox);
+    }
+    
+    void do_volpan_popup() {
+      IdWorks.VolumeAndPanPopUp dlg = new IdWorks.VolumeAndPanPopUp(this, "Volume / Pan: " + track.display_name);
+      //dlg.set_transient_for(this.get_transient_for());
+      dlg.set_volume(this.volume);
+      dlg.set_panorama(this.panorama);
+      dlg.volume_updated.connect(on_volume_updated);
+      dlg.panorama_updated.connect(on_panorama_updated);
+      dlg.run();
+      dlg.destroy();
+      dlg = null;
+    }
+    
+    void on_panorama_updated(double val) {
+        emit(this, Facility.SIGNAL_HANDLERS, Level.INFO, "on_pan_value_changed");
+        Model.AudioTrack audio_track = track as Model.AudioTrack;
+        if (audio_track != null) {
+            audio_track.set_pan(val);
+        }
+    }
+
+    /*void on_pan_value_changed() {
+        emit(this, Facility.SIGNAL_HANDLERS, Level.INFO, "on_pan_value_changed");
+        Model.AudioTrack audio_track = track as Model.AudioTrack;
+        if (audio_track != null) {
+            Gtk.Adjustment adjustment = pan.get_adjustment();
+            audio_track.set_pan(adjustment.get_value());
+        }
+    }*/
+    
+    void on_volume_updated(double val) {
+        emit(this, Facility.SIGNAL_HANDLERS, Level.INFO, "on_volume_value_changed");
+        Model.AudioTrack audio_track = track as Model.AudioTrack;
+        if (audio_track != null) {
+            audio_track.set_volume(val);
+        }
+    }
+    
+    /*void on_volume_value_changed() {
+        emit(this, Facility.SIGNAL_HANDLERS, Level.INFO, "on_volume_value_changed");
+        Model.AudioTrack audio_track = track as Model.AudioTrack;
+        if (audio_track != null) {
+            Gtk.Adjustment adjustment = volume.get_adjustment();
+            audio_track.set_volume(adjustment.get_value());
+        }
+    }*/
+    void on_parameter_changed(Model.Parameter parameter, double new_value) {
+        emit(this, Facility.SIGNAL_HANDLERS, Level.INFO, "on_parameter_changed");
+        Model.AudioTrack audio_track = track as Model.AudioTrack;
+        assert(audio_track != null);
+        switch(parameter) {
+            case Model.Parameter.VOLUME:
+                volume = new_value;
+            break;
+            case Model.Parameter.PAN:
+                panorama = new_value;
+            break;
+        }
+    }
+   /* void on_parameter_changed(Model.Parameter parameter, double new_value) {
+        emit(this, Facility.SIGNAL_HANDLERS, Level.INFO, "on_parameter_changed");
+        Model.AudioTrack audio_track = track as Model.AudioTrack;
+        assert(audio_track != null);
+        switch(parameter) {
+            case Model.Parameter.VOLUME:
+                volume.set_value(new_value);
+            break;
+            case Model.Parameter.PAN:
+                pan.set_value(new_value);
+            break;
+        }
+    }*/
+}
+
+class HeaderArea : Gtk.EventBox {
+    weak Model.Project project;
+    
+    Gtk.VBox vbox;
+    public Gdk.Color background_color = parse_color("#666");
+    
+    public HeaderArea(Recorder recorder, Model.TimeSystem provider, int height) {
+        this.project = recorder.project;
+        recorder.timeline.trackview_removed.connect(on_trackview_removed);
+        recorder.timeline.trackview_added.connect(on_trackview_added);
+        
+        set_size_request(TrackHeader.width, 0);
+        modify_bg(Gtk.StateType.NORMAL, background_color);
+        
+        vbox = new Gtk.VBox(false, 0);
+        add(vbox);
+        Gtk.DrawingArea status_bar = new View.StatusBar(project, provider, height);
+        
+        vbox.pack_start(status_bar, false, false, 0);
+
+        vbox.pack_start(new TrackSeparator(), false, false, 0);
+        
+        foreach (TrackView track in recorder.timeline.tracks) {
+            on_trackview_added(track);
+        }
+    }
+    
+    public void on_trackview_added(TrackView trackview) {
+        emit(this, Facility.SIGNAL_HANDLERS, Level.INFO, "on_trackview_added");
+        Model.AudioTrack audio_track = trackview.get_track() as Model.AudioTrack;
+        assert(audio_track != null);
+        //we are currently only supporting audio tracks.  We'll probably have
+        //a separate method for adding video track, midi track, aux input, etc
+
+        TrackHeader header = new AudioTrackHeader(audio_track, this, trackview.get_track_height());
+        vbox.pack_start(header, false, false, 0);
+        vbox.pack_start(new TrackSeparator(), false, false, 0);
+        vbox.show_all();
+        select(audio_track);
+    }
+    
+    public void on_trackview_removed(TrackView trackview) {
+        emit(this, Facility.SIGNAL_HANDLERS, Level.INFO, "on_trackview_removed");
+        Model.Track track = trackview.get_track();
+        TrackHeader? my_track_header = null;
+        Gtk.HSeparator? my_separator = null;
+        foreach(Gtk.Widget widget in vbox.get_children()) {
+            if (my_track_header == null) {
+                TrackHeader? track_header = widget as TrackHeader;
+                if (track_header != null && track_header.get_track() == track) {
+                    my_track_header = track_header;
+                }
+            } else {
+                my_separator = widget as Gtk.HSeparator;
+                break;
+            }
+        }
+        
+        if (my_track_header != null) {
+            vbox.remove(my_track_header);
+        }
+        
+        if (my_separator != null) {
+            vbox.remove(my_separator);
+        }
+
+        if (project.tracks.size != 0) {
+            select(project.tracks[0]);
+        }
+    }
+    
+    public void select(Model.Track track) {
+        foreach (Model.Track t in project.tracks)
+            t.set_selected(t == track);
+    }
+}
+