Modifying tooltips in Squeak

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
4 messages Options
MJK
Reply | Threaded
Open this post in threaded view
|

Modifying tooltips in Squeak

MJK
Hello,

I'm trying to learn Smalltalk and to understand the Squeak environment. I've done a couple of small applications and I've been learning basics of the language itself and the environment but now I'd like to learn something more concrete about Squeak. I thought that I would try to make some improvements and customizations for myself and learn that way.

The first project: to modify those quite comic-like balloon tooltips. But I'm not sure where to start. I have been poking around with BalloonMorph and managed to change the border width and the tooltip color, but I'm not sure if that is the right place to modify the appearance of the tooltips. I also don't understand where the tooltip gets those polygon coordinates that shape the balloon.

Could anyone give me some pointers, how to get started with the tooltip customization?

Thanks,

Matti Kärki
Reply | Threaded
Open this post in threaded view
|

Re: Modifying tooltips in Squeak

dcorking
MJK wrote:
> I also
> don't understand where the tooltip gets those polygon coordinates that shape
> the balloon.

As far as I can tell it is in
BalloonMorph class getVertices:

Hope that helps, David
_______________________________________________
Beginners mailing list
[hidden email]
http://lists.squeakfoundation.org/mailman/listinfo/beginners
MJK
Reply | Threaded
Open this post in threaded view
|

Re: Modifying tooltips in Squeak

MJK
dcorking wrote
As far as I can tell it is in
BalloonMorph class getVertices:
Thank you! That was it!

I already looked the getVertices: method but didn't realize that the code there actually created the balloon shape. It took me a while to understand what was going on. Now that I can see what is happening, I was able to rewrite the method and now my tooltips look much more enjoyable: http://i.imgur.com/BXdMA.png

-Matti
Reply | Threaded
Open this post in threaded view
|

Re: Modifying tooltips in Squeak

dcorking
I think it is neat how succinctly the code creates the triangular
callout pointing to the target.

I found that it was particularly hard to figure out how BalloonMorph
works, because when I put a breakpoint in it, Squeak would usually
freeze and wouldn't respond to the user interrupt.

I am not sure why: I think that by hovering over a morph with a
balloonText, I created a flood of breaks. My alternate hypothesis is
that it somehow blocked the process that gave me control of the hand
pointer.

I just updated my image from 4.3 to trunk, and while the freeze still
occurs, the new image saved a useful SqueakDebug.log file at the
breakpoint.

Have fun!

David

BreakPoint:
27 January 2012 1:57:07.022 pm

