Source File
functor
prepare
ArgSpec = record(defaults(rightmost type:bool default:true)
random(rightmost type:bool default:true))
%% DefaultScenario = d('Disney': ['Mickey'('Düsseldorf') 'Goofy'('Berlin')]
'Oz': ['Tinman'('München') 'Toto'('Saarbrücken')])
import
Application Tk TkTools
Configure(fonts colors goods)
AgentAbstractions(new)
Agents(broker)
Widgets(entryChooser
map)
Dialogs(about
addCompany remCompany
addDriver remDriver)
Randomizer('class')
define
TextBg = Configure.colors.textBg
TextFont = Configure.fonts.text
TextWidth = 4
BigTextWidth = 17
class Frontend
prop locking
feat
%% menu src dst what weight send map randomvar
%% agents broker randomizer
%% toplevel
attr
src:unit dst:unit
meth init(toplevel:T)
self.toplevel = T
ThisRandomizer = {New Randomizer.'class' init(broker:ThisBroker)}
RandGo = {New Tk.variable tkInit(false)}
RandSpeed = {New Tk.variable tkInit(1)}
Menu = {TkTools.menubar T T
[menubutton(text: 'Transportation'
feature: transportation
menu:
[command(label: 'About...'
action: self # about)
separator
command(label: 'Quit'
action: Application.exit # 0)])
menubutton(text: 'Configure'
feature: configure
menu:
[command(label: 'Add Company...'
action: self # addCompany
feature: addCompany)
command(label: 'Remove Company...'
action: self # remCompany
state: disabled
feature: remCompany)
separator
command(label: 'Add Driver...'
action: self # addDriver
state: disabled
feature: addDriver)
command(label: 'Remove Driver...'
action: self # remDriver
state: disabled
feature: remDriver)
separator
command(label: 'Add Defaults'
action: self # addDefaults
feature: addDefaults)])
menubutton(text: 'Random'
feature: random
menu:
[radiobutton(label: 'Slow'
action: ThisRandomizer # slow
variable: RandSpeed
value: 0)
radiobutton(label: 'Medium'
action: ThisRandomizer # medium
variable: RandSpeed
value: 1)
radiobutton(label: 'Fast'
action: ThisRandomizer # fast
variable: RandSpeed
value: 2)
separator
checkbutton(label: 'Go'
action: ThisRandomizer # toggle
variable: RandGo)])
menubutton(text: 'Windows'
feature: windows
menu: nil)]
nil}
CtyMap = {New Widgets.map init(parent:self)}
Query = {New Tk.frame tkInit(parent:T relief:sunken bd:3)}
FromL = {New Tk.label tkInit(parent:Query text:'From:')}
FromT = {New Tk.label tkInit(parent:Query width:BigTextWidth
anchor:w
bg:TextBg font:TextFont)}
ToL = {New Tk.label tkInit(parent:Query text:'To:')}
ToT = {New Tk.label tkInit(parent:Query width:BigTextWidth
anchor:w
bg:TextBg font:TextFont)}
WhatL = {New Tk.label tkInit(parent:Query text:'Good:')}
WhatT = {New Widgets.entryChooser
tkInit(parent:Query toplevel:T
entries: {Record.toList Configure.goods})}
WhgtL = {New Tk.label tkInit(parent:Query text:'Weight:')}
WhgtT = {New Tk.entry tkInit(parent:Query width:TextWidth
bg:TextBg font:TextFont)}
Send = {New Tk.button tkInit(parent:Query text:'Send to Broker'
action: self # send
state: disabled)}
{WhgtT tk(insert 0 25)}
ThisBroker
in
{ForAll [transportation configure random windows]
proc {$ F}
{Menu.F.menu tk(configure tearoff:false)}
end}
{Tk.batch [pack(FromL FromT ToL ToT
WhatL WhatT WhgtL WhgtT side:left padx:2)
pack(Send side:left padx:6)
pack(Menu CtyMap Query fill:x)]}
self.menu = Menu
self.src = FromT
self.dst = ToT
self.send = Send
self.map = CtyMap
self.weight = WhgtT
self.what = WhatT.entry
ThisBroker = {AgentAbstractions.new Agents.broker init(toplevel:self)}
self.agents = {Dictionary.new}
self.broker = ThisBroker
self.randomizer = ThisRandomizer
self.randomvar = RandGo
end
meth random
{self.randomvar tkSet(true)}
{self.randomizer toggle}
end
meth DisableMenus
{ForAll [transportation configure random]
proc {$ F}
{self.menu.F tk(configure state:disabled)}
end}
end
meth EnableMenus
{ForAll [transportation configure random]
proc {$ F}
{self.menu.F tk(configure state:normal)}
end}
end
meth CheckSend
S=@src D=@dst
in
{self.send tk(conf state:if S\=D andthen
{IsAtom S} andthen {IsAtom D}
then normal
else disabled
end)}
end
meth putSrc(Src)
lock
src <- Src {self.src tk(conf text:Src)}
Frontend, CheckSend
end
end
meth putDst(Dst)
lock
dst <- Dst {self.dst tk(conf text:Dst)}
Frontend, CheckSend
end
end
meth send
lock
W = {self.weight tkReturnInt(get $)}
in
if {IsInt W} then
{self.broker announce(src:@src dst:@dst weight:W
what:{self.what tkReturnAtom(get $)})}
end
end
end
meth about
lock
Frontend, DisableMenus
{Wait {New Dialogs.about init(master:self.toplevel)}.tkClosed}
Frontend, EnableMenus
end
end
meth addCompany
lock Agents=self.agents C in
Frontend, DisableMenus
{Wait {New Dialogs.addCompany init(master: self.toplevel
agents: Agents
company:C)}.tkClosed}
if {IsDet C} then
Menu = self.menu.configure
in
{Dictionary.put Agents C nil}
{self.broker add(company:C)}
{Menu.remCompany tk(entryconfigure state:normal)}
{Menu.addDriver tk(entryconfigure state:normal)}
if {Some {Arity DefaultScenario}
fun {$ C}
{Dictionary.member Agents C}
end} then
{Menu.addDefaults tk(entryconfigure state:disabled)}
end
end
Frontend, EnableMenus
end
end
meth remCompany
lock Agents=self.agents C in
Frontend, DisableMenus
{Wait {New Dialogs.remCompany init(master: self.toplevel
agents: Agents
company:C)}.tkClosed}
if {IsDet C} then
Menu = self.menu.configure
in
{Dictionary.remove Agents C}
{self.broker remove(company:C)}
if {Dictionary.entries Agents}==nil then
{Menu.remCompany tk(entryconf state:disabled)}
{Menu.addDriver tk(entryconf state:disabled)}
{Menu.remDriver tk(entryconf state:disabled)}
{Menu.addDefaults tk(entryconfigure state:normal)}
elseif {Not {Some {Arity DefaultScenario}
fun {$ C}
{Dictionary.member Agents C}
end}} then
{Menu.addDefaults tk(entryconfigure state:enabled)}
end
end
Frontend, EnableMenus
end
end
meth addDriver
lock Agents=self.agents C D Y in
Frontend, DisableMenus
{Wait {New Dialogs.addDriver init(master: self.toplevel
agents: Agents
company:C
driver: D
city: Y)}.tkClosed}
if {IsDet C} then
{Dictionary.put Agents C D|{Dictionary.get Agents C}}
{self.menu.configure.remDriver tk(entryconf state:normal)}
{self.broker add(company:C driver:D city:Y)}
end
Frontend, EnableMenus
end
end
meth remDriver
lock Agents=self.agents C D in
Frontend, DisableMenus
{Wait {New Dialogs.remDriver init(master: self.toplevel
agents: Agents
company: C
driver: D)}.tkClosed}
if {IsDet C} then
{Dictionary.put Agents C
{List.subtract {Dictionary.get Agents C} D}}
{self.broker remove(company:C driver:D)}
if {All {Dictionary.keys Agents}
fun {$ C}
{Dictionary.get Agents C}==nil
end}
then
{self.menu.configure.remDriver tk(entryconf state:disabled)}
end
end
Frontend, EnableMenus
end
end
meth addDefaults
lock Menu=self.menu.configure in
{Record.forAllInd DefaultScenario
proc {$ C Ds}
{Dictionary.put self.agents C {Map Ds Label}}
{self.broker add(company:C)}
{ForAll Ds
proc {$ D}
{self.broker add(driver:{Label D} company:C city:D.1)}
end}
end}
{Menu.addDefaults tk(entryconf state:disabled)}
{Menu.addDriver tk(entryconf state:normal)}
{Menu.remCompany tk(entryconf state:normal)}
{Menu.remDriver tk(entryconf state:normal)}
end
end
end
Args = {Application.getCmdArgs ArgSpec}
T = {New Tk.toplevel tkInit(title: 'Transportation'
delete: Application.exit # 0)}
F = {New Frontend init(toplevel:T)}
if Args.defaults orelse Args.random then
{F addDefaults}
end
if Args.random then
{F random}
end
end