<div id="__MailbirdStyleContent" style="font-size: 10pt;font-family: Arial;color: #000000;text-align: left" dir="ltr">
                                        > <span style="font-family: Calibri, Helvetica, sans-serif;font-size: 16px">is it legitimate to use #ignore outside an event filter, for instance in the example I gave in my last message?</span><div><span style="font-family: Calibri, Helvetica, sans-serif;font-size: 16px"><br></span></div><div><span style="font-family: Calibri, Helvetica, sans-serif;font-size: 16px">Not if you want to write robust code.</span></div><div><span style="font-family: Calibri, Helvetica, sans-serif;font-size: 16px"><br></span></div><div><span style="font-family: Calibri, Helvetica, sans-serif;font-size: 16px">> </span><span style="font-family: Calibri, Helvetica, sans-serif;font-size: 16px">Could you give me an example of where the framework needs to rely on #wasHandled not being reset?</span></div><div><span style="font-family: Calibri, Helvetica, sans-serif;font-size: 16px"><br></span></div><div><span style="font-family: Calibri, Helvetica, sans-serif;font-size: 16px">Why does it matter? Your code will be more robust if you treat event objects as read-only. If you choose to ignore this advice, it will just make it harder to evolve the framework without breaking existing code.</span></div><div><span style="font-family: Calibri, Helvetica, sans-serif;font-size: 16px"><br></span></div><div><span style="font-family: Calibri, Helvetica, sans-serif;font-size: 16px">Best,</span><br></div><div><span style="font-family: Calibri, Helvetica, sans-serif;font-size: 16px">Marcel</span></div><div class="mb_sig"></div>
                                        <blockquote class="history_container" type="cite" style="border-left-style: solid;border-width: 1px;margin-top: 20px;margin-left: 0px;padding-left: 10px;min-width: 500px">
                        <p style="color: #AAAAAA; margin-top: 10px;">Am 29.11.2021 21:43:43 schrieb Thiede, Christoph <christoph.thiede@student.hpi.uni-potsdam.de>:</p><div style="font-family:Arial,Helvetica,sans-serif">

<div id="divtagdefaultwrapper" style="font-size: 12pt;color: #000000;font-family: Calibri,Helvetica,sans-serif" dir="ltr">
<p>Hi Marcel,</p>
<p><br>
</p>
<p>is it legitimate to use #ignore outside an event filter, for instance in the example I gave in my last message?</p>
<p><br>
</p>
<p>If not: Could you give me an example of where the framework needs to rely on #wasHandled not being reset? :-) Maybe we could document #wasHandled as the only property that should be manipulated by Morphic applications.</p>
<p><br>
</p>
<p>Best,</p>
<p>Christoph</p>
</div>
<hr style="display:inline-block;width:98%" tabindex="-1">
<div id="divRplyFwdMsg" dir="ltr"><span style="font-family: Calibri, sans-serif;color: #000000"><b>Von:</b> Squeak-dev <squeak-dev-bounces@lists.squeakfoundation.org> im Auftrag von Taeumel, Marcel<br>
<b>Gesendet:</b> Montag, 29. November 2021 17:47:32<br>
<b>An:</b> squeak-dev<br>
<b>Betreff:</b> Re: [squeak-dev] Merge Request: pbKeyboard.1.cs</span>
<div> </div>
</div>
<div>
<div id="__MailbirdStyleContent" style="font-size: 10pt;font-family: Arial;color: #000000;text-align: left" dir="ltr">
Hi Christoph --
<div><br>
</div>
<div>Well, the framework developer has to rely on something. Having a virtually immutable event object in the client code is one of those "somethings" ;-) That's why there is an extra #ignore protocol for event filters.</div>
<div><br>
</div>
<div>Best,</div>
<div>Marcel</div>
<div class="mb_sig"></div>
<blockquote class="history_container" type="cite" style="border-left-style: solid;border-width: 1px;margin-top: 20px;margin-left: 0px;padding-left: 10px;min-width: 500px">
<p style="color: #AAAAAA; margin-top: 10px;">Am 27.11.2021 21:32:55 schrieb christoph.thiede@student.hpi.uni-potsdam.de <christoph.thiede@student.hpi.uni-potsdam.de>:</p>
<div style="font-family:Arial,Helvetica,sans-serif">Hi Marcel,<br>
<br>
thanks for merging! :-)<br>
<br>
> Also note that MorphicEvent >> #wasHandled: is not public! It belongs to internal event-dispatching logic. Clients should never mess with this flag except when overwriting #handle*: methods.<br>
<br>
This is a pity, can't we convert this into a public protocol? I have used this in many different situations already - it just allows you to express certain pieces of logic more compactly than repeating yourself in #handlesKey...: and #key...: (or even overriding
 #handleKey..., which is also private). Similar to EAFP vs LBYL.<br>
