# GNU Solfege - eartraining for GNOME
# Copyright (C) 2000, 2001, 2002  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

import gtk, gnome, gu
import const
from i18n import _
import cfg

class IntervallCheckBox(gtk.GtkHBox, cfg.ConfigUtils):
    def __init__(self, exname, varname):
        gtk.GtkHBox.__init__(self)
        cfg.ConfigUtils.__init__(self, exname)
        self.m_varname = varname
        intervalls = self.get_list(self.m_varname)
        if not intervalls:
            intervalls = range(1, 17)
            self.set_list(varname, intervalls)
        self.checkbox_dict = {}
        for x in range(1, 17):
            self.checkbox_dict[x] = c = gtk.GtkToggleButton(const.short_intervall_name[x])
            c.set_data('intervall', x)
            if x in intervalls:
                c.set_active(gtk.TRUE)
            c.connect('clicked', self.on_toggle)
            c.show()
            self.pack_start(c)
        self.add_watch(self.m_varname, self._watch_cb)
    def _watch_cb(self, name):
        V = self.get_list(self.m_varname)
        for k in range(1, 17):
            self.checkbox_dict[k].set_active(k in V)
    def on_toggle(self, _o):
        v = []
        keys = self.checkbox_dict.keys()
        for k in keys:
            if self.checkbox_dict[k].active:
                v.append(k)
        self.set_list(self.m_varname, v)


