# -*- coding: ISO-8859-1 -*-
""" capellaScript -- (c) Paul Villiger
>>> Sekundärklammer

- Das Plugin zeichnet eine Sekundärklammer zwischen zwei ausgewählten Notenzeilen.|
- Mehrfachklammern sind möglich durch einen erneuten Aufruf|
- Schlagzeugzeilen mit einer Linie werden berücksichtigt|
- Die Klammerbreite kann gewählt werden|
- Die Klammern können gelöscht werden.|
|
- Das Plugin zeichnet auch senkrechte Klammern vor Noten
- Eine senkrechte Linie, welche die Klammerhöhe bestimmt wird in eine Klammer umgewandelt|
- Klammern können in der ganzen Partitur umgewandelt werden oder einzeln an der Cursorposition|
- Schräge, waagrechte, rechte und linke (minus) Klammern sind möglich|
- Die Klammer wird senkrecht ausgerichtet, auf 1/2 Zw. gerundet und vor der Note platziert|
- Eine Zusatzlänge kann eingegeben werden.
    
<<<
<?xml version="1.0" encoding="ISO-8859-1"?>
<info>
  <lang id="en">
    <title>Secondary / vertical brackets</title>
    <descr>
      <p>- The plugin draws a secondary bracket between two selected
  staves.
- Multiple brackets are possible by opening the plugin again.
- Percussion staves with one line are considered.
- The width of the bracket is adjustable.
- The brackets can be deleted.</p>
<p>
- Also possible are vertical brackets in front of chords.
- A vertical line is converted to a bracket.
- The line height defines the bracket height.
- A bracket can be generated at the cursor position or in the
  whole score.
- Rectangular, oblique, right and left (minus) brackets are
  possible.
- The bracket is vertically aligned and placed in front of
  the chord.
- Additional length can be added.</p>
    </descr>
  </lang>

  <lang id="de">
    <title>Sekundär- / Vertikalklammer</title>
    <descr>
      <p>- Das Plugin zeichnet eine Sekundärklammer zwischen zwei
  ausgewählten Notenzeilen.
- Mehrfachklammern sind möglich durch einen erneuten Aufruf.
- Schlagzeugzeilen mit einer Linie werden berücksichtigt.
- Die Klammerbreite kann gewählt werden.
- Die Klammern können gelöscht werden.</p>
<p>
- Das Plugin zeichnet auch senkrechte Klammern vor Noten.
- Eine senkrechte Linie, welche die Klammerhöhe bestimmt,
  wird in eine Klammer umgewandelt.
- Klammern können in der ganzen Partitur umgewandelt werden
  oder einzeln an der Cursorposition.
- Schräge, waagrechte, rechte und linke (minus) Klammern sind
  möglich.
- Die Klammer wird senkrecht ausgerichtet und vor der Note
  platziert.
- Eine Zusatzlänge kann eingegeben werden.
</p>
</descr>
  </lang>

  <lang id="nl">
    <title>Secundaire / verticale haken</title>
    <descr>
      <p>- De plugin tekent een secundaire haak tussen twee
  geselecteerde notenbalken.
- Meervoudige haken zijn mogelijk door de plugin opnieuw te
  openen.
- Met slagwerkbalken van één lijn wordt rekening gehouden.
- De breedte van de haak is instelbaar.
- De haken kunnen worden verwijderd.</p>
<p>
- De Plugin tekent ook verticale haken vóór de noten.
- Een verticale lijn wordt omgezet in een haak.
- De hoogte van de lijn bepaalt de hoogte van de haak.
- Haken kunnen in de gehele partituur worden gegenereerd of
  afzonderlijk bij de cursorpositie.
- Schuine, rechthoekige, rechtse en linkse (min) haken zijn
  mogelijk.
- De haak wordt verticaal uitgelijnd en vóór de noot geplaatst
- De haak kan worden verlengd of verkort (min).
</p>
    </descr>
  </lang>
</info>


History:  27.11.18 - Erste Ausgabe
          28.11.18 - Behandlung von Schlagzeugzeilen
          30.11.18 - Korrektur extraDistance
          23.01.19 - WW Internationalisierung (en-de-nl)
          18.03.21 - Senkrechte Klammern
          16.03.21 - minor fix and delete vertical brackets
          22.03.21 - recalc of vertical brackets
                   - range selection
          16.06.21 - Nach Abbruch wird Partitur nicht mehr geladen
                   - Fehler bei senkrechten Klammern
          21.06.21 - U.a.m. Ausbreitung ins Niederl. übersetzt;
                     Übesetzungsfehler korrigiert und Dialog angepasst (WW)
          22.06.21 - Liniendicke 0.1 oder 0.2
                   - Ecken lassen sich ändern
          23.06.21 - 'Help' angepasst (WW)
"""
english = {
    'action'        :'Selection',
    'action_0'      :'Secondary brackets: Set',
    'action_1'      :'Secondary brackets: Delete',
    'action_2'      :'------------------------',
    'action_3'      :'Vertical brackets: Set',
    'action_4'      :'Vertical brackets: Recalculate',
    'action_5'      :'Vertical brackets: Delete',
    'vbox_1'        :'Secondary brackets',
    'vbox_2'        :'Vertical brackets',
    'bracketType'   :'Bracket type',
    'oblique'       :'Oblique angles',
    'orRight'       :'- Otherwise: Right angles',
    'thickLine'     :'Thick line',
    'chordDist'     :'Distance to chord',
    'type1'         :'No angles',
    'type2'         :'Top angles',
    'type3'         :'Bottom angles',
    'type4'         :'Top and bottom angles',

    'firstStaff'    :'First staff',
    'secondStaff'   :'Second staff',
    'bracketWidth'  :'Bracket width',
    'bracketWidth2' :'Bracket width oblique a.',
    'bracketWidth3' :'Bracket width right a.',
    'bracketAdd'    :'Enlarge section',
    'selectionText' :'Selected range: ',
    'slg'           :'  slg.',
    'wholeScore'    :'Whole score',
    'orSelection'   :'- Otherwise: Selected range',
    'hint1'         :'*** Remark ***',
    'hint2'         :'For a vertical bracket, the presence',
    'hint3'         :'of a vertical line is required.',    
    'secondaryBracket' : '-- Secondary and vertical brackets --',
    'help'          :'- The plugin draws a  s e c o n d a r y   b r a c k e t  between two selected staves.\n\
- Multiple brackets are possible by opening the plugin again.\n\
- Percussion staves with one line are considered.\n\
- The width of the bracket is adjustable.\n\
- The brackets can be deleted.\n\
--------------------------------\n\
- Also possible are  v e r t i c a l   b r a c k e t s  in front of chords.\n\
- A vertical line is converted to a polygon, which takes the form of a bracket.\n\
- Beginning and end of the line determine the height of the bracket.\n\
- A bracket can be generated at the cursor position or in the whole score.\n\
- Rectangular, oblique, right and left (minus) brackets are possible.\n\
- The bracket is vertically aligned and placed in front of the chord.\n\
- Additional length can be added\n\
- The option \'Recalculate\' is based on all parameters, except the bracket type. \
The bracket height can be changed by moving the correct polygon vertices \
before selecting \'Recalculate\'.'
}
german = {
    'action'        :'Auswahl',
    'action_0'      :'Sekundärklammern setzen',
    'action_1'      :'Sekundärklammern löschen',
    'action_2'      :'------------------------',
    'action_3'      :'Senkrechte Klammern setzen',
    'action_4'      :'Senkrechte Klammern neu berechnen',
    'action_5'      :'Senkrechte Klammern löschen',
    'vbox_1'        :'Sekundärklammern',
    'vbox_2'        :'Senkrechte Klammern',
    'bracketType'   :'Klammertyp',
    'oblique'       :'Schräge Ecken',
    'orRight'       :'- Sonst: Rechter Winkel', 
    'thickLine'     :'Dicke Linie',
    'chordDist'     :'Abstand vor Noten',
    'type1'         :'Keine Ecken',
    'type2'         :'Ecken oben',
    'type3'         :'Ecken unten',
    'type4'         :'Ecken oben und unten',
    
    'firstStaff'    :'Erste Notenzeile',
    'secondStaff'   :'Zweite Notenzeile',
    'bracketWidth'  :'Klammerbreite',
    'bracketWidth2' :'Klammerbreite schräg',
    'bracketWidth3' :'Klammerbreite waagr.',
    'bracketAdd'    :'Klammer verlängern',
    'selectionText' :'Gewählter Bereich: ',
    'slg'           :'  Zw.',
    'wholeScore'    :'Ganze Partitur',
    'orSelection'   :'- Sonst: Gewählter Bereich',
    'hint1'         :'*** Anmerkung ***',
    'hint2'         :'    Für eine senkrechte Klammer ist es das Vorhandensein',
    'hint3'         :'    einer senkrechten Linie erforderlich.',
    'secondaryBracket' : '-- Sekundäre und senkrechte Klammern --',
    'help'          :'- Das Plugin zeichnet eine  S e k u n d ä r k l a m m e r  zwischen zwei ausgewählten Notenzeilen.\n\
- Mehrfachklammern sind möglich durch einen erneuten Aufruf.\n\
- Schlagzeugzeilen mit einer Linie werden berücksichtigt.\n\
- Die Klammerbreite kann gewählt werden.\n\
- Die Klammern können gelöscht werden.\n\
----------------------------------------\n\
- Das Plugin zeichnet auch  s e n k r e c h t e   K l a m m e r n  vor Noten.\n\
- Eine vertikale Linie wird in ein Polygon umgewandelt, das die Form einer Klammer annimmt.\n\
- Anfang und Ende der Linie bestimmen die Klammerhöhe.\n\
- Klammern können in der ganzen Partitur umgewandelt werden oder einzeln an der Cursorposition.\n\
- Schräge, waagrechte, rechte und linke (minus) Klammern sind möglich.\n\
- Die Klammer wird senkrecht ausgerichtet und vor der Note platziert.\n\
- Eine Zusatzlänge kann eingegeben werden.\n\
- Die Option \'neu berechnen\' basiert auf allen Parametern, mit Ausnahme des Klammertyps. \
Die Klammerhöhe kann geändert werden, indem die richtigen Polygonpunkte \
verschoben werden, bevor \'neu berechnen\' ausgewählt wird.'
}
dutch = {
    'action'        :'Selectie',
    'action_0'      :'Secundaire haken zetten',
    'action_1'      :'Secundaire haken verwijderen',
    'action_2'      :'------------------------',
    'action_3'      :'Verticale haken zetten',
    'action_4'      :'Verticale haken opnieuw berekenen',
    'action_5'      :'Verticale haken verwijderen',
    'vbox_1'        :'Secundaire haken',
    'vbox_2'        :'Verticale haken',
    'bracketType'   :'Haaktype',
    'oblique'       :'Schuine hoeken',
    'orRight'       :'- Zo niet: Rechte hoeken',
    'thickLine'     :'Dikke lijn',
    'chordDist'     :'Afstand tot de noten',
    'type1'         :'Geen hoek',
    'type2'         :'Hoek boven',
    'type3'         :'Hoek onder',
    'type4'         :'Hoek boven en onder',

    'firstStaff'    :'Eerste notenbalk',
    'secondStaff'   :'Tweede notenbalk',
    'bracketWidth'  :'Haakbreedte',
    'bracketWidth2' :'Haakbreedte schuine h.',
    'bracketWidth3' :'Haakbreedte rechte h.',
    'bracketAdd'    :'Haak verlengen',
    'selectionText' :'Geselecteerd bereik: ',
    'slg'           :'  tu.',
    'wholeScore'    :'Gehele partituur',
    'orSelection'   :'- Zo niet: Geselecteerd bereik',
    'hint1'         :'*** Opmerking ***',
    'hint2'         :'Voor een verticale haak is de aanwezigheid',
    'hint3'         :'van een verticale lijn vereist.',
    'secondaryBracket' : '-- Secundaire en verticale haken --',
    'help'          :'- De plugin tekent een  s e c u n d a i r e   h a a k  tussen twee geselecteerde notenbalken.\n\
- Meervoudige haken zijn mogelijk door de plugin opnieuw te openen.\n\
- Met slagwerkbalken van één lijn wordt rekening gehouden.\n\
- De breedte van de haak is instelbaar.\n\
- De haken kunnen worden verwijderd.\n\
-------------------------------------\n\
- De Plugin tekent ook  v e r t i c a l e   h a k e n  vóór de noten.\n\
- Een verticale lijn wordt omgezet in een polygoon, die de vorm aanneemt van een haak.\n\
- Begin en eind van de lijn bepalen de hoogte van de haak.\n\
- Haken kunnen in de gehele partituur worden gegenereerd of afzonderlijk bij de cursorpositie.\n\
- Schuine, rechthoekige, rechtse en linkse (min) haken zijn mogelijk.\n\
- De haak wordt verticaal uitgelijnd en vóór de noot geplaatst.\n\
- Additionele lengte (ook min) kan worden ingevoerd.\n\
- De optie \'opnieuw berekenen\' is gebaseerd op alle parameters, uitgezonderd het haaktype. \
De hoogte van de haak kan worden veranderd door de juiste hoekpunten van de \
polygoon te verplaatsen alvorens \'opnieuw berekenen\' te selecteren.'    
}

