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

class HarmonicProgressionLabel(gtk.HBox):
    """
    This class can parse strings like I-(6,4)V(5,3)-I and can be used
    as button labels.
    """
    def __init__(self, str, align=''):
        gtk.HBox.__init__(self)
        self.show()
        self.set_text(str, align)
    def set_text(self, str, align=''):
        for o in self.get_children():
            o.destroy()
        self.m_str = str
        if align == 'center':
            self.pack_start(gtk.HBox())
        while self.m_str:
            T, A, B = self.get_next_token()
            if T == 'big' or T == 'err':
                self.bigchar(A)
            elif T == 'two':
                self.twoline(A, B)
            else:
                assert T == 'one'
                self.oneline(A)
        if align == 'center':
            self.pack_start(gtk.HBox())
        self.show_all()
    def get_next_token(self):
        m_re1 = re.compile("([^\(]+)")
        m_re2 = re.compile("\((\w*),\s*(\w*)\)")
        m_re3 = re.compile("\((\w*)\)")
        m1 = m_re1.match(self.m_str)
        m2 = m_re2.match(self.m_str)
        m3 = m_re3.match(self.m_str)
        if m1:
            self.m_str = self.m_str[len(m1.group()):]
            return "big", m1.groups()[0], None
        if m2:
            self.m_str = self.m_str[len(m2.group()):]
            return "two", m2.groups()[0], m2.groups()[1]
        if m3:
            self.m_str = self.m_str[len(m3.group()):]
            return "one", m3.groups()[0], None
        return "err"
    def twoline(self, A, B):
        vbox = gtk.VBox()
        t1 = gtk.Label(A)
        t1.set_name("ProgressionLabelNumber")
        t1.show();vbox.pack_start(t1);
        t1.set_alignment(0, 0);
        t2 = gtk.Label(B)
        t2.set_name("ProgressionLabelNumber")
        t2.show();vbox.pack_start(t2);
        t2.set_alignment(0, 0);
        self.pack_start(vbox, gtk.FALSE)
    def oneline(self, A):
        vbox = gtk.VBox()
        t = gtk.Label(A)
        t.set_name("ProgressionLabelNumber")
        t.show();vbox.pack_start(t);
        t.set_alignment(0, 0);
        self.pack_start(vbox, gtk.FALSE)
    def bigchar(self, A):
        t1 = gtk.Label(A)
        t1.set_name("ProgressionNameLabel")
        t1.show()
        self.pack_start(t1, gtk.FALSE)


class QuestionNameButtonTable(gtk.Table):
    """
    In lack of a better name for this class...
    This gtk.Table extension creates a table width buttons that is added
    in an intelligent way, and the labels of the buttons can be normal
    text or chord progression names. See: HarmonicProgressionLabel
    """
    def __init__(self):
        gtk.Table.__init__(self)
    def initialize(self, num, dir):
        self.m_num = num
        self.m_dir = dir
        self.m_x = 0
        self.m_y = 0
        for X in self.get_children():
            X.destroy()
    def add(self, key, label_code, style, callback):
        b = gtk.Button()
        b.set_data('pcode', key)
        if style == 'progression':
            b.add(HarmonicProgressionLabel(label_code, 'center'))
        else:
            b.add(gtk.Label(label_code))
        b.show_all()
        self.attach(b, self.m_x, self.m_x+1, self.m_y, self.m_y+1)
        b.connect('clicked', callback)
        if self.m_dir == 'vertic':
            self.m_y = self.m_y + 1
            if self.m_y == self.m_num:
                self.m_y = 0
                self.m_x = self.m_x + 1
        else:
            self.m_x = self.m_x + 1
            if self.m_x == self.m_num:
                self.m_x = 0
                self.m_y = self.m_y + 1
    def grab_focus_first_button(self):
        self.get_children()[-1].grab_focus()
