<div dir="ltr">Hi Marcel and Christoph,<div><br></div><div>After further thought the other day, I had arrived at the same concerns as Christoph and you; and had this version sitting dirty in my image.  In addition to yours, I myself also didn't care for passing the non-well-formed Event object which the method might in the future couple to beyond the type test.  Plus, the extra garbage.</div><div><br></div><div>All this is somewhat ameliorated in this edition, by simply allowing a Symbolic "directive" to be passed in alternately from an Event object (which would not be used even if it was).</div><div><br></div><div>This was done a few days ago.  Since then, Marcel submitted his workaround in Tools which is fine for now, but I just wanted to capture this latest version in the Inbox for future discussion rather than lose it.</div><div><br></div><div>Best,</div><div>  Chris</div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Mon, Jan 6, 2020 at 10:08 PM <<a href="mailto:commits@source.squeak.org" target="_blank">commits@source.squeak.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Chris Muller uploaded a new version of Morphic to project The Inbox:<br>
<a href="http://source.squeak.org/inbox/Morphic-cmm.1616.mcz" rel="noreferrer" target="_blank">http://source.squeak.org/inbox/Morphic-cmm.1616.mcz</a><br>
<br>
==================== Summary ====================<br>
<br>
Name: Morphic-cmm.1616<br>
Author: cmm<br>
Time: 6 January 2020, 10:07:44.246015 pm<br>
UUID: d5855100-f308-4287-b83d-2e51c3b4688c<br>
Ancestors: Morphic-mt.1615<br>
<br>
When a text selection cannot fit into its text pane, start by scrolling to its upper-left, rather than its lower-right until the next edit is made, at which point scroll to the edit.<br>
<br>
=============== Diff against Morphic-mt.1615 ===============<br>
<br>
Item was changed:<br>
  ----- Method: PluggableTextMorph>>handleEdit: (in category 'editor access') -----<br>
  handleEdit: editBlock<br>
        | result |<br>
        textMorph editor selectFrom: selectionInterval first to: selectionInterval last;<br>
                                                model: model.  "For, eg, evaluateSelection"<br>
        result := textMorph handleEdit: editBlock.   "Update selection after edit"<br>
+       self scrollSelectionIntoView: #scrollToPointBlock. "Special directive to scroll to text cursor"<br>
-       self scrollSelectionIntoView.<br>
        ^ result!<br>
<br>
Item was changed:<br>
  ----- Method: PluggableTextMorph>>scrollSelectionIntoView: (in category 'editor access') -----<br>
+ scrollSelectionIntoView: eventOrDirective<br>
- scrollSelectionIntoView: event <br>
        "Scroll my text into view. Due to line composition mechanism, we must never use the right of a character block because the lines last character block right value always comes from a global container and is *not* line specific."<br>
+       self flag: #fixIntervalCache.<br>
+       "mt: We should find a better design for discarding unused text editors in text morphs and restoring them on demand."<br>
- <br>
-       self flag: #fixIntervalCache. "mt: We should find a better design for discarding unused text editors in text morphs and restoring them on demand."<br>
        selectionInterval := textMorph editor markIndex to: textMorph editor pointIndex - 1.<br>
