*** empty log message ***
authorca
Thu, 05 Dec 2002 16:20:16 +0100
changeset 2398 bea17c9648e4
parent 2397 80f824a988c3
child 2399 949ec827ab3a
*** empty log message ***
DSVColumnView.st
--- a/DSVColumnView.st	Thu Nov 28 18:51:39 2002 +0100
+++ b/DSVColumnView.st	Thu Dec 05 16:20:16 2002 +0100
@@ -17,7 +17,8 @@
 
 View subclass:#DSVColumnView
 	instanceVariableNames:'labelView listHolder editValue editView multipleSelectOk useIndex
-		selectedColIndex selectedRowIndex selectRowOnDefault rowHeight
+		selectedColIndex selectedRowIndex selectRowOnDefault
+		buttonMotionAction buttonReleaseAction rowHeight
 		columnDescriptors viewOrigin colorMap rowFontAscent lockRowIndex
 		rowIfAbsentBlock columnHolder registererImages list fgColor
 		separatorSize catchChangeEvents beDependentOfRows bgColor
@@ -26,11 +27,11 @@
 		buttonLightColor buttonShadowColor buttonHalfLightColor
 		buttonHalfShadowColor checkToggleExtent checkToggleForm
 		checkToggleActiveImage checkTogglePassiveImage checkToggleLevel
-		comboButtonExtent comboButtonForm comboButtonLevel clickPosition
-		dragAccessPoint dragIsActive dropTarget dropSource columnAdaptor
-		tabAtEndAction tabAtStartAction modifiedChannel autoScroll
-		autoScrollBlock needFitColumns scrollWhenUpdating
-		selectionForegroundColor selectionBackgroundColor previousExtent'
+		comboButtonExtent comboButtonForm comboButtonLevel dropTarget
+		dropSource columnAdaptor tabAtEndAction tabAtStartAction
+		modifiedChannel autoScroll autoScrollBlock needFitColumns
+		scrollWhenUpdating selectionForegroundColor
+		selectionBackgroundColor previousExtent'
 	classVariableNames:'DefaultForegroundColor DefaultBackgroundColor
 		DefaultHilightForegroundColor DefaultHilightBackgroundColor
 		ButtonLightColor ButtonShadowColor CheckToggleActiveImage
@@ -70,6 +71,10 @@
         editValue               <Model>                 current editing model
         editView                <View>                  current editing component
 
+        buttonReleaseAction     <Action or nil>         called if the mouse button is released
+        buttonMotionAction      <Action or nil>         called during mouse motion with one
+                                                        argument the point under the mouse.
+
         multipleSelectOk        <Boolean>               multiple selection enabled/disabled
 
         selectedColIndex        <Integer>               selected column index or 0
@@ -140,10 +145,6 @@
         comboButtonExtent       <Point>                 extent of a comboList or -Box
         comboButtonLevel        <SmallInteger>          level used to draw a comboList or -Box
 
-        clickPosition           <Point>                 click position of the mouse
-
-        dragAccessPoint         <Point>                 point where the drag operation starts
-        dragIsActive            <Boolean>               true if a drag operation is active
         dropTarget              <DropTarget>            drag & drop target
         dropSource              <DropSource>            drag & drop source
 
@@ -155,7 +156,6 @@
         DataSetColumn
         DataSetView
 "
-
 ! !
 
 !DSVColumnView class methodsFor:'accessing forms'!
@@ -1514,11 +1514,11 @@
 !
 
 startDragAt:aPoint
