from Tkinter import *
from tkMessageBox import askokcancel
from TkExtensions.Slider import VertSlider
import ButtonImages
import Sound


class SliderSet:

  def __init__(self, title, nbSliders):
    ## On retient le nombre de sliders
    self.nbSliders = nbSliders
    if self.nbSliders == 0: return
    ## Creation de la fenetre
    self.window = Toplevel()
    self.window.title(title)
    ## Frame pour la caracteristique editee
    frm = Frame(self.window, bg=Sound.Sound.bg)
    frm.pack(side=TOP, fill=X)
    ## Menu pour l'ensemble edite
    lbl = Label(frm, text='Edit: ', font=Sound.Sound.boldFont, bg=Sound.Sound.bg, fg=Sound.Sound.fg)
    lbl.pack(side=LEFT)
    self.setVar = StringVar()
    mnubtn = Menubutton(frm, textvariable=self.setVar, bg=Sound.Sound.bg, fg=Sound.Sound.fg, font=Sound.Sound.stdFont, relief=RAISED)
    mnubtn.pack(side=LEFT)
    self.setMenu = Menu(mnubtn, fg=Sound.Sound.fg, bg=Sound.Sound.bg, tearoff=0)
    mnubtn['menu'] = self.setMenu
    ## Entree pour la valeur max
    lbl = Label(frm, text='   Max. value: +/-', font=Sound.Sound.boldFont, bg=Sound.Sound.bg, fg=Sound.Sound.fg)
    lbl.pack(side=LEFT)
    self.maxValVar = IntVar()
    ent = Entry(frm, textvariable=self.maxValVar, bg=Sound.Sound.bg, fg=Sound.Sound.fg, \
                font=Sound.Sound.stdFont, insertbackground=Sound.Sound.fg, selectbackground=Sound.Sound.fg)
    ent.pack(side=LEFT)
    ## Canvas pour les sliders
    cnv = Canvas(self.window, bg=Sound.Sound.bg)
    cnv.pack(side=TOP, fill=BOTH)
    ## Frame pour les sliders
    sldFrm = Frame(cnv, bg=Sound.Sound.bg)
    ## Creation de la fenetre sur le frame
    cnv.create_window(0, 0, window=sldFrm, anchor=NW)
    ## Les sliders
    self.sliderVars = []
    for i in range(self.nbSliders):
      ## Creation de la variable
      var = IntVar()
      self.sliderVars.append(var)
      ## Le slider
      sld = VertSlider(sldFrm, -100, 100, bg=Sound.Sound.bg, fg=Sound.Sound.fg, troughcolor=Sound.Sound.fg, width=4, \
                       font=Sound.Sound.stdFont, activebackground=Sound.Sound.fg, variable=var)
      sld.pack(side=LEFT)
    ## Creation et configuration de l'ascenceur
    cnv['scrollregion'] = (0, 0, self.nbSliders * sld.winfo_reqwidth(), 0)
    scrBar = Scrollbar(self.window, orient=HORIZONTAL)
    scrBar.pack(side=TOP, fill=X)
    scrBar['command'] = cnv.xview
    cnv['xscrollcommand'] = scrBar.set
    ## Dimensionnement du canvas
    cnv['width'] = 20 * sld.winfo_reqwidth()
    cnv['height'] = sld.winfo_reqheight()
    ## Frame pour les boutons
    btnFrm = Frame(self.window, bg=Sound.Sound.bg)
    btnFrm.pack(side=TOP, fill=X)
    ## Bouton save
    self.saveBtnImg = BitmapImage(data=ButtonImages.saveData, foreground=Sound.Sound.btnClr)
    saveBtn = Button(btnFrm, image=self.saveBtnImg, bg=Sound.Sound.bg, command=self.saveSet, bd=0, highlightthickness=0)
    saveBtn.pack(side=LEFT)
    self.closeBtnImg = BitmapImage(data=ButtonImages.closeData, foreground=Sound.Sound.btnClr)
    closeBtn = Button(btnFrm, image=self.closeBtnImg, bg=Sound.Sound.bg, command=self.close, bd=0, highlightthickness=0)
    closeBtn.pack(side=RIGHT)
    ## Initialisation de l'ensemble des valeurs editables
    self.editableSets = {}
    self.maxValues = {}
    self.values = {}
    self.currentSet = None
    
    
  ## METHODE ADD.EDITABLE.SET:
  ## -------------------------
  # Ajoute un ensemble de caracteristiques editables
  
  def addEditableSet(self, setName, setVars):
    ## Si pas le bon nombre, erreur
    if len(setVars) <> self.nbSliders:
      raise ValueError, "Wrong number of variables in set (%s)" % len(setVars)
    ## Ajout du nom au menu
    self.setMenu.add_radiobutton(label=setName, font=Sound.Sound.stdFont, variable=self.setVar, command=self.changeSet)
    ## On retient si c'est le premier
    isFirst = (self.editableSets == {})
    ## Ajout aux valeurs
    self.editableSets[setName] = setVars
    ## Calcul du max
    max = 0
    for v in setVars:
      val = v.get()
      if   val > max: max =   val
      if - val > max: max = - val
    ## Conversion en entier
    if max - int(max) <> 0:
      max = int(max) + 1
    else:
      max = int(max)
    self.maxValues[setName] = max
    ## Conversion des valeurs en pourcentage
    self.values[setName] = [ 0 ] * self.nbSliders
    for i in range(self.nbSliders):
      if max == 0:
        self.values[setName][i] = 0
      else:
        self.values[setName][i] = int((self.editableSets[setName][i].get() * 100.0) / max)
    ## Si premier ensemble, on le choisit
    if isFirst: self.setSet(setName)


  ## METHODE SET.SET:
  ## ----------------
  
  def setSet(self, setName):
    ## Choix dans le menu
    self.setVar.set(setName)
    ## Valeur max
    self.maxValVar.set(self.maxValues[setName])
    ## Sliders
    for i in range(self.nbSliders):
      self.sliderVars[i].set(self.values[setName][i])
    ## Ensemble courant
    self.currentSet = setName
      
  
  ## METHODE CHANGE.SET:
  ## -------------------
  # Changement d'ensemble
  
  def changeSet(self):
    changed = 0
    ## Si max different, ca a change
    if self.maxValVar.get() <> self.maxValues[self.currentSet]:
      changed = 1
    ## Si besoin, parcours des valeurs affichees
    if not changed:
      for i in range(self.nbSliders):
        ## Si valeur differente de l'ancienne, on arrete
        if self.sliderVars[i].get() <> self.values[self.currentSet][i]:
          changed = 1
          break
    ## Si changement, on demande confirmation
    if changed:
      if not askokcancel('Values changed', 'Values have changed. Discard changes?'):
        ## Si pas confirme, on repasse a l'ancien ensemble
        self.setVar.set(self.currentSet)
        return 0
    ## Sinon, on change d'ensemble
    self.setSet(self.setVar.get())
    return 1
  
  
  ## METHODE SAVE.SET:
  ## -----------------
  # Enregistrement de l'ensemble courant
  
  def saveSet(self):
    max = self.maxValVar.get()
    self.maxValues[self.currentSet] = max
    for i in range(self.nbSliders):
      val = self.sliderVars[i].get()
      self.editableSets[self.currentSet][i].set(int(max * val / 100.0))
      self.values[self.currentSet][i] = val
  
  
  ## METHODE CLOSE:
  ## --------------
  # Fermeture de la fenetre
  
  def close(self):
    ## Pour demande de confirmation
    if self.changeSet():
      ## Si OK, fermeture de la fenetre
      self.window.destroy()
