Building an Envy Application Browser in Smalltalk

It’s bin a while, but here we go :)

A collegue of mine runs www.vastgoodies.com. A place where VA Smalltalk developers can share their open source projects and tools.

VAStGoodies created by a3aan

At home I use Pharo Smalltalk for my hobby projects, so stuff developed at work  (like nice plugin wrappers for jqGrid and jsTree) all need to be ported manually to Pharo which is a pain to do.

So I came up with the idea to create a Monticello repository client in Pharo and extend vastgoodies.com to export Monticello Packages using some conventions which will only fit MY needs. I know there are many differences between the dialects, but if it can exchange my plugin wrappers and other cool seaside stuff using standard conventions my goals are achieved :)

To get to know Envy, i wanted to start with something simple. The Browse button for applications was showing a place holder for a application browser so I decided to start with that.

The basic layout for the application browser consists of 4 columns with a 2 tabs at the bottom.

The first columns shows al the applications in the configuration map, the second shows the classes in the selected application, the third lists the categories in the selected class and enables the user to select the instance or class side of the categories.

And the fourth column shows the methods in that protocol. Multiple protocols can be selected and it will list all methods in these protocols.

The first tab shows the Class definition and the second the method source.

Once you click on a method, the source code is shown with a Syntax Hihglighter using the Smalltalk Brush created by Daan van Berkel.

Some more details….

A3aan already wrote a Envy Library Accessor which I extended to retrieve the extra data from the Envy repository. All operations on the Envy Repository are mutally exclusive, which means that no process can access the repository at the same time. This support was already built in, so I just used that :)

EnvySeasideLibraryAccessor>>applicationsFor: aConfigurationMapOrNil

	(aConfigurationMapOrNil isNil)
		ifTrue: [ ^#() ]. 

	^self do: [ aConfigurationMapOrNil shadowApplications ]
EnvySeasideLibraryAccessor>>do: aBlock

	"No problem to call this nested (from one process).
	Nesting is faster then repeated call anyway."

	^[Mutex critical: aBlock] ifCurtailed: [EmLibrary startUp]

The applicationsFor: returns a collection of  EmShadowApplication instances where I would only like to print the signature in the list.

EnvySeasideConfigurationMapVersionBrowserComponent>>renderAppColumnOn: html 
	(html select)
		size: 20;
		on: #app of: self;
		list: self applications;
		labels: [:each | each signature];
		onChange: (html jQuery ajax serializeThisWithHidden script:
						[:s |
						category := nil.
						method := nil.
						className := nil.
						self renderRerenderClassScriptOn: s.
						self renderRerenderCategoryScriptOn: s.
						self renderRerenderMethodScriptOn: s.
						self renderRerenderContentsScriptOn: s])

When the onChange event fires, I reset the instance variables category, method and class name and rerender the columns and content pane on the bottom.

EnvySeasideConfigurationMapVersionBrowserComponent>>renderRerenderClassScriptOn: s
	s << (s jQuery id: #classColumn) html: [:h | self renderClassColumnOn: h]

Interaction with the other select lists is done in pretty the same way.

Getting the source code is also a very simple operation:

EnvySeasideLibraryAccessor>>sourceCodeFor: aSelector in: aShadowClassInstance
	^self do: [aShadowClassInstance sourceCodeAt: aSelector ifAbsent: ['']]

Where do these shiny colors come from?

Using the syntax highlighter supplied described above works pretty well if the source code content is already in the DOM before you call the syntax highlighter.

But if the source code is loaded using a ajax call, the syntax highligher does not know it needs to redraw the preformatted area.

Luckily, the syntax highlighter can be invoked to restyle the preformatted area pretty easily.

EnvySeasideLibraryAccessor>>renderRerenderContentsScriptOn: s
	s << (s jQuery id: #classDef) html: [:h | self renderClassDefOn: h].
	s << (s jQuery id: #code) html: [:h | self renderPreformattedCodeOn: h].
	s << (JSStream on: 'SyntaxHighlighter.highlight();').
	s << (s jQuery id: #contents) tabs select: 1

I could write a wrapper around the SyntaxHighlighter javascript library, but this works as well :)

So that’s it! Pretty easy exercise  to get an application browser into vastgoodies.

Advertisement

  1. Leave a Comment

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.