In this example, you'll add to your To-Do List example to illustrate how you might implement an application which acts as a desktop launcher for other applications. These other applications will be packaged as ICs. The desktop launcher will be packaged as a leaf IC and will explicitly load and unload the other ICs and launch the associated applications based on the user's selection.
You already have one sample application which you can launch from your desktop launcher, the To-do List. The other will be an example provided with VisualAge Smalltalk, EwxDrawnListExample in EwExamples.
First, you need ICs for the two applications your desktop launcher will be launching. The first you already have, the To-do List, in ictest.ic. In this example, we're not going to go over again the packaging of the To-do List. If you don't have ictest.ic, perform the steps listed in Creating a reusable and a leaf IC. Note that ictest.ic is actually a leaf IC which you're not really going to use as a leaf IC in this example.
You can verify that the To-do List as packaged in ictest.ic will behave correctly when launched by the desktop launcher by executing code to simulate what the desktop launcher does. Try the following (be sure that you do not have IcTestView or IcTestModel already loaded in your image).
|status| (status:=System loadComponent: 'ictest.ic') isNil ifTrue: [System message: 'ictest.ic already loaded; please unload.'] ifFalse: [status ifTrue: [#ToDoListView asClass new openWidget] ifFalse: [System message: 'Could not load ictest.ic']]
Next, you're going to package EwxDrawnListExample in EwExamples. Since you will be managing the loading and unloading of the To-Do List and EwxDrawnListExample ICs from your desktop launcher application, you can package these ICs as either reusable or leaf ICs. As usual, there are trade-offs between the two approaches. First, as leaf ICs and unlike reusable ICs, the packager will eliminate unneeded code during the reduction step resulting in a smaller IC in most cases. This is a factor in packaging EwExamples since you're using only one of the examples provided in the application. Second, should you ever want to run one of these applications without the desktop launcher, you can do so if you package it as a leaf IC. However, if you package, for example, EwExamples as a leaf IC and perform reduction, the resulting IC is less reusable since the only code it contained is code in support of EwxDrawnListExample.
Therefore, in the interests of reusability and to show that you can load and use both leaf and reusable ICs from your desktop launcher, you're going to package EwExamples as a reusable IC.
|status| (status:=System loadComponent: 'list.ic') isNil ifTrue: [System message: 'list.ic already loaded; please unload.'] ifFalse: [status ifTrue: [#EwxDrawnListExample asClass new open] ifFalse: [System message: 'Could not load list.ic'] ]
Now, You're ready to create your simple desktop launcher application.
finalInitialize (self subpartNamed: 'DrawnListLoaded') value: false. (self subpartNamed: 'ToDoListLoaded') value: false.
finalInitialize initializes both variables to false and will be invoked automatically on startup.
launchToDoList | unloadResult loadResult | (self subpartNamed: 'DrawnListLoaded') value ifTrue: [ System showBusyCursorWhile: [unloadResult := System removeComponent: 'list.ic']. unloadResult ifTrue: [ ^System message: 'Could not unload list.ic'] ifFalse: [ (self subpartNamed: 'DrawnListLoaded') value: false. (self subpartNamed: 'DrawnList') enable]]. System showBusyCursorWhile: [loadResult := System loadComponent: 'ictest.ic']. loadResult isNil ifTrue: [ System message: 'Could not load ictest.ic'] ifFalse: [ loadResult ifTrue: [ (self subpartNamed: 'ToDoListLoaded') value: true. (self subpartNamed: 'ToDoList') disable. #ToDoListView asClass new openWidget] ifFalse: [ System message: 'Could not load ictest.ic']]
launchDrawnList | unloadResult loadResult | (self subpartNamed: 'ToDoListLoaded') value ifTrue: [ System showBusyCursorWhile: [unloadResult := System removeComponent: 'ictest.ic']. unloadResult ifTrue: [ ^System message: 'Could not unload ictest.ic'] ifFalse: [ (self subpartNamed: 'ToDoListLoaded') value: false. (self subpartNamed: 'ToDoList') enable]]. System showBusyCursorWhile: [loadResult := System loadComponent: 'list.ic']. loadResult isNil ifTrue: [ System message: 'Could not load list.ic'] ifFalse: [ loadResult ifTrue: [ (self subpartNamed: 'DrawnListLoaded') value: true. (self subpartNamed: 'DrawnList') disable. #EwxDrawnListExample asClass new open] ifFalse: [ System message: 'Could not load list.ic']]
launchToDoList and launchIconTree handle the
unloading of one IC if it is already loaded and the loading of the other IC
for the selected application.
![]() | System loadComponent: returns nil only when
attempting to load an IC that has already been loaded. Since you are
disabling the push button which loads the IC just loaded, this should not
happen. Nonetheless, you've included the code for
robustness.
Further, note that you're launching the selected application with, for example, #EwxDrawnListExample asClass new open instead of EwxDrawnListExample new open. You're doing this for two reasons. First, it prevents a packaging error because of an out-of-scope reference to EwxDrawnListExample since EwExamples is not included in IcTestDesktopLauncher's prerequisites. Second, during development, assuming you are testing with ICs for To-Do List and EwxDrawnListExample and not the loaded applications, if the ICs are not loaded, the class names are undefined because the classes are not loaded. Specifying the launch code as you did allows you to resolve these potential problems. |
abt -ilauncher.ic
In the three previous examples you've seen how to create both reusable and leaf ICs. You've also seen how to let the VisualAge runtime system manage the loading of ICs or how you can manage the same programmatically from an application. In these examples, the ICs you have created have been platform independent. That is, they are portable across all platforms on which VisualAge Smalltalk runs. The ICs that contain your example applications are platform portable because they contain no platform specific code. All platform specific code necessary for their execution is contained in the VisualAge Smalltalk runtime ICs which they define as prerequisites.
However desirable it may be to avoid platform specific code, it is not always possible. Sometimes, you may desire or need to write platform specific code in one or more of your Smalltalk applications. Having platform specific code introduces complexities into the process of creating ICs. The last example looks at how to create platform specific ICs.