<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name="Generator" content="Microsoft Exchange Server">
<!-- converted from text --><style><!-- .EmailQuote { margin-left: 1pt; padding-left: 4pt; border-left: #800000 2px solid; } --></style>
</head>
<body>
<meta content="text/html; charset=UTF-8">
<style type="text/css" style="">
<!--
p
        {margin-top:0;
        margin-bottom:0}
-->
</style>
<div dir="ltr">
<div id="x_divtagdefaultwrapper" dir="ltr" style="font-size:12pt; color:#000000; font-family:Calibri,Helvetica,sans-serif">
<p>> <span style="font-size:12pt">I appreciate being able to easily </span><span style="font-size:12pt">see the summary information directly in the merge commit notice.</span></p>
<p><span style="font-size:12pt"><br>
</span></p>
<p><span style="font-size:12pt">+1, at least at the moment. If we manage to display all ancestors in the update transcript stream, I could dispense with this note.</span></p>
<div id="x_Signature">
<div id="x_divtagdefaultwrapper" dir="ltr" style="font-size:12pt; color:rgb(0,0,0); font-family:Calibri,Helvetica,sans-serif,EmojiFont,"Apple Color Emoji","Segoe UI Emoji",NotoColorEmoji,"Segoe UI Symbol","Android Emoji",EmojiSymbols">
<div name="x_divtagdefaultwrapper" style="font-family:Calibri,Arial,Helvetica,sans-serif; font-size:; margin:0">
<div><font size="2" color="#808080"></font></div>
</div>
</div>
</div>
</div>
<hr tabindex="-1" style="display:inline-block; width:98%">
<div id="x_divRplyFwdMsg" dir="ltr"><font face="Calibri, sans-serif" color="#000000" style="font-size:11pt"><b>Von:</b> Squeak-dev <squeak-dev-bounces@lists.squeakfoundation.org> im Auftrag von David T. Lewis <lewis@mail.msen.com><br>
<b>Gesendet:</b> Sonntag, 8. März 2020 18:56:59<br>
<b>An:</b> Chris Muller<br>
<b>Cc:</b> The general-purpose Squeak developers list<br>
<b>Betreff:</b> Re: [squeak-dev] The Trunk: Morphic-nice.1635.mcz</font>
<div> </div>
</div>
</div>
<font size="2"><span style="font-size:10pt;">
<div class="PlainText">Hi Chris,<br>
<br>
On Sun, Mar 08, 2020 at 01:17:33AM -0600, Chris Muller wrote:<br>
> David,<br>
> <br>
> This particular personal convenience is a matter of query, your _personal_<br>
> query, not the shape of the internal model, and certainly not the<br>
> responsibility of Squeak and every current and future user. to host this<br>
> "convenience" for you.  Nicolas already agreed with me privately, please do<br>
> not try to solve your query limitations by mutilating the model.<br>
> <br>
> Remember the other day when you asked people to not reply emails with<br>
> graphical content?  You should offer the same kind of respect.<br>
<br>
<br>
Well, you got me on that one. I conceed the point :-)<br>
<br>
Nevertheless, I stand by my opinion that the method comment for<br>
Morphic-nice.1635 is a good thing. I appreciate being able to easily<br>
see the summary information directly in the merge commit notice.<br>
<br>
Dave<br>
<br>
> <br>
>  - Chris<br>
> <br>
> On Fri, Mar 6, 2020 at 9:59 PM David T. Lewis <lewis@mail.msen.com> wrote:<br>
> <br>
> > Chris,<br>
> ><br>
> > I disagree. Commit notices are provided for provided for the benefit<br>
> > of the reader. I find the commit notice for Morphic-nice.1635 to be<br>
> > clear and meaningful. It helps me to easily understand what was merged<br>
> > and why. It provides a clear explanation of what I should expect to<br>
> > see if I browse the ancestry, and it clearly identifies what was<br>
> > included in the merge. This is not bloat, it is useful information<br>
> > and I appreciate it.<br>
> ><br>
> > Dave<br>
> ><br>
> > On Fri, Mar 06, 2020 at 07:33:51PM -0600, Chris Muller wrote:<br>
> > > Jakob, we can accomplish that convenient email reading idea by upgrading<br>
> > > the code which produces the email diff -- just enumerate the immediate<br>
> > > ancestors and paste in their descriptions.  The code is in the /ss<br>
> > > repository if you want to take a crack at it.  As the one doing the work,<br>
> > > you'd get to choose how it gets delineated, and since its generated it'd<br>
> > be<br>
> > > consistent each time we submit a "Merge" object.<br>
> > ><br>
> > > Thanks,<br>
> > >   Chris<br>
> > ><br>
> > > On Fri, Mar 6, 2020 at 6:58 PM Chris Muller <asqueaker@gmail.com> wrote:<br>
> > ><br>
> > > > Would you be willing to find another way to re-read the same thing<br>
> > > > multiple times than bloating the image with multiple copies of the same<br>
> > > > text?  Would you be willing to find another way to re-read the same<br>
> > thing<br>
> > > > multiple times than bloating the image with multiple copies of the same<br>
> > > > text?<br>
> > > ><br>
> > > > On Fri, Mar 6, 2020 at 6:07 PM Jakob Reschke <forums.jakob@resfarm.de><br>
> > > > wrote:<br>
> > > ><br>
> > > >> I find it convenient to re-read here what was merged, without reading<br>
> > > >> the source code diff or looking up other mails.<br>
> > > >> But I agree it would be even better if original changes introduced<br>
> > > >> during the merge were pointed out at the top, not in between or at the<br>
> > > >> bottom. I overlooked the "integrator note" until after Chris replied.<br>
> > > >><br>
> > > >> Am Sa., 7. M??rz 2020 um 00:51 Uhr schrieb Chris Muller <<br>
> > > >> asqueaker@gmail.com>:<br>
> > > >> ><br>
> > > >> > Versions about merging can be concisely described with merely<br>
> > "Merge."<br>
> > > >> and actually provide a clearer description of what that Version<br>
> > object is<br>
> > > >> about -- a merge, not code changes.  Since they're a unit of change<br>
> > of the<br>
> > > >> ancestry, not the code, including the prior descriptions about code<br>
> > changes<br>
> > > >> isn't necessary and even adds some confusion whether this is a simple<br>
> > merge<br>
> > > >> or something more..<br>
> > > >> ><br>
> > > >> > IMO, the original descriptions should remain with the original<br>
> > > >> submissions _only_.<br>
> > > >> ><br>
> > > >> >  - Chris<br>
> > > >> ><br>
> > > >> > On Fri, Mar 6, 2020 at 4:54 PM <commits@source.squeak.org> wrote:<br>
> > > >> >><br>
> > > >> >> Nicolas Cellier uploaded a new version of Morphic to project The<br>
> > Trunk:<br>
> > > >> >> <a href="http://source.squeak.org/trunk/Morphic-nice.1635.mcz">http://source.squeak.org/trunk/Morphic-nice.1635.mcz</a><br>
> > > >> >><br>
> > > >> >> ==================== Summary ====================<br>
> > > >> >><br>
> > > >> >> Name: Morphic-nice.1635<br>
> > > >> >> Author: nice<br>
> > > >> >> Time: 6 March 2020, 11:54:05.017411 pm<br>
> > > >> >> UUID: 2db3548c-1ac5-4197-bf5e-2df91ee604ed<br>
> > > >> >> Ancestors: Morphic-mt.1634, Morphic-nice.1616, Morphic-ct.1622,<br>
> > > >> Morphic-cmm.1489<br>
> > > >> >><br>
> > > >> >> Merge Morphic-mt.1634, Morphic-nice.1616, Morphic-ct.1622,<br>
> > > >> Morphic-cmm.1489<br>
> > > >> >><br>
> > > >> >> Mainly set smoother scrolling in postscript now that our VM support<br>
> > > >> that.<br>
> > > >> >> Note that this removes shared mouseWheelState as discussed in<br>
> > thread<br>
> > > >> >><br>
> > > >><br>
> > <a href="http://lists.squeakfoundation.org/pipermail/squeak-dev/2020-January/206227.html">
http://lists.squeakfoundation.org/pipermail/squeak-dev/2020-January/206227.html</a><br>
> > > >> >> (this was Morphic-nice.1613, but was refactored a bit since then).<br>
> > > >> >><br>
> > > >> >> Morphic-nice.1616:<br>
> > > >> >>         Provide smoother scrolling in response to mouse wheel<br>
> > events<br>
> > > >> >><br>
> > > >> >> Instead of delivering the events when wheelDelta reaches 120, make<br>
> > > >> this threshold a Preference (minimumWheelDelta)<br>
> > > >> >><br>
> > > >> >> Reminder: 120 represents a single notch for traditional mouse wheel<br>
> > > >> with notches, but trackpads can deliver much smaller deltas<br>
> > > >> >><br>
> > > >> >> Rather than accumulating the wheelDeltas into MouseWheelState, do<br>
> > it<br>
> > > >> when we #generateMouseWheelEvent:<br>
> > > >> >> Indeed, small deltas will come in packets of successive events, and<br>
> > > >> it's more efficient to regroup then, exactly like we do with mouse<br>
> > trails...<br>
> > > >> >><br>
> > > >> >> Also MouseWheelState did ignore time outs (long delays between<br>
> > deltas)<br>
> > > >> and other state changes (buttons/modifiers), which was not ideal.<br>
> > > >> >><br>
> > > >> >> Directly get those states from the raw eventBuffer, like any other<br>
> > > >> mouse event. This requires integration of tose 2 PR:<br>
> > > >> >> <a href="https://github.com/OpenSmalltalk/opensmalltalk-vm/pull/461">
https://github.com/OpenSmalltalk/opensmalltalk-vm/pull/461</a> for<br>
> > Windows<br>
> > > >> >> <a href="https://github.com/OpenSmalltalk/opensmalltalk-vm/pull/462">
https://github.com/OpenSmalltalk/opensmalltalk-vm/pull/462</a> for OSX<br>
> > > >> and linux<br>
> > > >> >><br>
> > > >> >> Honour larger wheelDeltas too in ScrollPane>>#mouseWheel: event<br>
> > > >> handling<br>
> > > >> >> Honour horizontal mouse wheels too in ScrollPane<br>
> > > >> >> Note that the scroll pane still won't deliver<br>
> > > >> sub-scrollDeltaWidth/scrollDeltaHeight with those changes, the number<br>
> > of<br>
> > > >> scroll deltas is still rounded to 1.<br>
> > > >> >><br>
> > > >> >> With patched VM, and following settings, I get a reasonnable<br>
> > scrolling<br>
> > > >> experience on OSX:<br>
> > > >> >><br>
> > > >> >>         HandMorph minimumWheelDelta: 20.<br>
> > > >> >>         Smalltalk sendMouseWheelEvents: true.<br>
> > > >> >><br>
> > > >> >> NOTE: it is tricky to add/remove inst. var. to such HandMorph<br>
> > because<br>
> > > >> obsolete CompiledMethod pointing to old inst. var. offset are still<br>
> > active<br>
> > > >> on the stack and can mess things up (unless you do not load the<br>
> > package<br>
> > > >> from UI but rather from command line...).<br>
> > > >> >><br>
> > > >> >> Since accessing 'lastMouseEvent' in such obsolete CompiledMethod is<br>
> > > >> causing grief, preserve its offset by swapping inst. var. order with<br>
> > > >> 'targetOffset' which is less likely used.<br>
> > > >> >><br>
> > > >> >> Morphic-ct.1622:<br>
> > > >> >>         Proposal: Swap key and item of an Integer's explorer<br>
> > contents.<br>
> > > >> Integer representations are not really keys, but rather values. In an<br>
> > > >> explorer's code pane, this allows you to interact with the selected<br>
> > string<br>
> > > >> representation (for example '101010') which is much more interesting<br>
> > than<br>
> > > >> the base name (for example 'binary').<br>
> > > >> >><br>
> > > >> >> Morphic-cmm.1489:<br>
> > > >> >>         Fix TextEditor>>#hasMultipleLinesSelected to consider<br>
> > actual<br>
> > > >> lines, instead of wrapped lines.<br>
> > > >> >><br>
> > > >> >> integrator note: but I also let it consider case of LF<br>
> > > >> >><br>
> > > >> >> =============== Diff against Morphic-mt.1634 ===============<br>
> > > >> >><br>
> > > >> >> Item was changed:<br>
> > > >> >>   Morph subclass: #HandMorph<br>
> > > >> >> +       instanceVariableNames: 'mouseFocus keyboardFocus<br>
> > > >> eventListeners mouseListeners keyboardListeners eventCaptureFilters<br>
> > > >> mouseCaptureFilters keyboardCaptureFilters mouseClickState<br>
> > mouseOverHandler<br>
> > > >> targetOffset lastMouseEvent damageRecorder cacheCanvas<br>
> > cachedCanvasHasHoles<br>
> > > >> temporaryCursor temporaryCursorOffset hardwareCursor hasChanged<br>
> > savedPatch<br>
> > > >> userInitials lastEventBuffer genieGestureProcessor<br>
> > keyboardInterpreter'<br>
> > > >> >> +       classVariableNames: 'CompositionWindowManager<br>
> > DoubleClickTime<br>
> > > >> DragThreshold EventStats MinimalWheelDelta NewEventRules NormalCursor<br>
> > > >> PasteBuffer SendMouseWheelToKeyboardFocus ShowEvents<br>
> > > >> SynthesizeMouseWheelEvents'<br>
> > > >> >> -       instanceVariableNames: 'mouseFocus keyboardFocus<br>
> > > >> eventListeners mouseListeners keyboardListeners eventCaptureFilters<br>
> > > >> mouseCaptureFilters keyboardCaptureFilters mouseClickState<br>
> > mouseOverHandler<br>
> > > >> mouseWheelState lastMouseEvent targetOffset damageRecorder cacheCanvas<br>
> > > >> cachedCanvasHasHoles temporaryCursor temporaryCursorOffset<br>
> > hardwareCursor<br>
> > > >> hasChanged savedPatch userInitials lastEventBuffer<br>
> > genieGestureProcessor<br>
> > > >> keyboardInterpreter'<br>
> > > >> >> -       classVariableNames: 'CompositionWindowManager<br>
> > DoubleClickTime<br>
> > > >> DragThreshold EventStats NewEventRules NormalCursor PasteBuffer<br>
> > > >> SendMouseWheelToKeyboardFocus ShowEvents SynthesizeMouseWheelEvents'<br>
> > > >> >>         poolDictionaries: 'EventSensorConstants'<br>
> > > >> >>         category: 'Morphic-Kernel'!<br>
> > > >> >><br>
> > > >> >>   !HandMorph commentStamp: '<historical>' prior: 0!<br>
> > > >> >>   The cursor may be thought of as the HandMorph.  The hand's<br>
> > submorphs<br>
> > > >> hold anything being carried by dragging.<br>
> > > >> >><br>
> > > >> >>   There is some minimal support for multiple hands in the same<br>
> > world.!<br>
> > > >> >><br>
> > > >> >> Item was added:<br>
> > > >> >> + ----- Method: HandMorph class>>minimumWheelDelta (in category<br>
> > > >> 'preferences') -----<br>
> > > >> >> + minimumWheelDelta<br>
> > > >> >> +       <preference: 'Minimal Mouse Wheel Detection Threshold'<br>
> > > >> >> +               categoryList: #(Morphic mouse)<br>
> > > >> >> +               description: 'Answer the minimal scrolling units<br>
> > taken<br>
> > > >> into account<br>
> > > >> >> + Defaults to 120 (See #scrollUnitsPerMouseWheelNotch),<br>
> > corresponding<br>
> > > >> to a single mouse wheel notch.<br>
> > > >> >> + Use a lower value (20 - See #minimalScrollUnitsPerEvent) if<br>
> > wanting<br>
> > > >> smoother scrolling with trackpads.'<br>
> > > >> >> +               type: #Number><br>
> > > >> >> +       ^MinimalWheelDelta ifNil: [MouseWheelEvent<br>
> > > >> scrollUnitsPerMouseWheelNotch].!<br>
> > > >> >><br>
> > > >> >> Item was added:<br>
> > > >> >> + ----- Method: HandMorph class>>minimumWheelDelta: (in category<br>
> > > >> 'preferences') -----<br>
> > > >> >> + minimumWheelDelta: anInteger<br>
> > > >> >> +       MinimalWheelDelta := anInteger ifNotNil: [anInteger<br>
> > > >> >> +               clampLow: MouseWheelEvent<br>
> > minimalScrollUnitsPerEvent<br>
> > > >> >> +               high: MouseWheelEvent<br>
> > scrollUnitsPerMouseWheelNotch]!<br>
> > > >> >><br>
> > > >> >> Item was changed:<br>
> > > >> >>   ----- Method: HandMorph>>generateMouseWheelEvent: (in category<br>
> > > >> 'private events') -----<br>
> > > >> >>   generateMouseWheelEvent: evtBuf<br>
> > > >> >>         "Generate the appropriate mouse wheel event for the given<br>
> > raw<br>
> > > >> event buffer"<br>
> > > >> >><br>
> > > >> >> +       | buttons modifiers deltaX deltaY stamp nextEvent |<br>
> > > >> >> -       | buttons modifiers deltaX deltaY stamp |<br>
> > > >> >>         stamp := evtBuf second.<br>
> > > >> >>         stamp = 0 ifTrue: [stamp := Time eventMillisecondClock].<br>
> > > >> >>         deltaX := evtBuf third.<br>
> > > >> >>         deltaY := evtBuf fourth.<br>
> > > >> >> +       buttons := evtBuf fifth.<br>
> > > >> >> +       modifiers := evtBuf sixth.<br>
> > > >> >> +       [(deltaX abs + deltaY abs < self class minimumWheelDelta)<br>
> > > >> >> +                       and: [(nextEvent := Sensor peekEvent)<br>
> > notNil<br>
> > > >> >> +                       and: [nextEvent first = evtBuf first<br>
> > > >> >> +                       and: [nextEvent fifth = evtBuf fifth<br>
> > > >> >> +                       and: [nextEvent sixth = evtBuf sixth]<br>
> > > >> >> +                       and: [nextEvent third isZero = evtBuf third<br>
> > > >> isZero "both horizontal or vertical"]]]]]<br>
> > > >> >> +               whileTrue:<br>
> > > >> >> +                       ["nextEvent is similar.  Remove it from the<br>
> > > >> queue, and check the next."<br>
> > > >> >> +                       nextEvent := Sensor nextEvent.<br>
> > > >> >> +                       deltaX := deltaX + nextEvent third.<br>
> > > >> >> +                       deltaY := deltaY + nextEvent fourth].<br>
> > > >> >> -       modifiers := evtBuf fifth.<br>
> > > >> >> -       buttons := (modifiers bitShift: 3) bitOr: (lastMouseEvent<br>
> > > >> buttons bitAnd: 7).<br>
> > > >> >>         ^ MouseWheelEvent new<br>
> > > >> >>                 setType: #mouseWheel<br>
> > > >> >>                 position: self position<br>
> > > >> >>                 delta: deltaX@deltaY<br>
> > > >> >> -               direction: 2r0000<br>
> > > >> >>                 buttons: buttons<br>
> > > >> >>                 hand: self<br>
> > > >> >>                 stamp: stamp!<br>
> > > >> >><br>
> > > >> >> Item was changed:<br>
> > > >> >>   ----- Method: HandMorph>>generateMouseWheelEvent:direction: (in<br>
> > > >> category 'private events') -----<br>
> > > >> >>   generateMouseWheelEvent: keystrokeEvent direction: direction<br>
> > > >> >>         "Generate the appropriate mouse wheel event from the<br>
> > > >> keystrokeEvent. Before calling this, ensure that the control key is<br>
> > pressed.<br>
> > > >> >><br>
> > > >> >>         This method can be discarded once the VM produces real<br>
> > mouse<br>
> > > >> wheel events."<br>
> > > >> >><br>
> > > >> >>         ^ MouseWheelEvent new<br>
> > > >> >>                 setType: #mouseWheel<br>
> > > >> >>                 position: keystrokeEvent position<br>
> > > >> >> +               delta: 0 @ ((direction anyMask: 2r1000 "wheel up")<br>
> > > >> ifTrue: [MouseWheelEvent scrollUnitsPerMouseWheelNotch] ifFalse:<br>
> > > >> [MouseWheelEvent scrollUnitsPerMouseWheelNotch negated])<br>
> > > >> >> -               delta: 0 @ ((direction anyMask: 2r1000 "wheel up")<br>
> > > >> ifTrue: [120] ifFalse: [-120])<br>
> > > >> >>                 direction: direction<br>
> > > >> >>                 buttons: (keystrokeEvent buttons bitAnd: 2r01111)<br>
> > > >> "drop control key pressed for this conversion"<br>
> > > >> >>                 hand: keystrokeEvent hand<br>
> > > >> >>                 stamp: keystrokeEvent timeStamp!<br>
> > > >> >><br>
> > > >> >> Item was changed:<br>
> > > >> >>   ----- Method: HandMorph>>handleEvent: (in category<br>
> > > >> 'events-processing') -----<br>
> > > >> >>   handleEvent: unfilteredEvent<br>
> > > >> >><br>
> > > >> >>         | filteredEvent |<br>
> > > >> >>         owner ifNil: [^ unfilteredEvent  "not necessary but good<br>
> > style<br>
> > > >> -- see Morph >> #handleEvent:"].<br>
> > > >> >><br>
> > > >> >>         self logEvent: unfilteredEvent.<br>
> > > >> >><br>
> > > >> >>         "Mouse-over events occur really, really, really often. They<br>
> > > >> are kind of the heart beat of the Morphic UI process."<br>
> > > >> >>         unfilteredEvent isMouseOver ifTrue: [^ self sendMouseEvent:<br>
> > > >> unfilteredEvent].<br>
> > > >> >><br>
> > > >> >>         self showEvent: unfilteredEvent.<br>
> > > >> >>         self sendListenEvents: unfilteredEvent.<br>
> > > >> >><br>
> > > >> >>         filteredEvent := self sendFilterEventCapture:<br>
> > unfilteredEvent<br>
> > > >> for: nil.<br>
> > > >> >>         "filteredEvent := unfilteredEvent" " <-- use this to<br>
> > disable<br>
> > > >> global capture filters"<br>
> > > >> >><br>
> > > >> >>         filteredEvent wasIgnored ifTrue: [<br>
> > > >> >>                 self mouseOverHandler processMouseOver:<br>
> > lastMouseEvent.<br>
> > > >> >>                 ^ filteredEvent].<br>
> > > >> >><br>
> > > >> >>         filteredEvent isWindowEvent ifTrue: [<br>
> > > >> >>                 self sendEvent: filteredEvent focus: nil.<br>
> > > >> >>                 self mouseOverHandler processMouseOver:<br>
> > lastMouseEvent.<br>
> > > >> >>                 ^ filteredEvent].<br>
> > > >> >><br>
> > > >> >>         filteredEvent isKeyboard ifTrue:[<br>
> > > >> >>                 self sendKeyboardEvent: filteredEvent.<br>
> > > >> >>                 self mouseOverHandler processMouseOver:<br>
> > lastMouseEvent.<br>
> > > >> >>                 ^ filteredEvent].<br>
> > > >> >><br>
> > > >> >>         filteredEvent isDropEvent ifTrue:[<br>
> > > >> >>                 self sendEvent: filteredEvent focus: nil.<br>
> > > >> >>                 self mouseOverHandler processMouseOver:<br>
> > lastMouseEvent.<br>
> > > >> >>                 ^ filteredEvent].<br>
> > > >> >><br>
> > > >> >>         filteredEvent isMouse ifFalse: [<br>
> > > >> >>                 self mouseOverHandler processMouseOver:<br>
> > lastMouseEvent.<br>
> > > >> >>                 ^ filteredEvent].<br>
> > > >> >><br>
> > > >> >>         " ********** MOUSE EVENT *********** "<br>
> > > >> >><br>
> > > >> >>         lastMouseEvent := filteredEvent.<br>
> > > >> >><br>
> > > >> >>         "Check for pending drag or double click operations."<br>
> > > >> >>         mouseClickState ifNotNil:[<br>
> > > >> >>                 (mouseClickState handleEvent: filteredEvent from:<br>
> > > >> self) ifFalse:[<br>
> > > >> >>                         "Possibly dispatched #click: or something<br>
> > and<br>
> > > >> will not re-establish otherwise"<br>
> > > >> >>                         self mouseOverHandler processMouseOver:<br>
> > > >> lastMouseEvent.<br>
> > > >> >>                         ^ filteredEvent]].<br>
> > > >> >><br>
> > > >> >>         filteredEvent isMouseWheel ifTrue: [<br>
> > > >> >> +               self class sendMouseWheelToKeyboardFocus<br>
> > > >> >> +                       ifFalse: [self sendMouseEvent:<br>
> > filteredEvent]<br>
> > > >> >> +                       ifTrue: [self sendEvent: filteredEvent<br>
> > focus:<br>
> > > >> self keyboardFocus clear: [self keyboardFocus: nil]].<br>
> > > >> >> -               mouseWheelState ifNil: [mouseWheelState :=<br>
> > > >> MouseWheelState new].<br>
> > > >> >> -               mouseWheelState handleEvent: filteredEvent from:<br>
> > self.<br>
> > > >> >>                 self mouseOverHandler processMouseOver:<br>
> > lastMouseEvent.<br>
> > > >> >>                 ^ filteredEvent].<br>
> > > >> >><br>
> > > >> >>         filteredEvent isMove ifTrue:[<br>
> > > >> >>                 self position: filteredEvent position.<br>
> > > >> >>                 self sendMouseEvent: filteredEvent.<br>
> > > >> >>                 self mouseOverHandler processMouseOver:<br>
> > lastMouseEvent.<br>
> > > >> >>                 ^ filteredEvent].<br>
> > > >> >><br>
> > > >> >>         "Issue a synthetic move event if we're not at the position<br>
> > of<br>
> > > >> the event"<br>
> > > >> >>         filteredEvent position = self position<br>
> > > >> >>                 ifFalse: [self moveToEvent: filteredEvent].<br>
> > > >> >><br>
> > > >> >>         "Drop submorphs on button events"<br>
> > > >> >>         self hasSubmorphs<br>
> > > >> >>                 ifTrue:[self dropMorphs: filteredEvent]<br>
> > > >> >>                 ifFalse:[self sendMouseEvent: filteredEvent].<br>
> > > >> >><br>
> > > >> >>         self mouseOverHandler processMouseOver: lastMouseEvent.<br>
> > > >> >>         ^ filteredEvent "not necessary but good style -- see Morph<br>
> > >><br>
> > > >> #handleEvent:"    !<br>
> > > >> >><br>
> > > >> >> Item was changed:<br>
> > > >> >>   ----- Method: Integer>>explorerContents (in category<br>
> > > >> '*Morphic-Explorer') -----<br>
> > > >> >>   explorerContents<br>
> > > >> >><br>
> > > >> >>         ^#(<br>
> > > >> >>                 ('hexadecimal' 16)<br>
> > > >> >>                 ('octal' 8)<br>
> > > >> >>                 ('binary' 2)) collect: [ :each |<br>
> > > >> >>                         ObjectExplorerWrapper<br>
> > > >> >> +                               with: (self printStringBase: each<br>
> > > >> second)<br>
> > > >> >> +                               name: each first translated<br>
> > > >> >> -                               with: each first translated<br>
> > > >> >> -                               name: (self printStringBase: each<br>
> > > >> second)<br>
> > > >> >>                                 model: self ]!<br>
> > > >> >><br>
> > > >> >> Item was added:<br>
> > > >> >> + ----- Method: MouseWheelEvent<br>
> > > >> class>>convertScrollUnits:intoScrollDelta: (in category 'utility')<br>
> > -----<br>
> > > >> >> + convertScrollUnits: scrollUnits intoScrollDelta:<br>
> > > >> scrollDeltaPerMouseWheelNotch<br>
> > > >> >> +       "Convert the scrolling units provided by the VM into<br>
> > scrolling<br>
> > > >> delta (increment) used by Morph.<br>
> > > >> >> +       The morph knows how many scroll delta it wants per single<br>
> > > >> wheel notch.<br>
> > > >> >> +       I know how many scrolling units is generated by a single<br>
> > wheel<br>
> > > >> notch."<br>
> > > >> >> +<br>
> > > >> >> +       ^scrollUnits abs * scrollDeltaPerMouseWheelNotch // self<br>
> > > >> scrollUnitsPerMouseWheelNotch max: 1!<br>
> > > >> >><br>
> > > >> >> Item was added:<br>
> > > >> >> + ----- Method: MouseWheelEvent class>>minimalScrollUnitsPerEvent<br>
> > (in<br>
> > > >> category 'constants') -----<br>
> > > >> >> + minimalScrollUnitsPerEvent<br>
> > > >> >> +       "Answer how many scroll units a single mouse wheel event<br>
> > can<br>
> > > >> generate.<br>
> > > >> >> +       This reflects a value hardcoded in the VM.<br>
> > > >> >> +       The VM aggregate wheel events until this threshold is<br>
> > reached."<br>
> > > >> >> +<br>
> > > >> >> +       ^20!<br>
> > > >> >><br>
> > > >> >> Item was added:<br>
> > > >> >> + ----- Method: MouseWheelEvent<br>
> > class>>scrollUnitsPerMouseWheelNotch<br>
> > > >> (in category 'constants') -----<br>
> > > >> >> + scrollUnitsPerMouseWheelNotch<br>
> > > >> >> +       "Answer how many scroll units a single mouse wheel notch<br>
> > does<br>
> > > >> generate.<br>
> > > >> >> +       This reflects a value hardcoded in the VM.<br>
> > > >> >> +       The value is chosen high enough so as to enable:<br>
> > > >> >> +       - smoother scrolling on notch-less devices.<br>
> > > >> >> +       - while preserving Integer arithmetic<br>
> > > >> >> +       Interpretation (scaling) of scrolling units is left to the<br>
> > > >> client morphs.<br>
> > > >> >> +       Typically, 120 units (1 notch) represents 3 lines of text."<br>
> > > >> >> +<br>
> > > >> >> +       ^120!<br>
> > > >> >><br>
> > > >> >> Item was added:<br>
> > > >> >> + ----- Method: MouseWheelEvent>>horizontalScrollDelta: (in<br>
> > category<br>
> > > >> 'accessing') -----<br>
> > > >> >> + horizontalScrollDelta: scrollDeltaPerMouseWheelNotch<br>
> > > >> >> +       "Convert scrolling units into unsigned scrolling increment.<br>
> > > >> >> +       The morph knows how many scroll delta it wants per single<br>
> > > >> wheel notch.<br>
> > > >> >> +       Note that returned increment value is always positive,<br>
> > > >> regardless of direction."<br>
> > > >> >> +       ^self class convertScrollUnits: delta x intoScrollDelta:<br>
> > > >> scrollDeltaPerMouseWheelNotch!<br>
> > > >> >><br>
> > > >> >> Item was added:<br>
> > > >> >> + ----- Method: MouseWheelEvent>>setDirection (in category<br>
> > > >> 'initialization') -----<br>
> > > >> >> + setDirection<br>
> > > >> >> +       delta x > 0 ifTrue: [self setWheelRight].<br>
> > > >> >> +       delta x < 0 ifTrue: [self setWheelLeft].<br>
> > > >> >> +<br>
> > > >> >> +       delta y > 0 ifTrue: [self setWheelUp].<br>
> > > >> >> +       delta y < 0 ifTrue: [self setWheelDown].!<br>
> > > >> >><br>
> > > >> >> Item was added:<br>
> > > >> >> + ----- Method:<br>
> > > >> MouseWheelEvent>>setType:position:delta:buttons:hand:stamp: (in<br>
> > category<br>
> > > >> 'private') -----<br>
> > > >> >> + setType: evtType position: evtPos delta: evtDelta buttons:<br>
> > > >> evtButtons hand: evtHand stamp: stamp<br>
> > > >> >> +       type := evtType.<br>
> > > >> >> +       position := evtPos.<br>
> > > >> >> +       buttons := evtButtons.<br>
> > > >> >> +       source := evtHand.<br>
> > > >> >> +       wasHandled := false.<br>
> > > >> >> +       direction := 2r0000.<br>
> > > >> >> +       delta := evtDelta.<br>
> > > >> >> +       timeStamp := stamp.<br>
> > > >> >> +       self setDirection!<br>
> > > >> >><br>
> > > >> >> Item was added:<br>
> > > >> >> + ----- Method: MouseWheelEvent>>verticalScrollDelta: (in category<br>
> > > >> 'accessing') -----<br>
> > > >> >> + verticalScrollDelta: scrollDeltaPerMouseWheelNotch<br>
> > > >> >> +       "Convert scrolling units into unsigned scrolling increment.<br>
> > > >> >> +       The morph knows how many scroll delta it wants per single<br>
> > > >> wheel notch.<br>
> > > >> >> +       Note that returned increment value is always positive,<br>
> > > >> regardless of direction."<br>
> > > >> >> +       ^self class convertScrollUnits: delta y intoScrollDelta:<br>
> > > >> scrollDeltaPerMouseWheelNotch!<br>
> > > >> >><br>
> > > >> >> Item was removed:<br>
> > > >> >> - Object subclass: #MouseWheelState<br>
> > > >> >> -       instanceVariableNames: 'currentDelta'<br>
> > > >> >> -       classVariableNames: ''<br>
> > > >> >> -       poolDictionaries: ''<br>
> > > >> >> -       category: 'Morphic-Events'!<br>
> > > >> >><br>
> > > >> >> Item was removed:<br>
> > > >> >> - ----- Method: MouseWheelState>>handleEvent:from: (in category<br>
> > 'event<br>
> > > >> processing') -----<br>
> > > >> >> - handleEvent: aMouseWheelEvent from: aHand<br>
> > > >> >> -       "Every 120 units, raise the wheel flags for convenient<br>
> > mouse<br>
> > > >> wheel programming. We choose not to send multiple mouse-wheel events<br>
> > for<br>
> > > >> multiples of 120 because applications can always react to the actual<br>
> > delta<br>
> > > >> values if they want to do more scrolling or zooming."<br>
> > > >> >> -<br>
> > > >> >> -       | sign |<br>
> > > >> >> -       currentDelta := currentDelta + aMouseWheelEvent wheelDelta.<br>
> > > >> >> -<br>
> > > >> >> -       sign := currentDelta sign.<br>
> > > >> >> -       currentDelta := currentDelta abs.<br>
> > > >> >> -<br>
> > > >> >> -       (currentDelta x // 120) > 0 ifTrue: [<br>
> > > >> >> -               sign x = 1<br>
> > > >> >> -                       ifTrue: [aMouseWheelEvent setWheelRight]<br>
> > > >> >> -                       ifFalse: [aMouseWheelEvent setWheelLeft]].<br>
> > > >> >> -<br>
> > > >> >> -       (currentDelta y // 120) > 0 ifTrue: [<br>
> > > >> >> -               sign y = 1<br>
> > > >> >> -                       ifTrue: [aMouseWheelEvent setWheelUp]<br>
> > > >> >> -                       ifFalse: [aMouseWheelEvent setWheelDown]].<br>
> > > >> >> -<br>
> > > >> >> -       currentDelta := currentDelta \\ 120.<br>
> > > >> >> -       currentDelta := currentDelta * sign.<br>
> > > >> >> -<br>
> > > >> >> -       "Finally, send the event."<br>
> > > >> >> -       HandMorph sendMouseWheelToKeyboardFocus<br>
> > > >> >> -               ifFalse: [aHand sendMouseEvent: aMouseWheelEvent]<br>
> > > >> >> -               ifTrue: [aHand sendEvent: aMouseWheelEvent focus:<br>
> > > >> aHand keyboardFocus clear: [aHand keyboardFocus: nil]].<br>
> > > >> >> - !<br>
> > > >> >><br>
> > > >> >> Item was removed:<br>
> > > >> >> - ----- Method: MouseWheelState>>initialize (in category<br>
> > > >> 'initialize-release') -----<br>
> > > >> >> - initialize<br>
> > > >> >> -<br>
> > > >> >> -       super initialize.<br>
> > > >> >> -       currentDelta := 0@0.!<br>
> > > >> >><br>
> > > >> >> Item was changed:<br>
> > > >> >>   MorphicModel subclass: #ScrollPane<br>
> > > >> >>         instanceVariableNames: 'scrollBar scroller<br>
> > > >> retractableScrollBar scrollBarOnLeft getMenuSelector<br>
> > getMenuTitleSelector<br>
> > > >> hasFocus hScrollBar hScrollBarPolicy vScrollBarPolicy<br>
> > scrollBarThickness'<br>
> > > >> >> +       classVariableNames:<br>
> > 'HorizontalScrollDeltaPerMouseWheelNotch<br>
> > > >> UseRetractableScrollBars VerticalScrollDeltaPerMouseWheelNotch'<br>
> > > >> >> -       classVariableNames: 'UseRetractableScrollBars'<br>
> > > >> >>         poolDictionaries: ''<br>
> > > >> >>         category: 'Morphic-Windows'!<br>
> > > >> >><br>
> > > >> >>   !ScrollPane commentStamp: 'mk 8/9/2005 10:34' prior: 0!<br>
> > > >> >>   The scroller (a transform) of a scrollPane is driven by the<br>
> > > >> scrollBar.  The scroll values vary from 0.0, meaning zero offset to<br>
> > 1.0<br>
> > > >> meaning sufficient offset such that the bottom of the scrollable<br>
> > material<br>
> > > >> appears 3/4 of the way down the pane.  The total distance to achieve<br>
> > this<br>
> > > >> range is called the totalScrollRange.<br>
> > > >> >><br>
> > > >> >>   Basic clue about utilization of the ScrollPane class is given in:<br>
> > > >> >>         ScrollPane example1.<br>
> > > >> >>         ScrollPane example2.!<br>
> > > >> >><br>
> > > >> >> Item was added:<br>
> > > >> >> + ----- Method: ScrollPane<br>
> > > >> class>>horizontalScrollDeltaPerMouseWheelNotch (in category<br>
> > 'preferences')<br>
> > > >> -----<br>
> > > >> >> + horizontalScrollDeltaPerMouseWheelNotch<br>
> > > >> >> +<br>
> > > >> >> +       <preference: 'horizontal scroll increment per single mouse<br>
> > > >> wheel'<br>
> > > >> >> +               category: #scrolling<br>
> > > >> >> +               description: 'How many horizontal scroll increments<br>
> > > >> should be caused in response to a single mouse wheel notch.<br>
> > > >> >> + Typically, the scroll panes increment are about 1 character width<br>
> > > >> for list and text panes (see #scrollDeltaWidth).<br>
> > > >> >> + The default setting is 3 so as to match the most widely used<br>
> > > >> convention.'<br>
> > > >> >> +               type: #Number><br>
> > > >> >> +       ^ HorizontalScrollDeltaPerMouseWheelNotch ifNil: [3]!<br>
> > > >> >><br>
> > > >> >> Item was added:<br>
> > > >> >> + ----- Method: ScrollPane<br>
> > > >> class>>horizontalScrollDeltaPerMouseWheelNotch: (in category<br>
> > 'preferences')<br>
> > > >> -----<br>
> > > >> >> + horizontalScrollDeltaPerMouseWheelNotch: anIntegerOrNil<br>
> > > >> >> +<br>
> > > >> >> +       HorizontalScrollDeltaPerMouseWheelNotch := anIntegerOrNil!<br>
> > > >> >><br>
> > > >> >> Item was added:<br>
> > > >> >> + ----- Method: ScrollPane<br>
> > > >> class>>verticalScrollDeltaPerMouseWheelNotch (in category<br>
> > 'preferences')<br>
> > > >> -----<br>
> > > >> >> + verticalScrollDeltaPerMouseWheelNotch<br>
> > > >> >> +<br>
> > > >> >> +       <preference: 'vertical scroll increment per single mouse<br>
> > wheel'<br>
> > > >> >> +               category: #scrolling<br>
> > > >> >> +               description: 'How many vertical scroll increments<br>
> > > >> should be caused in response to a single mouse wheel notch.<br>
> > > >> >> + Typically, the scroll panes increment are one line height for<br>
> > list<br>
> > > >> and text panes (see #scrollDeltaHeight).<br>
> > > >> >> + The default setting is 3 so as to match the most widely used<br>
> > > >> convention.'<br>
> > > >> >> +               type: #Number><br>
> > > >> >> +       ^ VerticalScrollDeltaPerMouseWheelNotch ifNil: [3]!<br>
> > > >> >><br>
> > > >> >> Item was added:<br>
> > > >> >> + ----- Method: ScrollPane<br>
> > > >> class>>verticalScrollDeltaPerMouseWheelNotch: (in category<br>
> > 'preferences')<br>
> > > >> -----<br>
> > > >> >> + verticalScrollDeltaPerMouseWheelNotch: anIntegerOrNil<br>
> > > >> >> +<br>
> > > >> >> +       VerticalScrollDeltaPerMouseWheelNotch := anIntegerOrNil!<br>
> > > >> >><br>
> > > >> >> Item was changed:<br>
> > > >> >>   ----- Method: ScrollPane>>mouseWheel: (in category 'event<br>
> > handling')<br>
> > > >> -----<br>
> > > >> >>   mouseWheel: evt<br>
> > > >> >><br>
> > > >> >> +       evt isWheelUp ifTrue: [scrollBar scrollUp: (evt<br>
> > > >> verticalScrollDelta: self class<br>
> > verticalScrollDeltaPerMouseWheelNotch)].<br>
> > > >> >> +       evt isWheelDown ifTrue: [scrollBar scrollDown: (evt<br>
> > > >> verticalScrollDelta: self class<br>
> > verticalScrollDeltaPerMouseWheelNotch)].<br>
> > > >> >> +       evt isWheelLeft ifTrue: [hScrollBar scrollUp: (evt<br>
> > > >> horizontalScrollDelta: self class<br>
> > verticalScrollDeltaPerMouseWheelNotch)].<br>
> > > >> >> +       evt isWheelRight ifTrue: [hScrollBar scrollDown: (evt<br>
> > > >> horizontalScrollDelta: self class<br>
> > verticalScrollDeltaPerMouseWheelNotch)].!<br>
> > > >> >> -       evt isWheelUp ifTrue: [scrollBar scrollUp: 3].<br>
> > > >> >> -       evt isWheelDown ifTrue: [scrollBar scrollDown: 3].!<br>
> > > >> >><br>
> > > >> >> Item was changed:<br>
> > > >> >>   ----- Method: TextEditor>>hasMultipleLinesSelected (in category<br>
> > > >> 'typing support') -----<br>
> > > >> >>   hasMultipleLinesSelected<br>
> > > >> >> +       ^ self selection includesAnyOf: CharacterSet crlf!<br>
> > > >> >> -<br>
> > > >> >> -       ^ self hasSelection and: [self startBlock top < self<br>
> > stopBlock<br>
> > > >> top]!<br>
> > > >> >><br>
> > > >> >> Item was changed:<br>
> > > >> >> + (PackageInfo named: 'Morphic') postscript: '''Set a smoother<br>
> > > >> scrolling, especially useful for trackpads"<br>
> > > >> >> + HandMorph minimumWheelDelta: 20.<br>
> > > >> >> + Smalltalk sendMouseWheelEvents: true.'!<br>
> > > >> >> - (PackageInfo named: 'Morphic') postscript: 'PluggableListMorph<br>
> > > >> allSubInstancesDo: [:m |<br>
> > > >> >> -       m scroller layoutPolicy: TableLayout new.<br>
> > > >> >> -       m listMorph<br>
> > > >> >> -               cellPositioning: #leftCenter;<br>
> > > >> >> -               cellInset: 3@0;<br>
> > > >> >> -               vResizing: #shrinkWrap;<br>
> > > >> >> -               removeProperty: #errorOnDraw. "Just in case."<br>
> > > >> >> -       m updateList.<br>
> > > >> >> -       m hScrollBarPolicy: #never].<br>
> > > >> >> - '!<br>
> > > >> >><br>
> > > >> >><br>
> > > >> ><br>
> > > >><br>
> > > >><br>
> > > >><br>
> ><br>
> > ><br>
> ><br>
> ><br>
<br>
</div>
</span></font>
</body>
</html>