<br>
See also Morphic-ct.1777 (inbox) for another example.<br>
<br>
Best,<br>
Christoph<br>
<br>
<span style="color: #808080">---<br>
</span><span style="color: #808080"><i>Sent from </i></span><span style="color: #808080"><i><a href="https://github.com/hpi-swa-lab/squeak-inbox-talk"><u><span style="color: #808080">Squeak Inbox Talk</span></u></a></i></span><br>
<br>
On 2021-11-26T17:54:11+01:00, marcel.taeumel@hpi.de wrote:<br>
<br>
> Merged.<br>
> Am 06.11.2021 21:47:16 schrieb christoph.thiede at student.hpi.uni-potsdam.de <christoph.thiede at student.hpi.uni-potsdam.de>:<br>
> ==================== Summary ====================<br>
> <br>
> Change Set:        pbKeyboard<br>
> Date:            2 November 2021<br>
> Author:            Christoph Thiede<br>
> <br>
> This changeset improves keyboard shortcut for preference button in the PreferenceBrowser. You can now select a preference in the browser and press escape to trigger the menu or cmd + (m|b | n | i | c | C) to browse senders/implementors / inspect the preference,
 or copy its content, resp. Also fixes up a few Law of Demeter violations in PBPreferenceView and improves multilingual support.<br>