try:
    setStringTable(
        ("en", english),
        ("de", german),
        ("nl", dutch))
except:
    def tr(s):
        return german[s]
#-------------------------------------------------
from xml.dom.minidom import NodeList, Node, Element
import new

scriptTag  = '21793-80'
scriptTag1 = '21793-81'
continuePlugin = True

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 getChildNodes(node, tagName=''):
    result = []
    for n in node.childNodes:
        if n.nodeType == n.ELEMENT_NODE:
            if tagName:
                if n.tagName in tagName:
                    result.append(n)
            else:
                result.append(n)
    return result
    

def getAllLayouts(score):
    staffLayouts = []
    for staffLayout in score.getElementsByTagName('staffLayout'):
        staffLayouts.append(staffLayout.getAttribute('description'))
    return staffLayouts

options = ScriptOptions() 
opt = options.get()

def getCursorSelection():
    
    sel = curSelection()
    if not sel:
        return None
    else:
        (sy1, st1,vo1,ob1), (sy2,st2,vo2,ob2) = sel
        if sy1 == sy2:
            if st1 == st2:
                if vo1 == vo2:
                    (ob1,ob2) = ( min(ob1,ob2), max(ob1,ob2) )
                    if ob1 == ob2:
                        selectionText = "System %s, Staff %s, Voice %s, Object %s" % (sy1+1, st1+1, vo1+1, ob1+1)
                    else:
                        selectionText = "System %s, Staff %s, Voice %s, Object %s - %s" % (sy1+1, st1+1, vo1+1, ob1+1, ob2+1)
                else:
                    (vo1,vo2) = ( min(vo1,vo2), max(vo1,vo2) )
                    ob1=0
                    ob2=999
                    selectionText = "System %s, Staff %s, Voice %s - %s" % (sy1+1, st1+1, vo1+1, vo2+1)
            else:
                (st1,st2) = ( min(st1,st2), max(st1,st2) )
                vo1=ob1=0
                vo2=ob2=999
                selectionText = "System %s, Staff %s - %s" % (sy1+1, st1+1, st2+1)
        else:
            (sy1,sy2) = ( min(sy1,sy2), max(sy1,sy2) )
            st1=vo1=ob1=0
            st2=vo2=ob2=999
            selectionText = "System %s - %s" % (sy1+1, sy2+1)
            
        return  (sy1, st1,vo1,ob1), (sy2,st2,vo2,ob2), selectionText

