[squeak-dev] Review Request: openToolsInHandStrategy.1.cs

Jaromir Matas mail at jaromir.net
Sat Apr 2 18:22:04 UTC 2022

Hi Christoph,
I like the #always option :)
I’d like to repeat my suggestion to place the new window under the hand asymmetrically: I’m proposing an offset of 20-25% instead of 50% to avoid opening new windows partly outside of the screen if your hand is positioned near the upper or left screen edge.


Jaromír Matas

mail at jaromir.net

From: christoph.thiede at student.hpi.uni-potsdam.de<mailto:christoph.thiede at student.hpi.uni-potsdam.de>
Sent: Friday, April 1, 2022 16:05
To: squeak-dev at lists.squeakfoundation.org<mailto:squeak-dev at lists.squeakfoundation.org>
Subject: [squeak-dev] Review Request: openToolsInHandStrategy.1.cs

=============== Summary ===============

Change Set:        openToolsInHandStrategy
Date:            1 April 2022
Author:            Christoph Thiede

Revises preferences for opening tools in hand. Deprecates #openToolsAttachedToMouseCursor and replaces it with a new #openToolsInHandStrategy that can be set to #never, #always, or #clicks. The third mode preserves the behavior of the former preference, whereas the second mode is new and will open every tool in hand, independently on whether it was triggered via a mouse or keyboard interaction. This behavior has been requested by multiple Squeakers before. See: http://lists.squeakfoundation.org/pipermail/squeak-dev/2022-February/218981.html

Other changes in this patch:
- Update the preference wizard morph to support all strategies.
- Add commonly-used util #dontOpenToolsInHandDuring: on UIManager.
- While installing updates, do not open the transcript in the hand any longer to improve readability.
- Simplify SystemWindow>>#justDroppedInto:event:.

!! Merger note: !! When merging interactionModes.cs, make sure to move the new logic from SystemWindow>>#openAsTool to UIManager>>#shouldOpenToolsInHandNow.

=============== Postscript ===============

PreferenceWizardMorph removeSelector: #toggleAttachToolsToMouse

=============== Diff ===============

BrowseTest>>withImmediatelyOpeningWindowsDo: {private} · ct 3/26/2022 20:34 (changed)
withImmediatelyOpeningWindowsDo: aBlock
    "Turn off any preferences that defer to the user to open a window."
