# -*- coding: ISO-8859-1 -*-
""" capellaScript -- (c) Paul Villiger
>>> Systeme abschliessen

    Mit diesem Skript können Systeme mit einem festen Taktstrich abgeschlossen werden.
    Der Taktstrich kann als "durchgezogen" oder "offen" definiert werden.
    Fehlende Taktstriche werden ersetzt.  Tonart- und Taktwechsel am Zeilenende werden berücksichtigt.
    Das Skript sucht in einem System den ersten festen Taktstrich am Zeilenende und setzt diesen bei allen Zeilen ein.
    Die Taktstriche lassen sich auch wieder löschen.
    Einfache Notenzeilen können am Zeilenbeginn bit einem Taktstrich abgeschlossen werden.
      
<<<

History:  07.02.2006 - Erste Version. Anregung von Diethard Bernstein
          08.02.2006 - Tonart- und Taktwechsel am Zeilenende
          10.02.2006 - Leere Zeilen ignorieren
          17.04.2006 - Taktstriche am Zeilenbeginn von einfachen Notenzeilen
         
"""

import xml.dom, new
from xml.dom.minidom import parseString, NodeList, Node, Element

doc = parseString('<score/>')

def gotoChild(self, name, new=False):
    newEl = None
    if new:
        pass
    else:
        for child in self.childNodes:
            if child.nodeType == child.ELEMENT_NODE and child.tagName == name:
                newEl = child
                break
    if newEl == None:
        newEl = doc.createElement(name)
        self.appendChild(newEl)
    return newEl
Node.gotoChild = new.instancemethod(gotoChild,None,Node)
                    
    
def changeDoc(score):
    for system in score.getElementsByTagName('system'):
        barlineType = 'single'      # per Default wird ein einfacher Taktstrich gesetzt
        
        # erste "barline" im System suchen und merken
        for voice in system.getElementsByTagName('voice'):
            noteObjects = voice.gotoChild('noteObjects')
            child = noteObjects.lastChild
            while child:
                if child and child.ELEMENT_NODE == child.nodeType:
                    if child.tagName == 'barline':
                        barlineType = child.getAttribute('type')
                        break
                    elif child.tagName == 'keySign':
                        barlineType = 'double'
                    elif child.tagName == 'timeSign':
                        barlineType = 'single'
                    elif child.tagName in ['chord','rest']:
                        break
                child = child.previousSibling

            if not child:   # Leere Zeilen ignorieren
                barlineType = 'single'


        for voice in system.getElementsByTagName('voice'):
            noteObjects = voice.gotoChild('noteObjects')
            child = noteObjects.lastChild
            pChild = child
            autoBarline = False
            while child:
                if child and child.ELEMENT_NODE == child.nodeType:
                    if child.tagName == 'barline':
                        break
                    elif child.tagName == 'keySign':
                        autoBarline = True
                    elif child.tagName in ['chord','rest']:
                        newChild = doc.createElement('barline')
                        child.parentNode.insertBefore(newChild, pChild)
                        child = newChild
                        break
                pChild = child
                child = child.previousSibling

            if not child:   # Leere Zeilen ignorieren
                continue

            if dialogResult == 0:
                child.setAttribute('range','full')
                child.setAttribute('type',barlineType)
            else:
                # Einfache Taktstriche am Zeilenende werden entfernt
                if dialogResult == 2 and (barlineType == 'single' or not barlineType or autoBarline):
                    noteObjects.removeChild(child)
                    child.unlink()
                else:                    
                    child.setAttribute('range','auto')
                    child.setAttribute('type',barlineType)

tag = '21793-987'
def deleteFrontBarline():
    for sy in activeScore().systems():
        if sy.nStaves() <> 1:
            continue
        for vo in sy.voices():
            for no in vo.noteObjs():
                i = no.nDrawObjs() -1
                while i >= 0:
                    do =no.drawObj(i)
                    if do['type'] == 'line' and do.has_key('tag') and do['tag'] == tag:
                        no.deleteDrawObj(i)
                    i -= 1

def createFrontBarline():
    for sy in activeScore().systems():
        if sy.nStaves() <> 1:
            continue
        for vo in sy.voices():
            for no in vo.noteObjs():
                if no.isChord() or no.isRest():
                    line = {}
                    line['type'] = 'line'
                    line['x1'] = line['x2']= - no.posX()
                    line['y1'] = 2.0
                    line['y2'] = -2.0
                    line['tag'] = tag
                    no.addDrawObj(line)
                    break


def getDialog():
    select = Radio(['Taktstriche durchgezogen','Taktstriche offen', 'Taktstriche entfernen','Taktstrich Zeilenbeginn','Taktstrich Zeilenbeginn entfernen'], value = 0)
    dlg = Dialog('Taktstriche am Systemende',
                 VBox([select,
                       Label(' ')])
                 )
    if dlg.run():
        return select.value()
    else:
        return None


# Hauptprogramm:

from caplib.capDOM import ScoreChange
import tempfile

class ScoreChange(ScoreChange):
    def changeScore(self, score):
        changeDoc(score)


if activeScore():
    dialogResult = getDialog()
    if dialogResult <> None:
        activeScore().registerUndo("Systeme_Abschliessen")
    
    if dialogResult == 3:
        deleteFrontBarline()
        createFrontBarline()
    elif dialogResult == 4:
        deleteFrontBarline()
    elif dialogResult in [0,1,2]:
        tempInput = tempfile.mktemp('.capx')
        tempOutput = tempfile.mktemp('.capx')
        activeScore().write(tempInput)
        
        ScoreChange(tempInput, tempOutput)

        activeScore().read(tempOutput)
        os.remove(tempInput)
        os.remove(tempOutput)

