# -*- coding: ISO-8859-1 -*-
""" capellaScript -- 24.02.2006 Andreas Herzog
>>> Tempomat

    Mit diesem Skript kann man eine Tempoangabe einfügen.|
    |
    Das Skript formatiert gleichzeitig die Systeme mit der richtigen Abspielgeschwindigkeit.
    |
    Version 1.1   |
    
    |
    
        |

<<<


"""
# Version 1.0: Ursprungsversion
#         1.1: 22.11.10 Korrekturen punktierte Noten (Vlg)

import xml.dom
import string
import tkFont
import Tkinter

from xml.dom.minidom import NodeList

Notenwerte = ['Ganze','Halbe','Viertel','Achtel','Sechszehntel']


# doc = [] # parentNode von score

def latin1_e(u):
    return u.encode('Latin-1')
def latin1_d(u):
    return u.decode('Latin-1')
    

def Test(text):
    messageBox('Test',str(text))

def addElementNode(el,tagName):
    # add new Node to el if Node "tagName" does not exist
    # otherwise return the existing Node
    global doc
    childs = el.childNodes
    for n in range(childs.length):
        if childs[n].nodeType ==childs[n].ELEMENT_NODE and childs[n].tagName == tagName:
            return childs[n]
    newChild = doc.createElement(tagName)
    el.appendChild(newChild)
    return newChild
    

def addNewElementNode(el,tagName):
    # add new Node with tagName "tagName" to el 
    global doc
    newChild = doc.createElement(tagName)
    el.appendChild(newChild)
    return newChild

    
def getFonts():
    root = Tkinter.Tk()
    FontListT= tkFont.families()
    FontList  = []
    FontList2  = []
    i=0
    while i < len(FontListT):
        try: 
            FontList += [latin1_e(FontListT[i])]
        except:    
            FontList += ['FEHLER']    
        i+=1
    j=0
    while j < len(FontList):
        FontName = FontList[j]
        FontList[j] = FontName[0].upper() + FontName[1:]
        j+=1       
    FontList.sort()
    
    return FontList  

def getDialogValues1():

    global Notenwert, BPMstring, Punktierung, BPMinteger
    global NurLoeschen, Font, Systeme
    

    BPMEdit  = Edit (value = BPMstring,  width=5, min=1, max=300)
     
    
    equalLab = Label('=', width = 0)
    FontLab = Label('Schriftart:  ', width = 0)
    
    NurLoeschenCheck = CheckBox('Nur Elemente dieses Skripts löschen!', value=0)
    
    NotenwerteBox = ComboBox(Notenwerte, value=Notenwert, width=8)
    punktierungBox = ComboBox(['ohne','1fach','2fach'], value=Punktierung, width=8)
    
    SystemeRadio = Radio(['alle Systeme','alle Systeme ab Cursor','nur System mit Cursor', 'kein System'], text = 'Tempo einstellen für',value=1, width=1)
    
    Fonts = getFonts()
    
    try:
        FontNr = Fonts.index(Font)
    except:
        FontNr = 0    
    
    FontBox = ComboBox(Fonts, value=FontNr, width=20)
    punkierungLab = Label('Punktierung: ', width = 0)
    
    hbox01 = HBox([NotenwerteBox,equalLab, BPMEdit], padding = 2)
    hbox02 = HBox([punkierungLab,punktierungBox], padding = 0)
    hbox03 = HBox([FontLab, FontBox], padding = 0)
    
    vbox00= VBox([hbox01,hbox02,hbox03,SystemeRadio,NurLoeschenCheck], padding = 8)
    
    dlg = Dialog('Bitte wählen: ', vbox00)

    
    if dlg.run():
        Notenwert = NotenwerteBox.value()
        NurLoeschen = NurLoeschenCheck.value()
        BPMstring = BPMEdit.value()
        BPMinteger = string.atoi(BPMstring)
        Punktierung = punktierungBox.value()
        Font = Fonts[FontBox.value()]
        Systeme = SystemeRadio.value()
        return True
  
    else:
        return False

    
        
