Squeak
  links to this page:    
View this PageEdit this PageUploads to this PageHistory of this PageTop of the SwikiRecent ChangesSearch the SwikiHelp Guide
ImageCoderMorph
Last updated at 11:02 am UTC on 3 October 2020
ToDo: check and update the content if necessary (October 2020)

About including graphics with the code you distribute


2007

Introduction

But first how I got here (cue dreamy fade-in)...

So one day I find myself with the beginnings of an application (or "set of cooperating objects" if you prefer) and start to wonder how to provide a GUI.

Being a newbie my first thought is to throw something together using Morphic drag-n-drop but my feeble efforts fail as soon as I start getting too ambitious. For example doing layouts more than one level deep.

Anyway, I'm still not clear how I would then hook-up a manually created GUI to my non-morphic code.

EToy scripting seemed reasonable but I quickly got into serious trouble, locking myself out of the Squeak image because I had tried to share a semaphore between Morphic/non-Morphic code - OUCH!

On the plus side I discover that I can just drag-n-drop a graphic file to the Squeak window and a SketchMorph magically appears with my graphic!

So if I can safely isolate my non-Morphic code from the hand-crafted morphic GUI and just drag-in my graphics I'm almost home.

But then I wonder what impact all this will have when I come to distribute my app and should I even have to care at this point?
It turns out I do because there are several distribution methods and some do not cater for packaging graphics with code.

With my main objective fading quickly into the dim and dingy past I think "well others includes graphics with their code... how do they do that?".

Web searching bares little fruit and like a naive tourist caught in quicksand I, a mere newbie, am forced to go deep Squeaking yet again (the mantra of "RTFC" echos consistently through my mind, somewhat mockingly).

Just in the nick of time, gasping for air, I discover a common technique seems to be to embed the graphic data in a method that returns a "Form".

Whooo Hoooo now I only have to find the "tool" that does this! Oh no, more deep Squeaking and I'm still exhausted! Nothing for it but to create my own tool for this ...


A Morph that Creates Code that Creates a Form based on My Graphics


Catchy title eh? No? Awwwwww :-( I reluctantly adopt the title "ImageCoderMorph". This morph will accept a drop (from say Windows Explorer) of a image file and then spit out the code needed to produce a form with the image data embedded as an array. Not only that but it has to look good as well... but to do that it needs a good graphic to represent it... but to do that I need an ImageCoderMorph. I scream but no one hears. Still dizzy after Deep Squeak Diving and distracted by the constant niggling voice (rtfc, rtfc, rtfc...) I employ a hack-n-slash approach...

I subclass from ImageMorph and from PasteUpMorph I extract #dropFiles:anEvent and associated stuff and replace the guts with a call to my own code-creation method:

dropFiles: anEvent 
	| numFiles stream |
	numFiles := anEvent contents.
	1
		to: numFiles
		do: [:i | 
			stream := FileStream requestDropStream: i.
			[
				self createFormCode: stream
			
			] ensure: [stream close]
		]

My code-creation method is a similar hack-n-slash...

createFormCode: aStream
	"Create code to generate a form for an image"
	
	| handler aForm name |
	
	handler := ExternalDropHandler lookupExternalDropHandler: aStream.
	handler ifNil: [^self].

	aStream binary.
	aForm := Form fromBinaryStream: (RWBinaryOrTextStream with: aStream contents) reset.
	name := aStream localName.
	
	Transcript show: (FileDirectory baseNameFor: name)
			, 'Form
	"Original file: ' , name , '"
	^ Form
		extent: ' , aForm width asString , ' @ ' , aForm height asString , '
		depth: ' , aForm depth asString , '
		fromArray: ' , aForm bits asArray asString , '
		offset: 0 @ 0
'

Note that a chunk of the above is mainly single quoted text and I am just filling in the blanks and sending it to a Transcript window.

Now I jump to GIMP create a nice graphic, save it, back to Squeak, instantiate ImageCoderMorph and drop my new image file on it. I rename the Transcript output and add it as a method to ImageCoderMorph as so...

myDefaultForm
	"Original file: imagecodericon.png"
	^ Form
		extent: 64 @ 64
		depth: 32
		fromArray: #(5725850 4284243354 4284047002 ...)
		offset: 0 @ 0

Now I edit the init method to use my new graphic as so...

initialize
	super initialize.
	self image: (self myDefaultForm).
	self setBalloonText: '...'.



The result (code attached)


Job done but I wimp out and simply file-out and attach it here. Exhausted I go to bed perhaps to dream of days long past when I was working on a "real" application.

ImageCoderMorph.st


Epilogue

AlterEgo: Hey, not bad! Especially for a Sunday morning! Pat yourself on the head and take the rest of the day off.

Me: Gee thanks, I'm glad you like it. But tell me, surely this has already been done or is it so trivial that newbies are just expected to know how to do it?

AlterEgo: Hey, no point asking me! I'm just your alter-ego and only know as-much or as-little as you do. I'm disturbed you didn't know this. You definately need sleep dude.

Me: Huh, no point arguing I suppose... (cue lights out)