# -*- coding: ISO-8859-1 -*-
""" capellaScript -- ©Paul Villiger
>>> Notenzeilen Abstand

Mit diesem Skript können für die Notenzeilenabstände auch negative Werte eingegeben werden, was capella nicht erlaubt.||

Anwendungsfall: Zwei Systeme nebeneinander. |
- System umbrechen|
- 2tes System einrücken|
- Cursor im ersten System auf die letzte Notenzeile setzen|
- Skript aufrufen und für "Abstand unten" die entsprechende negative Zahl eingeben|
|
Einschränkung:|
-In Systemen mit negativem Abstand kann nicht mit der Maus navigiert werden.|
-In der Notenzeile mit negativem Abstand sind Text- und Grafikobjekte unsichtbar


<<<
History:  06.06.05  - Erste Version
          20.06.05  - Beschreibung erweitert

Rückmeldungen bitte an villpaul@swissonline.ch                     

"""


import xml.dom
import new, string
from xml.dom.minidom import NodeList, Node, Element

def gotoChild(self, name, new=False, first=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)
        if first and self.firstChild:
            self.insertBefore(newEl, self.firstChild )            
        else:
            self.appendChild(newEl)
    return newEl
Node.gotoChild = new.instancemethod(gotoChild,None,Node)

def getCursor():
    sel = curSelection()
    (sy1,st1,vo1,ob1),(sy2,st2,vo2,ob2) = sel
    sel = (min(sy1,sy1), min(st1,st2),min(vo1,vo2),min(ob1,ob2)),(max(sy1,sy1), max(st1,st2),max(vo1,vo2),max(ob1,ob2))
    (sy1,st1,vo1,ob1),(sy2,st2,vo2,ob2) = sel
    sel = (sy1,st1,vo1,ob1)
    return sel


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 getDialogValues(top, bottom):
    vTop = top
    vBottom = bottom
    valTop = Edit(vTop, width = 5)
    valBottom = Edit(vBottom, width = 5)
    
    dlg = Dialog('Notenzeilen Abstand',
                 VBox([Label(' '),
                      HBox([Label('Abstand oben:', width = 15),valTop]),
                      HBox([Label('Abstand unten:', width = 15),valBottom]),
                      Label(' '),
                      Label('Auch negative Werte sind erlaubt'),
                      Label(' ')]))

    if dlg.run():
        vTop = str(valTop.value())
        vBottom = str(valBottom.value())

        return True, vTop, vBottom
    else:
        return False, '0', '0'
    
def changeDoc(score):
    global doc
    doc = score.parentNode    
    (sy1, st1, vo1, ob1) = getCursor()

    sy = 0
    for system in score.getElementsByTagName('system'):
        if sy1 == sy :
            st = 0
            for staff in system.getElementsByTagName('staff'):
                if st1 == st:
                    top = '0'
                    bottom = '0'
                    for extraDistance in staff.getElementsByTagName('extraDistance'):
                        if extraDistance.getAttribute('top'):
                            top = extraDistance.getAttribute('top')
                        if extraDistance.getAttribute('bottom'):
                            bottom = extraDistance.getAttribute('bottom')

                    ok, top, bottom = getDialogValues(str(top), str(bottom))
                    
                    if ok:
                        extraDistance = staff.gotoChild('extraDistance', first=True)
                        extraDistance.setAttribute('top',top)
                        extraDistance.setAttribute('bottom',bottom)
                st += 1
        sy += 1

# Hauptprogramm:

from caplib.capDOM import ScoreChange
import tempfile

class Zeilenabstand(ScoreChange):
    def changeScore(self, score):
        changeDoc(score)

if activeScore():
    activeScore().registerUndo("Notenzeilen_Abstand")
    tempInput = tempfile.mktemp('.capx')
    tempOutput = tempfile.mktemp('.capx')
    activeScore().write(tempInput)
    
    Zeilenabstand(tempInput, tempOutput)

    activeScore().read(tempOutput)
    os.remove(tempInput)
    os.remove(tempOutput)
