]> git.donarmstrong.com Git - lilypond.git/commitdiff
* ikebana.py (NotationApplication.tree_selection_changed): new
authorhanwen <hanwen>
Fri, 29 Jul 2005 11:35:52 +0000 (11:35 +0000)
committerhanwen <hanwen>
Fri, 29 Jul 2005 11:35:52 +0000 (11:35 +0000)
function.

* music.py (ClefEvent.__init__): add
(NoteEvent.ly_expression): add
(Music.has_children): new method.

* musictree.py (MusicTreeView.selection_changed): add Tree view of
music model.

ChangeLog
ikebana.py
music.py
musictree.py [new file with mode: 0644]
notation.py
notationcanvas.py

index 33fd62dd0e712dd84f88230ad90fb25842ba1c4d..e188fcc52091dc101e6f32f79bc84a42ebc4a9f2 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,19 @@
+2005-07-29  Han-Wen Nienhuys  <hanwen@xs4all.nl>
+
+       * ikebana.py (NotationApplication.tree_selection_changed): new
+       function.
+
+       * music.py (ClefEvent.__init__): add 
+       (NoteEvent.ly_expression): add 
+       (Music.has_children): new method.
+
+       * musictree.py (MusicTreeView.selection_changed): add Tree view of
+       music model.
+
 2005-07-28  Han-Wen Nienhuys  <hanwen@xs4all.nl>
 
        * server.ly: use Completion_heads_engraver
+       use version number. 
 
        * music.py (Music.set_start): use Rationals for lengths.
 
index ddd709d2e0563b7a2b1121cefef0310ec592d1f1..2d4ab757bbcc7f9134c34f682477a0ed8d82d67d 100644 (file)
@@ -1,5 +1,6 @@
 #!/usr/bin/env python
 
+import musictree
 import os
 import gtk
 import gnomecanvas
@@ -14,16 +15,40 @@ def mainquit (*args):
 
 class NotationApplication:
     def __init__ (self):
-        self.music = music.Music_document ()
+        self.document = music.Music_document ()
         
-        nc = notation.Notation_controller (self.music)
+        nc = notation.Notation_controller (self.document)
         self.notation_controller = nc
 
         ncc = notationcanvas.Notation_canvas_controller (nc.notation)
         self.notation_canvas_controller = ncc
         
         self.window = self.create_window ()
+        self.tree_window =self.create_tree_window ()
+
+    def tree_selection_changed (self, music_obj):
+        nc = self.notation_controller
+        nc.notation.set_cursor (music_obj)
+        self.notation_canvas_controller.check_update()
+        
+    def create_tree_window (self):
+        win = gtk.Window ()
+        (w,h) = (500,300)
+        win.set_size_request (w, h) 
+        
+        win.connect ('destroy', mainquit)
+        win.set_title ('Ikebana - music representation')
         
+        treeview = musictree.MusicTreeView (self.document.music)
+        win.add(treeview)
+        win.show()
+        treeview.selection_change_callback = self.tree_selection_changed
+
+        notation = self.notation_canvas_controller.notation
+        notation.set_cursor_callback = treeview.cursor_changed
+        
+        return win
+
     def create_window (self):
         win = gtk.Window ()
         win.connect ('destroy', mainquit)
index 14a767b80fd8a2aee4e309d8dc82774f2e1cf059..4db0b8e26af8e9bd76120e4761deecc4d666dcea 100644 (file)
--- a/music.py
+++ b/music.py
@@ -61,14 +61,16 @@ class Pitch:
        def steps (self):
                return self.step + self.octave * 7
        
-       def ly_expression (self):
-
+       def ly_step_expression (self): 
                str = 'cdefgab'[self.step]
                if self.alteration > 0:
                        str += 'is'* (self.alteration/2)
                elif self.alteration < 0:
                        str += 'es'* (-self.alteration/2)
-
+               return str
+       
+       def ly_expression (self):
+               str = self.ly_step_expression ()
                if self.octave >= 0:
                        str += "'" * (self.octave + 1) 
                elif self.octave < -1:
@@ -94,6 +96,15 @@ class Music:
        def get_properties (self):
                return ''
        
+       def has_children (self):
+               return False
+       
+       def get_index (self):
+               if self.parent:
+                       return self.parent.elements.index (self)
+               else:
+                       return None
+               
        def lisp_expression (self):
                name = self.name()
                tag = ''
@@ -128,7 +139,8 @@ class NestedMusic(Music):
        def __init__ (self):
                Music.__init__ (self)
                self.elements = [] 