def newText(drawObjAncer,  width, height,size, contents, IndexTag):
    global FingerGruppierung, FingerFontGroesse, BogenStaerke, StrichAbstand
    
    drawObj = addNewElementNode(drawObjAncer,'drawObj')
        
    text = addNewElementNode(drawObj,'text')    
        
    text.setAttribute('x',str(width))
    text.setAttribute('y',str(height))

    content = addNewElementNode(text,'content')
    textNode = doc.createTextNode(contents)
    content.appendChild(textNode)
    text.setAttribute('align','center')
    GraficalTag = '56294-13'+IndexTag
    basic = addElementNode(drawObj,'basic')                            
    basic.setAttribute('tag',GraficalTag)    

    font = addNewElementNode(text,'font')
    font.setAttribute('face',Font)
    font.setAttribute('color','')
    font.setAttribute('height',str(size))
    font.setAttribute('charSet','1')
    font.setAttribute('pitchAndFamily','2')     

    return text

def newCapText(drawObjAncer,  width, height, size, contents, IndexTag):
    global FingerGruppierung, FingerFontGroesse, BogenStaerke, StrichAbstand
    
    drawObj = addNewElementNode(drawObjAncer,'drawObj')
        
    text = addNewElementNode(drawObj,'text')    
        
    text.setAttribute('x',width)
    text.setAttribute('y',height)

    content = addNewElementNode(text,'content')
    textNode = doc.createTextNode(latin1_d(contents))
    content.appendChild(textNode)
    text.setAttribute('align','center')
    GraficalTag = '56294-13'+IndexTag
    basic = addElementNode(drawObj,'basic')                            
    basic.setAttribute('tag',GraficalTag)    

    font = addNewElementNode(text,'font')
    font.setAttribute('face','capella3')
    font.setAttribute('color','')
    font.setAttribute('height',str(size))
    font.setAttribute('charSet','2')
    font.setAttribute('pitchAndFamily','2')     

    return text                    
def clearNote(chord):
                                            
    for drawObjects in chord.getElementsByTagName('drawObjects'):                    # Alle drawObj mit tag == GraficalTag löschen
          for drawObj in drawObjects.childNodes:
             if drawObj.nodeType == drawObj.ELEMENT_NODE and drawObj.tagName == 'drawObj':
                for basic in drawObj.getElementsByTagName('basic'):
                     if basic.hasAttribute('tag') and basic.getAttribute('tag') == '56294-1300':
                        drawObjects.removeChild(drawObj)
              
    for drawObjects in chord.getElementsByTagName('drawObjects'):                    # Alle drawObj mit tag == GraficalTag löschen
         for drawObj in drawObjects.childNodes:
            if drawObj.nodeType == drawObj.ELEMENT_NODE and drawObj.tagName == 'drawObj':
                for basic in drawObj.getElementsByTagName('basic'):
                    if basic.hasAttribute('tag') and basic.getAttribute('tag')[0:8] == '56294-13':
                        drawObjects.removeChild(drawObj)         

         if drawObjects.getElementsByTagName('drawObj').length == 0:                    # Wenn drawObjects keine Elemente mehr enthält, dann löschen  
             drawObjects.parentNode.removeChild(drawObjects)

            
def getCursor():
    sel = curSelection()
    result = None
    if sel == 0:
        messageBox('Fehler', 'keine aktive Partitur')
        return result
    result = sel[0]
    return result

def getElementObjects(objList):  # returns a List
    newList = NodeList()
    for n in range(objList.length):
        if objList[n].nodeType == objList[n].ELEMENT_NODE:
            newList.append(objList[n])
    return newList


def makeNewElement(obj):
    global BPMinteger
    
    drawObjects = addElementNode(obj,'drawObjects')                # Notennamen
    drawObj = addNewElementNode(drawObjects, 'drawObj')
    
    group = addNewElementNode(drawObj,'group')
    basicGroup = addNewElementNode(drawObj,'basic')
    basicGroup.setAttribute('tag','56294-1300')
    
    if Notenwert == 0:
        text01 = newCapText(group, str(-1.0), str(-3.5),12, 'ã', '01')
        BPMquotient = 4.0
    if Notenwert == 1:
        text02 = newCapText(group, str(-1.0), str(-3.5),12, '®', '02')
        BPMquotient = 2.0
    if Notenwert == 2:
        text03 = newCapText(group, str(-1.0), str(-3.5),12, '¢', '03')    
        BPMquotient = 1.0
    if Notenwert == 3:
        text04 = newCapText(group, str(-1.0), str(-3.5),12, '¤', '04')
        BPMquotient = 0.5
    if Notenwert == 4:
        text05 = newCapText(group, str(-1.0), str(-3.5),12, '¦', '05')                    
        BPMquotient = 0.25
    
    
    if Punktierung == 1:
        text31 = newCapText(group, str(-0.7), str(-3.3),9, '.', '31')
        BPMquotient = BPMquotient * 1.5
    if Punktierung == 2:
        text31 = newCapText(group, str(-0.8), str(-3.3),9, '.', '31')
        text32 = newCapText(group, str(-0.5), str(-3.3),9, '.', '32')
        BPMquotient = BPMquotient * 1.75
    
    text11 = newText(group, str(0.5), str(-3.1),7, '=', '22')            
    text21 = newText(group, str(2.9), str(-3.1),8, str(BPMstring), '21')    
    
    BPMinteger = BPMinteger * BPMquotient
    
    