sel1, sel2, selectionText = getCursorSelection()


def getDialogInfo(score):
    global opt, selectionText
    
    actionValue = int( opt.get('actionValue', '0') )

    action =  ComboBox([tr('action_0'),
                        tr('action_1'),
                        tr('action_2'),
                        tr('action_3'),
                        tr('action_4'),
                        tr('action_5')], value = actionValue, width = 38)
    
    staffLayouts = []
    for staffLayout in score.getElementsByTagName('staffLayout'):
        staffLayouts.append(staffLayout.getAttribute('description'))

    firstStaff  = ComboBox( staffLayouts, value = 0, width=15)
    secondStaff = ComboBox( staffLayouts, value = 0, width=15)
    bracketWidth = Edit(opt.get('bracketWidth', '2'), width = 15)
    bracketWidth2 = Edit(opt.get('bracketWidth2', '0.5'), width = 15)
    bracketWidth3 = Edit(opt.get('bracketWidth3', '1.0'), width = 15)
    thickLine = CheckBox('', value = eval(opt.get('thickLine', '1')))
    chordDistance = Edit(opt.get('chordDistance', '0.75'), width = 15)
    bracketType   = ComboBox( [tr('type1'),tr('type2'),tr('type3'),tr('type4')],
                              value = int( opt.get('bracketType', '3') ),
                              width = 20 )
    wholeScore  = CheckBox('', value = eval(opt.get('wholeScore', '1')))
    deleteBrackets = CheckBox('', value = False)
    obliqueBrackets = CheckBox('', value = eval(opt.get('obliqueBrackets', '1')) )
    bracketAdd = Edit(opt.get('bracketAdd', '0.1'), width = 15)

    dlg = Dialog(tr('secondaryBracket'),
                 
                 VBox([ HBox([Label(tr('action'), width = 7), action, Label('', width = 2)]),
                        VBox([
                            HBox([Label(tr('firstStaff'), width = 20), firstStaff, Label('', width = 5)]),
                            HBox([Label(tr('secondStaff'), width = 20), secondStaff]),
                            HBox([Label(tr('bracketWidth'), width = 20), bracketWidth, Label(tr('slg'), width = 7)])
                            ], text = tr('vbox_1'), padding = 1),
                        VBox([
                            HBox([Label(tr('bracketType'), width = 20), bracketType, Label('', width = 2)]),
                            HBox([Label(tr('oblique'), width = 20), obliqueBrackets, Label(tr('orRight'))]),
                            HBox([Label(tr('bracketWidth2'), width = 20), bracketWidth2, Label(tr('slg'))]),
                            HBox([Label(tr('bracketWidth3'), width = 20), bracketWidth3, Label(tr('slg'))]),
                            HBox([Label(tr('chordDist'), width = 20), chordDistance, Label(tr('slg'))]),
                            HBox([Label(tr('bracketAdd'), width = 20), bracketAdd, Label(tr('slg'))]),
                            HBox([Label(tr('thickLine'), width = 20), thickLine]),
                            HBox([Label(tr('wholeScore'), width = 20), wholeScore, Label(tr('orSelection'))]), 
                            HBox([Label(tr('selectionText')), Label(selectionText)]),
                            Label(''),
                            Label(''),
                            HBox([Label(tr('hint1'))]),
                            HBox([Label(tr('hint2'))]),
                            HBox([Label(tr('hint3'))]),
                            ], text = tr('vbox_2'), padding = 1),
                        ], padding = 8),help=tr('help')
                 )

    if dlg.run():
        actionValue = action.value()
        firstStaff = staffLayouts[firstStaff.value()]
        secondStaff = staffLayouts[secondStaff.value()]
        bracketWidth = eval(bracketWidth.value())
        bracketWidth2 = eval(bracketWidth2.value())
        bracketWidth3 = eval(bracketWidth3.value())
        chordDistance = eval(chordDistance.value())
        thickLine = thickLine.value()
        bracketAdd = eval(bracketAdd.value())
        obliqueBrackets = obliqueBrackets.value()
        wholeScore = wholeScore.value()
        bracketType = bracketType.value()
        
        
        opt['actionValue'] = str(actionValue)
        opt['firstStaff'] = firstStaff
        opt['secondStaff'] = secondStaff
        opt['bracketWidth'] = str(bracketWidth)

        opt['bracketWidth2'] = str(bracketWidth2)
        opt['bracketWidth3'] = str(bracketWidth3)
        opt['chordDistance'] = str(chordDistance)
        opt['thickLine'] = str(thickLine)
        opt['bracketType'] = str(bracketType)
        opt['bracketAdd'] = str(bracketAdd)
        opt['wholeScore'] = str(wholeScore)
        opt['obliqueBrackets'] = str(obliqueBrackets)
        options.set(opt)
        return True
    else:
        return False
    
    

