# CellTracking.py
# By MW, Jun 2013
# GPLv3+
#
# Class managing the controls of a player.
#+ It interacts with a State instance to manage the position inside a movie. It does not launch a timer by itself.
import gtk, logging
[docs]class Controls :
    def __init__(self, player) :
        self.player = player
        self.state_player = self.player.state.get_subclass('player')
        self.channels_list = None
        self.play_i = gtk.Image()
        self.pause_i = gtk.Image()
        self.play_i.set_from_stock(gtk.STOCK_MEDIA_PLAY, gtk.ICON_SIZE_SMALL_TOOLBAR)
        self.pause_i.set_from_stock(gtk.STOCK_MEDIA_PAUSE, gtk.ICON_SIZE_SMALL_TOOLBAR)
        
[docs]    def get_controls(self) :
        # Getting some info
        frame_nb = self.player.state.get_frame_nb()
        index = self.state_player.get_current_index()
        self.controls = gtk.VBox() # The main box
        
        # Line 1 : Slider
        line1 = gtk.HBox()
        adjustment = gtk.Adjustment(float(index), 0.0, frame_nb, 1.0, 1, 1)
        self.scale = gtk.HScale(adjustment)
        self.scale.set_digits(0)
        self.scale.connect("value-changed", self.slider_moved)
        self.position_l = gtk.Label(self.get_position_label(index))
        line1.pack_start(self.scale, expand=True, fill=True)
        line1.pack_start(self.position_l, expand=False, fill=False)
        self.controls.pack_start(line1)
        # Line 2 : Controls
        line2 = gtk.HBox()
        previous_frame = gtk.Button()
        previous_frame_i = gtk.Image()
        previous_frame_i.set_from_stock(gtk.STOCK_MEDIA_PREVIOUS, gtk.ICON_SIZE_SMALL_TOOLBAR)
        previous_frame.add(previous_frame_i)
        previous_frame.set_tooltip_text("Previous frame")
        previous_frame.connect("clicked", self.previous_next_clicked, -1)
        next_frame = gtk.Button()
        next_frame_i = gtk.Image()
        next_frame_i.set_from_stock(gtk.STOCK_MEDIA_NEXT, gtk.ICON_SIZE_SMALL_TOOLBAR)
        next_frame.add(next_frame_i)
        next_frame.set_tooltip_text("Next frame")
        next_frame.connect("clicked", self.previous_next_clicked, +1)
        self.play = gtk.Button()
        play_i = gtk.Image()
        self.play.add(self.play_i)
        self.play.connect("clicked", self.play_clicked)
        speed_l = gtk.Label("Speed:")
        speed_l.set_tooltip_text("Change playing speed")
        self.speed = gtk.combo_box_new_text() # This function is deprecated and should be replaced by gtk.ComboBoxText
        self.speed.append_text("0.05x")
        self.speed.append_text("0.1x")
        self.speed.append_text("0.2x")
        self.speed.append_text("0.5x")
        self.speed.append_text("1x")
        self.speed.append_text("2x")
        self.speed.append_text("5x")
        self.speed.append_text("10x")
        self.speed.append_text("20x")
        self.speed.append_text("50x")
        self.speed.connect('changed', self.speed_changed)
        self.speed.set_active(4)
        self.manual = gtk.CheckButton(label='Manual mode')
        self.manual.connect('toggled', self.auto_clicked)
        
        line2.pack_start(previous_frame, expand=False, fill=False)
        line2.pack_start(next_frame, expand=False, fill=False)
        line2.pack_start(self.play, expand=False, fill=False)
        line2.pack_start(speed_l, expand=False, fill=False)
        line2.pack_start(self.speed, expand=False, fill=False)
        line2.pack_start(self.manual, expand=False, fill=False)
        self.controls.pack_start(line2, expand=False, fill=False)
        # Line 3 : Zoom and channels
        line3 = gtk.HBox()
        zoom_l = gtk.Label("Zoom:")
        zoom_l.set_tooltip_text("Change the zoom level of the movie")
        self.zoom = gtk.combo_box_new_text()
        self.zoom.append_text("x0.1")
        self.zoom.append_text("x0.25")
        self.zoom.append_text("x0.5")
        self.zoom.append_text("x1")
        self.zoom.append_text("x2")
        self.zoom.append_text("x5")
        self.zoom.append_text("x10")
        self.zoom.append_text("x25")
        self.zoom.set_active(3)
        self.zoom.connect('changed', self.zoom_changed)
        channel_l = gtk.Label("Channel:")
        channel_l.set_tooltip_text("Select the displayed channel")
        self.channel = gtk.combo_box_new_text() # This function is deprecated and should be replaced by gtk.ComboBoxText
        self.channels_list = self.player.state.movie.Channels.get_channels_dict()
        for ch in self.channels_list.keys() :
            self.channel.append_text(ch)
        self.channel.set_active(self. channels_list.keys().index( self.state_player.current_channel))
        self.channel.connect('changed', self.channel_changed)
        logging.warning("Function get_controls to be fully implemented yet")
        
        line3.pack_start(zoom_l, expand=False, fill=False)
        line3.pack_start(self.zoom, expand=False, fill=False)
        line3.pack_start(channel_l, expand=False, fill=False)
        line3.pack_start(self.channel, expand=False, fill=False)
        #self.line3 = line3 # Big hack to fix, port the button auto-padding from CT 0.x
        self.controls.pack_start(line3, expand=False, fill=False)
        return self.controls
 