-
+       def has_children (self):
+               return self.elements
        def set_tag (self, counter, dict):
                counter = Music.set_tag (self, counter, dict)
                for e in self.elements :
@@ -285,6 +297,54 @@ class NoteEvent(RhythmicEvent):
                return '%s%s' % (self.pitch.ly_expression (),
                                 self.duration.ly_expression ())
 
+
+
+class KeySignatureEvent (Event):
+       def __init__ (self, tonic, scale):
+               Event.__init__ (self)
+               self.scale = scale
+               self.tonic = tonic
+       def name (self):
+               return 'KeySignatureEvent'
+       def ly_expression (self):
+               return '\\key %s \\major' % self.tonic.ly_step_expression ()
+       
+       def lisp_expression (self):
+               pairs = ['(%d . %d)' % (i , self.scale[i]) for i in range (0,7)]
+               scale_str = ("'(%s)" % string.join (pairs))
+
+               return """ (make-music 'KeyChangeEvent
+          'pitch-alist %s) """ % scale_str
+
+class ClefEvent (Event):
+       def __init__ (self, t):
+               Event.__init__ (self)
+               self.type = t
+       def name (self):
+               
+               return 'ClefEvent'
+       def ly_expression (self):
+               return '\\clef "%s"' % self.type
+       clef_dict = {
+               "G": ("clefs.G", -2, -6),
+               "C": ("clefs.C", 0, 0),
+               "F": ("clefs.F", 2, 6),
+               }
+       
+       def lisp_expression (self):
+               (glyph, pos, c0) = self.clef_dict [self.type]
+               clefsetting = """
+               (make-music 'SequentialMusic
+               'elements (list
+      (context-spec-music
+       (make-property-set 'clefGlyph "%s") 'Staff)
+      (context-spec-music
+       (make-property-set 'clefPosition %d) 'Staff)
+      (context-spec-music
+       (make-property-set 'middleCPosition %d) 'Staff)))
+""" % (glyph, pos, c0)
+               return clefsetting
+
 def test_expr ():
        m = SequentialMusic()
        l =2 
@@ -302,7 +362,6 @@ def test_expr ():
        evc.insert_around (None, n, 0)
        m.insert_around (None, evc, 0)
 
-
        evc = EventChord()
        n = NoteEvent()
        n.duration.duration_log = l
@@ -310,15 +369,26 @@ def test_expr ():
        evc.insert_around (None, n, 0)
        m.insert_around (None, evc, 0)
 
+       evc = ClefEvent("G")
+       m.insert_around (None, evc, 0)
+
+       evc = EventChord()
+       tonic = Pitch ()
+       tonic.step = 2
+       tonic.alteration = -2
+       n = KeySignatureEvent(tonic, [0, 0, -2, 0, 0,-2,-2]  )
+       evc.insert_around (None, n, 0)
+       m.insert_around (None, evc, 0)
+
        return m
 
 
 if __name__ == '__main__':
        expr = test_expr()
        expr.set_start (Rational (0))
-
-       start = 0.25
-       stop = 0.5
+       print expr.ly_expression()
+       start = Rational (0,4)
+       stop = Rational (4,2)
        def sub(x, start=start, stop=stop):
                ok = x.start >= start and x.start +x.length() <= stop
                return ok
