"====================================================================== | | Smalltalk GUI generic inspectors | | $Revision: 1.7.5$ | $Date: 2000/05/28 16:56:52$ | $Author: pb$ | ======================================================================" "====================================================================== | | Copyright 1988-92, 1994-95, 1999, 2000 Free Software Foundation, Inc. | Written by Brad Diller. | | This file is part of GNU Smalltalk. | | GNU Smalltalk is free software; you can redistribute it and/or modify it | under the terms of the GNU General Public License as published by the Free | Software Foundation; either version 2, or (at your option) any later version. | | GNU Smalltalk is distributed in the hope that it will be useful, but WITHOUT | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | FOR A PARTICULAR PURPOSE. See the GNU General Public License for more | details. | | You should have received a copy of the GNU General Public License along with | GNU Smalltalk; see the file COPYING. If not, write to the Free Software | Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ====================================================================== " GuiData subclass: #GenericInspector instanceVariableNames: 'theObject instVars currentVariable ' classVariableNames: '' poolDictionaries: '' category: 'Graphics-Browser' ! !GenericInspector methodsFor: 'initializing'! inspectMenu: listView "Initialize menu for variable list pane" ^((PopupMenu new: listView label: '') selectors: #(('Inspect' evalAndInspectResult: listView)) receiver: self argument: listView). ! openOn: anObject | topView pane | topView := BrowserShell new: ('%1 for %2' bindWith: self species name with: (anObject class nameIn: Namespace current)). topView data: self. topView blox x: 0 y: 330 width: 300 height: 100. pane := Form new: 'forms' in: topView. topView addChildView: pane. self openOn: anObject in: pane. topView display. ! openOn: anObject in: pane "Initialize Inspector and open an Inspector window on anObject" | listView textView container | "Initialize instance variable, instVars, which governs display of variable list pane" instVars := self instVarsSortBlock ifNil: [ OrderedCollection new ] ifNotNil: [ :block | SortedCollection sortBlock: block ]. self setInstanceVars: anObject. "Create a Form manager which will contain the variable and text pane" container := pane blox. "Create a text window and position it in first third of window" pane addChildView: ( (listView := PList new: 'InstanceVars' in: pane) initialize; data: self; stateChange: #variableList; handleUserChange: #variable:; listMsg: #variableList; hiliteItemInitMsg: #variableName; menuInit: (self inspectMenu: listView); yourself). listView blox xPixels: 2; yPixels: 2. listView blox height: pane blox height; heightOffset: -4. listView blox width: 100; widthOffset: -4. "Create text pane and position it in right 2/3s of window" pane addChildView: ((textView := PText new: pane) data: self; stateChange: #text; handleUserChange: #setArg:from:; textMsg: #text; canBeDirty: false; yourself). textView blox yPixels: 2; xOffset: 2. textView blox height: pane blox height; heightOffset: -4. textView blox width: pane blox width - 100; widthOffset: -4. textView blox posHoriz: (listView blox). "Initialize popup for text pane" textView menuInit: ((PopupMenu new: textView label: '') selectors: #(('Cut' gstCut) ('Copy' gstCopy) ('Paste' gstPaste) () ('Clear' gstClear) () ('Line...' line) ('Find...' find) ()) receiver: textView argument: nil; selectors: #(('Do it' eval: textView) ('Print it' evalAndPrintResult: textView) ('Inspect' inspectValue: textView)) receiver: self argument: textView; selectors: #(() ('Accept' compileIt) ('Cancel' revert) () ('Close' close)) receiver: textView argument: nil; yourself). self changeState: #variableList. Primitive updateViews. ! ! !GenericInspector methodsFor: 'private'! currentVariableValue self subclassResponsibility ! currentVariable: obj self subclassResponsibility ! instVarsSortBlock "nil = use OrderedCollection, else a block to be used as instVars' sort block." ^nil ! setInstanceVars: anObject "Store a string representation of the inspected object, anObject, in instVars. The first string is self. The subsequent values are the object's complete set of instance variables names. If the object is a variable class, append numerical indices from one to number of indexed variables" self subclassResponsibility ! ! !GenericInspector methodsFor: 'accessing'! text "Return string representation of currently selected instance or indexed variable" ^currentVariable == 0 ifTrue: [ '' ] ifFalse: [ self currentVariableValue printString ] ! variable: assoc "Set variable list index to 'index'. Record state change and update windows" currentVariable := assoc key. self changeState: #text. Primitive updateViews. ! variableName ^currentVariable ! variableList "Return list of variable names displayed in the variable list pane" ^instVars ! ! !GenericInspector methodsFor: 'text view menu'! eval: aView "Invoked from text pane popup. Evaluate selected expression in text pane" | pos aStream text | text := aView blox getSelection. (text isNil or: [text size = 0]) ifTrue: [^aView beep]. aStream := WriteStream on: (String new: 0). theObject class evaluate: text to: theObject. ! inspectValue: aView "Open an inspector for evaluated selected expression. If selected expression contains parsing error(s), the error description is selected and printed at end of selection" | obj text | text := aView blox getSelection. (text isNil or: [text size = 0]) ifTrue: [^aView beep]. obj := theObject class evaluate: text to: theObject ifError: [:fname :lineNo :errorString | aView displayError: errorString. ^nil]. obj inspect. ! evalAndPrintResult: aView "Print result of evaluation of selected expression to its right" | pos result text | text := aView blox getSelection. (text isNil or: [text size = 0]) ifTrue: [^aView beep]. result := theObject class evaluate: text to: theObject ifError: [:fname :lineNo :errorString | errorString ]. aView blox insertTextSelection: result printString. ! setArg: aString from: aView "Store result of evaluation of selected expression in selected instance or indexed variable" | obj | (aString isNil or: [aString size = 0]) ifTrue: [^aView beep]. (currentVariable isNil or: [currentVariable <= 1]) ifTrue: [^aView beep]. "Evaluate selected expression. If expression contains a parsing error, the description is output at end of expression and nil is returned" obj := theObject class evaluate: aString to: theObject ifError: [:fname :lineNo :errorString | aView displayError: errorString at: lineNo. ^nil ]. self currentVariable: obj. ! ! !GenericInspector methodsFor: 'variable list menu'! evalAndInspectResult: listView currentVariable isNil ifTrue: [ ^listView beep ]. self currentVariableValue inspect. ! ! GenericInspector subclass: #Inspector instanceVariableNames: 'base ' classVariableNames: '' poolDictionaries: '' category: 'Graphics-Browser' ! !Inspector methodsFor: 'private'! currentVariableValue currentVariable == 0 ifTrue: [ ^nil ]. currentVariable == 1 ifTrue: [ ^theObject ]. ^currentVariable > base ifTrue: [ (theObject basicAt: currentVariable - base) ] ifFalse: [ (theObject instVarAt: currentVariable - 1) ]. ! currentVariable: obj currentVariable > base ifTrue: [ theObject basicAt: (currentVariable - base) put: obj] ifFalse: [theObject instVarAt: (currentVariable - 1) put: obj]. ! setInstanceVars: anObject "Store a string representation of the inspected object, anObject, in instVars. The first string is self. The subsequent values are the object's complete set of instance variables names. If the object is a variable class, append numerical indices from one to number of indexed variables" | instVarNames | theObject := anObject. currentVariable := nil. instVars add: 'self'. instVarNames := theObject class allInstVarNames. 1 to: instVarNames size do: [ :x | instVars add: (instVarNames at: x) asString ]. base := instVars size. theObject class isVariable ifTrue: [ 1 to: theObject validSize do: [ :x | instVars add: x printString]]. ! ! ! Object methodsFor: 'debugging' ! basicInspect "Open an Inspector window on self" Inspector new openOn: self ! inspect "Open an inspection window on self -- by default, the same Inspector used in #basicInspect." Inspector new openOn: self ! inspect: pane "Open an Inspector window on self" Inspector new openOn: self in: pane ! !