def getLayoutDist(score, staffName):
    top = bootom = 0
    single = False
    for staffLayout in score.getElementsByTagName('staffLayout'):
        if staffLayout.getAttribute('description') == staffName:
            for distances in staffLayout.getElementsByTagName('distances'):
                if distances.hasAttribute('top'):
                    top = int(distances.getAttribute('top'))
                if distances.hasAttribute('bottom'):
                    bottom = int(distances.getAttribute('bottom'))
                if distances.hasAttribute('group'):
                    bottom += int(distances.getAttribute('group'))
            # check for single noteline (percussion)
            for notation in staffLayout.getElementsByTagName('notation'):
                if notation.hasAttribute('notelines'):
                    if notation.getAttribute('notelines') == '1':
                        single = True
                

    return (top, bottom, single)
    

def drawSecondaryBracket(score, staffName1, staffName2):
    global opt

    bracketWidth = eval(opt.get('bracketWidth', '0.75'))
    
    systems = score.getElementsByTagName('system')
    for sy in range(systems.length):
        staffs = systems[sy].getElementsByTagName('staff')

        # get staffs and distances
        staff1 = staff2 = -1
        extraDistance = 0
        notation = [False, False]
        for st in range(staffs.length):
            staffName = staffs[st].getAttribute('layout')
            (top, bottom, single) = getLayoutDist(score, staffName)
            if staffName == staffName1:
                staff1 = st
                extraDistance += bottom
                for extraDist in staffs[st].getElementsByTagName('extraDistance'):
                    if extraDist.hasAttribute('bottom'):
                        extraDistance += int(extraDist.getAttribute('bottom'))
                notation[0] = single
                continue
            if staffName == staffName2:
                staff2 = st
                extraDistance += top
                for extraDist in staffs[st].getElementsByTagName('extraDistance'):
                    if extraDist.hasAttribute('top'):
                        extraDistance += int(extraDist.getAttribute('top'))
                notation[1] = single
                continue

            if staff1 <> -1 and staff2 == -1:
                for extraDist in staffs[st].getElementsByTagName('extraDistance'):
                    if extraDist.hasAttribute('bottom'):
                        extraDistance += int(extraDist.getAttribute('bottom'))
                for extraDist in staffs[st].getElementsByTagName('extraDistance'):
                    if extraDist.hasAttribute('top'):
                        extraDistance += int(extraDist.getAttribute('top'))
                extraDistance += top
                extraDistance += bottom


        if staff1 == -1 or staff2 == -1:
            continue

        # get 1st object in 1st voice
        firstChord = None
        ob = 0
        for voice in staffs[staff1].getElementsByTagName('voice'):
            noteObjects = voice.getElementsByTagName('noteObjects')[0]
            firsChord = None
            for obj in noteObjects.childNodes:
                if obj.nodeType == obj.ELEMENT_NODE:
                    ob += 1
                    if obj.tagName in ['chord','rest']:
                        firstChord = obj
                        break
            break
        
        if not firstChord:
            continue

        def drawLine(anchor, x1, y1, x2, y2):
            drawObj = anchor.gotoChild('drawObj', True)
            line = drawObj.gotoChild('line')
            basic = drawObj.gotoChild('basic')
            basic.setAttribute('noAdjust', 'true')
            line.setAttribute( 'x1', str(x1) )
            line.setAttribute( 'y1', str(y1) )
            line.setAttribute( 'x2', str(x2) )
            line.setAttribute( 'y2', str(y2) )
            

        system = activeScore().system(sy)
        staff = system.staff(staff1)
        voice = staff.voice(0)
        posx = voice.noteObj(ob - 1).posX()

        # handling of single lines (percussion)
        topAdd = -2
        bottomAdd = +2
        if notation[0]:
            topAdd = 0
        if notation[1]:
            bottomAdd = 0
            
        drawObjects = firstChord.gotoChild('drawObjects')
        drawObj = drawObjects.gotoChild('drawObj', True)
        group = drawObj.gotoChild('group')
        basic = drawObj.gotoChild('basic')
        basic.setAttribute('tag', scriptTag)
        drawLine(group, - posx,                topAdd,                    - posx - bracketWidth, topAdd               )
        drawLine(group, - posx - bracketWidth, topAdd,                    - posx - bracketWidth, extraDistance + bottomAdd)
        drawLine(group, - posx,                extraDistance + bottomAdd, - posx - bracketWidth, extraDistance + bottomAdd)