> <br>
> =============== Diff ===============<br>
> <br>
> PBPreferenceButtonMorph>>handlesKeyboard: {event handling} · ct 11/1/2021 22:54<br>
> + handlesKeyboard: anEvent<br>
> +<br>
> +     ^ anEvent isKeystroke<br>
> <br>
> PBPreferenceButtonMorph>>highlightOn {highlighting} · ct 11/1/2021 23:14 (changed)<br>
> highlightOn<br>
>     <br>
>     self color: ((UserInterfaceTheme current get: #selectionColor for: PluggableListMorph) ifNil: [Color gray alpha: 0.1]).<br>
> <br>
>     self label<br>
>         color: ((UserInterfaceTheme current get: #selectionTextColor for: PluggableListMorph) ifNil: [Color black]);<br>
>         font: (((UserInterfaceTheme current get: #font for: PluggableListMorph) ifNil: [TextStyle defaultFont])<br>
>             emphasized: TextEmphasis bold emphasisCode).<br>
>     <br>
> -     self addExtraControls.<br>
> +     self addExtraControls.<br>
> +     <br>
> +     self currentHand newKeyboardFocus: self.<br>
> <br>
> PBPreferenceButtonMorph>>keyStroke: {event handling} · ct 11/1/2021 23:02<br>
> + keyStroke: anEvent<br>
> +<br>
> +     ^ self preferenceView keyStroke: anEvent browser: self model<br>
> <br>
> PBPreferenceView>>keyStroke:browser: {user interface} · ct 11/2/2021 15:41<br>
> + keyStroke: anEvent browser: aPreferenceBrowser<br>
> +<br>
> +     anEvent commandKeyPressed<br>
> +         ifFalse: [<br>
> +             anEvent keyCharacter = Character escape<br>
> +                 ifTrue: [^ self offerPreferenceNameMenu: aPreferenceBrowser].<br>
> +             ^ anEvent wasHandled: false].<br>
> +     <br>
> +     anEvent keyCharacter<br>
> +         caseOf: {<br>
> +             [$b] -> [aPreferenceBrowser findCategoryFromPreference: self preference].<br>
> +             [$c] -> [self copyName].<br>
> +             [$C] -> [self copyCode].<br>
> +             [$i] -> [self preference inspect].<br>
> +             [$m] -> [self browse].<br>
> +             [$n] -> [self browseSenders]}<br>
> +         otherwise: [anEvent wasHandled: false].<br>
> <br>
> PBPreferenceView>>offerPreferenceNameMenu: {user interface} · ct 11/2/2021 15:44 (changed)<br>
> offerPreferenceNameMenu: aPreferenceBrowser<br>
>     "the user clicked on a preference name -- put up a menu"<br>
> <br>
>     | aMenu readableName |<br>
>     readableName := self preference readableName.<br>
>     aMenu := MenuMorph new<br>
>         defaultTarget: self preference;<br>
>         addTitle: readableName.<br>
> <br>
>     (Preferences okayToChangeProjectLocalnessOf: self preference name) ifTrue:<br>
>         [aMenu<br>
>             addUpdating: #isProjectLocalString target: self preference action: #toggleProjectLocalness;<br>
> -             balloonTextForLastItem: 'Some preferences are best applied uniformly to all projects, and others are best set by each individual project. If this item is checked, then this preference will be printed in bold and will have a separate value for
 each project'].<br>
> +             balloonTextForLastItem: 'Some preferences are best applied uniformly to all projects, and others are best set by each individual project. If this item is checked, then this preference will be printed in bold and will have a separate value for
 each project' translated].<br>
> <br>
>     aMenu<br>
>         addLine;<br>
> -         add: 'browse senders' translated<br>
> -             target: self systemNavigation<br>
> -             selector: #browseAllSelect:name:autoSelect:<br>
> -             argumentList: {<br>
> -                 [:m | self preference selectors anySatisfy: [:sel | m hasLiteral: sel]].<br>
> -                 'Preference senders: {1}' translated format: {self preference name}.<br>
> -                 self preference selectors first };<br>
> -         balloonTextForLastItem: 'This will open a method-list browser on all methods that the send the preference "'<br>
> -             , readableName , '".'.<br>
> +         add: 'browse senders (n)' translated<br>
> +             action: #browseSenders;<br>
> +         balloonTextForLastItem: ('This will open a method-list browser on all methods that the send the preference "{1}".' translated format: {readableName}).<br>
>     self preference provider ifNotNil: [<br>
>         aMenu<br>
> -             add: 'browse implementation' translated<br>
> -                 target: ToolSet<br>
> -                 selector: #browse:selector:<br>
> -                 argumentList: {<br>
> -                     self preference provider class.<br>
> -                     self preference selectors first };<br>
> -             balloonTextForLastItem: 'This will open a browser on the method that stores the preference "' , readableName , '".'].<br>
> +             add: 'browse implementation (m)' translated<br>
> +                 action: #browse;<br>
> +             balloonTextForLastItem: ('This will open a browser on the method that stores the preference "{1}".' translated format: {readableName})].<br>
>     aMenu<br>
> -         add: 'inspect preference' translated<br>
> -             target: self preference<br>
> -             selector: #inspect;<br>
> -         balloonTextForLastItem: 'This will open an Inspector on the preference "' , readableName , '".'.<br>
> +         add: 'inspect preference (i)' translated<br>
> +             action: #inspect;<br>
> +         balloonTextForLastItem: ('This will open an inspector on the preference "{1}".' translated format: {readableName}).<br>
>     aMenu<br>
>         addLine;<br>
> -         add: 'show category'<br>
> +         add: 'show category (b)' translated<br>
>             target: aPreferenceBrowser<br>
>             selector: #findCategoryFromPreference:<br>
>             argument: self preference;<br>
> -         balloonTextForLastItem: 'Allows you to find out which category, or categories, this preference belongs to.'.<br>
> +         balloonTextForLastItem: 'Allows you to find out which category, or categories, this preference belongs to.' translated.<br>
> <br>
>     Smalltalk isMorphic ifTrue:<br>
>         [aMenu<br>
> -             add: 'hand me a button for this preference'<br>
> +             add: 'hand me a button for this preference' translated<br>
>                 target: self<br>
>                 selector: #tearOffButton;<br>
> -             balloonTextForLastItem: 'Will give you a button that governs this preference, which you may deposit wherever you wish'].<br>
> +             balloonTextForLastItem: 'Will give you a button that governs this preference, which you may deposit wherever you wish' translated].<br>
> <br>
>     aMenu<br>
> -         add: 'copy name to clipboard'<br>
> -             target: self preference<br>
> -             selector: #copyName;<br>
> -         balloonTextForLastItem: 'Copy the name of the preference to the text clipboard, so that you can paste into code somewhere'.<br>
> +         add: 'copy name to clipboard (c)' translated<br>
> +             action: #copyName;<br>
> +         balloonTextForLastItem: 'Copy the name of the preference to the text clipboard, so that you can paste into code somewhere' translated.<br>
>     aMenu<br>
> -         add: 'copy code to clipboard'<br>
> -             target: self preference<br>
> -             selector: #copyCode;<br>
> -         balloonTextForLastItem: 'Copy the code to access the current preference value to the clipboard, so that you can paste into code somewhere'.<br>
> +         add: 'copy code to clipboard (C)' translated<br>
> +             action: #copyCode;<br>
> +         balloonTextForLastItem: 'Copy the code to access the current preference value to the clipboard, so that you can paste into code somewhere' translated.<br>
> <br>
>     aMenu popUpInWorld<br>
> <br>
> PragmaPreference>>browse {browsing} · ct 11/1/2021 22:56<br>
> + browse<br>
> +<br>
> +     ToolSet<br>
> +         browse: self provider class<br>
> +         selector: self selectors first.<br>
> <br>
> Preference>>browse {browsing} · ct 11/1/2021 22:56<br>
> + browse<br>
> +<br>
> +     ToolSet<br>
> +         browse: Preferences class<br>
> +         selector: self selectors first.<br>
> <br>
> Preference>>browseSenders {browsing} · ct 11/1/2021 22:42<br>
> + browseSenders<br>
> +<br>
> +     self systemNavigation<br>
> +         browseAllSelect: [:m | self selectors anySatisfy: [:sel | m hasLiteral: sel]]<br>
> +         name: ('Preference senders: {1}' translated format: {self name})<br>
> +         autoSelect: self selectors first.<br>
> <br>
> PreferenceBrowser>>findCategoryFromPreference: {find} · ct 11/2/2021 15:03 (changed)<br>
> findCategoryFromPreference: aPreference<br>
>     "Find all categories in which the preference occurs"<br>
> <br>
> -     | aMenu|<br>
> -     aMenu := MenuMorph new defaultTarget: self.<br>
> +     | categories menu |<br>
> +     categories := aPreference categoryList.<br>
> +     categories size = 0<br>
> +         ifTrue: [^ self].<br>
> +     categories size = 1<br>
> +         ifTrue: [^ self selectedCategory: categories first].<br>
> +     <br>
> +     menu := MenuMorph new defaultTarget: self.<br>
>     aPreference categoryList do:<br>
> -         [:aCategory | aMenu add: aCategory target: self selector: #selectedCategory: argument: aCategory].<br>
> -     aMenu popUpInWorld<br>
> +         [:aCategory | menu add: aCategory target: self selector: #selectedCategory: argument: aCategory].<br>
> +     menu popUpInWorld<br>
> <br>
> PreferenceBrowserMorph>>assureKeyboardFocus: {event handling} · ct 11/1/2021 23:14<br>
> + assureKeyboardFocus: aHandMorph<br>
> +<br>
> +     aHandMorph keyboardFocus = self<br>
> +         ifTrue: [^ self].<br>
> +     <br>
> +     (aHandMorph keyboardFocus notNil and: [aHandMorph keyboardFocus hasOwner: self])<br>
> +         ifTrue: [^ self].<br>
> +     <br>
> +     aHandMorph newKeyboardFocus: self.<br>
> <br>
> PreferenceBrowserMorph>>mouseDownOn:event: {event handling} · ct 11/1/2021 23:13 (changed)<br>
> mouseDownOn: aPreferenceView event: anEvent<br>
> -     anEvent hand newKeyboardFocus: self preferenceList scroller.<br>
> +     self assureKeyboardFocus: anEvent hand.<br>
>     anEvent yellowButtonPressed<br>
>         ifTrue: [aPreferenceView offerPreferenceNameMenu: self model]<br>
> <br>
> PreferenceView>>browse {user interface} · ct 11/1/2021 22:43<br>
> + browse<br>
> +<br>
> +     ^ self preference browse<br>
> <br>
> PreferenceView>>browseSenders {user interface} · ct 11/1/2021 22:42<br>
> + browseSenders<br>
> +<br>
> +     ^ self preference browseSenders<br>
> <br>
> <br>
> ---<br>
> Sent from Squeak Inbox Talk [https://github.com/hpi-swa-lab/squeak-inbox-talk]<br>
> -------------- next part --------------<br>
> An HTML attachment was scrubbed...<br>
> URL: <http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20211126/aace27ea/attachment.html><br>
> <br>
> </div>
</blockquote>
</div>
</div>
</div></blockquote></div>