"
COPYRIGHT (c) 1995 by Claus Gittinger
All Rights Reserved
This software is furnished under a license and may be used
only in accordance with the terms of that license and with the
inclusion of the above copyright notice. This software may not
be provided or otherwise made available to, or used by, any
other person. No title to or ownership of the software is
hereby transferred.
"
Model subclass:#ApplicationModel
instanceVariableNames:'builder resources'
classVariableNames:''
poolDictionaries:''
category:'Interface-Framework'
!
ApplicationModel class instanceVariableNames:'ClassResources'
"
The following class instance variables are inherited by this class:
Model -
Object -
"
!
!ApplicationModel class methodsFor:'documentation'!
copyright
"
COPYRIGHT (c) 1995 by Claus Gittinger
All Rights Reserved
This software is furnished under a license and may be used
only in accordance with the terms of that license and with the
inclusion of the above copyright notice. This software may not
be provided or otherwise made available to, or used by, any
other person. No title to or ownership of the software is
hereby transferred.
"
!
documentation
"
Since many ST-80 classes are subclasses of ApplicationModel, this class
is provided here to allow easier porting of ST-80 code.
It does not (currently) provide much functionality and is NOT
compatible to the corresponding ST80 class; therefore, manual
changes have to be made to get those applications to run under ST/X.
(but at least, this enables you to fileIn that code and have a superclass
for them)
As time goes by, ST/X applications are going to be converted to
become subclasses of this abstract class - see NewLauncher for a
first concrete example.
ApplicationModel is prepared to build a view from a windowSpec, as
created by the windowBuilder. If your subclass does not provide such
a spec, you should at least redefine:
#openInterface - to create a topview and open it
you may want to redefine:
#closeRequest - to catch window closing
#focusSequence - to define a sequence for focus-stepping
Once the interfaceBuilder is finished & released, subclasses can
alternatively provide the spec via a #windowSpec method.
The classResources have been put into this class to allow ST/X
applications (which used to be subclasses of StandardSystemView)
to migrate smoothly into ApplicationModels (which is better design ...).
[Instance variables:]
resources ResourcePack language string translation
builder WindowBuilder a builder who knows how to create
a window hierarchy from a specification
Notice: this class was implemented using protocol information
from alpha testers and PD code - it may not be complete or compatible to
the corresponding ST-80 class. If you encounter any incompatibilities,
please forward a note to the ST/X team.
[author:]
Claus Gittinger
[see also:]
StandardSystemView
WindowGroup DeviceWorkstation
"
! !
!ApplicationModel class methodsFor:'initialization'!
initialize
self == ApplicationModel ifTrue:[
Smalltalk addDependent:self
]
"
ApplicationModel initialize
"
! !
!ApplicationModel class methodsFor:'instance creation'!
new
"return a new initialized instance"
^ super new basicInitialize initialize
"Modified: 24.4.1996 / 09:42:14 / cg"
! !
!ApplicationModel class methodsFor:'change & update'!
update:something
"flush resources on language changes"
something == #Language ifTrue:[
"flush resources on language changes"
self flushAllClassResources
]
! !
!ApplicationModel class methodsFor:'queries'!
interfaceSpecFor:aSelector
"return an interface spec"
^ self perform:aSelector
! !
!ApplicationModel class methodsFor:'resources'!
classResources
"if not already loaded, get the classes resourcePack
and return it"
ClassResources isNil ifTrue:[
ClassResources := ResourcePack for:self.
].
^ ClassResources
!
classResources:aResourcePack
"allow setting of the classResources"
ClassResources := aResourcePack
!
flushAllClassResources
"flush all classes resource translations.
Needed after a resource file / language setting has changed."
ResourcePack flushCachedResourcePacks.
self flushClassResources.
self allSubclassesDo:[:aClass |
aClass flushClassResources.
]
!
flushClassResources
"flush classes resource string translations.
Needed whenever a resource file / language setting has changed"
ClassResources := nil.
!
updateClassResources
"update my classResources"
ClassResources := nil.
self classResources
! !
!ApplicationModel class methodsFor:'startup'!
open
"create an instance of the application and open its view"
^ self new open
"
self open
"
"Modified: 3.5.1996 / 13:39:21 / cg"
!
openInterface:anInterfaceSymbol
"create an instance of the application and open a view as
specified by anInterfaceSymbol."
self new openInterface:anInterfaceSymbol
"Modified: 5.9.1995 / 17:54:50 / claus"
!
openOn:anApplicationModel
"send an open message to the argument, anApplicationModel.
I dont really understand what this method is useful for ..."
anApplicationModel open
"Modified: 24.4.1996 / 09:43:04 / cg"
!
openOnDevice:aDevice
"create an instance of the application and open its view
on ANOTHER device.
For more info, read the document on multiple display
support and the documentation of the DeviceWorkstation class."
self new openOnDevice:aDevice
"Modified: 24.4.1996 / 09:44:19 / cg"
! !
!ApplicationModel methodsFor:'accessing'!
builder
"return the applications builder; this one has more information
about views, components etc."
^ builder
!
builder:aBuilder
"set the applications builder. Normally, you should not set it
directly, but depend on the default builder, as created when the application
was created."
builder := aBuilder
!
focusSequence
"return a focusSequence for stepping through the applications views.
The builder usually keeps track of so-called 'tabable' views.
Stepping is done with the FocusNext/FocusPrevius keys, which are
typically bound to Meta-CursorUp/Meta-CursorDown.
Subclasses which do not use the builder (but instead build their view
programmatically) should redefine this method to return a collection of
views which defines the sequence."
builder notNil ifTrue:[
^ builder focusSequence
].
^ nil
!
resources
"return the applications resources - thats a ResourcePack containing
language strings"
^ resources
!
window
"return my topWindow"
^ builder window
!
window:aTopView
"set my topWindow"
builder window:aTopView
"Created: 18.4.1996 / 14:55:26 / cg"
!
windowGroup
"return the applications windowGroup"
^ builder window windowGroup
! !
!ApplicationModel methodsFor:'initialization'!
addTopViewsToCurrentProject
"add all of my topViews to the current projects list of views.
This allows hiding views on a per-project basis."
self windowGroup topViews do:[:aView |
aView addToCurrentProject
]
!
basicInitialize
"initialize the application.
Since ST-80 applications seem commonly to redefine initialize
without doing a super initialize, the real initialization is
done here ..."
super initialize.
"claus: I wanted to delay the creation & assignment of the
builder till later, to allow setting to another builder.
however, some ST-80 code accesses the builder right after instance
creation ..."
"/ "
"/ Create a windowBuilder to have someone around which
"/ understands the builder protocol. Since UIBuilder is not present
"/ in all systems, this allows operation without one (unless a spec
"/ is read later ...)
"/ "
builder := self createBuilder.
builder notNil ifTrue:[builder application:self].
resources := self class classResources.
!
createBuilder
"create a UI Builder for me.
This method can be redefined if (eventually) there are
spec readers for other UI languages (motif UIL ?)"
|cls|
(cls := UIBuilder) isNil ifTrue:[
(cls := WindowBuilder) isNil ifTrue:[
^ nil
]
].
^ cls new
!
initialize
"nothing done here;
but can be redefined in concrete applications"
! !
!ApplicationModel methodsFor:'misc'!
withCursor:aCursor do:aBlock
"evaluate aBlock, showing aCursor in my topView and all of its subviews.
Return the value of aBlock."
^ self window withCursor:aCursor do:aBlock
!
withExecuteCursorDo:aBlock
"evaluate aBlock, showing an executeCursor in my topView and all of its subviews.
Return the value of aBlock."
^ self withCursor:(Cursor execute) do:aBlock
"Created: 14.12.1995 / 20:57:03 / cg"
!
withReadCursorDo:aBlock
"evaluate aBlock, showing a readCursor in my topView and all of its subviews.
Return the value of aBlock."
^ self withCursor:(Cursor read) do:aBlock
"Created: 14.12.1995 / 20:56:47 / cg"
"Modified: 14.12.1995 / 20:57:36 / cg"
!
withWaitCursorDo:aBlock
"evaluate aBlock, showing a waitCursor in my topView and all of its subviews.
Return the value of aBlock."
^ self withCursor:Cursor wait do:aBlock
! !
!ApplicationModel methodsFor:'queries'!
processName
"return a name to be shown for me in the process monitor"
^ 'Application'
! !
!ApplicationModel methodsFor:'startup'!
allButOpenFrom:aSpec
"create my views but do not open the main window"
|realBuilder|
"/ DISABLED; see comment in basicInitialize
"/
"/ "
"/ here, we kludge a bit: up to now, the builder was an
"/ instance of the no-op WindowBuilder. Now, it becomes
"/ a UIBuilder ....
"/ This allows for ApplicationModels without a UIBuilder
"/ if not needed.
"/ "
"/ realBuilder := UIBuilder new.
"/ builder := realBuilder.
"/ builder application:self.
"/ builder bindings:builder bindings.
self preBuildWith:builder.
builder buildFromSpec:aSpec.
builder window model:self.
builder window application:self.
self postBuildWith:builder.
!
allButOpenInterface:aSymbol
"create my views but do not open the main window"
|spec|
spec := self class interfaceSpecFor:aSymbol.
self allButOpenFrom:spec.
^ builder
!
close
"this is sent by my topView when about to be closed
by the program (not by the windowManager).
Could be redefined in subclasses."
self closeDownViews
!
closeDownViews
"close down the applications view"
|wg views|
(wg := self windowGroup) notNil ifTrue:[
views := wg topViews.
views notNil ifTrue:[
views copy do:[:aView |
aView notNil ifTrue:[aView destroy]
]
]
]
!
closeRequest
"this is sent by my topView when about to be closed by the
windowmanager. Can be redefined to inform & query about unsafed
view contents, to send #close on ok, or ignore the closeRequest."
self closeDownViews
!
menuFor:aSymbol
"create a new menuBuilder, to read specs and
create a menu from it. Return this menu"
|spec mbuilder|
spec := self class interfaceSpecFor:aSymbol.
mbuilder := UIBuilder new.
mbuilder buildFromSpec:spec.
builder componentAt:#windowMenuHolder put:(mbuilder window asValue).
^ mbuilder window
!
open
"open a standard interface"
^ self openInterface
"Modified: 3.5.1996 / 13:39:15 / cg"
!
openInterface
"open a standard interface on another device.
Subclasses which do not have an interfaceSpec
should redefine this method and create & open their view(s) there.
(see NewLauncher as an example)."
self openInterface:#windowSpec
"Modified: 24.4.1996 / 09:35:43 / cg"
!
openInterface:aSymbol
"open a specific interface.
The argument, aSymbol specifies which interface. The concrete
application subclass must provide a method with that name,
which must return an interfaceSpec. This is forwarded to
the builder to create the views.
Typically, applications only use one interface,
returned by the #windowSpec method."
self allButOpenInterface:aSymbol.
builder openWithExtent:nil.
^ builder
"Modified: 24.4.1996 / 09:37:11 / cg"
!
opened
"the topView has been opened.
This is sent by my topView when its finally open"
self addTopViewsToCurrentProject.
self postOpenWith:builder
"Modified: 24.4.1996 / 09:37:28 / cg"
!
postBuildWith:aBuilder
"this is sent after an interface is built from a spec.
Can be redefined in subclasses.
mhmh - what should this do here ?"
!
postOpenWith:aBuilder
"this is sent after the applications main window is opened.
Can be redefined in subclasses.
mhmh - what should this do here ?"
!
preBuildWith:aBuilder
"this is sent before an interface is built from a spec.
Can be redefined in subclasses.
mhmh - what should this do here ?"
!
restarted
"sent by my windowGroup, when restarted from an image.
Nothing done here, but can be redefined to perform any actions
required to reset the application after an image-restart.
(for example: check if application files are still around, restart
subprocesses etc.)."
!
saveAndTerminateRequest
"some windowManagers send this to shut down an application
and have it save its state for restart.
Can be redefined in subclasses"
self closeRequest
! !
!ApplicationModel methodsFor:'window events'!
showActivity:someMessage
"some activityNotification shalt be communicated to
the user. Forwarded from the topView and ignored here.
Can be redefined in concrete applications to show the
message either in some infoView (infoLabel as in Windows)
or in the title area (as done in the browsers)"
^ self
"Created: 16.12.1995 / 18:41:04 / cg"
"Modified: 24.4.1996 / 09:34:22 / cg"
!
windowEvent:anEvent from:anApplicationWindow
"dummy: windowEvent forwarding is not yet implemented"
^ self
"Modified: 24.4.1996 / 09:32:50 / cg"
! !
!ApplicationModel class methodsFor:'documentation'!
version
^ '$Header: /cvs/stx/stx/libview2/ApplicationModel.st,v 1.24 1996-05-03 11:46:53 cg Exp $'
! !
ApplicationModel initialize!