class MultipleIntervallConfigWidget(gtk.GtkVBox, cfg.ConfigUtils):
    """
    This class gives  you some spin buttons and two rows of buttons
    where you select what intervalls to use for exercises where you
    select one or more intervalls.
    """
    def __init__(self, exname):
        gtk.GtkVBox.__init__(self)
        cfg.ConfigUtils.__init__(self, exname)
        self.MAX_INT = self.get_int('maximum_number_of_intervalls')
        if self.MAX_INT == 0:
            self.MAX_INT = 10
        self._watched_intervall_id = None
        self._watched_intervall = None
        self.m_ignore_iclick = 0
        box = gu.bHBox(self, expand=gtk.FALSE)
        box.set_spacing(gnome.uiconsts.PAD_SMALL)
        box.pack_start(gtk.GtkLabel(_("Number of intervalls:")), gtk.FALSE)
        self.g_num_int_spin = gu.nSpinButton(self.m_exname,
                       'number_of_intervalls',
                       gtk.GtkAdjustment(1, 1, self.MAX_INT, 1, 10))
        self.add_watch('number_of_intervalls', self.on_num_int_spin)
        box.pack_start(self.g_num_int_spin, gtk.FALSE)
        self.g_all_int_button = gu.bButton(box,
                  _("Configure all intervalls in this exercise like this"),
                  self.configure_all_like_active_intervall, expand=gtk.FALSE)
        self.add_watch('number_of_intervalls', lambda n, self=self: \
               self.g_all_int_button.set_sensitive(self.get_int(n)!=1))

        box = gu.bHBox(self, expand=gtk.FALSE)
        box.set_spacing(gnome.uiconsts.PAD_SMALL)
        box.pack_start(gtk.GtkLabel(
                _("Togglebuttons is for intervall number:")), gtk.FALSE)
        self.m_int_sel_adjustment \
             = gtk.GtkAdjustment(1, 1, self.get_int('number_of_intervalls'), 1)
        self.g_int_sel_spin = gu.nSpinButton(self.m_exname,
                  'cur_edit_intervall', self.m_int_sel_adjustment, digits=0)
        self.g_int_sel_spin.connect('changed', self.on_int_sel_spin)
        box.pack_start(self.g_int_sel_spin, gtk.FALSE)
        table = gtk.GtkTable()
        self.pack_start(table, gtk.FALSE)

        label = gtk.GtkLabel(_("Up:"))
        label.set_alignment(1.0, 0.5)
        table.attach(label, 0, 1, 0, 1, xpadding=gnome.uiconsts.PAD_SMALL)
        self.g_intervall_chk = {}
        V = self.get_list("ask_for_intervalls_%i"
                  % (self.g_int_sel_spin.get_value_as_int()-1))
        for x in range(1, 17):
            self.g_intervall_chk[x] = c = gtk.GtkToggleButton(const.short_intervall_name[x])
            c.set_data('intervall', x)
            if x in V:
                c.set_active(gtk.TRUE)
            c.show()
            c.connect('clicked', self.on_intervall_chk_clicked)
            table.attach(c, x, x+1, 0, 1)

        box = gu.bHBox(self, expand=gtk.FALSE)
        label = gtk.GtkLabel(_("Down:"))
        label.set_alignment(1.0, 0.5)
        table.attach(label, 0, 1, 1, 2, xpadding=gnome.uiconsts.PAD_SMALL)
        v = range(-16, 0)
        v.reverse()
        for x in v:
            self.g_intervall_chk[x] = c = gtk.GtkToggleButton(const.short_intervall_name[-x])
            c.set_data('intervall', x)
            if x in V:
                c.set_active(gtk.TRUE)
            c.show()
            c.connect('clicked', self.on_intervall_chk_clicked)
            table.attach(c, -x, -x+1, 1, 2)
        table.show_all()
        if self.g_num_int_spin.get_value_as_int() == 1:
            self.g_all_int_button.set_sensitive(gtk.FALSE)
        gu.bButton(self, _("Reset to default values"), self.reset_to_default,
                  gtk.FALSE, gtk.FALSE)
        self._watch_intervall(self.get_int('cur_edit_intervall')-1)
    def reset_to_default(self, _o):
        self.set_int('cur_edit_intervall', 1)
        self.set_int('number_of_intervalls', 1)
        self.set_list('ask_for_intervalls_0', range(-16, 0)+range(1, 17))
    def configure_all_like_active_intervall(self, _o):
        v = self.get_list('ask_for_intervalls_%i' \
                               % (self.g_int_sel_spin.get_value_as_int()-1))
        for i in range(self.get_int('number_of_intervalls')):
            self.set_string('ask_for_intervalls_%i' % i, str(v))
    def on_intervall_chk_clicked(self, _o):
        if self.m_ignore_iclick:
            return
        i = self.g_int_sel_spin.get_value_as_int() - 1
        v = self.get_list('ask_for_intervalls_%i' % i)
        if _o.active:
            if not _o.get_data('intervall') in v:
                v.append(_o.get_data('intervall'))
        else:
            if _o.get_data('intervall') in v:
                del v[v.index(_o.get_data('intervall'))]
        self.set_list('ask_for_intervalls_%i' % i, v)
    def on_num_int_spin(self, _o):
        a = self.g_int_sel_spin.get_adjustment()
        #a.upper = self.get_int('number_of_intervalls')
        a.set_all(self.get_int('cur_edit_intervall'), 1,
                  self.get_int('number_of_intervalls'), 1, 10, 10)
        self.g_int_sel_spin.set_adjustment(a)
        self.g_int_sel_spin.update()
    def on_int_sel_spin(self, _o):
        self._watch_intervall(self.get_int('cur_edit_intervall')-1)
        self.update_togglebuttons(self.get_int('cur_edit_intervall')-1)
    def update_togglebuttons(self, i):
        self.m_ignore_iclick = 1
        v = self.get_list('ask_for_intervalls_%i' % i)
        for i in range(-16, 0)+range(1, 17):
            self.g_intervall_chk[i].set_active(i in v)
        self.m_ignore_iclick = 0
    def _watch_intervall(self, i):
        """
        Add a watch for the correct ask_for_intervalls_%i variable.
        Remove old watches. Do nothing if we are already watching the
        correct data.
        """
        if self._watched_intervall == i:
            return
        if self._watched_intervall != None:
            self.remove_watch('ask_for_intervalls_%i' % self._watched_intervall,
                          self._watched_intervall_id)
        self._watched_intervall = i
        self._watched_intervall_id = self.add_watch('ask_for_intervalls_%i' % i,
                                                  self._intervall_watch_cb)
    def _intervall_watch_cb(self, name):
        self.update_togglebuttons(self._watched_intervall)