VM: Mac OS - Smalltalk
Image: Squeak4.3 [latest update: #11860]

SecurityManager state:
Restricted: false
FileAccess: true
SocketAccess: true
Working Dir /Users/dcorking/Applications/squeak/Squeak4.3
Trusted Dir /foobar/tooBar/forSqueak/bogus
Untrusted Dir /Users/dcorking/Library/Preferences/Squeak/Internet/My Squeak

BalloonMorph class(Object)>>break
        Receiver: BalloonMorph
        Arguments and temporary variables:

        Receiver's instance variables:
                superclass: PolygonMorph
                methodDict: a
MethodDictionary(#adjustedCenter->(BalloonMorph>>#adjustedCenter
...etc...
                format: 172
                instanceVariables: #('target' 'offsetFromTarget' 'balloonOwner')
                organization: ('accessing' balloonOwner)
('initialization' defaultBorderColor d...etc...
                subclasses: nil
                name: #BalloonMorph
                classPool: a Dictionary(#BalloonColor->(TranslucentColor r: 0.91 g:
0.94 b: 1.0...etc...
                sharedPools: nil
                environment: Smalltalk globals "a SystemDictionary with lots of globals"
                category: #'Morphic-Widgets'

BalloonMorph class>>getVertices:
        Receiver: BalloonMorph
        Arguments and temporary variables:
                t1: 0@0 corner: 104@14
                t2: nil
        Receiver's instance variables:
                superclass: PolygonMorph
                methodDict: a
MethodDictionary(#adjustedCenter->(BalloonMorph>>#adjustedCenter
...etc...
                format: 172
                instanceVariables: #('target' 'offsetFromTarget' 'balloonOwner')
                organization: ('accessing' balloonOwner)
('initialization' defaultBorderColor d...etc...
                subclasses: nil
                name: #BalloonMorph
                classPool: a Dictionary(#BalloonColor->(TranslucentColor r: 0.91 g:
0.94 b: 1.0...etc...
                sharedPools: nil
                environment: Smalltalk globals "a SystemDictionary with lots of globals"
                category: #'Morphic-Widgets'

BalloonMorph class>>string:for:corner:
        Receiver: BalloonMorph
        Arguments and temporary variables:
                str: 'browse class hierarchy'
                morph: a PluggableButtonMorphPlus(3898)
                cornerName: #bottomLeft
                tm: a TextMorph(3026)
                vertices: nil
        Receiver's instance variables:
                superclass: PolygonMorph
                methodDict: a
MethodDictionary(#adjustedCenter->(BalloonMorph>>#adjustedCenter
...etc...
                format: 172
                instanceVariables: #('target' 'offsetFromTarget' 'balloonOwner')
                organization: ('accessing' balloonOwner)
('initialization' defaultBorderColor d...etc...
                subclasses: nil
                name: #BalloonMorph
                classPool: a Dictionary(#BalloonColor->(TranslucentColor r: 0.91 g:
0.94 b: 1.0...etc...
                sharedPools: nil
                environment: Smalltalk globals "a SystemDictionary with lots of globals"
                category: #'Morphic-Widgets'

BalloonMorph class>>string:for:
        Receiver: BalloonMorph
        Arguments and temporary variables:
                str: 'browse class hierarchy'
                morph: a PluggableButtonMorphPlus(3898)
        Receiver's instance variables:
                superclass: PolygonMorph
                methodDict: a
MethodDictionary(#adjustedCenter->(BalloonMorph>>#adjustedCenter
...etc...
                format: 172
                instanceVariables: #('target' 'offsetFromTarget' 'balloonOwner')
                organization: ('accessing' balloonOwner)
('initialization' defaultBorderColor d...etc...
                subclasses: nil
                name: #BalloonMorph
                classPool: a Dictionary(#BalloonColor->(TranslucentColor r: 0.91 g:
0.94 b: 1.0...etc...
                sharedPools: nil
                environment: Smalltalk globals "a SystemDictionary with lots of globals"
                category: #'Morphic-Widgets'

PluggableButtonMorphPlus(Morph)>>showBalloon:hand:
        Receiver: a PluggableButtonMorphPlus(3898)
        Arguments and temporary variables:
                msgString: 'browse class hierarchy'
                aHand: a HandMorph(3216)
                w: a PasteUpMorph(1622) [world]
                balloon: nil
                h: a HandMorph(3216)
        Receiver's instance variables:
                bounds: 505@221 corner: 581@243
                owner: a PluggablePanelMorph(3222)
                submorphs: {an AlignmentMorph(1790)}
                fullBounds: 505@221 corner: 581@243
                color: (Color r: 0.906 g: 0.906 b: 0.906)
                extension: a MorphExtension (3108) [balloonText]  [other:
(layoutPolicy -> a T...etc...
                borderWidth: 1
                borderColor: Color gray
                model: a Browser
                label: 'hierarchy'
                getStateSelector: nil
                actionSelector: #classHierarchy
                getLabelSelector: nil
                getMenuSelector: nil
                shortcutCharacter: nil
                askBeforeChanging: false
                triggerOnMouseDown: false
                offColor: Color white
                onColor: Color veryLightGray
                feedbackColor: Color red
                showSelectionFeedback: false
                allButtons: nil
                arguments: nil
                argumentsProvider: nil
                argumentsSelector: nil
                style: nil
                enabled: true
                action: nil
                getColorSelector: nil
                getEnabledSelector: nil
                updateMap: nil

HandMorph>>spawnBalloonFor:
        Receiver: a HandMorph(3216)
        Arguments and temporary variables:
                aMorph: a PluggableButtonMorphPlus(3898)
        Receiver's instance variables:
                bounds: 549@233 corner: 565@249
                owner: a PasteUpMorph(1622) [world]
                submorphs: #()
                fullBounds: 549@233 corner: 565@249
                color: Color blue
                extension: a MorphExtension (539) [eventHandler = an EventHandler]
                mouseFocus: nil
                keyboardFocus: nil
                eventListeners: nil
                mouseListeners: nil
                keyboardListeners: a WeakArray(a DockingBarMorph(3368))
                mouseClickState: nil
                mouseOverHandler: a MouseOverHandler
                lastMouseEvent: [549@232 549@233 mouseMove 177917]
                targetOffset: 8@4
                damageRecorder: a DamageRecorder
                cacheCanvas: nil
                cachedCanvasHasHoles: true
                temporaryCursor: nil
                temporaryCursorOffset: nil
                hardwareCursor: nil
                hasChanged: true
                savedPatch: nil
                userInitials: ''
                lastEventBuffer: #(1 177917 549 233 0 0 0 1)
                genieGestureProcessor: nil
                keyboardInterpreter: a MacUnicodeInputInterpreter

MorphicAlarm(MessageSend)>>value
        Receiver: MorphicAlarm(#spawnBalloonFor: -> a HandMorph(3216))
        Arguments and temporary variables:

        Receiver's instance variables:
                receiver: a HandMorph(3216)
                selector: #spawnBalloonFor:
                arguments: {a PluggableButtonMorphPlus(3898)}
                scheduledTime: 178460
                sequenceNumber: 1951
                numArgs: 1

MorphicAlarm>>value:
        Receiver: MorphicAlarm(#spawnBalloonFor: -> a HandMorph(3216))
        Arguments and temporary variables:
                anArgument: 178466
                nArgs: 1
        Receiver's instance variables:
                receiver: a HandMorph(3216)
                selector: #spawnBalloonFor:
                arguments: {a PluggableButtonMorphPlus(3898)}
                scheduledTime: 178460
                sequenceNumber: 1951
                numArgs: 1

[] in WorldState>>triggerAlarmsBefore:
        Receiver: a WorldState
        Arguments and temporary variables:
                nowTime: a MorphicAlarmQueue()
                pending: 178466
        Receiver's instance variables:
                hands: {a HandMorph(3216)}
                activeHand: a HandMorph(3216)
                viewBox: 0@0 corner: 800@600
                canvas: a FormCanvas on: DisplayScreen(800x600x32)
                damageRecorder: a DamageRecorder
                stepList: a Heap(StepMessage(#stepAt: -> a ClockMorph(3002)'1:57:06
pm')(a Cloc...etc...
                lastStepTime: 178446
                lastStepMessage: nil
                lastCycleTime: 178511
                commandHistory: a CommandHistory
                alarms: a MorphicAlarmQueue()
                lastAlarmTime: 178446
                remoteServer: nil
                multiCanvas: nil

[] in WorldState>>lockAlarmsDuring:
        Receiver: a WorldState
        Arguments and temporary variables:
                actionBlock: [closure] in WorldState>>triggerAlarmsBefore:
        Receiver's instance variables:
                hands: {a HandMorph(3216)}
                activeHand: a HandMorph(3216)
                viewBox: 0@0 corner: 800@600
                canvas: a FormCanvas on: DisplayScreen(800x600x32)
                damageRecorder: a DamageRecorder
                stepList: a Heap(StepMessage(#stepAt: -> a ClockMorph(3002)'1:57:06
pm')(a Cloc...etc...
                lastStepTime: 178446
                lastStepMessage: nil
                lastCycleTime: 178511
                commandHistory: a CommandHistory
                alarms: a MorphicAlarmQueue()
                lastAlarmTime: 178446
                remoteServer: nil
                multiCanvas: nil

BlockClosure>>ensure:
        Receiver: [closure] in WorldState>>lockAlarmsDuring:
        Arguments and temporary variables:
                aBlock: [closure] in [] in Mutex>>critical:
                complete: nil
                returnValue: nil
        Receiver's instance variables:
                outerContext: WorldState>>lockAlarmsDuring:
                startpc: 40
                numArgs: 0

[] in Mutex>>critical:
        Receiver: a Mutex
        Arguments and temporary variables:
                aBlock: [closure] in WorldState>>lockAlarmsDuring:
                activeProcess: a Process in nil
        Receiver's instance variables:
                semaphore: a Semaphore(a Process in [] in Semaphore>>critical:)
                owner: a Process in nil

[] in Semaphore>>critical:
        Receiver: a Semaphore(a Process in [] in Semaphore>>critical:)
        Arguments and temporary variables:
                mutuallyExcludedBlock: [closure] in Mutex>>critical:
                caught: #(true)
        Receiver's instance variables:
                firstLink: a Process in [] in Semaphore>>critical:
                lastLink: a Process in [] in Semaphore>>critical:
                excessSignals: 0

BlockClosure>>ensure:
        Receiver: [closure] in Semaphore>>critical:
        Arguments and temporary variables:
                aBlock: [closure] in Semaphore>>critical:
                complete: nil
                returnValue: nil
        Receiver's instance variables:
                outerContext: Semaphore>>critical:
                startpc: 38
                numArgs: 0

Semaphore>>critical:
        Receiver: a Semaphore(a Process in [] in Semaphore>>critical:)
        Arguments and temporary variables:
                mutuallyExcludedBlock: [closure] in Mutex>>critical:
                caught: #(true)
        Receiver's instance variables:
                firstLink: a Process in [] in Semaphore>>critical:
                lastLink: a Process in [] in Semaphore>>critical:
                excessSignals: 0

Mutex>>critical:
        Receiver: a Mutex
        Arguments and temporary variables:
                aBlock: [closure] in WorldState>>lockAlarmsDuring:
                activeProcess: a Process in nil
        Receiver's instance variables:
                semaphore: a Semaphore(a Process in [] in Semaphore>>critical:)
                owner: a Process in nil

WorldState>>lockAlarmsDuring:
        Receiver: a WorldState
        Arguments and temporary variables:
                actionBlock: [closure] in WorldState>>triggerAlarmsBefore:
        Receiver's instance variables:
                hands: {a HandMorph(3216)}
                activeHand: a HandMorph(3216)
                viewBox: 0@0 corner: 800@600
                canvas: a FormCanvas on: DisplayScreen(800x600x32)
                damageRecorder: a DamageRecorder
                stepList: a Heap(StepMessage(#stepAt: -> a ClockMorph(3002)'1:57:06
pm')(a Cloc...etc...
                lastStepTime: 178446
                lastStepMessage: nil
                lastCycleTime: 178511
                commandHistory: a CommandHistory
                alarms: a MorphicAlarmQueue()
                lastAlarmTime: 178446
                remoteServer: nil
                multiCanvas: nil

WorldState>>triggerAlarmsBefore:
        Receiver: a WorldState
        Arguments and temporary variables:
                nowTime: 178466
        Receiver's instance variables:
                hands: {a HandMorph(3216)}
                activeHand: a HandMorph(3216)
                viewBox: 0@0 corner: 800@600
                canvas: a FormCanvas on: DisplayScreen(800x600x32)
                damageRecorder: a DamageRecorder
                stepList: a Heap(StepMessage(#stepAt: -> a ClockMorph(3002)'1:57:06
pm')(a Cloc...etc...
                lastStepTime: 178446
                lastStepMessage: nil
                lastCycleTime: 178511
                commandHistory: a CommandHistory
                alarms: a MorphicAlarmQueue()
                lastAlarmTime: 178446
                remoteServer: nil
                multiCanvas: nil

WorldState>>runLocalStepMethodsIn:
        Receiver: a WorldState
        Arguments and temporary variables:
                aWorld: a PasteUpMorph(1622) [world]
                now: 178466
                morphToStep: nil
                stepTime: nil
                priorWorld: a PasteUpMorph(1622) [world]
        Receiver's instance variables:
                hands: {a HandMorph(3216)}
                activeHand: a HandMorph(3216)
                viewBox: 0@0 corner: 800@600
                canvas: a FormCanvas on: DisplayScreen(800x600x32)
                damageRecorder: a DamageRecorder
                stepList: a Heap(StepMessage(#stepAt: -> a ClockMorph(3002)'1:57:06
pm')(a Cloc...etc...
                lastStepTime: 178446
                lastStepMessage: nil
                lastCycleTime: 178511
                commandHistory: a CommandHistory
                alarms: a MorphicAlarmQueue()
                lastAlarmTime: 178446
                remoteServer: nil
                multiCanvas: nil


--- The full stack ---
BalloonMorph class(Object)>>break
BalloonMorph class>>getVertices:
BalloonMorph class>>string:for:corner:
BalloonMorph class>>string:for:
PluggableButtonMorphPlus(Morph)>>showBalloon:hand:
HandMorph>>spawnBalloonFor:
MorphicAlarm(MessageSend)>>value
MorphicAlarm>>value:
[] in WorldState>>triggerAlarmsBefore:
[] in WorldState>>lockAlarmsDuring:
BlockClosure>>ensure:
[] in Mutex>>critical:
[] in Semaphore>>critical:
BlockClosure>>ensure:
Semaphore>>critical:
Mutex>>critical:
WorldState>>lockAlarmsDuring:
WorldState>>triggerAlarmsBefore:
WorldState>>runLocalStepMethodsIn:
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
WorldState>>runStepMethodsIn:
PasteUpMorph>>runStepMethods
WorldState>>doOneCycleNowFor:
WorldState>>doOneCycleFor:
PasteUpMorph>>doOneCycle
[] in Project class>>spawnNewProcess
[] in BlockClosure>>newProcess
_______________________________________________
Beginners mailing list
[hidden email]
http://lists.squeakfoundation.org/mailman/listinfo/beginners