# GNU Solfege - ear training for GNOME
# Copyright (C) 2000, 2001, 2002, 2003, 2004  Tom Cato Amundsen
#
# 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

if __name__ == '__main__':
    import sys
    import pygtk
    pygtk.require("2.0")
    import sys
    sys.path.append(".")
    sys.path.append("src")
    import i18n
    i18n.setup(".")

import gtk, gobject
import mpd, gu, cfg
import gobject

DELAY1 = 500
DELAY2 = 50

class NotenameSpinButton(gtk.HBox):
    def __init__(self, default_value):
        gtk.HBox.__init__(self)
        self.m_value = mpd.notename_to_int(default_value)
        self.g_label = gtk.Label(mpd.int_to_user_notename(self.m_value))
        self.g_label.set_use_markup(1)
        frame = gtk.Frame()
        e = gtk.EventBox()
        frame.add(e)
        self.pack_start(frame, False)
        self.g_label.set_size_request(60, -1)#FIXME hardcoded value
        frame.set_shadow_type(gtk.SHADOW_IN)
        e.add(self.g_label)
        vbox = gtk.VBox()
        self.pack_start(vbox, False)
        # up
        self.g_up = gtk.Arrow(gtk.ARROW_UP, gtk.SHADOW_OUT)
        eb1 = gtk.EventBox()
        eb1.connect('button-press-event', self.on_up_press)
        eb1.connect('button-release-event', self.on_up_release)
        frame = gtk.Frame()
        frame.set_shadow_type(gtk.SHADOW_OUT)
        frame.add(self.g_up)
        eb1.add(frame)
        vbox.pack_start(eb1)
        # down
        self.g_down = gtk.Arrow(gtk.ARROW_DOWN, gtk.SHADOW_ETCHED_IN)
        eb2 = gtk.EventBox()
        eb2.connect('button-press-event', self.on_down_press)
        eb2.connect('button-release-event', self.on_down_release)
        frame = gtk.Frame()
        frame.set_shadow_type(gtk.SHADOW_OUT)
        frame.add(self.g_down)
        eb2.add(frame)
        vbox.pack_start(eb2)
        self.m_timeout = None
    def on_up_press(self, eb, ev):
        if self.m_timeout:
            gobject.source_remove(self.m_timeout)
            self.m_timeout = None
        if ev.type == gtk.gdk.BUTTON_PRESS:
            if self.m_value < 127:
                self.up()
            if self.m_value < 127:
                self.m_timeout = gobject.timeout_add(DELAY1, self.on_up_timeout)
    def on_up_release(self, eb, ev):
        if self.m_timeout:
            gobject.source_remove(self.m_timeout)
            self.m_timeout = None
    def on_up_timeout(self, *v):
        if self.m_value < 127:
            self.up()
            self.m_timeout = gobject.timeout_add(DELAY2, self.on_up_timeout)
    def up(self):
        self.m_value += 1
        self.g_label.set_text(mpd.int_to_user_notename(self.m_value))
        self.g_label.set_use_markup(1)
        self.emit('value-changed', self.m_value)
    def on_down_press(self, eb, ev):
        if self.m_timeout:
            gobject.source_remove(self.m_timeout)
            self.m_timeout = None
        if ev.type == gtk.gdk.BUTTON_PRESS:
            if self.m_value > 0:
                self.down()
            if self.m_value > 0:
                self.m_timeout = gobject.timeout_add(DELAY1, self.on_down_timeout)
    def on_down_release(self, eb, ev):
        if self.m_timeout:
            gobject.source_remove(self.m_timeout)
            self.m_timeout = None
    def on_down_timeout(self, *v):
        if self.m_value > 0:
            self.down()
            self.m_timeout = gobject.timeout_add(DELAY2, self.on_down_timeout)
    def down(self):
        self.m_value -= 1
        self.g_label.set_text(mpd.int_to_user_notename(self.m_value))
        self.g_label.set_use_markup(1)
        self.emit('value-changed', self.m_value)
    def get_value(self):
        return self.m_value
    def set_value(self, val):
        self.m_value = val
        self.g_label.set_text(mpd.int_to_user_notename(val))
        self.g_label.set_use_markup(1)