def getNoteData(obj):
    global Notenwert, BPMstring, Punktierung, secondPoint, Font

    for drawObjects in obj.getElementsByTagName('drawObjects'):
        for drawObj in drawObjects.childNodes:
            if drawObj.nodeType == drawObj.ELEMENT_NODE and drawObj.tagName == 'drawObj':
                for basic in drawObj.getElementsByTagName('basic'):
                    if basic.hasAttribute('tag') and basic.getAttribute('tag')[0:8] == '56294-13':
                        AttributeFound=basic.getAttribute('tag')
                        if AttributeFound == '56294-1301':
                            Notenwert = 0 
                        if AttributeFound == '56294-1302':
                            Notenwert = 1 
                        if AttributeFound == '56294-1303':
                            Notenwert = 2 
                        if AttributeFound == '56294-1304':
                            Notenwert = 3 
                        if AttributeFound == '56294-1305':
                            Notenwert = 4                                                           
                        if AttributeFound == '56294-1321':
                            for content in drawObj.getElementsByTagName('content'):
                                BPMstring = latin1_e(content.firstChild.nodeValue)
                            for font in drawObj.getElementsByTagName('font'):
                                Font = font.getAttribute('face')
                        if AttributeFound == '56294-1331':
                            if secondPoint == False:
                                Punktierung = 1                                
                        if AttributeFound == '56294-1332':
                            secondPoint = True
                            Punktierung = 2                         
                    
def changeDoc(score):
    global Notenwert, BPMstring, Punktierung, secondPoint, Font

    secondPoint = False
    Notenwert = 2
    BPMstring = '120'
    Punktierung = 0
    Font = 'Arial'

    sel = getCursor()
    if sel == None:
        #
        return
    else:
        system = score.getElementsByTagName('system')[sel[0]]
        staff = system.getElementsByTagName('staff')[sel[1]]
        voice = staff.getElementsByTagName('voice')[sel[2]]
        noteObject = voice.getElementsByTagName('noteObjects')[0]
        objList = getElementObjects(noteObject.childNodes)
        if objList.length <= sel[3]:
            return

        
        obj = objList[sel[3]]
        if obj.tagName in ['chord', 'rest']:
            getNoteData(obj)
            if getDialogValues1():

                clearNote(obj)

                if NurLoeschen == 0:
                    makeNewElement(obj)
                    if Systeme == 0:
                        for systems in score.getElementsByTagName('systems'):
                            for allSystems in systems.getElementsByTagName('system'):
                                allSystems.setAttribute('tempo',str(int(BPMinteger)))
                    if Systeme == 1:
                        BeginningFromCursor = False
                        for systems in score.getElementsByTagName('systems'):
                            for allSystems in systems.getElementsByTagName('system'):
                                if allSystems == system:
                                    BeginningFromCursor = True
                                if BeginningFromCursor:    
                                    allSystems.setAttribute('tempo',str(int(BPMinteger)))
                    if Systeme == 2:
                        system.setAttribute('tempo',str(int(BPMinteger)))


# Hauptprogramm:

from caplib.capDOM import ScoreChange
import tempfile

class ScoreChange(ScoreChange):
    
    def changeScore(self, score):
       global doc
       doc = score.parentNode  
       changeDoc(score)


if activeScore():
    
    activeScore().registerUndo("Tempoangabe")
    tempInput = tempfile.mktemp('.capx')
    tempOutput = tempfile.mktemp('.capx')
    activeScore().write(tempInput)
    ScoreChange(tempInput, tempOutput)
    activeScore().read(tempOutput)
    os.remove(tempInput)
    os.remove(tempOutput)