diff --git a/musictree.py b/musictree.py
new file mode 100644 (file)
index 0000000..29b7b09
--- /dev/null
@@ -0,0 +1,174 @@
+#!/usr/bin/env python
+'''Tree View/Generic Tree Model
+
+This test is designed to demonstrate creating a new type of tree model
+in python for use with the new tree widget in gtk 2.0.'''
+
+import gtk
+import gobject
+
+# to create a new GtkTreeModel from python, you must derive from
+# TreeModel.
+class MusicTreeModel(gtk.GenericTreeModel):
+    '''This class represents the model of a tree.  The iterators used
+    to represent positions are converted to python objects when passed
+    to the on_* methods.  This means you can use any python object to
+    represent a node in the tree.  The None object represents a NULL
+    iterator.
+
+    In this tree, we use simple tuples to represent nodes, which also
+    happen to be the tree paths for those nodes.  This model is a tree
+    of depth 3 with 5 nodes at each level of the tree.  The values in
+    the tree are just the string representations of the nodes.'''
+
+    def __init__(self, music):
+        '''constructor for the model.  Make sure you call
+        PyTreeModel.__init__'''
+        gtk.GenericTreeModel.__init__(self)
+       self.music = music
+       
+    # the implementations for TreeModel methods are prefixed with on_
+    def on_get_flags(self):
+        '''returns the GtkTreeModelFlags for this particular type of model'''
+        return 0
+
+    def on_get_n_columns(self):
+        '''returns the number of columns in the model'''
+        return 2
+
+    def on_get_column_type(self, index):
+        '''returns the type of a column in the model'''
+        return gobject.TYPE_STRING
+
+    def on_get_path(self, node):
+        '''returns the tree path(a tuple of indices at the various
+        levels) for a particular node.'''
+
+#      print 'on_get_path'  
+       if node.parent:
+               return tuple (list (self.on_get_path (node.parent))
+                             +
+                             [node.get_index ()])
+       else:
+               return (0,)
+               
+    def on_get_iter(self, path):
+        '''returns the node corresponding to the given path.  In our
+        case, the node is the path'''
+
+#      print 'on_get_iter'  , path
+
+       ptr = self.music
+       for i in path[1:]:
+               ptr = ptr.elements[i]
+               
+        return ptr
+
+    def on_get_value(self, node, column):
+        '''returns the value stored in a particular column for the node'''
+
+       str = ''
+       if column == 0:
+               str = node.name()
+       elif column==1:
+               str = node.ly_expression()
+               
+        return str
+
+    def on_iter_next(self, node):
+        '''returns the next node at this level of the tree'''
+#      print 'on_iter_next', node
+       if not node.parent:
+               return None 
+
+       neigh = node.parent.get_neighbor (node, 1)
+       if neigh <> node:
+               return neigh
+       else:
+               return None
+       
+    def on_iter_children(self, node):
+        '''returns the first child of this node'''
+#      print 'on_iter_children', node
+       if node.has_children ():
+               return node.elements[0]
+       else:
+               return None
+
+    def on_iter_has_child(self, node):
+        '''returns true if this node has children'''
+       hc = node.has_children ()
+       
+#      print node, 'has_child', hc
+
+       return hc
+
+    def on_iter_n_children(self, node):
+        '''returns the number of children of this node'''
+       assert  node <> None
+               
+#      print 'on_iter_n_children', node 
+
+       return len (node.elements)
+           
+    def on_iter_nth_child(self, node, n):
+        '''returns the nth child of this node'''
+        if node == None:
+            return self.music
+    
+#      print 'on_iter_nth_child', node , n
+
+        return node.elements[n]
+
+    def on_iter_parent(self, node):
+        '''returns the parent of this node'''
+       
+#      print 'on_iter_parent', node 
+
+       return node.parent
+
+class MusicTreeView(gtk.ScrolledWindow):
+    def __init__(self, music):
+        gtk.ScrolledWindow.__init__(self)
+        self.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
+
+        model = MusicTreeModel (music)
+       self.model = model
+        tree_view = gtk.TreeView(model)
+        cell = gtk.CellRendererText()
+       
+        # the text in the column comes from column 0
+        column = gtk.TreeViewColumn("Type", cell, text=0)
+        tree_view.append_column(column)
+        column = gtk.TreeViewColumn("Contents", cell, text=1)
+        tree_view.append_column(column)
+       self.tree_selection = tree_view.get_selection()
+
+        self.add(tree_view)
+        self.show_all()
+
+       self.tree_selection.connect ('changed', self.selection_changed)
+       self.selection_change_callback = None
+       
+    def selection_changed (self, a):
+           if self.selection_change_callback:
+                   (model, iter) = a.get_selected()
+                   path = model.get_path (iter)
+                   obj = model.on_get_iter (path)
+                   if obj.name() in ('RestEvent', 'NoteEvent'):
+                           self.selection_change_callback(obj)
+           
+    def select_music (self, music):
+           path = self.model.on_get_path (music)
+           self.tree_selection.select_path (path)
+           
+    def cursor_changed (self, notation):
+           self.select_music (notation.music_cursor)
+           
+def main():
+    GenericTreeModelDemo()
+    gtk.main()
+
+if __name__ == '__main__':
+    main()
+
index 5fa77eb264c437e7c4b0c2be839091eed63d48b0..457dd14ee9cc2d7a379f6044fa737399f47fb873 100644 (file)
@@ -25,18 +25,6 @@ time_sig = (4, 4)
 measure_length = Rational (time_sig[0], time_sig[1])
 measure_count = 4
 
-scale_str = ("'(%s)" % 
-             string.join (['(%d . %d)' % (i , scale_alterations[i]) for i in range (0,7)], ' '))
-
-"'((0 . 0) (1 . 0) (2 . -2) (3 . 0) (4 . 0) (5 . -2) (6 . -2))"
-clefsetting = """
-      (context-spec-music
-       (make-property-set 'clefGlyph "clefs.C") 'Staff)
-      (context-spec-music
-       (make-property-set 'clefPosition 0) 'Staff)
-      (context-spec-music
-       (make-property-set 'middleCPosition 0) 'Staff)
-"""
 
 try:
     server = os.environ['IKEBANASERVER']