-    (dragIsActive not and:[dropSource notNil]) ifTrue:[
-        dragIsActive := true.
-        dropSource startDragIn:self at:aPoint
+
+    dropSource notNil ifTrue:[
+        dropSource startDragIn:self at:aPoint.
+        buttonReleaseAction := buttonMotionAction := nil.
     ]
-
 ! !
 
 !DSVColumnView methodsFor:'drawing'!
@@ -1866,81 +1866,85 @@
 
 !DSVColumnView methodsFor:'event handling'!
 
+buttonControlPressAtRowNr:aStartRow
+    |isSelected prvRow doAdd chgSet|
+
+    buttonMotionAction := nil.
+    isSelected         := self isInSelection:aStartRow.
+
+    isSelected ifTrue:[ self removeRowFromSelection:aStartRow ]
+              ifFalse:[ self addRowToSelection:aStartRow ].
+
+    multipleSelectOk ifFalse:[ ^ self ].
+
+    prvRow := aStartRow.
+    chgSet := IdentitySet new.
+    doAdd  := isSelected not.
+
+    buttonMotionAction := [:p| |rowNr mustRestore step f|
+        rowNr := self yVisibleToRowNr:(p y).
+
+        (rowNr notNil and:[rowNr ~~ prvRow]) ifTrue:[
+            rowNr == aStartRow ifTrue:[
+                mustRestore := true
+            ] ifFalse:[
+                rowNr > aStartRow ifTrue:[ mustRestore := (rowNr < prvRow) ]
+                                 ifFalse:[ mustRestore := (rowNr > prvRow) ].
+            ].
+            prvRow > rowNr ifTrue:[ step := -1 ]
+                          ifFalse:[ step :=  1 ].
+            mustRestore ifTrue:[
+                [ prvRow ~~ rowNr ] whileTrue:[
+                    (chgSet removeIdentical:prvRow ifAbsent:nil) notNil ifTrue:[
+                        doAdd ifFalse:[ self addRowToSelection:prvRow ]
+                               ifTrue:[ self removeRowFromSelection:prvRow ].
+                    ].
+                    prvRow := prvRow + step.
+                ].
+            ] ifFalse:[
+                [ prvRow ~~ rowNr ] whileTrue:[
+                    prvRow := prvRow + step.
+
+                    doAdd ~~ (self isInSelection:rowNr) ifTrue:[
+                        chgSet add:prvRow.
+
+                        doAdd ifTrue:[ self addRowToSelection:prvRow ]
+                             ifFalse:[ self removeRowFromSelection:prvRow ].
+                    ]
+                ].
+            ].
+        ].
+    ].
+!
+
 buttonMotion:buttonMask x:x y:y
     "mouse-move while button was pressed - handle multiple selection changes
     "
-    |lnNr p oldSelection step|
-
-    buttonMask = 0 ifTrue:[
-        dragAccessPoint := nil.
-        dragIsActive := false.
-    ].
-
     self isEnabled ifFalse:[^ self].
 
-    dragAccessPoint notNil ifTrue:[
-        dragIsActive ifFalse:[
-            p := x @ y.
-            (clickPosition dist:p) > 5.0 ifTrue:[ self startDragAt:p ]
-        ].
-        ^ self
-    ].
-    self sensor ctrlDown ifTrue:[^ self ].
-
-    (multipleSelectOk and:[selectedColIndex == 0 and:[selectedRowIndex notNil]]) ifFalse:[
-        ^ self
-    ].
-    "is it the select or 1-button ?"
-
-    self sensor leftButtonPressed ifFalse:[^ self].
-
-    autoScroll ifTrue:[
-        "/ if moved outside of view, start autoscroll
-        (y < 0) ifTrue:[
-            ^ self startAutoScroll:[self scrollUp] distance:y.
-        ].
-        (y > height) ifTrue:[
-            ^ self startAutoScroll:[self scrollDown] distance:(y - height).
-        ].
-    ].
-
-    "move inside - stop autoscroll if any"
-    self stopAutoScroll.
-
-    y > height ifTrue:[
-        lnNr := self yVisibleToRowNr:(height + rowHeight).
-    ] ifFalse:[
-        y < 0 ifTrue:[
-            lnNr := self yVisibleToRowNr:(rowHeight negated).
-        ] ifFalse:[
-            lnNr := self yVisibleToRowNr:y.
+    buttonMotionAction notNil ifTrue:[
+        buttonMotionAction value:(x@y).
+
+        buttonMotionAction notNil ifTrue:[
+            autoScroll ifTrue:[
+                "/ if moved outside of view, start autoscroll
+                (y < 0) ifTrue:[
+                    ^ self startAutoScroll:[self scrollUp] distance:y.
+                ].
+                (y > height) ifTrue:[
+                    ^ self startAutoScroll:[self scrollDown] distance:(y - height).
+                ].
+            ]
         ]
     ].
-
-    (lnNr isNil or:[lnNr < 1]) ifTrue:[
-        ^ self
-    ].
-
-    oldSelection     := selectedRowIndex asOrderedCollection.
-    selectedRowIndex := OrderedCollection new.
-
-    clickPosition isNil ifTrue:[
-        clickPosition := oldSelection at:1 ifAbsent:lnNr
-    ].
-
-    step := lnNr < clickPosition ifTrue:[-1] ifFalse:[1].
-
-    clickPosition to:lnNr by:step do:[:i|
-        selectedRowIndex add:i.
-        oldSelection removeIdentical:i ifAbsent:[ self invalidateRowAt:i colAt:0 ].
-    ].
-    oldSelection do:[:i| self invalidateRowAt:i colAt:0 ].
-    self scrollToRowAt:lnNr colAt:0.
+    self stopAutoScroll.
 !
 
 buttonMultiPress:button x:x y:y
     "a button was pressed twice - handle doubleclick here
     "
+    buttonMotionAction := buttonReleaseAction := nil.
+
     self isEnabled ifFalse:[^ self].
 
     ((button == 1) or:[button == #select]) ifFalse:[
@@ -1960,97 +1964,80 @@
 buttonPress:button x:x y:y
     "a button was pressed - handle selection here
     "
-    |rowNr colNr menu sz first sensor|
+    |rowNr colNr menu sensor clickPoint|
+
+    buttonMotionAction := buttonReleaseAction := nil.
 
     self isEnabled ifFalse:[^ self].
 
     sensor := self sensor.
-
-    clickPosition   := nil.
-    dragAccessPoint := nil.
-    dragIsActive    := false.
+    sensor isNil ifTrue:[^ self].
 
     ((button == 2) or:[button == #menu]) ifTrue:[
-        (menu := self findMenuForSelection) notNil ifTrue:[
-            ^ self startUpMenu:menu
-        ]
-    ] ifFalse:[
-        (     (button == 1 or:[button == #select])
-         and:[(rowNr := self yVisibleToRowNr:y) notNil
-         and:[(colNr := self xVisibleToColNr:x) notNil]]
-        ) ifTrue:[
-            multipleSelectOk ifTrue:[
-                sensor ctrlDown ifTrue:[
-                    "/ toggle
-                    selectedColIndex ~~ 0 ifTrue:[
-                        colNr := 0
-                    ] ifFalse:[
-                        (sz := self numberOfSelections == 0) ifFalse:[
-                            (self isInSelection:rowNr) ifTrue:[
-                                sz == 1 ifTrue:[
-                                    self selectColIndex:0 rowIndex:nil.
-                                    sensor flushMotionEventsFor:self.
-                                    ^ self    
-                                ].
-                                selectedRowIndex remove:rowNr.
-                            ] ifFalse:[
-                                selectedRowIndex add:rowNr
-                            ].
-                            self invalidateRowAt:rowNr.
-                            self selectionChanged.
-                            sensor flushMotionEventsFor:self.
-                            ^ self
-                        ]
-                    ]
-                ] ifFalse:[
-                    "/ range
-                    (     selectedColIndex == 0
-                     and:[(first := self firstIndexSelected) ~~ 0
-                     and:[sensor shiftDown]]
-                    ) ifTrue:[|step list|
-                        list := OrderedCollection new.
-                        step := first < rowNr ifTrue:[1] ifFalse:[-1].
-                        first to:rowNr by:step do:[:i|list add:i].
-                        self selectedRowIndex:list.
-                        ^ self.
-                    ]
-                ]
-            ].
-            (self canDrag and:[self isSelected:rowNr inColumn:colNr]) ifTrue:[
-                clickPosition   := x @ y.
-                dragAccessPoint := (colNr @ rowNr).
-            ] ifFalse:[
-                self withWaitCursorDo:[
-                    self selectRowAt:rowNr colAt:colNr atPoint:(x @ y)
-                ]
-            ].
-            ^ self
+        menu := self findMenuForSelection.
+
+        menu notNil ifTrue:[ self startUpMenu:menu ]
+                   ifFalse:[ super buttonPress:button x:x y:y ].
+        ^ self
+    ].
+
+    (     (rowNr := self yVisibleToRowNr:y) notNil
+     and:[(colNr := self xVisibleToColNr:x) notNil]
+    ) ifFalse:[
+        super buttonPress:button x:x y:y.
+        ^ self
+    ].
+
+    sensor ctrlDown ifTrue:[
+        self buttonControlPressAtRowNr:rowNr.
+        ^ self
+    ].
+
+    sensor shiftDown ifTrue:[
+        (multipleSelectOk and:[selectedRowIndex size ~~ 0]) ifTrue:[
+            self selectRowFrom:(selectedRowIndex min min:rowNr)
+                            to:(selectedRowIndex max max:rowNr).
+        ] ifFalse:[
+            self selectColIndex:0 rowIndex:rowNr.
+        ].
+        ^ self
+    ].
+
+    (self canDrag and:[self isSelected:rowNr inColumn:colNr]) ifTrue:[
+        clickPoint := x @ y.
+        buttonReleaseAction := [ self selectRowAt:rowNr colAt:colNr atPoint:(x @ y) ].
+
+        buttonMotionAction := [:aPoint|
+            (clickPoint dist:aPoint) > 5.0 ifTrue:[
+                buttonReleaseAction := buttonMotionAction := nil.
+                self startDragAt:aPoint.
+            ]
+        ].
+        ^ self.
+    ].
+
+    self withWaitCursorDo:[
+        self selectRowAt:rowNr colAt:colNr atPoint:(x @ y)
+    ].
+
+    (multipleSelectOk and:[selectedColIndex == 0 and:[selectedRowIndex size == 1]]) ifTrue:[
+        buttonMotionAction := [:p| |r|
+            r := self yVisibleToRowNr:(p y).
+            r notNil ifTrue:[ self selectRowFrom:rowNr to:r ].
         ]
     ].
-    super buttonPress:button x:x y:y
 !
 
 buttonRelease:button x:x y:y
 
+    buttonMotionAction := nil.
     self stopAutoScroll.
 
-    clickPosition notNil ifTrue:[
-        dragAccessPoint notNil ifTrue:[
-            dragIsActive ifFalse:[
-                self selectRowAt:(dragAccessPoint y)
-                           colAt:(dragAccessPoint x)
-                         atPoint:clickPosition
-            ].
-            dragAccessPoint := nil.
-            dragIsActive := false.
-        ] ifFalse:[
-            self selectionChanged
-        ].        
-        clickPosition := nil.
+    buttonReleaseAction notNil ifTrue:[
+        buttonReleaseAction value.
+        buttonReleaseAction := nil.
     ].
     super buttonRelease:button x:x y:y
-
-
 !
 
 characterPress:aChar x:x y:y
@@ -2542,7 +2529,6 @@
     horizontalSpacing  := self class horizontalSpacing.
     colorMap           := Dictionary new.
     catchChangeEvents  := false.
-    dragIsActive       := false.
     rowFontAscent      := 1.                            "/ dummy initialization
     separatorSize      := 1.                            "/ separators mode 2D
     selectRowOnDefault := true.
@@ -2841,11 +2827,14 @@
 yVisibleToRowNr:y
     "returns the row number assigned to a physical y or nil
     "
-    |y0|
-
-    y0 := (y + viewOrigin y - margin) // rowHeight + 1.
-  ^ (y0 <= list size) ifTrue:[y0] ifFalse:[nil]
-
+    |rowNr|
+
+    rowNr := (y + viewOrigin y - margin) // rowHeight + 1.
+
+    (rowNr between:1 and:(list size)) ifTrue:[
+        ^ rowNr
+    ].
+    ^ nil
 ! !
 
 !DSVColumnView methodsFor:'queries'!
@@ -3258,25 +3247,25 @@
     "
     |newSelection|
 
-    multipleSelectOk ifFalse:[^ self].
-
-    selectedRowIndex size == 0 ifTrue:[
-        self selectedRowIndex:aRowNr.
+    self numberOfSelections == 0 ifTrue:[
+        self selectColIndex:0 rowIndex:aRowNr.
         ^ self
     ].
-    (selectedRowIndex includesIdentical:aRowNr) ifTrue:[
+    (self isInSelection:aRowNr) ifTrue:[^ self].
+
+    multipleSelectOk ifFalse:[
+        self selectColIndex:0 rowIndex:aRowNr.    
         ^ self
     ].
     newSelection := selectedRowIndex copyWith:aRowNr.
 
     selectedColIndex ~~ 0 ifTrue:[
-        "/ there is a column selected (including an editor..)
         self selectColIndex:0 rowIndex:newSelection.
-        ^ self
+    ] ifFalse:[
+        selectedRowIndex := selectedRowIndex copyWith:aRowNr.
+        self invalidateRowAt:aRowNr.
+        self selectionChanged.
     ].
-    selectedRowIndex := newSelection.
-    self invalidateRowAt:aRowNr colAt:0.
-    self selectionChanged.
 !
 
 deselect
@@ -3456,6 +3445,20 @@
     ^ selectedRowIndex size
 !
 
+removeRowFromSelection:aRowNr
+    "remove a row from the selection
+    "
+    (self isInSelection:aRowNr) ifFalse:[^ self].
+
+    self numberOfSelections == 1 ifTrue:[
+        self deselect.
+    ] ifFalse:[
+        selectedRowIndex := selectedRowIndex copyWithout:aRowNr.
+        self invalidateRowAt:aRowNr.
+        self selectionChanged.
+    ].
+!
+
 selectAllRows
     "select all
     "
@@ -3503,6 +3506,46 @@
     ].
 !
 
+selectRowFrom:start to:stop
+    |step oldSelect newSelect|
+
+    start == stop ifTrue:[
+        self selectColIndex:0 rowIndex:start.
+        ^ self
+    ].
+
+    start <= stop ifTrue:[ step :=  1 ]
+                 ifFalse:[ step := -1 ].
+
+    newSelect := OrderedCollection new.
+    start to:stop by:step do:[:i| newSelect add:i ].
+
+    selectedColIndex ~~ 0 ifTrue:[
+        newSelect := OrderedCollection new.
+        start to:stop by:step do:[:i| newSelect add:i ].
+        self selectColIndex:0 rowIndex:newSelect.
+        ^ self
+    ].
+    oldSelect := selectedRowIndex ? #().
+    selectedRowIndex := OrderedCollection new.
+
+    start to:stop by:step do:[:i|
+        selectedRowIndex add:i.
+
+        (oldSelect includesIdentical:i) ifFalse:[
+            self invalidateRowAt:i    
+        ].
+    ].
+
+    oldSelect do:[:i|
+        (selectedRowIndex includesIdentical:i) ifFalse:[
+            self invalidateRowAt:i
+        ]
+    ].
+        
+    self selectionChanged.
+!
+
 selectRowIndex:something
     "set selection of rows
     "
@@ -3789,5 +3832,5 @@
 !DSVColumnView class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libwidg2/DSVColumnView.st,v 1.159 2002-11-12 08:27:20 ca Exp $'
+    ^ '$Header: /cvs/stx/stx/libwidg2/DSVColumnView.st,v 1.160 2002-12-05 15:20:16 ca Exp $'
 ! !