def getPolygonData(drwObj, opt):
    newOpt = opt

    polygon = getChildNodes(drwObj, 'polygon')
    if polygon:
        polygon = polygon[0]
    else:
        return None, newOpt

    basic = getChildNodes(drwObj, 'basic')
    if basic:
        basic = basic[0]
    else:
        return None, newOpt

    if basic.hasAttribute('tag') and basic.getAttribute('tag') == scriptTag1:
        pass
    else:
        return None, newOpt
    
    oblique = False
    bracketWidth = 1.0
    linePoints = [-1.0, -2.0, -1.0, 2.0]
    bracketType = 3
    
    points = polygon.getElementsByTagName('point')
    count = len(points)
    if count == 6:       # Ecken oben und unten
        x1 = eval(points[1].getAttribute('x'))
        y1 = eval(points[1].getAttribute('y'))
        x2 = eval(points[2].getAttribute('x'))
        y2 = eval(points[2].getAttribute('y'))
        bracketType = 3
        bracketWidth = x2 - x1
        if y1 <> y2:
            oblique = True
        else:
            oblique = False
    elif count == 5:       # Ecken unten
        x1 = eval(points[1].getAttribute('x'))
        y1 = eval(points[1].getAttribute('y'))
        x2 = eval(points[2].getAttribute('x'))
        y2 = eval(points[2].getAttribute('y'))
        x3 = eval(points[3].getAttribute('x'))
        y3 = eval(points[3].getAttribute('y'))
        bracketType = 2     # unten
        bracketWidth = x2 - x1
        if y1 <> y2:
            oblique = True
        else:
            oblique = False

    elif count == 4:       # Ecken oben
        x1 = eval(points[1].getAttribute('x'))
        y1 = eval(points[1].getAttribute('y'))
        x2 = eval(points[2].getAttribute('x'))
        y2 = eval(points[2].getAttribute('y'))
        x3 = eval(points[3].getAttribute('x'))
        y3 = eval(points[3].getAttribute('y'))
        bracketType = 1     # oben
        bracketWidth = x3 - x2
        if y2 <> y3:
            oblique = True
        else:
            oblique = False

    elif count == 3:        # Keine Ecken
        bracketType = 0     
        bracketWidth = 0.0
        oblique = False

    # newOpt['bracketWidth2'] = str(bracketWidth)
    # newOpt['bracketWidth3'] = str(bracketWidth)

    # newOpt['obliqueBrackets'] = str(oblique)
    newOpt['bracketType'] = str(bracketType)
    
        
    if count in[3,4,5,6]:       # Linie berechnen
        x1 = eval(points[0].getAttribute('x'))
        y1 = eval(points[0].getAttribute('y'))
        x2 = eval(points[1].getAttribute('x'))
        y2 = eval(points[1].getAttribute('y'))
        linePoints = [x1, y1, x2, y2]
        
        return linePoints, newOpt
    else:
        return None, newOpt

