.
"
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.
"
'From Smalltalk/X, Version:2.10.5 on 24-mar-1995 at 9:31:53 am'!
Model subclass:#ApplicationModel
instanceVariableNames:'builder resources'
classVariableNames:''
poolDictionaries:''
category:'Interface-Framework'
!
ApplicationModel class instanceVariableNames:'ClassResources'!
!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.
"
!
version
"
$Header: /cvs/stx/stx/libview2/Attic/AppModel.st,v 1.16 1995-09-09 02:29:25 claus Exp $
"
!
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 you 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
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.
"
! !
!ApplicationModel class methodsFor:'initialization'!
initialize
self == ApplicationModel ifTrue:[
Smalltalk addDependent:self
]
"
ApplicationModel initialize
"
! !
!ApplicationModel class methodsFor:'instance creation'!
new
^ super new basicInitialize initialize
! !
!ApplicationModel class methodsFor:'startup'!
open
"create an instance of the application and open its view"
self new open
"
self open
"
!
openOn:anApplicationModel
"I dont really understand what this method is useful for ..."
anApplicationModel open
!
openOnDevice:aDevice
"create an instance of the application and open its view
on another device.
EXPERIMENTAL and unfinished."
self new openOnDevice:aDevice
!
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"
! !
!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 methodsFor:'initialization'!
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
!
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.
!
initialize
"nothing done here;
but can be redefined in concrete applications"
!
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
]
! !
!ApplicationModel methodsFor:'queries'!
processName
"return a name to be shown for me in the process monitor"
^ 'Application'
! !
!ApplicationModel methodsFor:'startup'!
allButOpenInterface:aSymbol
"create my views but do not open the main window"
|spec|
spec := self class interfaceSpecFor:aSymbol.
self allButOpenFrom:spec.
^ builder
!
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.
!
open
"open a standard interface"
self openInterface
!
openInterface
"open a standard interface on another device.
Subclasses which do not have an interfaceSpec
may want to redefine this method and create & open their view(s)
there. (see NewLauncher as an example)."
self openInterface:#windowSpec
!
openInterface:aSymbol
"open an interface on another display;
the argument, aSymbol specifies which interface.
Typically, applications only use one interface,
returned by the #windowSpec method."
self allButOpenInterface:aSymbol.
builder openWithExtent:nil.
^ builder
!
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
!
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]
]
]
]
!
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
!
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
!
opened
"this is sent by my topView when its finally open"
self addTopViewsToCurrentProject.
self postOpenWith:builder
!
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
!
preBuildWith:aBuilder
"this is sent before an interface is built from a spec.
Can be redefined in subclasses.
mhmh - what should this do here ?"
!
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 ?"
! !
!ApplicationModel methodsFor:'accessing'!
resources
"return the applications resources - thats a ResourcePack containing
language strings"
^ resources
!
window
"return my topWindow"
^ builder window
!
windowGroup
"return the applications windowGroup"
^ builder window windowGroup
!
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
! !
!ApplicationModel methodsFor:'window events'!
windowEvent:anEvent from:anApplicationWindow
^ self
! !
!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
!
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
! !