optimize redraw routine
authorca
Thu, 19 Feb 1998 10:35:34 +0100
changeset 769 15fafccfed86
parent 768 5fa51db3bdb5
child 770 f197d1f5a246
optimize redraw routine
SelTreeV.st
SelectionInTreeView.st
--- a/SelTreeV.st	Wed Feb 18 23:13:49 1998 +0100
+++ b/SelTreeV.st	Thu Feb 19 10:35:34 1998 +0100
@@ -496,31 +496,67 @@
 !SelectionInTreeView methodsFor:'drawing basics'!
 
 drawFromVisibleLine:startVisLineNr to:endVisLineNr with:fg and:bg
+    "redraw a visible line range with clearing the background
+    "
+    |y0 y1 sz|
 
-    |size end index yBot yTop yCtr level figWidthDiv2
-     x xFig xStr node lv idx image xCross|
+    shown ifTrue:[
+        y0  := self yOfVisibleLine:startVisLineNr.
+        y0  := y0 - 1.
+        sz  := endVisLineNr - startVisLineNr + 1.
+        y1  := sz * fontHeight.
+
+    "/  clear rectangle line and set background color
+        self paint:bg.
+        self fillRectangleX:0 y:y0 width:width height:y1.
+
+        (y1 := self visibleLineToAbsoluteLine:startVisLineNr) notNil ifTrue:[
+            self redrawLinesX:0 y:y0 toX:width start:y1 stop:(y1 + sz)
+        ]
+    ]
+!
+
+drawLabelIndex:anIndex atX:x y:yCenter
+    "draw text label at x and y centered
+    "
+    |lbl|
+
+    (lbl := (listOfNodes at:anIndex) name) notNil ifTrue:[
+        self displayOpaqueString:lbl x:x y:(yCenter + labelOffsetY).
+    ]    
+!
+
+redrawLinesX:x0 y:y0 toX:x1 start:start stop:stop
+    "redraw from line to line without clearing the background
+    "
+    |chgdPaint node image isSelected
+     x      "{ Class:SmallInteger }"
+     yTop   "{ Class:SmallInteger }"
+     yBot   "{ Class:SmallInteger }"
+     yCtr   "{ Class:SmallInteger }"
+     size   "{ Class:SmallInteger }"
+     end    "{ Class:SmallInteger }"
+     index  "{ Class:SmallInteger }"
+     xCross "{ Class:SmallInteger }"
+     xFig   "{ Class:SmallInteger }"
+     xStr   "{ Class:SmallInteger }"
+     idx    "{ Class:SmallInteger }"
+     level  "{ Class:SmallInteger }"
+     lv     "{ Class:SmallInteger }"
+     figWidthDiv2 "{ Class:SmallInteger }"
+    |
 
     level := nil. "/ to force evaluation of #ifFalse in loop
-
-    index := self visibleLineToAbsoluteLine:startVisLineNr.
+    yTop  := y0.
+    index := start.
     size  := listOfNodes size.
-    yTop  := self yOfVisibleLine:startVisLineNr.
-    yTop  := yTop - 1.
-    end   := endVisLineNr - startVisLineNr + 1.
+    end   := stop min:size.
 