def getLineData(drwObj):
   
    lines = getChildNodes(drwObj, 'line')
    if lines:
        line = lines[0]
    else:
        return None

    basics = getChildNodes(drwObj, 'basic')
    if basics:
        basic = basics[0]
        if basic.hasAttribute('tag'):
            return None      # only handle untages lines
    
    x1 = float(line.getAttribute('x1'))
    x2 = float(line.getAttribute('x2'))
    y1 = float(line.getAttribute('y1'))
    y2 = float(line.getAttribute('y2'))

    # check if approx straigt line
    #if abs(x1 - x2) > 1.0:
    if (y1-y2) <> 0 and abs( (x1-x2)/(y1-y2) ) > 0.1 :
        return  None     # return if not straight line

    # check for line bottom up
    if y2 < y1:
        x3 = x1
        y3 = y1
        x1 = x2
        y1 = y2
        x2 = x3
        y2 = y3

    return [x1,y1,x2,y2]
    


def drawVerticalBracket(drwObj, line, opt):

    # bracketType: bit 0 Klammer oben
    #              bit 1 Klammer unten
    #              bit 2 Klammer schräg

    bracketWidth = eval(opt.get('bracketWidth2'))
    bracketWidth3 = eval(opt.get('bracketWidth3'))
    chordDistance = eval(opt.get('chordDistance'))
    bracketType = eval(opt.get('bracketType'))
    oblique = eval(opt.get('obliqueBrackets'))
    bracketAdd = eval(opt.get('bracketAdd'))
    if oblique:
        bracketType += 4

    [x1,y1,x2,y2] = line

    x2 = x1 = - chordDistance       # make line vertical
    y1 = round(2.0 * y1) / 2.0 - bracketAdd     # round vertical position
    y2 = round(2.0 * y2) / 2.0 + bracketAdd

    # draw bracket with a polygon

    polDrwObj = drwObj.parentNode.gotoChild('drawObj', True)
    polygonObj = polDrwObj.gotoChild('polygon')
    if eval(opt.get('thickLine')):
        polygonObj.setAttribute('lineWidth','0.2')
    else:
        if polygonObj.hasAttribute('lineWidth'):
            polygonObj.removeAttribute('lineWidth')
    basic = polDrwObj.gotoChild('basic')
    basic.setAttribute('tag', scriptTag1)
    polygonObj.setAttribute('filled','false')
    polygonObj.setAttribute('fillColor','FFFFFF')
    points = polygonObj.gotoChild('points')

    point = points.gotoChild('point', True)
    point.setAttribute('x', str(x1) )
    point.setAttribute('y', str(y1) )

    point = points.gotoChild('point', True)
    point.setAttribute('x', str(x1) )
    point.setAttribute('y', str(y2) )

    if bracketType & 2:
        point = points.gotoChild('point', True)
        if bracketType & 4:
            point.setAttribute('x', str(x1 + bracketWidth) )
            point.setAttribute('y', str(y2 + abs(bracketWidth)) )
        else:
            point.setAttribute('x', str(x1 + bracketWidth3) )
            point.setAttribute('y', str(y2) )
    
        point = points.gotoChild('point', True)
        point.setAttribute('x', str(x1) )
        point.setAttribute('y', str(y2) )
    
    point = points.gotoChild('point', True)
    point.setAttribute('x', str(x1) )
    point.setAttribute('y', str(y1) )

    if bracketType & 1:
        point = points.gotoChild('point', True)
        if bracketType & 4:
            point.setAttribute('x', str(x1 + bracketWidth) )
            point.setAttribute('y', str(y1 - abs(bracketWidth)) )
        else:
            point.setAttribute('x', str(x1 + bracketWidth3) )
            point.setAttribute('y', str(y1) )

    # remove initial vertical line
    drwObj.parentNode.removeChild(drwObj)
    