gobject.signal_new('value-changed', NotenameSpinButton,
                   gobject.SIGNAL_RUN_FIRST,
                   gobject.TYPE_NONE,
                   (gobject.TYPE_PYOBJECT,))


class NotenameRangeController(object):
    def __init__(self, spin_low, spin_high, lowest_value, highest_value):
        self.g_spin_low = spin_low
        self.g_spin_low.connect('value-changed', self.on_low_changed)
        self.g_spin_high = spin_high
        self.g_spin_high.connect('value-changed', self.on_high_changed)
        self.m_lowest_value = mpd.notename_to_int(lowest_value)
        self.m_highest_value = mpd.notename_to_int(highest_value)
    def on_low_changed(self, widget, *v):
        if widget.get_value() > self.g_spin_high.get_value():
            self.g_spin_low.set_value(self.g_spin_high.get_value())
        elif widget.get_value() < self.m_lowest_value:
            self.g_spin_low.set_value(self.m_lowest_value)
    def on_high_changed(self, widget, *v):
        if widget.get_value() < self.g_spin_low.get_value():
            self.g_spin_high.set_value(self.g_spin_low.get_value())
        elif widget.get_value() > self.m_highest_value:
            self.g_spin_high.set_value(self.m_highest_value)

class nNotenameRangeController(NotenameRangeController, cfg.ConfigUtils):
    def __init__(self, spin_low, spin_high, lowest_value, highest_value,
                 exname, name_low, name_high):
        NotenameRangeController.__init__(self, spin_low, spin_high,
                lowest_value, highest_value)
        cfg.ConfigUtils.__init__(self, exname)
        self.m_name_low = name_low
        self.m_name_high = name_high
        low = mpd.notename_to_int(self.get_string(self.m_name_low))
        high = mpd.notename_to_int(self.get_string(self.m_name_high))
        if low > high:
            low = high
        self.g_spin_low.set_value(low)
        self.g_spin_high.set_value(high)
    def on_low_changed(self, w, v):
        NotenameRangeController.on_low_changed(self, w, v)
        self.set_string(self.m_name_low, mpd.int_to_notename(self.g_spin_low.get_value()))
    def on_high_changed(self, w, v):
        NotenameRangeController.on_high_changed(self, w, v)
        self.set_string(self.m_name_high, mpd.int_to_notename(self.g_spin_high.get_value()))
    def set_range(self, lowest_value, highest_value):
        """
        Set the lowest and highest tone allowed.
        make a separate function for NotenameRangeController if we need it.
        """
        assert mpd.compare_notenames(lowest_value, highest_value) <= 0
        self.m_lowest_value = mpd.notename_to_int(lowest_value)
        self.m_highest_value = mpd.notename_to_int(highest_value)
        if self.m_lowest_value > self.g_spin_low.get_value():
            self.set_string(self.m_name_low, lowest_value)
            self.g_spin_low.set_value(self.m_lowest_value)
        if self.m_highest_value < self.g_spin_high.get_value():
            self.set_string(self.m_name_high, highest_value)
            self.g_spin_high.set_value(self.m_highest_value)

def _test():
    w = gtk.Window(gtk.WINDOW_TOPLEVEL)
    vbox = gtk.VBox()
    w.add(vbox)
    #####
    ns  = NotenameSpinButton("cis''")
    ns.show()
    vbox.pack_start(ns, False)
    #####
    adj = gtk.Adjustment(mpd.notename_to_int('c'), 1.0, 127.0, 1.0, 12.0, 0.0)
    n = NotenameSpinButton("d'")
    vbox.pack_start(n)

    hbox = gtk.HBox()
    vbox.pack_start(hbox)
    s1 = NotenameSpinButton("c")
    s2 = NotenameSpinButton("c'")
    hbox.pack_start(s1)
    hbox.pack_start(s2)
    con = NotenameRangeController(s1, s2, "c,", "c''")

    l = gtk.Entry()
    l.set_text("test<sup>3</sup>")
    vbox.pack_start(l)
    w.show_all()
    w.connect('delete_event', gtk.main_quit)
    gtk.main()
if __name__ == '__main__':
    sys.path.append(".")
    _test()
