| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819 | Smalltalk current createPackage: 'Helios-Core'!InterfacingObject subclass: #HLModel	instanceVariableNames: 'announcer environment'	package: 'Helios-Core'!!HLModel commentStamp!I am the abstract superclass of all models of Helios.I am the "Model" part of the MVC pattern implementation in Helios.I provide access to an `Environment` object and both a local (model-specific) and global (system-specific) announcer.The `#withChangesDo:` method is handy for performing model changes ensuring that all widgets are aware of the change and can prevent it from happening.Modifications of the system should be done via commands (see `HLCommand` and subclasses).!!HLModel methodsFor: 'accessing'!announcer	^ announcer ifNil: [ announcer := Announcer new ]!environment	^ environment ifNil: [ self manager environment ]!environment: anEnvironment	environment := anEnvironment!manager	^ HLManager current!systemAnnouncer	^ self environment systemAnnouncer! !!HLModel methodsFor: 'error handling'!withChangesDo: aBlock	[ 		self announcer announce: (HLAboutToChange new			actionBlock: aBlock).		aBlock value.	]		on: HLChangeForbidden 		do: [ :ex | ]! !!HLModel methodsFor: 'testing'!isBrowserModel	^ false!isReferencesModel	^ false!isToolModel	^ false! !HLModel subclass: #HLToolModel	instanceVariableNames: 'selectedClass selectedPackage selectedProtocol selectedSelector'	package: 'Helios-Core'!!HLToolModel commentStamp!I am a model specific to package and class manipulation. All browsers should either use me or a subclass as their model.I provide methods for package, class, protocol and method manipulation and access, forwarding to my environment.I also handle compilation of classes and methods as well as compilation and parsing errors.!!HLToolModel methodsFor: 'accessing'!allSelectors	^ self environment allSelectors!availableClassNames	^ self environment availableClassNames!availablePackageNames	^ self environment availablePackageNames!availablePackages	^ self environment availablePackageNames!availableProtocols	^ self environment availableProtocolsFor: self selectedClass!packages	^ self environment packages!selectedClass	^ selectedClass!selectedClass: aClass	(self selectedClass = aClass and: [ aClass isNil ]) 		ifTrue: [ ^ self ].		self withChangesDo: [		selectedClass = aClass ifTrue: [ 			self selectedProtocol: nil ].    		aClass    			ifNil: [ selectedClass := nil ]    		ifNotNil: [				self selectedPackage: aClass theNonMetaClass package.				self showInstance    					ifTrue: [ selectedClass := aClass theNonMetaClass ]     				ifFalse: [ selectedClass := aClass theMetaClass ] ].		self selectedProtocol: nil.		self announcer announce: (HLClassSelected on: self selectedClass) ]!selectedMethod	^ self selectedClass ifNotNil: [ 		self selectedClass methodDictionary 			at: selectedSelector 			ifAbsent: [ nil ] ]!selectedMethod: aCompiledMethod	selectedSelector = aCompiledMethod ifTrue: [ ^ self ].        self withChangesDo: [		aCompiledMethod    		ifNil: [ selectedSelector := nil ]      		ifNotNil: [				selectedClass := aCompiledMethod methodClass.				selectedPackage := selectedClass theNonMetaClass package.				selectedSelector := aCompiledMethod selector ].		self announcer announce: (HLMethodSelected on: aCompiledMethod) ]!selectedPackage	^ selectedPackage!selectedPackage: aPackage	selectedPackage = aPackage ifTrue: [ ^ self ].    	self withChangesDo: [		selectedPackage := aPackage.		self selectedClass: nil.		self announcer announce: (HLPackageSelected on: aPackage) ]!selectedProtocol	^ selectedProtocol!selectedProtocol: aString	selectedProtocol = aString ifTrue: [ ^ self ].	self withChangesDo: [		selectedProtocol := aString.		self selectedMethod: nil.		self announcer announce: (HLProtocolSelected on: aString) ]! !!HLToolModel methodsFor: 'actions'!addInstVarNamed: aString	self environment addInstVarNamed: aString to: self selectedClass.	self announcer announce: (HLInstVarAdded new		theClass: self selectedClass;		variableName: aString;		yourself)!save: aString	self announcer announce: HLSourceCodeSaved new.		(self shouldCompileClassDefinition: aString)		ifTrue: [ self compileClassDefinition: aString ]		ifFalse: [ self compileMethod: aString ]!saveSourceCode	self announcer announce: HLSaveSourceCode new! !!HLToolModel methodsFor: 'commands actions'!commitPackage	self environment commitPackage: self selectedPackage!copyClassTo: aClassName	self withChangesDo: [ 		self environment 			copyClass: self selectedClass theNonMetaClass			to: aClassName ]!moveClassToPackage: aPackageName	self withChangesDo: [		self environment 			moveClass: self selectedClass theNonMetaClass			toPackage: aPackageName ]!moveMethodToClass: aClassName	self withChangesDo: [		self environment 			moveMethod: self selectedMethod 			toClass: aClassName ]!moveMethodToProtocol: aProtocol	self withChangesDo: [		self environment 			moveMethod: self selectedMethod 			toProtocol: aProtocol ]!openClassNamed: aString	| class |		self withChangesDo: [		class := self environment classNamed: aString.		self selectedPackage: class package.		self selectedClass: class ]!removeClass	self withChangesDo: [		self manager 			confirm: 'Do you REALLY want to remove class ', self selectedClass name			ifTrue: [ self environment removeClass: self selectedClass ] ]!removeMethod	self withChangesDo: [		self manager 			confirm: 'Do you REALLY want to remove method ', self selectedMethod methodClass name,' >> #', self selectedMethod selector			ifTrue: [ self environment removeMethod: self selectedMethod ] ]!removeProtocol	self withChangesDo: [		self manager 			confirm: 'Do you REALLY want to remove protocol ', self selectedProtocol			ifTrue: [ self environment 				removeProtocol: self selectedProtocol 				from: self selectedClass ] ]!renameClassTo: aClassName	self withChangesDo: [		self environment 			renameClass: self selectedClass theNonMetaClass			to: aClassName ]!renameProtocolTo: aString	self withChangesDo: [		self environment 			renameProtocol: self selectedProtocol			to: aString			in: self selectedClass ]! !!HLToolModel methodsFor: 'compiling'!compileClassComment: aString	self environment 		compileClassComment: aString 		for: self selectedClass!compileClassDefinition: aString	self environment compileClassDefinition: aString!compileMethod: aString	| method |		self withCompileErrorHandling: [ 		method := self environment 			compileMethod: aString 			for: self selectedClass			protocol: self compilationProtocol.		self selectedMethod: method ]! !!HLToolModel methodsFor: 'defaults'!allProtocol	^ '-- all --'!unclassifiedProtocol	^ 'as yet unclassified'! !!HLToolModel methodsFor: 'error handling'!handleCompileError: anError	self announcer announce: (HLCompileErrorRaised new		error: anError;		yourself)!handleParseError: anError	| split line column messageToInsert |		split := anError messageText tokenize: ' : '.	messageToInsert := split second.	"21 = 'Parse error on line ' size + 1"	split := split first copyFrom: 21 to: split first size.		split := split tokenize: ' column '.	line := split first.	column := split second.		self announcer announce: (HLParseErrorRaised new		line: line asNumber;		column: column asNumber;		message: messageToInsert;		error: anError;		yourself)!handleUnkownVariableError: anError	self announcer announce: (HLUnknownVariableErrorRaised new		error: anError;		yourself)!withCompileErrorHandling: aBlock	self environment		evaluate: [			self environment 			evaluate: [				self environment 					evaluate: aBlock					on: ParseError					do: [ :ex | self handleParseError: ex ] ]			on: UnknownVariableError			do: [ :ex | self handleUnkownVariableError: ex ] ]		on: CompilerError		do: [ :ex | self handleCompileError: ex ]! !!HLToolModel methodsFor: 'private'!compilationProtocol	| currentProtocol |		currentProtocol := self selectedProtocol.	currentProtocol ifNil: [ currentProtocol := self unclassifiedProtocol ].	self selectedMethod ifNotNil: [ currentProtocol := self selectedMethod protocol ].	^ currentProtocol = self allProtocol		ifTrue: [ self unclassifiedProtocol ]		ifFalse: [ currentProtocol ]!withHelperLabelled: aString do: aBlock	"TODO: doesn't belong here"	'#helper' asJQuery remove.	[ :html |		html div 			id: 'helper';			with: aString ] appendToJQuery: 'body' asJQuery.		[		aBlock value.		'#helper' asJQuery remove	] 		valueWithTimeout: 10! !!HLToolModel methodsFor: 'testing'!isToolModel	^ true!shouldCompileClassDefinition: aString	^ self selectedClass isNil or: [		aString match: '^[A-Z]' ]! !!HLToolModel class methodsFor: 'actions'!on: anEnvironment	^ self new    	environment: anEnvironment;        yourself! !ProgressHandler subclass: #HLProgressHandler	instanceVariableNames: ''	package: 'Helios-Core'!!HLProgressHandler commentStamp!I am a specific progress handler for Helios, displaying progresses in a modal window.!!HLProgressHandler methodsFor: 'progress handling'!do: aBlock on: aCollection displaying: aString	HLProgressWidget default		do: aBlock 		on: aCollection 		displaying: aString! !Widget subclass: #HLTabWidget	instanceVariableNames: 'widget label root'	package: 'Helios-Core'!!HLTabWidget commentStamp!I am a widget specialized into building another widget as an Helios tab.I should not be used directly, `HLWidget class >> #openAsTab` should be used instead.## Example    HLWorkspace openAsTab!!HLTabWidget methodsFor: 'accessing'!activate	self manager activate: self!add	self manager addTab: self!cssClass	^ self widget tabClass!displayLabel	^ self label size > 20 		ifTrue: [ (self label first: 20), '...' ]		ifFalse: [ self label ]!focus	self widget canHaveFocus ifTrue: [		self widget focus ]!label	^ label ifNil: [ '' ]!label: aString	label := aString!manager	^ HLManager current!widget	^ widget!widget: aWidget	widget := aWidget! !!HLTabWidget methodsFor: 'actions'!hide	root ifNotNil: [ root asJQuery css: 'visibility' put: 'hidden' ]!registerBindings	self widget registerBindings!remove	self widget unregister.	root ifNotNil: [ root asJQuery remove ]!show	root		ifNil: [ self appendToJQuery: 'body' asJQuery ]		ifNotNil: [ root asJQuery css: 'visibility' put: 'visible' ]! !!HLTabWidget methodsFor: 'rendering'!renderOn: html	root := html div		class: 'tab';		yourself.	self renderTab!renderTab	root contents: [ :html |		html div			class: 'amber_box';			with: [ self widget renderOn: html ] ]! !!HLTabWidget methodsFor: 'testing'!isActive	^ self manager activeTab = self! !!HLTabWidget class methodsFor: 'instance creation'!on: aWidget labelled: aString	^ self new		widget: aWidget;		label: aString;		yourself! !Widget subclass: #HLWidget	instanceVariableNames: 'wrapper'	package: 'Helios-Core'!!HLWidget commentStamp!I am the abstract superclass of all Helios widgets.I provide common methods, additional behavior to widgets useful for Helios, like dialog creation, command execution and tab creation.## API1. Rendering    Instead of overriding `#renderOn:` as with other Widget subclasses, my subclasses should override `#renderContentOn:`.2. Refreshing    To re-render a widget, use `#refresh`.3. Key bindings registration and tabs    When displayed as a tab, the widget has a chance to register keybindings with the `#registerBindingsOn:` hook method.    4. Unregistration    When a widget has subscribed to announcements or other actions that need to be cleared when closing the tab, the hook method `#unregister` will be called by helios.5. Tabs   To enable a widget class to be open as a tab, override the class-side `#canBeOpenAsTab` method to answer `true`. `#tabClass` and `#tabPriority` can be overridden too to respectively change the css class of the tab and the order of tabs in the main menu.6. Command execution    An helios command (instance of `HLCommand` or one of its subclass) can be executed with `#execute:`.!!HLWidget methodsFor: 'accessing'!manager	^ HLManager current!tabClass	^ self class tabClass!wrapper	^ wrapper! !!HLWidget methodsFor: 'actions'!confirm: aString ifTrue: aBlock	self manager confirm: aString ifTrue: aBlock!execute: aCommand	HLManager current keyBinder		activate;		applyBinding: aCommand asBinding!openAsTab	HLManager current addTab: (HLTabWidget on: self labelled: self class tabLabel)!request: aString do: aBlock	self manager request: aString do: aBlock!request: aString value: valueString do: aBlock	self manager 		request: aString 		value: valueString		do: aBlock!unregister	"This method is called whenever the receiver is closed (as a tab).	Widgets subscribing to announcements should unregister there"! !!HLWidget methodsFor: 'keybindings'!bindKeyDown: keyDownBlock keyUp: keyUpBlock	self wrapper asJQuery		keydown: keyDownBlock;		keyup: keyUpBlock!registerBindings	self registerBindingsOn: self manager keyBinder bindings!registerBindingsOn: aBindingGroup!unbindKeyDownKeyUp	self wrapper asJQuery		unbind: 'keydown';		unbind: 'keyup'! !!HLWidget methodsFor: 'rendering'!renderContentOn: html!renderOn: html	wrapper := html div.    [ :renderer | self renderContentOn: renderer ] appendToJQuery: wrapper asJQuery! !!HLWidget methodsFor: 'testing'!canHaveFocus	^ false! !!HLWidget methodsFor: 'updating'!refresh	self wrapper ifNil: [ ^ self ].    	self wrapper asJQuery empty.    [ :html | self renderContentOn: html ] appendToJQuery: self wrapper asJQuery! !!HLWidget class methodsFor: 'accessing'!openAsTab	HLManager current addTab: (HLTabWidget on: self new labelled: self tabLabel)!tabClass	^ ''!tabLabel	^ 'Tab'!tabPriority	^ 500! !!HLWidget class methodsFor: 'testing'!canBeOpenAsTab	^ false! !HLWidget subclass: #HLFocusableWidget	instanceVariableNames: ''	package: 'Helios-Core'!!HLFocusableWidget commentStamp!I am a widget that can be focused.## API Instead of overriding `#renderOn:` as with other `Widget` subclasses, my subclasses should override `#renderContentOn:`.To bring the focus to the widget, use the `#focus` method.!!HLFocusableWidget methodsFor: 'accessing'!focusClass	^ 'focused'! !!HLFocusableWidget methodsFor: 'events'!blur	self wrapper asJQuery blur!focus	self wrapper asJQuery focus! !!HLFocusableWidget methodsFor: 'rendering'!renderContentOn: html!renderOn: html    wrapper := html div     	class: 'hl_widget';		yourself.		       wrapper with: [ self renderContentOn: html ].		wrapper		at: 'tabindex' put: '0';		onBlur: [ self wrapper asJQuery removeClass: self focusClass ];        onFocus: [ self wrapper asJQuery addClass: self focusClass ]! !!HLFocusableWidget methodsFor: 'testing'!canHaveFocus	^ true!hasFocus	^ self wrapper notNil and: [ self wrapper asJQuery hasClass: self focusClass ]! !HLFocusableWidget subclass: #HLListWidget	instanceVariableNames: 'items selectedItem'	package: 'Helios-Core'!!HLListWidget methodsFor: 'accessing'!cssClassForItem: anObject	^ ''!findListItemFor: anObject	^ (((wrapper asJQuery find: 'li') 		filter: [ :thisArg :otherArg | (thisArg asJQuery data: 'item') = anObject ] currySelf) eq: 0)!items	^ items ifNil: [ items := self defaultItems ]!items: aCollection	items := aCollection!listCssClassForItem: anObject	^ self selectedItem = anObject		ifTrue: [ 'active' ]		ifFalse: [ 'inactive' ]!positionOf: aListItem	<    	return aListItem.parent().children().get().indexOf(aListItem.get(0)) + 1	>!selectedItem	^ selectedItem!selectedItem: anObject	selectedItem := anObject! !!HLListWidget methodsFor: 'actions'!activateFirstListItem	self activateListItem: ((wrapper asJQuery find: 'li.inactive') eq: 0)!activateItem: anObject	self activateListItem: (self findListItemFor: anObject)!activateListItem: aListItem	| item |		(aListItem get: 0) ifNil: [ ^ self ].	aListItem parent children removeClass: 'active'.	aListItem addClass: 'active'.    	self ensureVisible: aListItem.       "Activate the corresponding item"   item := aListItem data: 'item'.   self selectedItem == item ifFalse: [	   self selectItem: item ]!activateNextListItem	self activateListItem: (self wrapper asJQuery find: 'li.active') next.		"select the first item if none is selected"	(self wrapper asJQuery find: ' .active') get ifEmpty: [		self activateFirstListItem ]!activatePreviousListItem	self activateListItem: (self wrapper asJQuery find: 'li.active') prev!ensureVisible: aListItem		"Move the scrollbar to show the active element"		| parent position |	(aListItem get: 0) ifNil: [ ^ self ].	position := self positionOf: aListItem.	parent := aListItem parent.	    aListItem position top < 0 ifTrue: [		(parent get: 0) scrollTop: ((parent get: 0) scrollTop + aListItem position top - 10) ].    aListItem position top + aListItem height > parent height ifTrue: [ 		(parent get: 0) scrollTop: ((parent get: 0) scrollTop + aListItem height - (parent height - aListItem position top)) +10 ]!focus	super focus.    self items isEmpty ifFalse: [ 		self selectedItem ifNil: [ self activateFirstListItem ] ]!refresh	super refresh.	self ensureVisible: (self findListItemFor: self selectedItem)!selectItem: anObject	self selectedItem: anObject! !!HLListWidget methodsFor: 'defaults'!defaultItems	^ #()! !!HLListWidget methodsFor: 'events'!setupKeyBindings 	(HLRepeatedKeyDownHandler on: self)		whileKeyDown: 38 do: [ self activatePreviousListItem ];		whileKeyDown: 40 do: [ self activateNextListItem ];		rebindKeys! !!HLListWidget methodsFor: 'rendering'!renderButtonsOn: html!renderContentOn: html	html ul     	class: 'nav nav-pills nav-stacked';        with: [ self renderListOn: html ].    html div class: 'pane_actions form-actions'; with: [      	self renderButtonsOn: html ].           self setupKeyBindings!renderItem: anObject on: html	| li |    	li := html li.	li asJQuery data: 'item' put: anObject.    li		class: (self listCssClassForItem: anObject);        with: [         	html a            	with: [             		(html tag: 'i') class: (self cssClassForItem: anObject).  					self renderItemLabel: anObject on: html ];				onClick: [                  	self activateListItem: li asJQuery ] ]!renderItemLabel: anObject on: html	html with: anObject asString!renderListOn: html	self items do: [ :each  |     	self renderItem: each  on: html ]! !HLListWidget subclass: #HLNavigationListWidget	instanceVariableNames: 'previous next'	package: 'Helios-Core'!!HLNavigationListWidget methodsFor: 'accessing'!next	^ next!next: aWidget	next := aWidget.    aWidget previous = self ifFalse: [ aWidget previous: self ]!previous	^ previous!previous: aWidget	previous := aWidget.    aWidget next = self ifFalse: [ aWidget next: self ]! !!HLNavigationListWidget methodsFor: 'actions'!nextFocus	self next ifNotNil: [ self next focus ]!previousFocus	self previous ifNotNil: [ self previous focus ]! !!HLNavigationListWidget methodsFor: 'events'!setupKeyBindings	super setupKeyBindings.	self wrapper asJQuery keydown: [ :e |        e which = 39 ifTrue: [         	self nextFocus ].		e which = 37 ifTrue: [         	self previousFocus ] ]! !HLNavigationListWidget subclass: #HLToolListWidget	instanceVariableNames: 'model'	package: 'Helios-Core'!!HLToolListWidget methodsFor: 'accessing'!commandCategory	^ self label!label	^ 'List'!menuCommands	"Answer a collection of commands to be put in the cog menu"		^ ((HLToolCommand concreteClasses		select: [ :each | each isValidFor: self model ])			collect: [ :each | each for: self model ])			select: [ :each | 				each category = self commandCategory and: [ 					each isAction and: [ each isActive ] ] ]!model	^ model!model: aBrowserModel	model := aBrowserModel.        self 		observeSystem;		observeModel!selectedItem: anItem	"Selection changed, update the cog menu"		super selectedItem: anItem.	self updateMenu! !!HLToolListWidget methodsFor: 'actions'!activateListItem: anItem	self model withChangesDo: [ super activateListItem: anItem ]!activateNextListItem	self model withChangesDo: [ super activateNextListItem ]!activatePreviousListItem	self model withChangesDo: [ super activatePreviousListItem ]!observeModel!observeSystem!unregister	super unregister.		self model announcer unsubscribe: self.	self model systemAnnouncer unsubscribe: self! !!HLToolListWidget methodsFor: 'rendering'!renderContentOn: html	self renderHeadOn: html.		super renderContentOn: html!renderHeadOn: html	html div 		class: 'list-label';		with: [			html with: self label.			self renderMenuOn: html ]!renderMenuOn: html	| commands |		commands := self menuCommands.	commands isEmpty ifTrue: [ ^ self ].		html div 		class: 'btn-group cog';		with: [			html a				class: 'btn dropdown-toggle';				at: 'data-toggle' put: 'dropdown';				with: [ (html tag: 'i') class: 'icon-cog' ].		html ul 			class: 'dropdown-menu pull-right';			with: [ 				self menuCommands do: [ :each | 					html li with: [ html a 						with: each menuLabel;						onClick: [ self execute: each ] ] ] ] ]! !!HLToolListWidget methodsFor: 'updating'!updateMenu	(self wrapper asJQuery find: '.cog') remove.		[ :html | self renderMenuOn: html ] 		appendToJQuery: (self wrapper asJQuery find: '.list-label')! !!HLToolListWidget class methodsFor: 'instance creation'!on: aModel	^ self new     	model: aModel;        yourself! !HLListWidget subclass: #HLTabListWidget	instanceVariableNames: 'callback'	package: 'Helios-Core'!!HLTabListWidget commentStamp!I am a widget used to display a list of helios tabs.When a tab is selected, `callback` is evaluated with the selected tab as argument.!!HLTabListWidget methodsFor: 'accessing'!callback	^ callback ifNil: [ [] ]!callback: aBlock	callback := aBlock! !!HLTabListWidget methodsFor: 'actions'!selectItem: aTab	super selectItem: aTab.	self callback value: aTab! !!HLTabListWidget methodsFor: 'rendering'!renderItemLabel: aTab on: html	html span		class: aTab cssClass;		with: aTab label! !HLWidget subclass: #HLManager	instanceVariableNames: 'tabs activeTab environment history'	package: 'Helios-Core'!!HLManager methodsFor: 'accessing'!activeTab	^ activeTab!environment	"The default environment used by all Helios objects"    	^ environment ifNil: [ environment := self defaultEnvironment ]!environment: anEnvironment	environment := anEnvironment!history	^ history ifNil: [ history := OrderedCollection new ]!history: aCollection	history := aCollection!keyBinder	^ HLKeyBinder current!tabs	^ tabs ifNil: [ tabs := OrderedCollection new ]! !!HLManager methodsFor: 'actions'!activate: aTab	self keyBinder flushBindings.	aTab registerBindings.	activeTab := aTab.		self 		refresh;		addToHistory: aTab;		show: aTab!addTab: aTab	self tabs add: aTab.    self activate: aTab!addToHistory: aTab	self removeFromHistory: aTab.	self history add: aTab!confirm: aString ifFalse: aBlock	HLConfirmationWidget new		confirmationString: aString;		cancelBlock: aBlock;		show!confirm: aString ifTrue: aBlock	HLConfirmationWidget new		confirmationString: aString;		actionBlock: aBlock;		show!registerErrorHandler: anErrorHandler	self environment registerErrorHandler: anErrorHandler!registerInspector: anInspector	self environment registerInspector: anInspector!registerProgressHandler: aProgressHandler	self environment registerProgressHandler: aProgressHandler!removeActiveTab	self removeTab: self activeTab!removeFromHistory: aTab	self history: (self history reject: [ :each | each == aTab ])!removeTab: aTab	(self tabs includes: aTab) ifFalse: [ ^ self ].	self removeFromHistory: aTab.	self tabs remove: aTab.	self keyBinder flushBindings.	aTab remove.	self refresh.	self history ifNotEmpty: [		self history last activate ]!request: aString do: aBlock	self 		request: aString		value: ''		do: aBlock!request: aString value: valueString do: aBlock	HLRequestWidget new		confirmationString: aString;		actionBlock: aBlock;		value: valueString;		show! !!HLManager methodsFor: 'defaults'!defaultEnvironment	"If helios is loaded from within a frame, answer the parent window environment"		| parent parentSmalltalk |		parent := window opener ifNil: [ window parent ].	parent ifNil: [ ^ Environment new ].		parentSmalltalk := (parent at: 'requirejs') value: 'amber_vm/smalltalk'.	parentSmalltalk ifNil: [ ^ Environment new ].		^ (parentSmalltalk at: 'Environment') new! !!HLManager methodsFor: 'initialization'!initialize	super initialize.		HLErrorHandler register.	HLProgressHandler register.		self registerInspector: HLInspector.	self registerErrorHandler: ErrorHandler current.	self registerProgressHandler: ProgressHandler current.    self keyBinder setupEvents! !!HLManager methodsFor: 'rendering'!refresh	'.navbar' asJQuery remove.	self appendToJQuery: 'body' asJQuery!renderAddOn: html    html li     	class: 'dropdown';        with: [ 			html a         		class: 'dropdown-toggle';           	 	at: 'data-toggle' put: 'dropdown';            	with: [             		html with: 'Open...'.  					(html tag: 'b') class: 'caret' ].           html ul            		class: 'dropdown-menu';                with: [                  	((HLWidget withAllSubclasses                    	select: [ :each | each canBeOpenAsTab ])                        sorted: [ :a :b | a tabPriority < b tabPriority ])                        do: [ :each |  							html li with: [                      			html a                                 	with: each tabLabel;      								onClick: [ each openAsTab ] ] ] ] ]!renderContentOn: html	html div 		class: 'navbar navbar-fixed-top';		with: [ html div 			class: 'navbar-inner';			with: [ self renderTabsOn: html ] ]!renderTabsOn: html	html ul 		class: 'nav';		with: [         	self tabs do: [ :each |				html li 					class: (each isActive ifTrue: [ 'active' ] ifFalse: [ 'inactive' ]);					with: [						html a							with: [      							((html tag: 'i') class: 'close')  									onClick: [ self removeTab: each ].                              	html span 									class: each cssClass;									with: each displayLabel ];							onClick: [ each activate ] ] ].			self renderAddOn: html ]!show: aTab	self tabs do: [ :each | each hide ].	aTab show; focus! !HLManager class instanceVariableNames: 'current'!!HLManager class methodsFor: 'accessing'!current	^ current ifNil: [ current := self basicNew initialize ]! !!HLManager class methodsFor: 'initialization'!initialize	self current appendToJQuery: 'body' asJQuery! !!HLManager class methodsFor: 'instance creation'!new	"Use current instead"	self shouldNotImplement! !HLWidget subclass: #HLModalWidget	instanceVariableNames: ''	package: 'Helios-Core'!!HLModalWidget commentStamp!I implement an abstract modal widget.!!HLModalWidget methodsFor: 'accessing'!cssClass	^ ''! !!HLModalWidget methodsFor: 'actions'!cancel	self remove!confirm	"Override in subclasses"	self remove!remove	'.dialog' asJQuery removeClass: 'active'.	[ 		'#overlay' asJQuery remove.		'.dialog' asJQuery remove	] valueWithTimeout: 300!show	self appendToJQuery: 'body' asJQuery! !!HLModalWidget methodsFor: 'rendering'!hasButtons	^ true!renderButtonsOn: html	| confirmButton |		html div 		class: 'buttons';		with: [			html button				class: 'button';				with: 'Cancel';				onClick: [ self cancel ].			confirmButton := html button				class: 'button default';				with: 'Confirm';				onClick: [ self confirm ] ].	confirmButton asJQuery focus!renderContentOn: html	| confirmButton |		html div id: 'overlay'.	html div 		class: 'dialog ', self cssClass;		with: [			self renderMainOn: html.			self hasButtons ifTrue: [ 				self renderButtonsOn: html ] ].	'.dialog' asJQuery addClass: 'active'.	self setupKeyBindings!renderMainOn: html!setupKeyBindings	'.dialog' asJQuery keyup: [ :e |		e keyCode = String esc asciiValue ifTrue: [ self cancel ] ]! !HLModalWidget subclass: #HLConfirmationWidget	instanceVariableNames: 'confirmationString actionBlock cancelBlock'	package: 'Helios-Core'!!HLConfirmationWidget commentStamp!I display confirmation messages. Instead of creating an instance directly, use `HLWidget >> #confirm:ifTrue:`.!!HLConfirmationWidget methodsFor: 'accessing'!actionBlock	^ actionBlock ifNil: [ [] ]!actionBlock: aBlock	actionBlock := aBlock!cancelBlock	^ cancelBlock ifNil: [ [] ]!cancelBlock: aBlock	cancelBlock := aBlock!confirmationString	^ confirmationString ifNil: [ 'Confirm' ]!confirmationString: aString	confirmationString := aString! !!HLConfirmationWidget methodsFor: 'actions'!cancel	self cancelBlock value.	super cancel!confirm	super confirm.	self actionBlock value! !!HLConfirmationWidget methodsFor: 'rendering'!renderMainOn: html	html span with: self confirmationString! !HLConfirmationWidget subclass: #HLRequestWidget	instanceVariableNames: 'input value'	package: 'Helios-Core'!!HLRequestWidget commentStamp!I display a modal window requesting user input.Instead of creating instances manually, use `HLWidget >> #request:do:` and `#request:value:do:`.!!HLRequestWidget methodsFor: 'accessing'!cssClass	^ 'large'!value	^ value ifNil: [ '' ]!value: aString	value := aString! !!HLRequestWidget methodsFor: 'actions'!confirm	super confirm.	self actionBlock value: input asJQuery val! !!HLRequestWidget methodsFor: 'rendering'!renderMainOn: html	super renderMainOn: html.	input := html textarea.	input asJQuery val: self value! !HLModalWidget subclass: #HLProgressWidget	instanceVariableNames: 'progressBars visible'	package: 'Helios-Core'!!HLProgressWidget commentStamp!I am a widget used to display progress modal dialogs.My default instance is accessed with `HLProgressWidget class >> #default`.See `HLProgressHandler` for usage.!!HLProgressWidget methodsFor: 'accessing'!progressBars	^ progressBars ifNil: [ progressBars := OrderedCollection new ]! !!HLProgressWidget methodsFor: 'actions'!addProgressBar: aProgressBar	self show.	self progressBars add: aProgressBar.	aProgressBar appendToJQuery: (self wrapper asJQuery find: '.dialog')!do: aBlock on: aCollection displaying: aString	| progressBar |		progressBar := HLProgressBarWidget new		parent: self;		label: aString;		workBlock: aBlock;		collection: aCollection;		yourself.		self addProgressBar: progressBar.	progressBar start!flush	self progressBars do: [ :each |		self removeProgressBar: each ]!remove	self isVisible ifTrue: [		visible := false.		super remove ]!removeProgressBar: aProgressBar	self progressBars remove: aProgressBar ifAbsent: [].	aProgressBar wrapper asJQuery remove.		self progressBars ifEmpty: [ self remove ]!show	self isVisible ifFalse: [		visible := true.		super show ]! !!HLProgressWidget methodsFor: 'rendering'!renderMainOn: html	self progressBars do: [ :each |		html with: each ]! !!HLProgressWidget methodsFor: 'testing'!hasButtons	^ false!isVisible	^ visible ifNil: [ false ]! !HLProgressWidget class instanceVariableNames: 'default'!!HLProgressWidget class methodsFor: 'accessing'!default	^ default ifNil: [ default := self new ]! !HLModalWidget subclass: #HLTabSelectionWidget	instanceVariableNames: 'tabs tabList selectedTab selectCallback cancelCallback confirmCallback'	package: 'Helios-Core'!!HLTabSelectionWidget commentStamp!I am a modal window used to select or create tabs.!!HLTabSelectionWidget methodsFor: 'accessing'!cancelCallback	^ cancelCallback ifNil: [ [] ]!cancelCallback: aBlock	cancelCallback := aBlock!confirmCallback	^ confirmCallback ifNil: [ [] ]!confirmCallback: aBlock	confirmCallback := aBlock!selectCallback	^ selectCallback ifNil: [ [] ]!selectCallback: aBlock	selectCallback := aBlock!selectedTab	^ selectedTab!selectedTab: aTab	selectedTab := aTab!tabs	^ tabs ifNil: [ #() ]!tabs: aCollection	tabs := aCollection! !!HLTabSelectionWidget methodsFor: 'actions'!cancel	super cancel.	self cancelCallback value!confirm	super confirm.	self confirmCallback value: self selectedTab!selectTab: aTab	self selectedTab: aTab.	self selectCallback value: aTab!setupKeyBindings	super setupKeyBindings.	'.dialog' asJQuery keyup: [ :e |		e keyCode = String cr asciiValue ifTrue: [ self confirm ] ]! !!HLTabSelectionWidget methodsFor: 'rendering'!renderContentOn: html	super renderContentOn: html.	self tabList focus!renderMainOn: html	html div 		class: 'title'; 		with: 'Tab selection'.		html with: self tabList!renderTab: aTab on: html	html 		span 			class: aTab cssClass;			with: aTab label!renderTabsOn: html	self tabs do: [ :each |		html li with: [ 			html a 				with: [ 					self renderTab: each on: html ];				onClick: [ self selectTab: each ] ] ]!tabList	tabList ifNil: [ 		tabList := HLTabListWidget new.		tabList			callback: [ :tab | self selectTab: tab. tabList focus ];			selectedItem: self selectedTab;			items: self tabs ].		^ tabList! !HLWidget subclass: #HLProgressBarWidget	instanceVariableNames: 'label parent workBlock collection bar'	package: 'Helios-Core'!!HLProgressBarWidget commentStamp!I am a widget used to display a progress bar while iterating over a collection.!!HLProgressBarWidget methodsFor: 'accessing'!collection	^ collection!collection: aCollection	collection := aCollection!label	^ label!label: aString	label := aString!parent	^ parent!parent: aProgress	parent := aProgress!workBlock	^ workBlock!workBlock: aBlock	workBlock := aBlock! !!HLProgressBarWidget methodsFor: 'actions'!evaluateAt: anInteger	self updateProgress: (anInteger / self collection size) * 100.	anInteger <= self collection size		ifTrue: [ 			[ 				self workBlock value: (self collection at: anInteger).				self evaluateAt: anInteger + 1 ] valueWithTimeout: 10 ]		ifFalse: [ [ self remove ] valueWithTimeout: 500 ]!remove	self parent removeProgressBar: self!start	"Make sure the UI has some time to update itself between each iteration"		self evaluateAt: 1!updateProgress: anInteger	bar asJQuery css: 'width' put: anInteger asString, '%'! !!HLProgressBarWidget methodsFor: 'rendering'!renderContentOn: html	html span with: self label.	html div 		class: 'progress';		with: [			bar := html div 				class: 'bar';				style: 'width: 0%' ]! !HLProgressBarWidget class instanceVariableNames: 'default'!!HLProgressBarWidget class methodsFor: 'accessing'!default	^ default ifNil: [ default := self new ]! !HLWidget subclass: #HLSUnit	instanceVariableNames: ''	package: 'Helios-Core'!!HLSUnit class methodsFor: 'accessing'!tabClass	^ 'sunit'!tabLabel	^ 'SUnit'!tabPriority	^ 1000! !!HLSUnit class methodsFor: 'testing'!canBeOpenAsTab	^ true! !
 |