-     | openToolsAttachedToMouseCursor |
-     (UIManager default respondsTo: #openToolsAttachedToMouseCursor:) ifFalse:
-         [^aBlock value].

-     openToolsAttachedToMouseCursor := UIManager default openToolsAttachedToMouseCursor.
-     UIManager default openToolsAttachedToMouseCursor: false.
-     ^aBlock ensure:
-         [UIManager default openToolsAttachedToMouseCursor: openToolsAttachedToMouseCursor]
+     ^ UIManager dontOpenToolsInHandDuring: aBlock

MCMcmUpdater>>configureTranscript:during: {private} · ct 4/1/2022 15:26
+ configureTranscript: interactive during: aBlock
+     self flag: #hacked. "ct: Do not open transcript in hand to guarantee readability of update logs while the update is being performed. Otherwise, the transcript might stick at any corner of the display and cannot be moved before the update is completed."
+     ^ UIManager dontOpenToolsInHandDuring: [
+         | ensureTranscriptSetting |
+         ensureTranscriptSetting := MCConfiguration ensureOpenTranscript.
+         MCConfiguration ensureOpenTranscript: interactive.
+         ^ aBlock ensure:
+             [MCConfiguration ensureOpenTranscript: ensureTranscriptSetting]]

MCMcmUpdater>>doUpdate: {updating} · ct 4/1/2022 15:22 (changed)
doUpdate: interactive
    "Update the image by loading all pending updates from the server. If this is
    the default updater for the system, update the system version when complete.
    If interteractive use a modal notifier, otherwise only update the transcript.
    Flush all caches. If a previous download failed this is often helpful"

-     | previousUpdateLevel ensureTranscriptSetting |
+     | previousUpdateLevel |
    previousUpdateLevel := SystemVersion current highestUpdate.
    MCFileBasedRepository flushAllCaches.
-     ensureTranscriptSetting := MCConfiguration ensureOpenTranscript.
-     [MCConfiguration ensureOpenTranscript: interactive.
-      self updateFromRepository
-         ifNil:
-             [interactive ifTrue: [ ^self inform: 'Unable to retrieve updates from remote repository.' translated ].
-             Transcript cr; show: '========== Unable to retrieve updates from remote repository. ==========' translated; cr.
-             ^ self ]
-         ifNotNil: [:config| self logUpdateOf: config previousUpdateLevel: previousUpdateLevel interactive: interactive]]
-         ensure:
-             [MCConfiguration ensureOpenTranscript: ensureTranscriptSetting]
+     self configureTranscript: interactive during:
+         [self updateFromRepository
+             ifNil:
+                 [interactive ifTrue: [ ^self inform: 'Unable to retrieve updates from remote repository.' translated ].
+                 Transcript cr; show: '========== Unable to retrieve updates from remote repository. ==========' translated; cr.
+                 ^ self]
+             ifNotNil: [:config | self logUpdateOf: config previousUpdateLevel: previousUpdateLevel interactive: interactive]]

PreferenceWizardMorph>>adjustSettingsForLowPerformance {support} · ct 3/26/2022 20:41 (changed)

    self updateLowPerformanceLabel: 'Please wait, optimizing performance...' translated.
    self refreshWorld.

    self stateGradients "flat look" ifFalse: [self toggleGradients].
    self stateBlinkingCursor ifTrue: [self toggleBlinkingCursor].
    self stateFastDrag ifFalse: [self toggleFastDrag].

    self stateSoftShadows ifTrue: [self toggleSoftShadows].
    self stateHardShadows ifTrue: [self toggleHardShadows].

    self stateRoundedWindowLook ifTrue: [self toggleRoundedWindowLook].
    self stateRoundedButtonLook ifTrue: [self toggleRoundedButtonLook].

-     self stateAttachToolsToMouse ifTrue: [self toggleAttachToolsToMouse].
+     self stateAttachToolsToMouseForClicks ifTrue: [self toggleAttachToolsToMouseForClicks].
+     self stateAttachToolsToMouseAlways ifTrue: [self toggleAttachToolsToMouseAlways].
    self stateToolAndMenuIcons ifTrue: [self toggleToolAndMenuIcons].

    self stateSmartHorizontalSplitters ifTrue: [self toggleSmartHorizontalSplitters].
    self stateSmartVerticalSplitters ifTrue: [self toggleSmartVerticalSplitters].

        highlightHoveredRow: false;
        filterableLists: false;
        highlightPreSelection: true; "Feedback is important!"
        flashOnErrors: false.
    TheWorldMainDockingBar showSecondsInClock: false.
    Preferences disable: #balloonHelpInMessageLists.

    "Set simple background."
    self currentWorld setAsBackground: MorphicProject defaultFill.

    self updateLowPerformanceLabel: 'Settings were adjusted for optimal performance.' translated.

PreferenceWizardMorph>>initializePage04InteractionMore {initialization - pages} · ct 3/26/2022 20:38 (changed)

    | currentPage pane |
    currentPage := pages add: self createPage.
    pane := self createScrollPane.

    currentPage addMorphBack: (self createLabel: 'Choose more interaction settings' color: Color white).
    currentPage addMorphBack: pane.

    pane scroller firstSubmorph addAllMorphsBack: {
        self createCheckbox: 'Windows raise on click' translated for: #WindowsRaiseOnClick help: #(window raise).
        self createCheckbox: 'Windows always active' for: #WindowsAlwaysActive help: #(window content active).
        self createCheckbox: 'Window buttons always active' translated for: #WindowButtonsAlwaysActive help: #(window control active).
        self createVerticalSpace.
        self createCheckbox: 'Smart horizontal splitters' translated for: #SmartHorizontalSplitters help: #(horizontal splitter).
        self createCheckbox: 'Smart vertical splitters' translated for: #SmartVerticalSplitters help: #(vertical splitter).
        self createVerticalSpace.
        self createCheckbox: 'Filterable lists and trees' translated for: #FilterableLists help: 'Type something to filter lists. Press [return] to clear the filter. Press [backspace] to clear and restore prior selection.' translated.
        self createCheckbox: 'Filters clear if unfocused' translated for: #ClearFilterAutomatically help: #(filter clear).
        self createVerticalSpace.
-         self createCheckbox: 'Attach tools to mouse' translated for: #AttachToolsToMouse help: #(tools attach).
+         self createCheckbox: 'Attach tools to mouse - for clicks' translated for: #AttachToolsToMouseForClicks help: #(tools attach).
+         self createCheckbox: 'Attach tools to mouse - always' translated for: #AttachToolsToMouseAlways help: #(tools attach).

PreferenceWizardMorph>>stateAttachToolsToMouseAlways {actions - buttons} · ct 3/26/2022 20:40
+ stateAttachToolsToMouseAlways
+     ^ UIManager openToolsInHandAlways

PreferenceWizardMorph>>stateAttachToolsToMouseForClicks {actions - buttons} · ct 3/26/2022 20:40
+ stateAttachToolsToMouseForClicks
+     ^ UIManager openToolsInHandForClicks

PreferenceWizardMorph>>toggleAttachToolsToMouseAlways {actions - buttons} · ct 3/26/2022 20:44
+ toggleAttachToolsToMouseAlways
+     UIManager openToolsInHandAlways: UIManager openToolsInHandAlways not.
+     self changed: #stateAttachToolsToMouseAlways.
+     self changed: #stateAttachToolsToMouseForClicks.

PreferenceWizardMorph>>toggleAttachToolsToMouseForClicks {actions - buttons} · ct 3/26/2022 20:44
+ toggleAttachToolsToMouseForClicks
+     UIManager openToolsInHandForClicks: UIManager openToolsInHandForClicks not.
+     self changed: #stateAttachToolsToMouseAlways.
+     self changed: #stateAttachToolsToMouseForClicks.

ReleaseBuilder class>>setPreferences {scripts} · ct 3/26/2022 20:35 (changed)
    "Preferences class defaultValueTableForCurrentRelease"

"    Preferences outOfTheBox." "<-- uncomment after #defaultValueTableForCurrentRelease is fixed up."

    "General User interaction"
        enable: #generalizedYellowButtonMenu ;
        enable: #swapMouseButtons;
        disable: #mouseOverForKeyboardFocus.
    Morph indicateKeyboardFocus: true.
-     Project uiManager openToolsAttachedToMouseCursor: false.
+     Project uiManager openToolsInHandStrategy: #never.
    SearchBar useScratchPad: false.

    HandMorph sendMouseWheelToKeyboardFocus: false.
    HandMorph synthesizeMouseWheelEvents: true.

    "Text input."
         autoEnclose: true ;
         autoIndent: true ;
         encloseSelection: true ;
         destructiveBackWord: false ;
         blinkingCursor: true ;
         dumbbellCursor: false.
    PluggableTextMorph simpleFrameAdornments: false.
    TextMorphForEditView draggableTextSelection: true.

    SystemWindow reuseWindows: false.
    SystemWindow windowsRaiseOnClick: true.
    SystemWindow windowTitleActiveOnFirstClick: true.
    Model windowActiveOnFirstClick: false. "Not good for little screen real estate."
    Model useColorfulWindows: false.

        disable: #fastDragWindowForMorphic.
        gripThickness: 4;
        handleLength: 16.
        drawCornerResizeHandles: false;
        drawEdgeResizeHandles: false.
        showSplitterHandles: false;
        smartHorizontalSplitters: false;
        smartVerticalSplitters: false.

    "Scroll bars."
        enable: #scrollBarsNarrow;
        enable: #scrollBarsOnRight;
        enable: #alwaysHideHScrollbar;
        disable: #alwaysShowHScrollbar;
        disable: #alwaysShowVScrollbar.
        scrollBarsWithoutArrowButtons: true;
        scrollBarsWithoutMenuButton: true.
        useRetractableScrollBars: false.

    "Rounded corners."
    Morph preferredCornerRadius: 8.
    SystemWindow roundedWindowCorners: false.
    DialogWindow roundedDialogCorners: false.
    MenuMorph roundedMenuCorners: false.
    PluggableButtonMorph roundedButtonCorners: false.
    ScrollBar roundedScrollBarLook: false.

    SystemWindow gradientWindow: false.
    DialogWindow gradientDialog: false.
    MenuMorph gradientMenu: false.
    PluggableButtonMorph gradientButton: false.
    ScrollBar gradientScrollBar: false.

    Preferences enable: #menuAppearance3d.
    Morph useSoftDropShadow: true.

    "Lists and Trees"
        filterableLists: true;
        clearFilterAutomatically: false;
        clearFilterDelay: 500;
        highlightHoveredRow: true;
        highlightPreSelection: false;
        menuRequestUpdatesSelection: true.
        filterByLabelsOnly: false;
        maximumSearchDepth: 1.

    "Standard Tools"
        showWorldMainDockingBar: true;
        showSecondsInClock: true;
        twentyFourHourClock: true.
    SearchBar useSmartSearch: true.
    Workspace shouldStyle: false.
        forceUpdate: true;
        redirectToStdOut: false;
        characterLimit: 20000.
        listClassesHierarchically: true;
        showClassIcons: true;
        showMessageIcons: true;
        sortMessageCategoriesAlphabetically: true.
    SystemBrowser browseWithDragNDrop: true.
    MessageSet useUnifiedMessageLabels: true.
        enable: #annotationPanes;
        defaultAnnotationRequests: #(timeStamp author messageCategory implementorsCount allChangeSets);
        enable: #optionalButtons;
        disable: #diffsWithPrettyPrint;
        enable: #traceMessages;
        enable: #alternativeBrowseIt;
        enable: #menuWithIcons;
        enable: #visualExplorer;
        disable: #showSharedFlaps;
        maxBalloonHelpLineLength: 45.
    Preferences disable: #debugLogTimestamp.

        enable: #showBoundsInHalo ;
        disable: #alternateHandlesLook;
        disable: #showDirectionHandles;
        enable: #biggerHandles.
        haloForAll: true;
        metaMenuForAll: true.

    NetNameResolver enableIPv6: false.
        allowUnderscoreAsAssignment: true;
        prefAllowUnderscoreSelectors: true.

    Deprecation showDeprecationWarnings: true

    "that's all, folks"

SystemWindow>>justDroppedInto:event: {geometry} · ct 3/26/2022 20:09 (changed)
justDroppedInto: aMorph event: anEvent

        ifTrue: [self position: ((self position max: 0 at 0) grid: 8 at 8).
                collapsedFrame := self bounds]
        ifFalse: [fullFrame := self bounds].

    self beKeyWindow.
    self hasDropShadow: Preferences menuAppearance3d. "See #startDragFromLabel:."

    aMorph == self world ifTrue: [self assureLabelAreaVisible].

-     (Project uiManager openToolsAttachedToMouseCursor and: (self hasProperty: #initialDrop))
-         ifTrue: [
-             self removeProperty: #initialDrop.
+     (self removeProperty: #initialDrop)
+         ifNotNil: [
            (self submorphs detect: [:m | m isKindOf: BottomRightGripMorph] ifNone: [])
                ifNotNil: [:grip |
                        referencePoint: anEvent position - grip position;
                        backupAndHideTargetDropShadows. "See MorphicToolBuilder >> #open:"
                    self lookFocused.
                    anEvent hand newMouseFocus: grip]].

    ^super justDroppedInto: aMorph event: anEvent

SystemWindow>>openAsTool {*ToolBuilder-Morphic-opening} · ct 4/1/2022 15:34 (changed)
    "Open this window as a tool, that is, honor the preferences such as #reuseWindows and #openToolsAttachedToMouseCursor."
    | meOrSimilarWindow |
    meOrSimilarWindow := self openInWorldExtent: self extent.
-     (Project uiManager openToolsAttachedToMouseCursor "and: [ | event |
-         event := self currentEvent.
-         event isMouse and: [event isMouseUp]]") ifTrue: [
+     Project uiManager shouldOpenToolsInHandNow ifTrue: [
        meOrSimilarWindow setProperty: #initialDrop toValue: true.
        meOrSimilarWindow hasDropShadow: false.
        self currentHand attachMorph: meOrSimilarWindow].
    ^ meOrSimilarWindow

UIManager class>>dontOpenToolsInHandDuring: {support} · ct 3/26/2022 20:46
+ dontOpenToolsInHandDuring: aBlock
+     "Utility for various UI test/automation code."
+     | oldStrategy |
+     oldStrategy := self openToolsInHandStrategy.
+     self openToolsInHandStrategy: #never.
+     ^ aBlock ensure: [self openToolsInHandStrategy: oldStrategy]

UIManager class>>openToolsAttachedToMouseCursor {*60Deprecated-preferences} · ct 4/1/2022 15:40 (changed and recategorized)

-     <preference: 'Open Tools Attached to Mouse Cursor'
-         categoryList: #(Tools mouse)
-         description: 'If enabled, new tool windows will be attached to the mouse cursor to be positioned on screen with an additional click-drag. Only occurs if a mouse event triggered that tool opening to not interfere with keyboard-based interaction.'
-         type: #Boolean>
-     ^ OpenToolsAttachedToMouseCursor ifNil: [false]
+     self deprecated.
+     ^ self openToolsInHandStrategy ~= #never

UIManager class>>openToolsAttachedToMouseCursor: {*60Deprecated-preferences} · ct 3/26/2022 20:30 (changed and recategorized)
openToolsAttachedToMouseCursor: aBoolean

-     OpenToolsAttachedToMouseCursor := aBoolean.
+     self deprecated.
+     self openToolsInHandForClicks: aBoolean.

UIManager class>>openToolsInHandAlways {preferences} · ct 3/26/2022 20:25
+ openToolsInHandAlways
+     <preference: 'Open Tools Attached to Mouse Cursor - Always'
+         categoryList: #(Tools mouse)
+         description: 'If enabled, new tool windows will be attached to the mouse cursor, allowing users to position and resize them with a single click-drag gesture. NOTE: This mode activates the gesture always, even if the tool was opened via keyboard-based interaction.'
+         type: #Boolean>
+     ^ self openToolsInHandStrategy = #always

UIManager class>>openToolsInHandAlways: {preferences} · ct 3/26/2022 20:29
+ openToolsInHandAlways: aBoolean
+     self openToolsInHandStrategy:
+         (aBoolean ifTrue: [#always] ifFalse: [#never]).

UIManager class>>openToolsInHandForClicks {preferences} · ct 3/26/2022 20:25
+ openToolsInHandForClicks
+     <preference: 'Open Tools Attached to Mouse Cursor - for Clicks'
+         categoryList: #(Tools mouse)
+         description: 'If enabled, new tool windows will be attached to the mouse cursor, allowing users to position and resize them with a single click-drag gesture. NOTE: Only occurs if the tool was opened via a click; keyboard-based interactions remain unaffected.'
+         type: #Boolean>
+     ^ self openToolsInHandStrategy = #clicks

UIManager class>>openToolsInHandForClicks: {preferences} · ct 3/26/2022 20:28
+ openToolsInHandForClicks: aBoolean
+     self openToolsInHandStrategy:
+         (aBoolean ifTrue: [#clicks] ifFalse: [#never]).

UIManager class>>openToolsInHandStrategy {preferences} · ct 3/26/2022 20:32
+ openToolsInHandStrategy
+     self flag: #todo. "Once we have 'enumValues'-style preferences, merge #openToolsInHandAlways and #openToolsInHandForClicks here."
+     ^ OpenToolsInHandStrategy ifNil: [#never]

UIManager class>>openToolsInHandStrategy: {preferences} · ct 3/26/2022 20:15
+ openToolsInHandStrategy: aSymbol
+     self assert: (#(always clicks never) includes: aSymbol).
+     OpenToolsInHandStrategy := aSymbol.

UIManager>>openToolsAttachedToMouseCursor {*60Deprecated-accessing} · ct 4/1/2022 15:39 (changed and recategorized)
-     self flag: #todo. "mt: Let each instances of ui manager have its own setting."
+     self deprecated.
    ^ self class openToolsAttachedToMouseCursor

UIManager>>openToolsAttachedToMouseCursor: {*60Deprecated-accessing} · ct 3/26/2022 20:35 (changed and recategorized)
openToolsAttachedToMouseCursor: aBoolean
-     self flag: #todo. "mt: Let each instances of ui manager have its own setting."
-     self class openToolsAttachedToMouseCursor: aBoolean.
+     self deprecated.
+     ^ self class openToolsAttachedToMouseCursor: aBoolean

UIManager>>openToolsInHandStrategy {accessing} · ct 4/1/2022 15:44
+ openToolsInHandStrategy
+     self flag: #discuss. "Should each instance have its own setting?"
+     ^ self class openToolsInHandStrategy

UIManager>>openToolsInHandStrategy: {accessing} · ct 3/26/2022 20:19
+ openToolsInHandStrategy: aBoolean
+     self class openToolsInHandStrategy: aBoolean.

UIManager>>shouldOpenToolsInHandNow {accessing} · ct 4/1/2022 15:43
+ shouldOpenToolsInHandNow
+     ^ self openToolsInHandStrategy caseOf:
+         {[#never] -> [false].
+         [#clicks] -> [
+             | event |
+             self flag: '<<<<<<<<< workingCopy'. "ct: When merging interactionMode.cs, paste new logic from #openAsTool here!"
+             event := self currentEvent.
+             event isMouse or: [event isDropEvent]].
+         [#always] -> [true]}


Sent from Squeak Inbox Talk<https://github.com/hpi-swa-lab/squeak-inbox-talk>

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20220402/ec1a3553/attachment.html>

More information about the Squeak-dev mailing list