cd "C:/These/Projet Interface/COMETS/devCOMETS" source test_MetaUIExchanger.tcl # or source demo_DSVIS2008.tclAsk me questions if something unclear (which is certainly the case for many things!).

inherit CometTravel_CFC CommonFCSecond, we define the constructor, we need here at least 3 attributes:
method CometTravel_CFC constructor {} {
set this(loc_src) ""
set this(loc_dst) ""
set this(travel) ""
}
We can automatically generate accessors by using Generate_accessors command like that:
Generate_accessors CommonFC_Activator [list loc_src loc_dst travel]We define the others methods of the API:
method CommonFC_Activator Compute_travel {} {}
Finally we define explicitely what is the API. The API is divided between getters (which do not modify the internal state) and setter (which do modify the internal state).
Both are defined using a procedure that return a list <method name, parameters>:
proc P_L_methodes_get_CometTravel {} {return [list {get_loc_src { }} {get_loc_dst { }} {get_travel { }} ]}
proc P_L_methodes_set_CometTravel {} {return [list {set_loc_src {l}} {set_loc_dst {l}} {set_travel {t}} {Compute_travel {}} ]}
inherit CometTravel_LC Logical_consistencyThen we define the constructor, it instantiate the previously defined CFC and the related Logical Models (LM). Here there are 2 LM, one for presentation (named by suffixing "_LM_LP" to the name of the LC), the other for computation (this is the functional core part, named by suffixing _LM_FC to the name of the LC).
method CometTravel_LC constructor {name descr args} {
this inherited $name $descr
this set_GDD_id CT_CometTravel
set CFC "${objName}_CFC"; CometTravel_CFC $CFC
this set_Common_FC $CFC
set this(LM_LP) "${objName}_LM_LP";
CometTravel_LM_LP $this(LM_LP) $this(LM_LP) "The logical presentation of $name"
this Add_LM $this(LM_LP);
set this(LM_FC) "${objName}_LM_FC";
CometTravel_LM_FC $this(LM_FC) $this(LM_FC) "The logical functional core of $name"
this Add_LM $this(LM_FC);
eval "$objName configure $args"
return $objName
}
Don't forget to send back the name of the created object, and just before to interpret arguments:
eval "$objName configure $args"The semantic API can be automatically generated. Getters refer to the Common functional functional Core (CFC) with $this(FC). Setters refer to the CFC and the list of LM ($this(L_LM)):
return $objName
Methodes_get_LC CometTravel_LC [P_L_methodes_get_CometTravel] {$this(FC)}
Methodes_set_LC CometTravel_LC [P_L_methodes_set_CometTravel] {$this(FC)} {$this(L_LM)}
That's ALL for the LC! :)
inherit CometTravel_LM_LP Logical_presentationWe define the constructor, here the constructor mainly define Physical Models (PM) factories:
method CometTravel_LM_LP constructor {name descr args} {
this inherited $name $descr
# Adding some physical presentations
this Add_PM_factories [Generate_factories_for_PM_type [list {CometTravel_PM_P_TK_base Ptf_TK} \
{CometTravel_PM_P_U Ptf_ALL} \
] $objName]
eval "$objName configure $args"
return $objName
}
We can generate the semantic API automatically again.
Getters refers to the CFC. Setters do not modify the CFC (only the LC can) but propagate calls to the active PMs ($this(L_actives_PM)):
Methodes_set_LC CometTravel_LM_LP [P_L_methodes_set_CometTravel] {} {$this(L_actives_PM)}
Methodes_get_LC CometTravel_LM_LP [P_L_methodes_get_CometTravel] {$this(FC)}
In the LM, we can define a new list of methods that will support COMET/RE (basic support of multimodality notions of Redundancy and Equivalence bewteens the different PMs of a same LM, generally about presentation, but not necessarily) expressions:
proc P_L_methodes_set_CometTravel_COMET_RE {} {return [list {set_loc_src {l}} {set_loc_dst {l}} {Compute_travel {}}]}
We generate automatically the code that will manage these methods:
Generate_LM_setters CometTravel_LM_LP [P_L_methodes_set_CometTravel_COMET_RE]We can overload the set_PM_active of the LM to update each new PM:
method CometTravel_LM_LP set_PM_active {PM} {
this inherited $PM
if {[string equal [this get_LC] {}]} {return}
$PM set_loc_src [this get_loc_src]
$PM set_loc_dst [this get_loc_dst]
$PM set_travel [this get_travel]
}
That's all for a LM :)
inherit CometTravel_PM_P_TK_base PM_TKThen we define the constructor. Basically for a TK PM, a root is defined (this(top_frame)):
method CometTravel_PM_P_TK_base constructor {name descr args} {
this inherited $name $descr
this set_GDD_id CometTravel_PM_P_TK_base
set this(top_frame) ""
eval "$objName configure $args"
return $objName
}
Then we generate automatically the semantic API...
Methodes_set_LC CometTravel_PM_P_TK_base [P_L_methodes_set_CometTravel] {} {}
Methodes_get_LC CometTravel_PM_P_TK_base [P_L_methodes_get_CometTravel] {$this(FC)}
and the API related to COMET/RE:
Generate_PM_setters CometTravel_PM_P_TK_base [P_L_methodes_set_CometTravel_COMET_RE]The biggest thing to do for a PM TK is to overload the get_or_create_prims method. This method define the TK primitives...COME BACK !...it's just TK code!
method CometTravel_PM_P_TK_base get_or_create_prims {root} {
set this(top_frame) "$root.tk_${objName}_topframe"
if {![winfo exists $this(top_frame)]} {
frame $this(top_frame)
frame $this(top_frame).f_src
pack $this(top_frame).f_src -side top -expand 1 -fill x
label $this(top_frame).f_src.lab -text "From : "
pack $this(top_frame).f_src.lab -side left -expand 0 -fill none
global ${objName}_tk_txt_from; set ${objName}_tk_txt_from ""
entry $this(top_frame).f_src.ent -text ${objName}_tk_txt_from
pack $this(top_frame).f_src.ent -side left -expand 1 -fill x
frame $this(top_frame).f_dst
pack $this(top_frame).f_dst -side top -expand 1 -fill x
label $this(top_frame).f_dst.lab -text "To : "
pack $this(top_frame).f_dst.lab -side left -expand 0 -fill none
global ${objName}_tk_txt_to; set ${objName}_tk_txt_to ""
entry $this(top_frame).f_dst.ent -text ${objName}_tk_txt_to
pack $this(top_frame).f_dst.ent -side left -expand 1 -fill x
button $this(top_frame).bt_compute -text "GO !" -command "$objName Do_Compute"
pack $this(top_frame).bt_compute -side top -fill x
set this(img_tk_name) "[this get_LM]_Activator_PM_P_button_TK_TK_img_ressource"
image create photo $this(img_tk_name)
label $this(top_frame).lab_img -image $this(img_tk_name)
pack $this(top_frame).lab_img -side top -fill none
text $this(top_frame).txt_travel -height 4 -width 40 -state disabled
pack $this(top_frame).txt_travel -side top -fill both
}
this set_root_for_daughters $this(top_frame)
this set_loc_src [this get_loc_src]
this set_loc_dst [this get_loc_dst]
this set_travel [this get_travel]
return [this set_prim_handle $this(top_frame)]
}
Notice that the TK button do call a method nammed Do_compute...we defined it as:
method CometTravel_PM_P_TK_base Do_Compute {} {
if {![winfo exists $this(top_frame)]} {return}
global ${objName}_tk_txt_from
global ${objName}_tk_txt_to
this prim_set_loc_src [subst $${objName}_tk_txt_from]
this prim_set_loc_dst [subst $${objName}_tk_txt_to]
this prim_Compute_travel
}
Basically we call prim_* methods (prim_set_loc_src, prim_set_loc_dst, prim_Compute_travel).
These methods have been generated automatically before to manage COMET/RE expression.
method CometTravel_PM_P_TK_base set_loc_src {l} {
if {![winfo exists $this(top_frame)]} {return}
global ${objName}_tk_txt_from
set ${objName}_tk_txt_from $l
}
method CometTravel_PM_P_TK_base set_loc_dst {l} {
if {![winfo exists $this(top_frame)]} {return}
global ${objName}_tk_txt_to
set ${objName}_tk_txt_to $l
}
method CometTravel_PM_P_TK_base set_travel {t} {
if {![winfo exists $this(top_frame)]} {return}
image create photo $this(img_tk_name) -file [lindex $t 0]
$this(top_frame).txt_travel configure -state normal
$this(top_frame).txt_travel delete 0.0 end
$this(top_frame).txt_travel insert 0.0 [lindex $t 1]
$this(top_frame).txt_travel configure -state disabled
}
method CometTravel_PM_P_TK_base Compute_travel {} {}
Notice that the Compute_travel method don't do anything...it's normal, the job of a presentation PM is simply to interact with the user.
The real computation job will be done by functional PMs.
inherit CometTravel_PM_P_U PM_U_ContainerThen, in the constructor, we define the composite graph of COMET:
method CometTravel_PM_P_U constructor {name descr args} {
this inherited $name $descr
this set_GDD_id N_CometTravel_PM_P_U
# Nested COMET graph
set this(cont_root) [CPool get_a_comet CometContainer -Add_style_class root]
set this(spec_from) [CPool get_a_comet CometSpecifyer -Add_style_class from]
set this(spec_to) [CPool get_a_comet CometSpecifyer -Add_style_class from]
set this(act_go) [CPool get_a_comet CometActivator -Add_style_class compute_travel]
set this(img_trav) [CPool get_a_comet CometImage -Add_style_class travel]
set this(txt_trav) [CPool get_a_comet CometText -Add_style_class travel]
set this(cont_dght) [CPool get_a_comet CometContainer -Add_style_class root]
$this(cont_root) Add_daughters_R [list $this(spec_from) $this(spec_to) $this(act_go) $this(img_trav) $this(txt_trav) $this(cont_dght)]
# Specify where are the handles
this set_L_nested_handle_LM $this(cont_root)_LM_LP
this set_L_nested_daughters_LM $this(cont_dght)_LM_LP
# Subscribe to events...
$this(act_go) Subscribe_to_activate $objName "$objName Do_Compute" UNIQUE
eval "$objName configure $args"
return $objName
}
Notice that we have to specify the root COMET and the COMET under which daughters of the composite will be plugged.
This is done by indicating the presentation LM of the corresponding COMETs:
this set_L_nested_handle_LM $this(cont_root)_LM_LP this set_L_nested_daughters_LM $this(cont_dght)_LM_LPAs for the primitive PM TK, an activator COMET trigger the method Do_Compute that we have to implement. Basically we call the very same prim_* methods...
method CometTravel_PM_P_U Do_Compute {} {
this prim_set_loc_src [$this(spec_from) get_text]
this prim_set_loc_dst [$this(spec_to) get_text]
this prim_Compute_travel
}
As for a primitive PM, we have to implement the semantic API, it is pretty much faster here due to higher level of abstraction used (the composing COMETs instead of TK primitives):
method CometTravel_PM_P_U set_loc_src {l} {
$this(spec_from) set_text $l
}
method CometTravel_PM_P_U set_loc_dst {l} {
$this(spec_to) set_text $l
}
method CometTravel_PM_P_U set_travel {t} {
$this(img_trav) load_img [lindex $t 0]
$this(txt_trav) set_text [lindex $t 1]
}
method CometTravel_PM_P_U Compute_travel {} {}
That's ALL :) You now have 2 presentation PM that you can test. The composite one can be used with any technology (TK, OpenGL, HTML, vocal, etc.).
The advantage of using a tailored TK PM is that you are able to specify very precisely how it should be displayed and how it should interact with the user.
inherit CometTravel_LM_FC Logical_modelThe constructor basically instantiate some functional PM, here only one. Unlike the presentations PMs, the others PMs have to be instantiated explicitely as there is no automatical mechanism that create a graph of PM except for the presentation PMs.
method CometTravel_LM_FC constructor {name descr args} {
this inherited $name $descr
# Adding some physical models
set name ${objName}_PM_FC_pipo_[this get_a_unique_id]
CometTravel_PM_FC_pipo $name "Pipo FC for testing" ""
this Add_PM $name
this set_PM_active $name
eval "$objName configure $args"
return $objName
}
We generate automatically the code of the semantic API:
Methodes_set_LC CometTravel_LM_FC [P_L_methodes_set_CometTravel] {} {$this(L_actives_PM)}
Methodes_get_LC CometTravel_LM_FC [P_L_methodes_get_CometTravel] {$this(FC)}
We define a list of methods that will support COMET/RE expressions:
proc P_L_methodes_set_CometTravel_FC_COMET_RE {} {return [list {set_travel {t}}]}
And finally we generate these methods:
Generate_LM_setters CometTravel_LM_FC [P_L_methodes_set_CometTravel_FC_COMET_RE]That's all for the functional LM :)
inherit CometTravel_PM_FC_pipo Physical_modelThe constructor do nothing special:
method CometTravel_PM_FC_pipo constructor {name descr args} {
this inherited $name $descr
this set_GDD_id N_CometTravel_PM_FC_pipo
eval "$objName configure $args"
return $objName
}
Semantic API can be generated automatically...
Methodes_set_LC CometTravel_PM_FC_pipo [P_L_methodes_set_CometTravel] {} {}
Methodes_get_LC CometTravel_PM_FC_pipo [P_L_methodes_get_CometTravel] {$this(FC)}
...as for the API managing COMET/RE expression. Note that we use here a list of methods nammed P_L_methodes_set_CometTravel_FC_COMET_RE.
This list has been defined in the functional LM.
Generate_PM_setters CometTravel_PM_FC_pipo [P_L_methodes_set_CometTravel_FC_COMET_RE]The ONLY method that has to be overloaded in the semantic API of the CometTravel functional PMs is Compute_travel:
method CometTravel_PM_FC_pipo Compute_travel {} {
this prim_set_travel [list "[Comet_files_root]Comets/CometTravel/PM_Ps/FC/pipo_trajet.gif" "Turn left, then you are arrived...BRAVO !!!!"]
}
Of course a real functional PM would have to do some more serious stuff, such as querying google map...