Here are three patches that together make the following improvements to the
user interface:

   - When starting a new selection within an event, any previous
   selection now clears correctly
   - MMB now starts a selection within an event
   - Shift+MMB adds to a selection within an event or moves the selection
   within an event:
      - If done on or before the beginning of the existing selection,
      stretches the selection from the left
      - If done on or after the end of the existing selection,
      stretches the selection from the right
      - If done amid the selection, drags the whole selection
         - Currently the drag starts with the end of the selection
         where the mouse clicks, but the drag should start with the
selection exactly
         where it is
         - Ctrl+{L|R}MB now deselects an event if it's already
   selected
   - Shift+{L|R}MB now selects all events from the most recently selected
   event to the currently clicked event. Can be combined with Ctrl+LMB

Patches are included as attachments, and affect Event.py, EventViewer.py,
and Instrument.py

Daniel
Index: /home/daniel/workspace/Jokosher/Jokosher/EventViewer.py
===================================================================
--- /home/daniel/workspace/Jokosher/Jokosher/EventViewer.py     (revision 1494)
+++ /home/daniel/workspace/Jokosher/Jokosher/EventViewer.py     (working copy)
@@ -104,6 +104,7 @@
                # Selections--marking part of the waveform. Don't confuse this 
with
                # self.event.isSelected, which means the whole waveform is 
selected.
                self.isSelecting = False                # True if a selection 
is currently being set
+               self.isDraggingSelection = False# True if a selection is 
currently being dragged
                self.isDraggingFade = False             # True if the user is 
dragging a fade marker
                self.lane = lane                                # The parent 
lane for this object
                self.currentScale = 0                   # Tracks if the project 
viewScale has changed
@@ -108,9 +109,9 @@
                self.lane = lane                                # The parent 
lane for this object
                self.currentScale = 0                   # Tracks if the project 
viewScale has changed
                self.redrawWaveform = False             # Force redraw the 
cached waveform on next expose event
-               self.drawerAlignToLeft = True           #boolean; if the drawer 
should be at the left of current selection
+               self.drawerAlignToLeft = True   #boolean; if the drawer should 
be at the left of current selection
                                                                        
#otherwise it will be put on the right
-               self.fadeMarkers = [100,100]            #the values of the 
right and left fade markers on the selection
+               self.fadeMarkers = [100,100]    #the values of the right and 
left fade markers on the selection
 
                # Set accessibility helpers
                self.SetAccessibleName()
@@ -540,6 +541,7 @@
                                
                                
                        self.highlightCursor = None
+               
                elif self.isSelecting:
                        x2 = max(0,min(self.allocation.width,mouse.x))
                        self.event.selection[1] = self.SecFromPixX(x2)
@@ -556,6 +558,26 @@
                        #move the drawer to its proper position
                        self.UpdateDrawerPosition(selection_direction == "rtol")
                        
+               elif self.isDraggingSelection:
+                       #temp variable to keep track of length moved
+                       selectionDuration = 
self.PixXFromSec(self.event.selection[1] - self.event.selection[0])
+                       x1 = 
max(selectionDuration,min(self.allocation.width,mouse.x))#(mouse.x - 
mousedelta1)
+                       x0 = x1 - selectionDuration#(mouse.x - mousedelta0)
+                       self.event.selection[1] = self.SecFromPixX(x1)
+                       self.event.selection[0] = self.SecFromPixX(x0)
+                       self.UpdateFadeMarkers()
+                                               
+                       selection_direction = "ltor"
+                       selection = self.event.selection
+                       if selection[0] > selection[1]:
+                               selection_direction = "rtol"
+                               self.fadeMarkers.reverse()
+                       
+                       #set the drawer align position
+                       self.drawerAlignToLeft = (selection_direction == "rtol")
+                       #move the drawer to its proper position
+                       self.UpdateDrawerPosition(selection_direction == "rtol")
+                       
                else:
                        self.highlightCursor = mouse.x
                
@@ -570,8 +592,11 @@
                Possible click combinations to capture:
                        {L|R}MB: deselect all Events, remove any existing 
selection in
                                        this Event then select this Event and 
begin moving the Event.
-                       LMB+shift: remove any existing selection in this Event 
and begin
-                                       selecting part of this Event.
+                       MMB: remove any existing selection in this Event and 
begin selecting
+                                       part of this Event.
+                       MMB+shift: continue selecting in addition to an already 
selected part
+                                       of this Event.
+                       {L|R}MB+shift: select everything from last selected 
Event to this Event
                        {L|R}MB+ctrl: select this Event without deselecting 
other Events.
                        RMB: display a context menu.
                        LMB double-click: split this Event here.
@@ -592,13 +617,38 @@
                
                # {L|R}MB: deselect all events, select this event, begin moving 
the event
                # {L|R}MB+ctrl: select this event without deselecting other 