@@ -78,18 +66,9 @@ def set_measure_number (str, num):
        (make-property-set 'beatLength (ly:make-moment 1 %d)) 'Score)
       (context-spec-music
        (make-property-set 'currentBarNumber %d) 'Score)
-      (context-spec-music
-       (make-music 'EventChord
-        'elements
-        (list
-         (make-music 'KeyChangeEvent
-          'pitch-alist
-          %s)
-         ))
-       'Staff)
-
+    
     %s))""" % (time_sig[0], time_sig[1], time_sig[0],
-               time_sig[1], time_sig[1], num, scale_str, str)
+               time_sig[1], time_sig[1], num, str)
 
 def render_score (filename, ly):
     print ly
@@ -162,6 +141,7 @@ class Notation_controller:
     def interpret_line (self, offset, cause, bbox, name, fields):
        notation_item = self.notation.add_item (offset, cause, bbox, fields)
         notation_item.name = name
+        
     def touch_document (self):
         self.document.touched = True
         
@@ -196,7 +176,7 @@ class Notation_controller:
         new_stop = new_start + Rational (measure_count) * measure_length
 
         if new_start <> self.start_moment or new_stop <> self.stop_moment:
-            print "render interval", new_start, new_stop
+#            print "render interval", new_start, new_stop
             self.touch_document()
             
         self.start_moment = new_start
@@ -234,6 +214,7 @@ class Notation:
        self.notation_controller = controller
         self.touched = True
         self.cursor_touched = True
+        self.cursor_callback = None
         
         toplevel = controller.document.music
         self.music_cursor = toplevel.find_first (lambda x: x.name()== "NoteEvent") 
@@ -269,11 +250,15 @@ class Notation:
 
         canvas.set_cursor_to_music (self.music_cursor)
         self.touched = False
-        
+
     def set_cursor (self, music_expr):
-        self.music_cursor = music_expr
-        self.cursor_touched = True
-        self.ensure_cursor_visible ()
+        if music_expr <> self.music_cursor:
+            self.music_cursor = music_expr
+            self.cursor_touched = True
+            self.ensure_cursor_visible ()
+            proc = self.set_cursor_callback
+            if proc:
+                proc (self)
         
     def cursor_move (self, dir):
         mus = self.music_cursor
@@ -481,6 +466,7 @@ class Notation:
                 arp = music.ArpeggioEvent()
                 par.insert_around (self.music_cursor, arp, -1)
             self.touch_document()
+            
     def print_score(self):
         doc = self.notation_controller.document
         ly = doc.music.ly_expression()
index 0b769ebdcf389a206a491b13eee6d90e95782fc9..24a965376af5a365ba91ee88c19ee66a3e8b00dc 100644 (file)
@@ -122,19 +122,19 @@ class Notation_toolbar (gtk.VBox):
                         ('Shift+B', '+B',
                          lambda: self.notation.add_step (6), 2),
                         ('c', 'C',
-                         lambda: self.notation.set_step (0), 3),
+                         lambda: self.notation.set_step (0), 2),
                         ('d', 'D',
-                         lambda: self.notation.set_step (1), 3),
+                         lambda: self.notation.set_step (1), 2),
                         ('e', 'E',
-                         lambda: self.notation.set_step (2), 3),
+                         lambda: self.notation.set_step (2), 2),
                         ('f', 'F',
-                         lambda: self.notation.set_step (3), 3),
+                         lambda: self.notation.set_step (3), 2),
                         ('g', 'G',
-                         lambda: self.notation.set_step (4), 3),
+                         lambda: self.notation.set_step (4), 2),
                         ('a', 'A',
-                         lambda: self.notation.set_step (5), 3),
+                         lambda: self.notation.set_step (5), 2),
                         ('b', 'B',
-                         lambda: self.notation.set_step (6), 3)]:
+                         lambda: self.notation.set_step (6), 2)]:
                        
                        self.add_button (text, key_name, func, row)
 
@@ -145,7 +145,7 @@ class Notation_canvas (gnomecanvas.Canvas):
                gnomecanvas.Canvas.__init__ (self,
                                             #aa=True
                                             )
-               (w,h) = (400,200)
+               (w,h) = (400,150)
                self.set_size_request (w, h) 
                self.set_scroll_region (0, 0, w, h)
                root = self.root ()