# -*- coding: ISO-8859-1 -*-
""" capellaScript (c) Paul Villiger
>>> Grafik Mehrtaktpausen

    Mit diesem Skript können Mehrtaktpausen (MTP) an die Taktbreite angepasst
    und gezeichnet werden. Die Capella-MTP wird auf unsichtbar
    gesetzt und die neue MTP als Grafikobjekt eingefügt. Bestehende Grafikpausen
    werden ersetzt.
<<<

History: 28.11.03 - Erste Ausgabe
         01.12.03 - Dialog eingebaut
         14.10.04 - Eintaktpausen werden nicht mehr gesetzt
                  - Absturz wenn Takt fehlte
         11.03.12 - Der Takt wird berücksichtigt, z.B. 2 Takte bei 2/4


"""
from caplib.rational import Rational

skriptTag = '21793-1'
endWidth = 0.1   # in Notenzeilenabstand
endHight = 1.5   # in Notenzeilenabstand
barWidth = 0.8   # 80% der Taktbreite
barHight = 0.5   # in Notenzeilenabstand
fixSpace = True  # Abstand fix oder %
fixDist  = 2.0   # Abstand von Taktstrich
removeGraphicRest = False
actMeter = Rational('4/4')

def handleVoice(voice):
    global actMeter
    startPosX = endPosX = 0
    multiRest = 0
    multiRestFound = False
    keyFound = False
    for obj in voice.noteObjs():
        if (obj.subType() == NoteObj.REST) and ( obj.fullMeasures() > 0 ) and obj.duration() / actMeter > Rational('1'):
            # Mehrtaktpause
            multiRestFound = True
            restObj = obj
            if keyFound:
                startPosX = startPosX + abs(obj.curKey())
                #messageBox('Tonart',str(startPosX))

        keyFound = False                

        if obj.subType() in (NoteObj.EXPL_BARLINE,
                             NoteObj.KEY,
                             NoteObj.CLEF,
                             NoteObj.METER) or obj.implBarline() != 0:

            if obj.implBarline() != 0:
                endPosX = obj.implBarline().posX()
            else:
                endPosX = obj.posX()
            if multiRestFound:

                if fixSpace:
                    rand = fixDist
                else:
                    rand = (endPosX - startPosX) * ( 1 - barWidth ) / 2   # Abstand zum Taktstrich
                    
                breite1 = restObj.posX() - startPosX - rand
                breite2 = endPosX - restObj.posX() -rand

                frame = dict(
                    type = 'rectangle',
                    lineWidth = 0,
                    filled = True,
                    x1 = -breite1,  y1 = barHight / 2 ,
                    x2 =  breite2, y2 = -barHight / 2,
                    lineColor = Color.white,
                    fillColor = Color.black)

                barL = dict(
                    type = 'rectangle',
                    x1 = -breite1,        y1 =  (endHight / 2),
                    x2 = -breite1 + endWidth, y2 = -(endHight / 2),
                    lineWidth = 0,
                    filled = True,
                    fillColor = Color.black)

                barR = dict(
                    type = 'rectangle',
                    x1 =  breite2 - endWidth, y1 =  (endHight / 2),
                    x2 =  breite2,        y2 = -(endHight / 2),
                    lineWidth = 0,
                    filled = True,
                    fillColor = Color.black)

                txt = dict(
                    type = 'text',
                    x = (breite2 - breite1) / 2,
                    y = -2.9,
                    content = str(restObj.duration()/actMeter),
                    align = 'center',
                    font = dict(face='Capella3',
                                height=18,
                                charSet=2,
                                pitchAndFamily=2)
                    )

                group = dict(
                    type  = 'group',
                    items = [frame, barL, barR, txt],
                    tag = skriptTag
                    )
                
                restObj.addDrawObj(group)
                # ---------------------------------------------------------------
                # Hier sollte die Mehrtaktpause noch unsichtbar geschaltet werden.
                #-----------------------------------------------------------------
    
            if obj.implBarline() != 0:
                startPosX = obj.implBarline().posX()
            elif obj.subType() == NoteObj.METER:
                startPosX = obj.posX() + 1
            elif obj.subType() == NoteObj.KEY:
                # Tonartbreite berücksichtigen
                keyFound = True
                startPosX = obj.posX()
            elif obj.subType() == NoteObj.CLEF:
                startPosX = obj.posX() + 0.5
            else:
                startPosX = obj.posX()
            multiRestFound = False

        if obj.subType() == NoteObj.METER:
            actMeter = obj.meter()