def changeDoc(score):
    global opt, sel1, sel2, continuePlugin

    continuePlugin = getDialogInfo(score)

    if not continuePlugin:
        return

    actionValue = eval(opt.get('actionValue'))
    staffName1 = opt.get('firstStaff')
    staffName2 = opt.get('secondStaff')

    wholeScore = eval(opt.get('wholeScore'))
    if wholeScore:
        sel1, sel2 = (0,0,0,0), (999,999,999,999)
    (sy1,st1,vo1,ob1), (sy2,st2,vo2,ob2) = sel1, sel2

    # Draw secondary bracket
    if actionValue == 0 and staffName1:
        drawSecondaryBracket(score, staffName1, staffName2)

    # delete all secondary brackets
    # delete all straight brackets
    elif actionValue in [1]:
        pass        # handled after ScoreChange
    
    
    elif actionValue in [3,4,5]:
        syCount = stCount = voCount = obCount = 0
        for system in score.getElementsByTagName('system'):
            syCount += 1
            if not (sy1 <= syCount - 1 <= sy2):
                continue
            
            for staff in system.getElementsByTagName('staff'):
                stCount += 1
                if not (st1 <= stCount - 1 <= st2):
                    continue
                
                for voice in staff.getElementsByTagName('voice'):
                    voCount += 1
                    if not (vo1 <= voCount - 1 <= vo2):
                        continue
                    
                    noteObjects = voice.gotoChild('noteObjects')
                    for obj in getChildNodes(noteObjects):
                        obCount += 1
                        if not (ob1 <= obCount - 1 <= ob2):
                            continue

                        for drawObjects in getChildNodes(obj, 'drawObjects'):
                            for drawObj in getChildNodes(drawObjects, 'drawObj'):
                                if actionValue == 3:
                                    line = getLineData(drawObj)
                                    if line:
                                        drawVerticalBracket(drawObj, line, opt)
                                if actionValue == 4:
                                    line, newOpt = getPolygonData(drawObj, opt)
                                    #newOpt['bracketAdd'] = '0'
                                    if line:
                                        drawVerticalBracket(drawObj, line, newOpt)
                                if actionValue == 5:
                                    line, newOpt = getPolygonData(drawObj, opt)
                                    if line:
                                        drawObj.parentNode.removeChild(drawObj)
        

# 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("Sekundärklammer")

    tempInput = tempfile.mktemp('.capx')
    tempOutput = tempfile.mktemp('.capx')
    activeScore().write(tempInput)
    
    ScoreChange(tempInput, tempOutput)

    if continuePlugin:
        # delete all secondary brackets
        if eval(opt.get('actionValue')) == 1:
            activeScore().deleteTaggedGraphics(scriptTag)
        
        elif eval(opt.get('actionValue')) == 2:
            # Dummy entry
            pass
        
        else:
            activeScore().read(tempOutput)

    os.remove(tempInput)
    os.remove(tempOutput)