events
-               if 'GDK_CONTROL_MASK' not in mouse.state.value_names:
+               # {L|R}MB+shift: select all events from this one to last 
selected
+               if ('GDK_CONTROL_MASK' not in mouse.state.value_names) & 
('GDK_SHIFT_MASK' not in mouse.state.value_names):
                        self.project.ClearEventSelections()
                        self.project.SelectInstrument(None)
-               self.event.SetSelected(True)
-               
+                       self.event.SetSelected(True)
+               elif 'GDK_SHIFT_MASK' not in mouse.state.value_names:
+                       #deselect previously selected events
+                       if self.event.isSelected == True:
+                               self.event.SetSelected(False)
+                       else:
+                               self.event.SetSelected(True)
+               elif 'GDK_SHIFT_MASK' in mouse.state.value_names:
+                       #CTRL+SHIFT: add everything from last selected to self 
to selection
+                       #SHIFT: everything from last selected to self becomes 
the selection 
+                       if self.event.instrument.orderSelected == []:
+                               startSel = 
self.event.instrument.events.index(self.event) #If no event selected, select 
clicked
+                       else:
+                               startSel = 
self.event.instrument.orderSelected[-1] #Begin shift-selection at last part of 
orderSelected
+                       endSel = self.event.instrument.events.index(self.event) 
#End shift-selection at event clicked
+                       if 'GDK_CONTROL_MASK' not in mouse.state.value_names:
+                               self.project.ClearEventSelections()
+                               self.project.SelectInstrument(None)
+                       #select everything from startSel to endSel
+                       if endSel >= startSel:
+                               for i in range (startSel, endSel+1):
+                                       
self.event.instrument.events[i].SetSelected(True)
+                       else:
+                               for i in range (startSel, endSel-1, -1):
+                                       
self.event.instrument.events[i].SetSelected(True)
+       
                #Don't allow editing while playing back.
-               #It must be here to avoid afecting the selection behavior
+               #It must be here to avoid affecting the selection behavior
                if self.mainview.isPlaying or self.mainview.isPaused:
                        return True
                
@@ -605,6 +655,32 @@
                # RMB: context menu
                if mouse.button == 3:
                        self.ContextMenu(mouse)