-"/  clear rectangle line and set background color
-    self paint:bg.
-    self fillRectangleX:0 y:yTop width:width height:(end * fontHeight).
-
-    index isNil ifTrue:[^ self].
     figWidthDiv2 := imageWidth // 2.
     figWidthDiv2 odd ifTrue:[figWidthDiv2 := figWidthDiv2 + 1].
     yCtr := yTop - (fontHeight // 2).
 
-    self paint:fg on:bg.
-    (end := index + end) > size ifTrue:[end := size + 1].
-
-    [index < end] whileTrue:[
+    [index <= end] whileTrue:[
         node := listOfNodes at:index.
         yBot := yTop + fontHeight.
         yCtr := yCtr + fontHeight.
@@ -532,43 +568,78 @@
             xCross := (self xOfFigureLevel:(lv-1)) + figWidthDiv2.
         ].
 
+        (isSelected := self isInSelection:index) ifTrue:[
+            self paint:hilightFgColor on:hilightBgColor.
+        ] ifFalse:[
+            self paint:fgColor on:bgColor.
+        ].
+
         showLines ifTrue:[
-            (lineColor isNil or:[(self isInSelection:index)]) ifFalse:[
+            chgdPaint := (lineColor isNil or:[isSelected]) not.
+
+            chgdPaint ifTrue:[
                 self paint:lineColor.
             ].
+
             self mask:lineMask.
             self setMaskOrigin:(self viewOrigin + (0 @ 1) \\ (lineMask extent)).
 
-            (node isCollapsable and:[node numberOfChildren ~~ 0]) ifTrue:[
-                x := xFig + figWidthDiv2.
-                self displayLineFromX:x y:yCtr  toX:x y:yBot
-            ].
-            (level ~~ 1 and:[node parent children last == node]) ifTrue:[
-                self displayLineFromX:xCross y:yTop - 1 toX:xCross y:yCtr . "/ vertical
+            xCross < x1 ifTrue:[
+                (    ((x := xFig + figWidthDiv2) between:x0 and:x1)
+                 and:[node isCollapsable
+                 and:[node numberOfChildren ~~ 0]]
+                ) ifTrue:[
+                    self displayLineFromX:x y:yCtr toX:x y:yBot
+                ].
+
+                "/ vertical line from previous to current form
+                (     xCross >= x0
+                 and:[level ~~ 1
+                 and:[node parent children last == node]]
+                ) ifTrue:[
+                    self displayLineFromX:xCross y:yTop - 1 toX:xCross y:yCtr
+                ].
+
+                "/ horizontal line from previous to current form
+                (     xFig > x0
+                 and:[(level ~~ 1
+                  or:[showDirectoryIndicatorForRoot and:[showDirectoryIndicator]])]
+                ) ifTrue:[
+                    self displayLineFromX:xCross y:yCtr toX:xFig y:yCtr
+                ]
             ].
 
-            (level ~~ 1 or:[showDirectoryIndicatorForRoot and:[showDirectoryIndicator]]) ifTrue:[
-                self displayLineFromX:xCross y:yCtr toX:xFig y:yCtr .       "/ horizontal
-            ].
+        "/  draw all vertical lines to left side
+            xCross > x0 ifTrue:[
+                idx := index.
+
+                [(lv > 0 and:[(idx := idx + 1) <= size])] whileTrue:[
+                    (x := (listOfNodes at:idx) level) <= lv ifTrue:[
+                        lv := x - 1.
 
-        "/  draw vertical lines
-            idx := index.
-
-            [(lv > 0 and:[(idx := idx + 1) <= size])] whileTrue:[
-                (x := (listOfNodes at:idx) level) <= lv ifTrue:[
-                    lv := x - 1.
-                    x  := (self xOfFigureLevel:lv) + figWidthDiv2.
-                    self displayLineFromX:x y:yTop - 1 toX:x y:yBot.
+                        (x  := (self xOfFigureLevel:lv) + figWidthDiv2) < x0 ifTrue:[
+                            lv := 0
+                        ] ifFalse:[
+                            x <= x1 ifTrue:[
+                                self displayLineFromX:x y:yTop - 1 toX:x y:yBot
+                            ]
+                        ]
+                    ]
                 ]
             ].
             self mask:nil.
-            self paint:fg.
+
+            chgdPaint ifTrue:[
+                isSelected ifTrue:[self paint:hilightFgColor on:hilightBgColor]
+                          ifFalse:[self paint:fgColor        on:bgColor]
+            ]            
         ].
 
         "/ draw image
-        image := self figureFor:node.
-        image notNil ifTrue:[
-            self displayForm:image x:xFig y:(yCtr - (image height // 2)).
+        (image := self figureFor:node) notNil ifTrue:[
+            (xFig < x1 and:[(xFig + image width) > x0]) ifTrue:[
+                self displayForm:image x:xFig y:(yCtr - (image height // 2))
+            ]
         ].
 
         "/ draw text label
@@ -585,33 +656,65 @@
                     image := closeIndicator.
                     x := extentCloseIndicator.
                 ].
-                self displayForm:image x:(xCross - x x)
-                                       y:(yCtr   - x y)
+                idx := x x.
+
+                (xCross - idx < x1 and:[xCross + idx > x0]) ifTrue:[
+                    self displayForm:image x:(xCross - idx) y:(yCtr - x y)
+                ]
             ]
         ].
         "/ setup next line
         index := index + 1.
         yTop  := yBot.
-    ].
-
-    "Modified: 6.10.1997 / 13:31:51 / cg"
-!
-
-drawLabelIndex:anIndex atX:x y:yCenter
-    "draw text label at x and y centered
-    "
-    |lbl|
-
-    (lbl := (listOfNodes at:anIndex) name) notNil ifTrue:[
-        self displayOpaqueString:lbl x:x y:(yCenter + labelOffsetY).
-    ]    
+    ]
 !
 
 redrawX:x y:y width:w height:h
+    "a region must be redrawn"
 
-    self shown ifTrue:[
-        super redrawX:x y:y width:w height:h.
+    |saveClip
+     y0       "{ Class:SmallInteger }"
+     y1       "{ Class:SmallInteger }"
+     visStart "{ Class:SmallInteger }"
+     visEnd   "{ Class:SmallInteger }"
+     startLn  "{ Class:SmallInteger }"
+     stopLn   "{ Class:SmallInteger }"
+     maxY     "{ Class:SmallInteger }"
+     startY   "{ Class:SmallInteger }"|
+
+    shown ifFalse:[^ self].
+
+    visStart := self visibleLineOfY:y.
+    visEnd   := self visibleLineOfY:(y + h).
+    startLn  := self visibleLineToAbsoluteLine:visStart.
+
+    self paint:bgColor.
+    self fillRectangleX:x y:y width:w height:h.
+
+    startLn isNil ifTrue:[
+        ^ self
+    ].    
+    startY := (self yOfVisibleLine:visStart) - 1.
+    stopLn := startLn + visEnd - visStart.
+
+    saveClip := clipRect.
+    self clippingRectangle:(Rectangle left:x top:y width:w height:h).
+
+    self hasSelection ifTrue:[
+        maxY := y + h.
+
+        self selectionDo:[:i|
+            (i between:startLn and:stopLn) ifTrue:[
+                self paint:hilightBgColor.
+                y0 := (startY + (i - startLn * fontHeight)) max:y.
+                y1 := (y0 + fontHeight) min:maxY.
+                self fillRectangleX:x y:y0 width:w height:y1 - y0.
+            ]
+        ]
     ].
+    self redrawLinesX:x y:startY toX:(x + w) start:startLn stop:stopLn.
+    self clippingRectangle:saveClip.
+
 ! !
 
 !SelectionInTreeView methodsFor:'enumerating'!
@@ -1449,5 +1552,5 @@
 !SelectionInTreeView class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libwidg2/Attic/SelTreeV.st,v 1.39 1998-02-16 22:40:41 tz Exp $'
+    ^ '$Header: /cvs/stx/stx/libwidg2/Attic/SelTreeV.st,v 1.40 1998-02-19 09:35:34 ca Exp $'
 ! !
--- a/SelectionInTreeView.st	Wed Feb 18 23:13:49 1998 +0100
+++ b/SelectionInTreeView.st	Thu Feb 19 10:35:34 1998 +0100
@@ -496,31 +496,67 @@
 !SelectionInTreeView methodsFor:'drawing basics'!
 
 drawFromVisibleLine:startVisLineNr to:endVisLineNr with:fg and:bg
+    "redraw a visible line range with clearing the background
+    "
+    |y0 y1 sz|
 
-    |size end index yBot yTop yCtr level figWidthDiv2
-     x xFig xStr node lv idx image xCross|
+    shown ifTrue:[
+        y0  := self yOfVisibleLine:startVisLineNr.
+        y0  := y0 - 1.
+        sz  := endVisLineNr - startVisLineNr + 1.
+        y1  := sz * fontHeight.
+
+    "/  clear rectangle line and set background color
+        self paint:bg.
+        self fillRectangleX:0 y:y0 width:width height:y1.
+
+        (y1 := self visibleLineToAbsoluteLine:startVisLineNr) notNil ifTrue:[
+            self redrawLinesX:0 y:y0 toX:width start:y1 stop:(y1 + sz)
+        ]
+    ]
+!
+
+drawLabelIndex:anIndex atX:x y:yCenter
+    "draw text label at x and y centered
+    "
+    |lbl|
+
+    (lbl := (listOfNodes at:anIndex) name) notNil ifTrue:[
+        self displayOpaqueString:lbl x:x y:(yCenter + labelOffsetY).
+    ]    
+!
+
+redrawLinesX:x0 y:y0 toX:x1 start:start stop:stop
+    "redraw from line to line without clearing the background
+    "
+    |chgdPaint node image isSelected
+     x      "{ Class:SmallInteger }"
+     yTop   "{ Class:SmallInteger }"
+     yBot   "{ Class:SmallInteger }"
+     yCtr   "{ Class:SmallInteger }"
+     size   "{ Class:SmallInteger }"
+     end    "{ Class:SmallInteger }"
+     index  "{ Class:SmallInteger }"
+     xCross "{ Class:SmallInteger }"
+     xFig   "{ Class:SmallInteger }"
+     xStr   "{ Class:SmallInteger }"
+     idx    "{ Class:SmallInteger }"
+     level  "{ Class:SmallInteger }"
+     lv     "{ Class:SmallInteger }"
+     figWidthDiv2 "{ Class:SmallInteger }"
+    |
 
     level := nil. "/ to force evaluation of #ifFalse in loop
-
-    index := self visibleLineToAbsoluteLine:startVisLineNr.
+    yTop  := y0.
+    index := start.
     size  := listOfNodes size.
-    yTop  := self yOfVisibleLine:startVisLineNr.
-    yTop  := yTop - 1.
-    end   := endVisLineNr - startVisLineNr + 1.
+    end   := stop min:size.
 
-"/  clear rectangle line and set background color
-    self paint:bg.
-    self fillRectangleX:0 y:yTop width:width height:(end * fontHeight).
-
-    index isNil ifTrue:[^ self].
     figWidthDiv2 := imageWidth // 2.
     figWidthDiv2 odd ifTrue:[figWidthDiv2 := figWidthDiv2 + 1].
     yCtr := yTop - (fontHeight // 2).
 
-    self paint:fg on:bg.
-    (end := index + end) > size ifTrue:[end := size + 1].
-
-    [index < end] whileTrue:[
+    [index <= end] whileTrue:[
         node := listOfNodes at:index.
         yBot := yTop + fontHeight.
         yCtr := yCtr + fontHeight.
@@ -532,43 +568,78 @@
             xCross := (self xOfFigureLevel:(lv-1)) + figWidthDiv2.
         ].
 
+        (isSelected := self isInSelection:index) ifTrue:[
+            self paint:hilightFgColor on:hilightBgColor.
+        ] ifFalse:[
+            self paint:fgColor on:bgColor.
+        ].
+
         showLines ifTrue:[
-            (lineColor isNil or:[(self isInSelection:index)]) ifFalse:[
+            chgdPaint := (lineColor isNil or:[isSelected]) not.
+
+            chgdPaint ifTrue:[
                 self paint:lineColor.
             ].
+
             self mask:lineMask.
             self setMaskOrigin:(self viewOrigin + (0 @ 1) \\ (lineMask extent)).
 
-            (node isCollapsable and:[node numberOfChildren ~~ 0]) ifTrue:[
-                x := xFig + figWidthDiv2.
-                self displayLineFromX:x y:yCtr  toX:x y:yBot
-            ].
-            (level ~~ 1 and:[node parent children last == node]) ifTrue:[
-                self displayLineFromX:xCross y:yTop - 1 toX:xCross y:yCtr . "/ vertical
+            xCross < x1 ifTrue:[
+                (    ((x := xFig + figWidthDiv2) between:x0 and:x1)
+                 and:[node isCollapsable
+                 and:[node numberOfChildren ~~ 0]]
+                ) ifTrue:[
+                    self displayLineFromX:x y:yCtr toX:x y:yBot
+                ].
+
+                "/ vertical line from previous to current form
+                (     xCross >= x0
+                 and:[level ~~ 1
+                 and:[node parent children last == node]]
+                ) ifTrue:[
+                    self displayLineFromX:xCross y:yTop - 1 toX:xCross y:yCtr
+                ].
+
+                "/ horizontal line from previous to current form
+                (     xFig > x0
+                 and:[(level ~~ 1
+                  or:[showDirectoryIndicatorForRoot and:[showDirectoryIndicator]])]
+                ) ifTrue:[
+                    self displayLineFromX:xCross y:yCtr toX:xFig y:yCtr
+                ]
             ].
 
-            (level ~~ 1 or:[showDirectoryIndicatorForRoot and:[showDirectoryIndicator]]) ifTrue:[
-                self displayLineFromX:xCross y:yCtr toX:xFig y:yCtr .       "/ horizontal
-            ].
+        "/  draw all vertical lines to left side
+            xCross > x0 ifTrue:[
+                idx := index.
+
+                [(lv > 0 and:[(idx := idx + 1) <= size])] whileTrue:[
+                    (x := (listOfNodes at:idx) level) <= lv ifTrue:[
+                        lv := x - 1.
 
-        "/  draw vertical lines
-            idx := index.
-
-            [(lv > 0 and:[(idx := idx + 1) <= size])] whileTrue:[
-                (x := (listOfNodes at:idx) level) <= lv ifTrue:[
-                    lv := x - 1.
-                    x  := (self xOfFigureLevel:lv) + figWidthDiv2.
-                    self displayLineFromX:x y:yTop - 1 toX:x y:yBot.
+                        (x  := (self xOfFigureLevel:lv) + figWidthDiv2) < x0 ifTrue:[
+                            lv := 0
+                        ] ifFalse:[
+                            x <= x1 ifTrue:[
+                                self displayLineFromX:x y:yTop - 1 toX:x y:yBot
+                            ]
+                        ]
+                    ]
                 ]
             ].
             self mask:nil.
-            self paint:fg.
+
+            chgdPaint ifTrue:[
+                isSelected ifTrue:[self paint:hilightFgColor on:hilightBgColor]
+                          ifFalse:[self paint:fgColor        on:bgColor]
+            ]            
         ].
 
         "/ draw image
-        image := self figureFor:node.
-        image notNil ifTrue:[
-            self displayForm:image x:xFig y:(yCtr - (image height // 2)).
+        (image := self figureFor:node) notNil ifTrue:[
+            (xFig < x1 and:[(xFig + image width) > x0]) ifTrue:[
+                self displayForm:image x:xFig y:(yCtr - (image height // 2))
+            ]
         ].
 
         "/ draw text label
@@ -585,33 +656,65 @@
                     image := closeIndicator.
                     x := extentCloseIndicator.
                 ].
-                self displayForm:image x:(xCross - x x)
-                                       y:(yCtr   - x y)
+                idx := x x.
+
+                (xCross - idx < x1 and:[xCross + idx > x0]) ifTrue:[
+                    self displayForm:image x:(xCross - idx) y:(yCtr - x y)
+                ]
             ]
         ].
         "/ setup next line
         index := index + 1.
         yTop  := yBot.
-    ].
-
-    "Modified: 6.10.1997 / 13:31:51 / cg"
-!
-
-drawLabelIndex:anIndex atX:x y:yCenter
-    "draw text label at x and y centered
-    "
-    |lbl|
-
-    (lbl := (listOfNodes at:anIndex) name) notNil ifTrue:[
-        self displayOpaqueString:lbl x:x y:(yCenter + labelOffsetY).
-    ]    
+    ]
 !
 
 redrawX:x y:y width:w height:h
+    "a region must be redrawn"
 
-    self shown ifTrue:[
-        super redrawX:x y:y width:w height:h.
+    |saveClip
+     y0       "{ Class:SmallInteger }"
+     y1       "{ Class:SmallInteger }"
+     visStart "{ Class:SmallInteger }"
+     visEnd   "{ Class:SmallInteger }"
+     startLn  "{ Class:SmallInteger }"
+     stopLn   "{ Class:SmallInteger }"
+     maxY     "{ Class:SmallInteger }"
+     startY   "{ Class:SmallInteger }"|
+
+    shown ifFalse:[^ self].
+
+    visStart := self visibleLineOfY:y.
+    visEnd   := self visibleLineOfY:(y + h).
+    startLn  := self visibleLineToAbsoluteLine:visStart.
+
+    self paint:bgColor.
+    self fillRectangleX:x y:y width:w height:h.
+
+    startLn isNil ifTrue:[
+        ^ self
+    ].    
+    startY := (self yOfVisibleLine:visStart) - 1.
+    stopLn := startLn + visEnd - visStart.
+
+    saveClip := clipRect.
+    self clippingRectangle:(Rectangle left:x top:y width:w height:h).
+
+    self hasSelection ifTrue:[
+        maxY := y + h.
+
+        self selectionDo:[:i|
+            (i between:startLn and:stopLn) ifTrue:[
+                self paint:hilightBgColor.
+                y0 := (startY + (i - startLn * fontHeight)) max:y.
+                y1 := (y0 + fontHeight) min:maxY.
+                self fillRectangleX:x y:y0 width:w height:y1 - y0.
+            ]
+        ]
     ].
+    self redrawLinesX:x y:startY toX:(x + w) start:startLn stop:stopLn.
+    self clippingRectangle:saveClip.
+
 ! !
 
 !SelectionInTreeView methodsFor:'enumerating'!
@@ -1449,5 +1552,5 @@
 !SelectionInTreeView class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libwidg2/SelectionInTreeView.st,v 1.39 1998-02-16 22:40:41 tz Exp $'
+    ^ '$Header: /cvs/stx/stx/libwidg2/SelectionInTreeView.st,v 1.40 1998-02-19 09:35:34 ca Exp $'
 ! !