[docs]    def update_controls(self) :
        self.update_scale(self.state_player.get_current_index())
 
[docs]    def get_position_label(self, i) :
        """Function that generate the label for the frame progression
        on the form of 10/12000 for instance"""
        return "%s/%s" % (str(int(i)), str(int(self.player.state.get_frame_nb()-1)))
 
[docs]    def slider_moved(self, w) :
        """Function called when the slider is moved"""
        i = w.get_value()
        #self.update_scale(i, update_scale=False)
        self.position_l.set_label(self.get_position_label(i))# Update label
        self.state_player.set_current_frame_index(int(i)) # Update state        
 
[docs]    def update_scale(self, i, update_scale=True) :
        self.position_l.set_label(self.get_position_label(i))# Update label
        self.state_player.set_current_frame_index(int(i)) # Update state
        if update_scale :
            self.scale.set_value(i)
         
[docs]    def play_clicked(self, w) :
        """Binding for the play button"""
        stock = (self.play_i, self.pause_i) # Stock image loaded
        s=self.state_player.change_playing()
        self.play.set_image(stock[s])
 
[docs]    def previous_next_clicked(self, w, incr) :
        i = self.state_player.get_current_index()
        s = max(1, self.state_player.current_speed)
        incr_new = incr*s
        n = self.player.state.get_frame_nb() - 1
        i_new = max(0, min(n,i+incr_new))
        self.state_player.change_playing(False)
        self.play.set_image(self.play_i) # It is paused so display play button
        self.state_player.set_current_frame_index(i_new)
        self.update_scale(i_new)
     
[docs]    def auto_clicked(self, w) :
        """Function called when the 'auto mode' checkbox is clicked"""
        self.state_player.switch_manual(w.get_active())
         
[docs]    def speed_changed(self, w) :
        """Called when speed is changed"""
        speeds = self.state_player.speeds
        self.state_player.set_current_speed(speeds[w.get_active()])
 
[docs]    def zoom_changed(self, w) :
        """Called when speed is changed"""
        zooms = self.state_player.zooms
        self.state_player.set_current_zoom(zooms[w.get_active()])
 
[docs]    def channel_changed(self, w) :
        """Called when speed is changed"""
        ch =  self.channels_list.keys()[w.get_active()]
        self.state_player.set_current_channel(ch)