+               
+               # MMB: selecting part of this event     
+               elif mouse.button == 2:
+                       if 'GDK_SHIFT_MASK' not in mouse.state.value_names:
+                               # Remove any existing selection in this event, 
if 
+                               #   MMB is pressed without shift.
+                               self.event.selection[0] = 
self.SecFromPixX(mouse.x)
+                               self.event.selection[1] = 
self.SecFromPixX(mouse.x)
+                               self.isSelecting = True
+                               self.fadeMarkers = [100,100] 
+                       else: #if shift is on
+                               #If cursor is on or before selection, drag the 
leftmost portion of selection 
+                               if (self.SecFromPixX(mouse.x) <= 
self.event.selection[0]) & (self.SecFromPixX(mouse.x) <= 
self.event.selection[1]):
+                                       self.event.selection[0] = 
self.event.selection[1]
+                                       self.isSelecting = True
+                               #If cursor is amid selection, move the whole 
selection
+                               elif self.event.selection[0] < 
self.SecFromPixX(mouse.x) < self.event.selection[1]:
+                                       
+                                       self.isDraggingSelection = True
+                               #If cursor is on or after selection, drag the 
rightmost portion of selection
+                               else:
+                                       self.isSelecting = True
+                       
+                       if not self.selmessageID: 
+                               self.selmessageID = 
self.mainview.SetStatusBar(_("<b>Click</b> the buttons below the selection to 
do something to that portion of audio."))
+                       
                elif mouse.button == 1:
                        # check to see if the user clicked on the cancel button
                        if self.cancelButtonArea.x <= mouse.x <= 
self.cancelButtonArea.width+self.cancelButtonArea.x \
@@ -613,46 +689,37 @@
                                self.OnDelete()
                                return True
                        
-                       if 'GDK_SHIFT_MASK' in mouse.state.value_names:
-                               # LMB+shift: remove any existing selection in 
this event, begin 
-                               #   selecting part of this event
-                               self.isSelecting = True
-                               self.event.selection[0] = 
self.SecFromPixX(mouse.x)
-                               self.fadeMarkers = [100,100]
-                               if not self.selmessageID: 
-                                       self.selmessageID = 
self.mainview.SetStatusBar(_("<b>Click</b> the buttons below the selection to 
do something to that portion of audio."))
-                       else:
-                               if self.fadeMarkersContext and 
self.fadeMarkersContext.in_fill(mouse.x, mouse.y):
-                                       # LMB over a fadeMarker: drag that 
marker
-                                       self.isDraggingFade = True
-                                       if mouse.x > 
self.PixXFromSec(self.event.selection[1]) - self._PIXX_FADEMARKER_WIDTH - 1:
-                                               self.fadeBeingDragged = 1
-                                               return True
-                                       else:
-                                               self.fadeBeingDragged = 0
-                                               return True
-                               if mouse.type == gtk.gdk._2BUTTON_PRESS:
-                                       # LMB double-click: split here
-                                       self.mouseAnchor[0] = mouse.x
-                                       if self.event.isLoading == False:
-                                               self.OnSplit(None, mouse.x)
+                       if self.fadeMarkersContext and 
self.fadeMarkersContext.in_fill(mouse.x, mouse.y):
+                               # LMB over a fadeMarker: drag that marker
+                               self.isDraggingFade = True
+                               if mouse.x > 
self.PixXFromSec(self.event.selection[1]) - self._PIXX_FADEMARKER_WIDTH - 1:
+                                       self.fadeBeingDragged = 1
+                                       return True
+                               else:
+                                       self.fadeBeingDragged = 0
                                        return True
+                       if mouse.type == gtk.gdk._2BUTTON_PRESS:
+                               # LMB double-click: split here
+                               self.mouseAnchor[0] = mouse.x
+                               if self.event.isLoading == False:
+                                       self.OnSplit(None, mouse.x)
+                               return True
                                
-                               # remove any existing selection in this event
-                               self.event.selection = [0,0]
-                               if self.drawer.parent == self.lane.fixed:
-                                       self.lane.fixed.remove(self.drawer)
-                                       if self.volmessageID:   #clesr status 
bar if not already clear
-                                               
self.mainview.ClearStatusBar(self.volmessageID)
-                                               self.volmessageID = None
-                                       if self.selmessageID:   #clesr status 
bar if not already clear
-                                               
self.mainview.ClearStatusBar(self.selmessageID)
-                                               self.selmessageID = None        
-                               self.isDragging = True
+                       # remove any existing selection in this event
+                       self.event.selection = [0,0]
+                       if self.drawer.parent == self.lane.fixed:
+                               self.lane.fixed.remove(self.drawer)
+                               if self.volmessageID:   #clesr status bar if 
not already clear
+                                       
self.mainview.ClearStatusBar(self.volmessageID)
+                                       self.volmessageID = None
+                               if self.selmessageID:   #clesr status bar if 
not already clear
+                                       
self.mainview.ClearStatusBar(self.selmessageID)
+                                       self.selmessageID = None        
+                       self.isDragging = True
                                
-                               self.eventStart = self.event.start
-                               ptr = 
gtk.gdk.display_get_default().get_pointer()
-                               self.mouseAnchor = [ptr[1], ptr[2]]
+                       self.eventStart = self.event.start
+                       ptr = gtk.gdk.display_get_default().get_pointer()
+                       self.mouseAnchor = [ptr[1], ptr[2]]
        
                return True
 
@@ -957,6 +1024,14 @@
                        elif self.isSelecting:
                                self.isSelecting = False
                                self.ShowDrawer()
+               elif mouse.button == 2:
+               #For MMB selections
+                       if self.isSelecting:
+                               self.isSelecting = False
+                               self.ShowDrawer()
+                       elif self.isDraggingSelection:
+                               self.isDraggingSelection = False
+                               self.ShowDrawer()
 
        #_____________________________________________________________________
 
Index: /home/daniel/workspace/Jokosher/Jokosher/Instrument.py
===================================================================
--- /home/daniel/workspace/Jokosher/Jokosher/Instrument.py      (revision 1494)
+++ /home/daniel/workspace/Jokosher/Jokosher/Instrument.py      (working copy)
@@ -110,6 +110,7 @@
                self.isSolo = False                     # True if the 
instrument is solo'd (only instrument active)
                self.isVisible = True                   # True if the 
instrument should be displayed in the mixer views
                self.isSelected = False         # True if the instrument is 
currently selected
+               self.orderSelected = []         # The order in which events 
were selected (Used for shift-selection of events)
                
                self.level = 0.0                                # Current audio 
level in range 0..1
                self.volume = 1.0                       # Gain of the current 
instrument in range 0..1
Index: /home/daniel/workspace/Jokosher/Jokosher/Event.py
===================================================================
--- /home/daniel/workspace/Jokosher/Jokosher/Event.py   (revision 1494)
+++ /home/daniel/workspace/Jokosher/Jokosher/Event.py   (working copy)
@@ -840,10 +840,14 @@
                # No need to emit a signal when there is no change in selection 
state
                if self.isSelected is not sel:
                        self.isSelected = sel
+                       if sel == True:
+                               
self.instrument.orderSelected.append(self.instrument.events.index(self))
+                       else:
+                               
self.instrument.orderSelected.remove(self.instrument.events.index(self))
                        self.emit("selected")
        
        #_____________________________________________________________________
-       
+
        def MayPlace(self, xpos):
                """
                Checks if this event could be placed at xpos without 
_______________________________________________
jokosher-devel-list mailing list
jokosher-devel-list@gnome.org
http://mail.gnome.org/mailman/listinfo/jokosher-devel-list

Reply via email to