These file-ins provide a set of classes and methods to enhance the representation of smalltalk source code in the Objectworks\Smalltalk environment, using visual attributes (color, boldness, italics, etc.) and by indenting the code according to user specific criterias. Any smalltalk source code can be automatically formatted in the same manner, thus substantially improving the readability. The writing of smalltalk methods is also simplified, because the tool eliminates the need to spend time with formatting source code: the user just has to accept changes, then the source code is reformatted and redisplayed. In lack of a proper name (and because of my limited knowledge of the English language) this tool is called 'visual layout tool'. Contents of this file ===================== 1. Installation 2. Users guide 3. Documentation 4. Extending the visual layout tool 5. Known bugs and limitations 6. Disclaimer 1. Installation =============== The easiest way to install the visual layout tool is: 1. Take a clean image 2. File in 'VLTOOLS.ST' 3. File in 'VLAYOUT.ST' 4. Save image Annotations: 1. Although I have provided a method to get rid of the tool, once you do not longer want to use it, I suggest you install the tool in a clean image to evaluate whether it suits your needs and whether you want to use it or not (see step 3 for further explanation of changes to the smalltalk classes). 2. The visual layout tool requires the following tools: o change layout wrapper (class ChangeLayoutWrapper) o display view (classes DisplayView and DisplayController) o color picker (classes ColorPicker and ColorButton) o marked items list (classes MarkedItemsSelectionInListView and MarkedItemsTextList) These tools are available in the Manchester Smalltalk Library and should be installed before the visual layout tool is installed. In case you do not have access to these tools I have provided a file-in 'VLTOOLS.ST', which contains these tools (without further documentation). 3. This file-in installs the classes and methods of the visual layout tool. New classes and all of the methods and variables added to existing classes start with a 'vl'-prefix. The visual layout tool does some changes to a few Browser and Debugger methods. The original sources of these methods are saved with preceding 'VLORG's. After completion of the install process a list of all changed methods is displayed. So, if you have changed some of those listed methods, you can easily combine your changes with the changes required by the visual layout tool. To get rid of the visual layout tool simply perform . All added classes and methods will then be removed from the system, the saved methods will be restored (note: the tools that were added in step 2 will not be removed). 4. The tool is now "ready to go", i.e. from now on all browsers use the new capabilities to display smalltalk source code. Depending on your system, you may have to change the default settings (this can be done via the menus described below or by changing the initialize methods in class VLSettingsHolder). 2. Users guide ============== The visual layout tool is smoothly integrated in the smalltalk environment. The development tools (browsers, debuggers, etc.) can be used as usual. The user does not need any additional knowledge. Each time the user selects a new method, the source code is formatted according to the user's specifications, before it is being displayed. Likewise the code is being formatted and redisplayed, when the user accepts a new piece of code. If - in case of errors - no pretty printing for the selected method can be produced the unformatted source is displayed. Depending on the user's needs the usage of the visual layout tool can be easily influenced (e.g. for a large method it can be quite unsatisfactory to wait for the method to being formatted). The usage of the visual layout tool is determined by: o a global usage flag (on/off) o a usage flag for each specific browser class, e.g. for all debuggers (on/off/inherited = same as global flag) o a usage flag for a specific browser, e.g. an instance of NewBrowser (on/off/inherited = same as flag of browser class) The menu item 'format' in the browser's text menu has been replaced with the item 'visual layout': +-----------------+ ! again ! ! ... ! +-----------------+ +-----------------------------+ ! visual layout >! ! edit settings ... ! !-----------------! !-----------------------------+ ! ... ! ! all browsers (on) >! ! ... ! ! these browsers (inherited) >! +----------+ !-----------------! ! this browser (inherited) >! ! turn on ! ! hardcopy ! +-----------------------------+ ! turn off ! +-----------------+ +----------+ The lower part of the new menu serves two purposes: firstly, it shows the actual usage flags of the visual layout tool (in parenthesis). Secondly, the menu items on the right can be used to change the usage flag: either for all browsers, for a browser class or for a specific browser. This way the user can fully control the usage of the visual layout tool. For example the user can turn the global usage on, and, before displaying a quite large method, turn the visual layout usage for one specific browser off. OTOH the user generally could avoid the usage of the visual layout tool, and turn the usage for one specific browser on. By choosing the item 'edit settings ...' a new window pops up, in which the user can change the settings for producing layouted smalltalk source code according to his needs. This window is divided into two parts: in the lower half a sample method is being displayed, so that the user can immediately see the influence of changed settings (this method is the actually selected method in the browser when the window is being opened). +----------------------------------------------------------------+ ! +------------------+ +------------------+ +------------------+ ! ! !*smalltalkToken***! ! bold ! ! Arial ! ! ! ! assignment ! ! color ! ! Courier ! ! ! ! comment ! !*font*************! ! Helvetica ! ! ! ! inlineComment ! ! italic ! !*Times*Roman******! ! ! ! methodComment ! ! size ! ! ! ! ! +------------------+ +------------------+ +------------------+ ! ! +-------------------------------------------------+ +--------+ ! ! ! smalltalkToken = color: darkGray, tabStops: 18, ! ! update ! ! ! ! font: Times Roman, size: 14 ! +--------+ ! ! ! ! ! close ! ! ! ! ! +--------+ ! ! ! ! ! cancel ! ! ! +-------------------------------------------------+ +--------+ ! ! +------------------------------------------------------------+ ! ! ! browserAllCallsOn: aSymbol within: aBehaviour ! ! ! ! "Create and schedule a message browser on each ! ! ! ! method that calls on a Symbol" ! ! ! ! ! ! ! ! | label key | ! ! ! ! (aSymbol isMemberOf: Association) ! ! ! ! ifTrue: [ ! ! ! +------------------------------------------------------------+ ! +----------------------------------------------------------------+ The upper half consists of the following elements: o a token view This view shows the available language constructs in smalltalk: tokens (e.g. keyword selectors, comments, etc.). To change the way a piece of smalltalk code is displayed the user first must select the corresponding token. o an attribute view Each token has a set of attributes that can be changed. By selecting a token the available attributes are displayed in this view. Each attribute can be in two states: activated (i.e. a value assigned) or deactivated (no value assigned). Deactivated attributes are shown crossed out. In order to change the value of an attribute the user must first select the appropriate attribute and eventually activate it. o an attribute value view This view contains the visual representation of the actual selected attribute. This can be a list view, a button view, a slider, a color button view (hold down the shift key while clicking on it), etc., depending on the kind of attribute that is being displayed. o a description In this view the actual selected token is displayed with a description of all activated attributes and their values. o the buttons The user can perform the following actions: - update: update the display of the sample method - close: update the original browser and close the window - cancel: forget the changes and close the window The tokens are arranged in a hierarchy, e.g. a keyword selector is a special selector that itself is a special smalltalk token. Each token inherits the attributes from its super token (in case it has not been assigned ist own attribute values). This way you can easily assign one color value to all comment types (method comments, preceding comments, inline comments). The implemented token hierarchy is shown below: smalltalkToken assignment comment inlineComment methodComment precedingComment delimiter doubleQuoteDelimiter parenthesisDelimiter arrayParenthesisDelimiter blockParenthesisDelimiter bytearrayParenthesisDelimiter roundParenthesisDelimiter pointDelimiter quoteDelimiter returnDelimiter semicolonDelimiter spaceDelimiter verticalBarDelimiter literal arrayLiteral blockLiteral byteArrayLiteral characterLiteral numberLiteral specialLiteral falseSpecialLiteral nilSpecialLiteral trueSpecialLiteral stringLiteral symbolLiteral methodPattern primitive selector binarySelector keywordSelector unarySelector variable argumentVariable blockArgumentVariable methodArgumentVariable classInstanceVariable classVariable globalVariable classGlobalVariable nonClassGlobalVariable instanceVariable poolVariable specialVariable selfSpecialVariable superSpecialVariable thisContextSpecialVariable temporaryVariable The token view, attribute view and sometimes also the attribute value view provide the user with menus o for setting tokens or attributes to their default value o for activating/deactivating attributes o for searching for tokens o for showing/hiding branches of the token hierarchy etc. 3. Documentation ================ This section contains a rough overview of the implemented classes. They can be subdivided into two class areas: classes to administrate visual settings and classes that help producing the layouted source code. Administration classes ---------------------- Tokens are modeled by objects of the class VLToken. An instance of VLToken represents a certain smalltalk construct. A VLToken object knows its parent token, its subtokens and contains a set of visual attribute values. VLAttribute is an abstract class. At the moment there are five subclasses of this class: VLBooleanAttribute, VLColorAttribute, VLEnumerationAttribute, VLIntervalAttribute and VLListAttribute. Instances of these classes represent attributes, have a default value and know how to influence or act upon a FontDescription. They also know how to display a specific value of themselves on the screen. Instances of the class VLAttributeValue hold specific values of attributes. They know their actual value, their individual default value, the attribute, whose value they represent, and the token, they belong to. [Annotation: attribute value is an object that holds a value; to obtain the value you must send the message #value to it. From now on "attribute value" stands for the attribute value object, "value of attribute value" or "attribute value value" means the value itself (e.g. a number, a color, etc.). I am very sorry for this naming convention, but at the moment I do not have the time to change this ...] Example: An object of the class VLBooleanAttribute, a subclass of VLAttribute, represents an attribute with a boolean value. There is a method, which can display a boolean value in a view and allows the user to edit this value. There exist several different boolean attributes, e.g. boldness, underlining, etc. A boldness instance must know (in addition to the knowledge represented by the VLBooleanAttribute class), how to produce a boldfaced output (in conjunction with a FontDescription). Another instance, say italic, must know, how to act on a FontDescription to create source code in italics. To prevent the user from creating new classes for each attribute the general knowledge of boolean values is contained in the class, the information on how to produce the output is held in an instance variable (font block). For each attribute there exist several values, e.g. there is a value for the boldness attribute assigned to a keyword selector and another value of the same kind is assigned to literals. These values are represented by instances of class VLAttributeValue. An instance of class VLSettingsHolder holds a set of tokens and their attribute values. The user can inquire these attributes, e.g. aVLSHolder valueForToken: #methodPattern andAttribute: #useMultipleLines Class VLSettingsHolder also contains the necessary methods for displaying and editing the attribute values. To create an instance of VLSettingsHolder an instance of VLAttributeValueBuilder can be helpful. Such an instance administrates a set of attributes and is able to create specific attribute values. A new set of visual settings can be created by performing the following steps: o create a value builder (instance of VLAttributeValueBuilder) o create some attributes (VLAttribute); let the value builder administrate them o create a setting's holder (VLSettingsHolder) o create tokens (VLToken) and insert them into the settings holder o create attribute values (VLAttributeValue) by requesting them from the value builder and assign them to tokens Classes to create layouted smalltalk code ----------------------------------------- The creation of properly layouted smalltalk code uses the parse tree that is generated by the parser classes. This tree consists of a root node (MethodNode) and its subnodes (subclasses of ProgramNode, e.g. SequenceNode, VariableNode, etc.). By sending the message #printOn: to the root node a printed representation of the parse tree can be generated. To enhance this representation the below listed changes and additions have been made: o a new class for the administration of comments has been added (VLCommentNode). o a new class VLInfo has been introduced. Instances of VLInfo hold information, that is needed in the output generation phase, e.g. the original source code (for determining source positions), an instance of VLSettingsHolder (which holds the user specific settings), etc. Before the output is generated this VLInfo instance therefor is assigned to a new introduced instance variable of each program node in the parse tree. o a new class VLParser has been created (subclass of Parser), which contains the needed changes for the building phase of the parse tree. o Class VLProgramNodeBuilder is a subclass of ProgramNodeBuilder and initializes each new created program node with an appropriate VLInfo object. o ProgramNode and its subclasses have been extended to support the production of enhanced output of smalltalk source code. o Classes Browser and Debugger have been extended to - redisplay methods after selection and acceptance - provide additional menu items to allow editing of the settings - perform the required initializations for new instances The generation of formatted output of smalltalk source code is done by the program nodes. Via the VLInfo object a VLSettingsHolder can be asked for attribute values and character styles of specific tokens (the character styles can directly be used to change the emphasis of a RunArray). 5. Extending the visual layout tool =================================== Creating new attribute classes ------------------------------ New attribute classes should be subclasses of VLAttribute and must implement the following methods: o low This method should return one valid value according to the implemented attribute. o validValues This method should return all valid values (to allow validation checks for attribute values). If the valid values can not be enumerated, nil should be returned. o openViewIn: aWrapper on: aModel The method should implement a view, that can be plugged into the specified wrapper (aWrapper component: aView) and allows editing of an associated attribute value. The below listed messages can be sent to the model: - vlAttributeValueValue returns the actual value of the attribute value, that is about to being displayed - vlAttributeValueValue: aNewValue sets the value of an attribute value to the specified value - vlAttributeValue returns the attribute value object itself Creating new attributes and attribute values -------------------------------------------- New attributes can be created by sending the message #new: #anAttributeId to a subclass of VLAttribute. If you intend to create an attribute that influences font descriptions, the fontBlock of this attribute must be initialized properly. This block is evaluated with two arguments: a font description and the value of an attribute value. Example for a correct initialization: italicAttr := VLBooleanAttribute new: #italic. italicAttr fontBlock: [ :font :value | font italic: value ]. italicAttr is a new boolean attribute, which changes font descriptions according to the supplied attribute value value (damned naming conventions ...). To create a new attribute, the message #newValue can be used, e.g. methodPattern addAttributeValue: italicAttr newValue Adapting the generation of formatted code ----------------------------------------- To change the generation of formatted smalltalk source code the #vlPrint... methods in the class ProgramNode and its subclasses must be adapted. Consider for example the implementation of a new word wrap strategy for printing comments. For that purpose the method #vlPrintOn:indent: in class VLCommentNode needs to be adapted. If a fastWordWrap attribute had been introduced with fastWordWrapAttr := VLBooleanAttribute new: #fastWordWrap. vlSettingsHolder addAttributeValue: (fastWordWrapAttr newValue actualValue: true) toToken: #comment the output could be generated in dependency of the attribute value, e.g. vlPrintOn: aStream indent: level "print comment" (self vlInfo valueForToken: #comment andAttribute: #fastWordWrap) ifTrue: [ "perform a quick-and-diry word wrap" ] ifFalse: [ "normal word wrap" ] 5. Known bugs and limitations ============================= The visual layout tool has evolved step by step over a period of over four months. Though I have spent plenty of time with testing the tool, it is known not to be bug-free. Some of these bugs are listed below: o only one window for the editing of settings can be used at a time o placing of comments is sometimes not correct (in most cases sufficient, though) o variable scopes are not always correctly checked (applies only on equal names of instance and class instance variables) There are some other hacks included, as well. Because the production of well-formatted smalltalk source code is very time consuming, the tool may show poor performance on your system, depending on the system specifications (I suffer a little bit from the performance on my 486DX2/66 machine ...). Nevertheless, I have been quite satisfied with the tool. I can view source code written by other programmers according to my preferences. And there is no more need to spend lots of hours on formatting program code. 6. Disclaimer ============= Copyright (C) 1994 Gerhard Miller. Permission is granted to any individual or institution to use, copy, or redistribute this tool as long as it is not sold for profit and the original sources and documentation of this tool are included. Like anything else that is free, the visual layout tool is provided as is and comes with no warranty of any kind, either expressed or implied. In no event will the copyright holder be liable for any damages resulting from the use of this software. Please send comments, suggestions and improvements to: Gerhard Miller Schorndorfer Str. 24 70734 Fellbach Germany miller@dialog.informatik.uni-stuttgart.de CIS: 100326,1756