+       self scrollToShow:<br>
+               (textMorph editor hasSelection<br>
+                       ifTrue: [ textMorph editor startBlock topLeft corner: textMorph editor stopBlock bottomLeft ]<br>
+                       ifFalse: [ textMorph editor startBlock withWidth: 1 ]).<br>
+       (eventOrDirective notNil and: [ eventOrDirective = #scrollToPointBlock or: [ eventOrDirective isKeyboard ] ]) ifTrue:<br>
+               [ self scrollToShow: (textMorph editor pointBlock withWidth: 1) ].<br>
-       <br>
-       textMorph editor hasSelection<br>
-               ifFalse: [self scrollToShow: (textMorph editor startBlock withWidth: 1)]<br>
-               ifTrue: [<br>
-                       self scrollToShow: (textMorph editor startBlock topLeft corner: textMorph editor stopBlock bottomLeft).<br>
-                       self scrollToShow: (textMorph editor pointBlock withWidth: 1). "Ensure text cursor visibility."].<br>
-               <br>
        ^ true!<br>
<br>
Item was changed:<br>
  ----- Method: ScrollPane>>keyStroke: (in category 'event handling') -----<br>
+ keyStroke: aKeyboardEvent<br>
+       "If pane is not empty, let the last submorph handle the event."<br>
+       scroller submorphs ifNotEmpty: [ : subs | subs last keyStroke: aKeyboardEvent ]!<br>
- keyStroke: evt<br>
-       "If pane is not empty, pass the event to the last submorph,<br>
-       assuming it is the most appropriate recipient (!!)"<br>
- <br>
-       scroller submorphs last keyStroke: evt!<br>
<br>
Item was changed:<br>
  ----- Method: ScrollPane>>offsetToShow: (in category 'scrolling') -----<br>
  offsetToShow: aRectangle<br>
        "Calculate the offset necessary to show the rectangle."<br>
<br>
        | offset scrollRange target |<br>
        self fullBounds. "We need updated bounds."<br>
        offset := scroller offset.<br>
        scrollRange := self hTotalScrollRange @ self vTotalScrollRange.<br>
<br>
        "Normalize the incoming rectangle."<br>
        target := <br>
+               aRectangle left @ aRectangle top<br>
-                       (scroller width < aRectangle width<br>
-                               ifTrue: [offset x < aRectangle left "Coming from left?"<br>
-                                       ifTrue: [aRectangle right - scroller width]<br>
-                                       ifFalse: [aRectangle left]]<br>
-                               ifFalse: [aRectangle left])<br>
-               @<br>
-                       (scroller height < aRectangle height<br>
-                               ifTrue: [offset y < aRectangle top "Coming from top?"<br>
-                                       ifTrue: [aRectangle bottom - scroller height]<br>
-                                       ifFalse: [aRectangle top]]<br>
-                               ifFalse: [aRectangle top])<br>
                corner: <br>
                        (scroller width < aRectangle width<br>
                                ifTrue: [offset x + scroller width > aRectangle right "Coming from right?"<br>
                                        ifTrue: [aRectangle left + scroller width]<br>
                                        ifFalse: [aRectangle right]]<br>
                                ifFalse: [aRectangle right])<br>
                @<br>
                        (scroller height < aRectangle height<br>
                                ifTrue: [offset y + scroller height > aRectangle bottom "Coming from bottom?"<br>
                                        ifTrue: [aRectangle top + scroller height]<br>
                                        ifFalse: [aRectangle bottom]]<br>
                                ifFalse: [aRectangle bottom]).<br>
<br>
        "Vertical Scrolling"<br>
-       target top < offset y<br>
-               ifTrue: [offset := offset x @ target top].      <br>
        target bottom > (offset y + scroller height)<br>
                ifTrue: [offset := offset x @ (target bottom - scroller height)].<br>
+       target top < offset y<br>
+               ifTrue: [offset := offset x @ target top].      <br>
<br>
        "Horizontal Scrolling"<br>
-       target left < offset x<br>
-               ifTrue: [offset := target left @ offset y].<br>
        target right > (offset x + scroller width)<br>
                ifTrue: [offset := (target right - scroller width) @ offset y].<br>
+       target left < offset x<br>
+               ifTrue: [offset := target left @ offset y].<br>
<br>
        ^ (offset min: scrollRange - scroller extent) max: 0@0!<br>
<br>
Item was changed:<br>
  ----- Method: TextMorphForEditView>>keyStroke: (in category 'event handling') -----<br>
  keyStroke: evt<br>
        | view |<br>
<br>
        editView deleteBalloon.<br>
        self editor model: editView model.  "For evaluateSelection"<br>
        view := editView.  "Copy into temp for case of a self-mutating doit"<br>
        (acceptOnCR and: [evt keyCharacter = Character cr])<br>
                ifTrue: [^ self editor accept].<br>
<br>
        view hasUserEdited: false.<br>
        super keyStroke: evt.<br>
+       view scrollSelectionIntoView: evt.<br>
-       view scrollSelectionIntoView.<br>
<br>
        view hasUserEdited<br>
                ifTrue: [       view textEdited: self contents].!<br>
<br>
<br>
</blockquote></div>