<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
<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>How do you like that?</p>
<p><img size="29554" id="x_img206000" tabindex="0" style="max-width:99.9%" src="cid:b635a64a-7981-444c-af79-70188915420b"><br>
</p>
<p>Can you notice a real performance impact when activating the preference? What is on Raspi?</p>
<p><br>
</p>
<p>Best,</p>
<p>Christoph</p>
<div id="x_Signature">
<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>
<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 commits@source.squeak.org <commits@source.squeak.org><br>
<b>Gesendet:</b> Montag, 23. September 2019 16:44:39<br>
<b>An:</b> squeak-dev@lists.squeakfoundation.org<br>
<b>Betreff:</b> [squeak-dev] The Inbox: Morphic-ct.1540.mcz</font>
<div> </div>
</div>
</div>
<font size="2"><span style="font-size:10pt;">
<div class="PlainText">A new version of Morphic was added to project The Inbox:<br>
<a href="http://source.squeak.org/inbox/Morphic-ct.1540.mcz">http://source.squeak.org/inbox/Morphic-ct.1540.mcz</a><br>
<br>
==================== Summary ====================<br>
<br>
Name: Morphic-ct.1540<br>
Author: ct<br>
Time: 23 September 2019, 4:44:32.818523 pm<br>
UUID: 064f7940-90ea-1646-a6f5-6c0a82c06e91<br>
Ancestors: Morphic-mt.1539<br>
<br>
Proposal: Remember & explore provenance of any morph.<br>
<br>
Sure, this is a performance regression (that's why it's turned off by default), but when you are debugging, I could tell you of so many cases in which this can be a useful utility. Looking at #browseCreatorMethod, we can also use this to allow beginners for
quickly browsing the <example> method that created a morph.<br>
<br>
=============== Diff against Morphic-mt.1539 ===============<br>
<br>
Item was changed:<br>
Object subclass: #Morph<br>
instanceVariableNames: 'bounds owner submorphs fullBounds color extension'<br>
+ classVariableNames: 'HaloForAll IndicateKeyboardFocus MetaMenuForAll PreferredCornerRadius RememberProvenance UseSoftDropShadow'<br>
- classVariableNames: 'HaloForAll IndicateKeyboardFocus MetaMenuForAll PreferredCornerRadius UseSoftDropShadow'<br>
poolDictionaries: ''<br>
category: 'Morphic-Kernel'!<br>
<br>
!Morph commentStamp: 'klc 3/14/2017 11:30' prior: 0!<br>
A Morph (from the Greek "shape" or "form") is an interactive graphical object. General information on the Morphic system can be found at
<a href="http://wiki.squeak.org/squeak/30">http://wiki.squeak.org/squeak/30</a>. <br>
<br>
Morphs exist in a tree, rooted at a World (generally a PasteUpMorph). The morphs owned by a morph are its submorphs. Morphs are drawn recursively; if a Morph has no owner it never gets drawn. To hide a Morph and its submorphs, set its #visible property to
false using the #visible: method. <br>
<br>
The World (screen) coordinate system is used for most coordinates, but can be changed if there is a TransformMorph somewhere in the owner chain.
<br>
<br>
My instance variables have accessor methods (e.g., #bounds, #bounds:). Most users should use the accessor methods instead of using the instance variables directly.<br>
<br>
Structure:<br>
instance var Type Description <br>
bounds Rectangle A Rectangle indicating my position and a size that will enclose me.
<br>
owner Morph My parent Morph, or nil for the top-level Morph, which is a<br>
or nil world, typically a PasteUpMorph.<br>
submorphs Array My child Morphs. <br>
fullBounds Rectangle A Rectangle minimally enclosing me and my submorphs.
<br>
color Color My primary color. Subclasses can use this in different ways.
<br>
extension MorphExtension Allows extra properties to be stored without adding a<br>
or nil storage burden to all morphs.
<br>
<br>
By default, Morphs do not position their submorphs. Morphs may position their submorphs directly or use a LayoutPolicy to automatically control their submorph positioning.<br>
<br>
Although Morph has some support for BorderStyle, most users should use BorderedMorph if they want borders.!<br>
<br>
Item was added:<br>
+ ----- Method: Morph class>>rememberProvenance (in category 'preferences') -----<br>
+ rememberProvenance<br>
+ <br>
+ <preference: 'Remember provenance of each morph'<br>
+ categoryList: #(Morphic)<br>
+ description: 'If enabled, each morph will contain a debug item to view its creator stack. This allows you to explore its provenance later. May affect performance.'<br>
+ type: #Boolean><br>
+ ^ RememberProvenance ifNil: [false]!<br>
<br>
Item was added:<br>
+ ----- Method: Morph class>>rememberProvenance: (in category 'preferences') -----<br>
+ rememberProvenance: aBoolean<br>
+ <br>
+ RememberProvenance := aBoolean.!<br>
<br>
Item was added:<br>
+ ----- Method: Morph>>browseCreatorMethod (in category 'debug and other') -----<br>
+ browseCreatorMethod<br>
+ <br>
+ ^ (self valueOfProperty: #officialCreator) browse!<br>
<br>
Item was changed:<br>
----- Method: Morph>>buildDebugMenu: (in category 'debug and other') -----<br>
buildDebugMenu: aHand<br>
"Answer a debugging menu for the receiver. The hand argument is seemingly historical and plays no role presently"<br>
<br>
| aMenu aPlayer |<br>
aMenu := MenuMorph new defaultTarget: self.<br>
aMenu addStayUpItem.<br>
(self hasProperty: #errorOnDraw) ifTrue:<br>
[aMenu add: 'start drawing again' translated action: #resumeAfterDrawError.<br>
aMenu addLine].<br>
(self hasProperty: #errorOnStep) ifTrue:<br>
[aMenu add: 'start stepping again' translated action: #resumeAfterStepError.<br>
aMenu addLine].<br>
<br>
aMenu add: 'inspect morph' translated action: #inspectInMorphic:.<br>
aMenu add: 'inspect owner chain' translated action: #inspectOwnerChain.<br>
Smalltalk isMorphic ifFalse:<br>
[aMenu add: 'inspect morph (in MVC)' translated action: #inspect].<br>
<br>
self isMorphicModel ifTrue:<br>
[aMenu add: 'inspect model' translated target: self model action: #inspect;<br>
add: 'explore model' translated target: self model action: #explore].<br>
(aPlayer := self player) ifNotNil:<br>
[aMenu add: 'inspect player' translated target: aPlayer action: #inspect].<br>
<br>
aMenu add: 'explore morph' translated target: self selector: #exploreInMorphic:.<br>
<br>
aMenu addLine.<br>
aPlayer ifNotNil:<br>
[ aMenu add: 'viewer for Player' translated target: self player action: #beViewed.<br>
aMenu balloonTextForLastItem: 'Opens a viewer on my Player -- this is the same thing you get if you click on the cyan "View" halo handle' translated ].<br>
<br>
aMenu add: 'viewer for Morph' translated target: self action: #viewMorphDirectly.<br>
aMenu balloonTextForLastItem: 'Opens a Viewer on this Morph, rather than on its Player' translated.<br>
aMenu addLine.<br>
<br>
aPlayer ifNotNil:<br>
[aPlayer class isUniClass ifTrue: [<br>
aMenu add: 'browse player class' translated target: aPlayer selector: #haveFullProtocolBrowsedShowingSelector: argumentList: #(nil)]].<br>
aMenu add: 'browse morph class' translated target: self selector: #browseHierarchy.<br>
+ self isMorphicModel<br>
- (self isMorphicModel)<br>
ifTrue: [aMenu<br>
add: 'browse model class'<br>
target: self model<br>
selector: #browseHierarchy].<br>
+ (self valueOfProperty: #officialCreator ifAbsent: [nil]) ifNotNil: [<br>
+ aMenu add: 'browse creator method' action: #browseCreatorMethod].<br>
+ (self hasProperty: #creatorStack) ifTrue: [<br>
+ aMenu add: 'explore creator stack' action: #exploreCreatorStack].<br>
aMenu addLine.<br>
<br>
self addViewingItemsTo: aMenu.<br>
aMenu <br>
add: 'make own subclass' translated action: #subclassMorph;<br>
add: 'save morph in file' translated action: #saveOnFile;<br>
addLine;<br>
add: 'call #tempCommand' translated action: #tempCommand;<br>
add: 'define #tempCommand' translated action: #defineTempCommand;<br>
addLine;<br>
<br>
add: 'control-menu...' translated target: self selector: #invokeMetaMenu:;<br>
add: 'edit balloon help' translated action: #editBalloonHelpText.<br>
<br>
^ aMenu!<br>
<br>
Item was added:<br>
+ ----- Method: Morph>>exploreCreatorStack (in category 'debug and other') -----<br>
+ exploreCreatorStack<br>
+ <br>
+ ^ (self valueOfProperty: #creatorStack) explore!<br>
<br>
Item was changed:<br>
----- Method: Morph>>initialize (in category 'initialization') -----<br>
initialize<br>
"initialize the state of the receiver"<br>
owner := nil.<br>
submorphs := Array empty.<br>
bounds := self defaultBounds.<br>
+ color := self defaultColor.<br>
+ self class rememberProvenance ifTrue: [<br>
+ | creatorStack |<br>
+ creatorStack := thisContext home stack collect: #method.<br>
+ self setProperty: #creatorStack toValue: creatorStack.<br>
+ creatorStack<br>
+ detect: [:method | method hasPragma: #example]<br>
+ ifFound: [:method | self setProperty: #officialCreator toValue: method]].!<br>
- color := self defaultColor!<br>
<br>
<br>
</div>
</span></font>
</body>
</html>