def changeDoc(score):
    # Kann entfallen, wenn "setInvisible" als interne Methode verfügbar ist
    for rest in score.getElementsByTagName('rest'):
        for basic in rest.getElementsByTagName('basic'):
            if basic.hasAttributes and basic.getAttribute('tag') == skriptTag:
                # Nur Pausen mit dem aktuellen SkriptTag auf unsichtbar setzen
                displays = rest.getElementsByTagName('display')
                if displays.length == 0:
                    display = score.parentNode.createNode('display')
                    rest.appendNode(display)
                else:
                    display = displays[0]
                if removeGraphicRest:
                    display.setAttribute('invisible', 'false')
                else:
                    display.setAttribute('invisible', 'true')
        
from caplib.capDOM import ScoreChange
import tempfile

class HideBarRest(ScoreChange):
    # Kann entfallen, wenn "setInvisible" als interne Methode verfügbar ist
    def changeScore(self, score):
        changeDoc(score)

if activeScore():
    #---- Dialog BEGIN ------

    rad1 = Radio(['Abstand von Taktstrich fest',
                  'Pausenbreite % von Taktbreite',
                  'Grafische Mehrtaktpausen entfernen'], value = 0, padding = 0)
    edi1 = Edit(str(fixDist), width = 10)
    edi2 = Edit(str(barWidth*100), width = 10)
    vbox1 = VBox([edi1, edi2], padding=0)

    lab1 = Label(' Notenlinien')
    lab2 = Label(' %')
    vbox2 = VBox([lab1, lab2], padding = 8)

    hbox1 = HBox([rad1, vbox1, vbox2])

    lab3 = Label('Balkendicke:', padding=8)
    lab4 = Label('Strichbreite:', padding=8)
    lab5 = Label('Strichhöhe:', padding=8)
    vbox3 = VBox([lab3,lab4,lab5], padding=8)

    edi3 = Edit(str(barHight), width=10)
    edi4 = Edit(str(endWidth), width=10)
    edi5 = Edit(str(endHight), width=10)
    vbox4 = VBox([edi3,edi4,edi5], padding=0)

    lab6 = Label('Notenlinien')
    lab7 = Label('dto.')
    lab8 = Label('dto.')
    vbox5 = VBox([lab6,lab7,lab8], padding=8)

    hbox2 = HBox([vbox3,vbox4,vbox5], padding=8)

    vbox6 = VBox([hbox1,hbox2], padding=20)

    dlg = Dialog('Grafische Mehrtaktpausen', vbox6)

    if dlg.run():
        barHight = float(edi3.value())
        endWidth = float(edi4.value())
        endHight = float(edi5.value())
        barWidth = float(edi2.value()) / 100.0
        fixDist  = float(edi1.value())
        if rad1.value() == 0:
            fixSpace = True
        elif rad1.value() == 1:
            fixSpace = False
        else:
            removeGraphicRest = True

    #----- Dialog ENDE ---------        

        if not removeGraphicRest:
            activeScore().deleteTaggedGraphics(skriptTag)
            for staff in activeScore().staves():
                actMeter = staff.defaultMeter()
                for voice in staff.voices():
                    handleVoice(voice)

        # Kann entfallen, wenn "setInvisible" als interne Methode verfügbar ist
        tempFile1 = tempfile.mktemp('.capx')
        tempFile2 = tempfile.mktemp('.capx')
        activeScore().write(tempFile1)
    
        HideBarRest(tempFile1, tempFile2)
    
        activeScore().read(tempFile2)
        os.remove(tempFile1)
        os.remove(tempFile2)
        
        if removeGraphicRest:
            activeScore().deleteTaggedGraphics(skriptTag)
    

