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

christoph.thiede at student.hpi.uni-potsdam.de christoph.thiede at student.hpi.uni-potsdam.de
Fri Apr 1 14:05:30 UTC 2022


=============== 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)
adjustSettingsForLowPerformance

    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].
    
    PluggableListMorph
        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.
    
    "Done."
    self updateLowPerformanceLabel: 'Settings were adjusted for optimal performance.' translated.

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

    | 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)
setPreferences
    "Preferences class defaultValueTableForCurrentRelease"

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

    "General User interaction"
    Preferences
        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."
    TextEditor
         autoEnclose: true ;
         autoIndent: true ;
         encloseSelection: true ;
         destructiveBackWord: false ;
         blinkingCursor: true ;
         dumbbellCursor: false.
    PluggableTextMorph simpleFrameAdornments: false.
    TextMorphForEditView draggableTextSelection: true.
    
    "Windows"
    SystemWindow reuseWindows: false.
    SystemWindow windowsRaiseOnClick: true.
    SystemWindow windowTitleActiveOnFirstClick: true.
    Model windowActiveOnFirstClick: false. "Not good for little screen real estate."
    Model useColorfulWindows: false. 

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

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

    "Rounded corners."
    Morph preferredCornerRadius: 8.
    SystemWindow roundedWindowCorners: false.
    DialogWindow roundedDialogCorners: false.
    MenuMorph roundedMenuCorners: false.
    PluggableButtonMorph roundedButtonCorners: false.
    ScrollBar roundedScrollBarLook: false.
    
    "Gradients."
    SystemWindow gradientWindow: false.
    DialogWindow gradientDialog: false.
    MenuMorph gradientMenu: false.
    PluggableButtonMorph gradientButton: false.
    ScrollBar gradientScrollBar: false.

    "Shadows"
    Preferences enable: #menuAppearance3d.
    Morph useSoftDropShadow: true.
    
    "Lists and Trees"
    PluggableListMorph
        filterableLists: true;
        clearFilterAutomatically: false;
        clearFilterDelay: 500;
        highlightHoveredRow: true;
        highlightPreSelection: false;
        menuRequestUpdatesSelection: true.
    PluggableTreeMorph
        filterByLabelsOnly: false;
        maximumSearchDepth: 1.
    
    "Standard Tools"
    TheWorldMainDockingBar
        showWorldMainDockingBar: true;
        showSecondsInClock: true;
        twentyFourHourClock: true.
    SearchBar useSmartSearch: true.
    Workspace shouldStyle: false.
    TranscriptStream
        forceUpdate: true;
        redirectToStdOut: false;
        characterLimit: 20000.
    Browser
        listClassesHierarchically: true;
        showClassIcons: true;
        showMessageIcons: true;
        sortMessageCategoriesAlphabetically: true.
    SystemBrowser browseWithDragNDrop: true.
    MessageSet useUnifiedMessageLabels: true.
    Preferences
        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.

    "Halo"
    Preferences
        enable: #showBoundsInHalo ;
        disable: #alternateHandlesLook;
        disable: #showDirectionHandles;
        enable: #biggerHandles.
    Morph
        haloForAll: true;
        metaMenuForAll: true.

    "System"
    NetNameResolver enableIPv6: false.
    Scanner
        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

    isCollapsed
        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 | 
                    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)
openAsTool
    "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)
openToolsAttachedToMouseCursor

-     <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)
openToolsAttachedToMouseCursor
-     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]}

["openToolsInHandStrategy.1.cs"]

---
Sent from Squeak Inbox Talk
["openToolsInHandStrategy.1.cs"]
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20220401/ef33a705/attachment.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: openToolsInHandStrategy.1.cs
Type: application/octet-stream
Size: 16352 bytes
Desc: not available
URL: <http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20220401/ef33a705/attachment.obj>


More information about the Squeak-dev mailing list