TkInter wrapper for tcl/tk GUI: Difference between revisions
No edit summary |
No edit summary |
||
| (25 intermediate revisions by the same user not shown) | |||
| Line 1: | Line 1: | ||
This is a guide how you can check out the oldschool 90s tcl/tk interface of ASCEND which is part of engineering history and worth conserving. | This is a guide how you can check out the oldschool 90s tcl/tk interface of ASCEND which is part of engineering history and worth conserving. | ||
[[File:ascend_tcltk_GUI.png]] | |||
The TkInter wrapper is used to call the tcl legacy code: | The TkInter wrapper is used to call the tcl legacy code: | ||
| Line 33: | Line 35: | ||
ASCENDDIST.set("../../") | ASCENDDIST.set("../../") | ||
TKTABLE_LIBRARY = tkinter.StringVar() | TKTABLE_LIBRARY = tkinter.StringVar() | ||
TKTABLE_LIBRARY.set("/usr/lib/tcltk/x86_64-linux-gnu/Tktable2.10") | TKTABLE_LIBRARY.set("/usr/lib/tcltk/x86_64-linux-gnu/Tktable2.10") | ||
| Line 43: | Line 45: | ||
#Evaluation | #Evaluation | ||
gui.tk.eval('set env(ASCENDTK) %s' | gui.tk.eval('lappend auto_path {%s}' % './') | ||
gui.tk.eval('lappend auto_path {%s}' % '../interface') | |||
gui.tk.eval('lappend auto_path {%s}' % '../../ascend/compiler') | |||
gui.tk.eval('lappend auto_path {%s}' % '../../ascend/general') | |||
gui.tk.eval('lappend auto_path {%s}' % '../../ascend/system') | |||
gui.tk.eval('lappend auto_path {%s}' % '../../ascend/utilities') | |||
gui.tk.eval('package require color 1.0') #in ../../ascend/general/ | |||
gui.tk.eval('package require block 1.0') #in ../../ascend/system/ | |||
gui.tk.eval('package require error 1.0') #in ../../ascend/utilities/ | |||
gui.tk.eval('package require module 1.0') #in ../../ascend/compiler/ | |||
gui.tk.eval('package require LibraryProc 1.0') #in ../interface/ | |||
gui.tk.eval('set env(ASCENDTK) %s' % (ASCENDTK.get())) | |||
gui.tk.eval('set env(ASCENDBITMAPS) %s' % (ASCENDBITMAPS.get())) | gui.tk.eval('set env(ASCENDBITMAPS) %s' % (ASCENDBITMAPS.get())) | ||
gui.tk.eval('set env(ASCENDDIST) %s' | gui.tk.eval('set env(ASCENDDIST) %s' % (ASCENDDIST.get())) | ||
gui.tk.eval('set asc_swap_del_backspace %s' % (asc_swap_del_backspace.get())) | gui.tk.eval('set asc_swap_del_backspace %s' % (asc_swap_del_backspace.get())) | ||
| Line 54: | Line 69: | ||
gui.tk.eval('source {ascend.tcl}') | gui.tk.eval('source {ascend.tcl}') | ||
#Mainloop | #Mainloop | ||
gui.mainloop() | gui.mainloop() | ||
</source> | |||
The GUI starts if one comments all the lines loading the packages out (package require) and see the Notes section below what to change in the codebase. | |||
Shared libraries can be compiled and then provided as a package via pkgIndex.tcl in the respective folder for the shared libraries. | |||
Example for ascend/tcltk/interface/LibraryProc.c: | |||
$ gcc -fPIC -shared -DUSE_TCL_STUBS -I /usr/include/tcl8.5/ -I ../../ -o LibraryProc.so LibraryProc.c -L /usr/share/tcltk/tcl8.5 -ltclstub8.5 | |||
Create pkgIndex.tcl (case-sensitive!) in the same folder: | |||
<source lang="tcl"> | |||
package ifneeded LibraryProc 1.0 \ | |||
[list load [file join $dir LibraryProc[info sharedlibextension]]] | |||
</source> | </source> | ||
| Line 65: | Line 96: | ||
! style="background:#bfffbf;" | AscendRC | ! style="background:#bfffbf;" | AscendRC | ||
| <source lang="tcl" style="margin:0px; background:#cfffcf;"> | | <source lang="tcl" style="margin:0px; background:#cfffcf;"> | ||
global env tcl_platform | |||
global asc_swap_del_backspace | |||
proc user_shutdown | |||
</source> | </source> | ||
|- | |- | ||
! style="background:#bfffbf;" | ascend.tcl | ! style="background:#bfffbf;" | ascend.tcl | ||
| <source lang="tcl" style="margin:0px; background:#ffcfcf;"> | | <source lang="tcl" style="margin:0px; background:#ffcfcf;"> | ||
env | global env | ||
global ascSourceVect errorInfo | |||
global tcl_platform tk_version | |||
global ascGlobalVect | |||
proc AscGnuButton | |||
proc Help | |||
proc asc_source | |||
proc trace_var | |||
proc trace_log | |||
proc load_Templates | |||
proc mcgraw_notice | |||
proc balloon_notice | |||
</source> | </source> | ||
|- | |- | ||
! style="background:#bfffbf;" | GlobalProc.tcl | ! style="background:#bfffbf;" | GlobalProc.tcl | ||
| <source lang="tcl" style="margin:0px; background:#cfffcf;"> | | <source lang="tcl" style="margin:0px; background:#cfffcf;"> | ||
proc ascsetdebug | |||
proc asc_catch | |||
proc awin | |||
proc asc_fixiconnames | |||
proc Redraw | |||
proc set_cmuBindings | |||
proc asctk_textCut | |||
proc asctk_textCopy | |||
proc asctk_textPaste | |||
proc asc_export_selection | |||
proc set_Global_Defaults | |||
proc set_Template_defaults | |||
proc Glob_do_GNU | |||
proc ascShowInfo | |||
proc Global_Dismiss_Forever | |||
</source> | </source> | ||
|- | |- | ||
! style="background:#bfffbf;" | View.tcl | ! style="background:#bfffbf;" | View.tcl | ||
| <source lang="tcl" style="margin:0px; background:#cfffcf;"> | | <source lang="tcl" style="margin:0px; background:#cfffcf;"> | ||
global ascViewWindowVect | |||
proc setpos | |||
proc getpos | |||
proc sanegeometry | |||
proc osgpos | |||
proc ospos | |||
proc gospos | |||
proc Browser | |||
proc Debugger | |||
proc Display | |||
proc Global | |||
proc Library | |||
proc Matrix | |||
proc Probe | |||
proc Script | |||
proc Simulations | |||
proc Solver | |||
proc SolverGeneral | |||
proc Toolbox | |||
proc Units | |||
proc AscPlot | |||
proc Environment | |||
proc Set_ViewVect_Values | |||
proc Set_View_Option_Values | |||
proc View_Options | |||
proc View_Appearance | |||
proc View_Get_Proc_Name | |||
proc View_Save_Values | |||
proc View_InitDialog | |||
proc View_WindowInitDialog | |||
proc View_Set_Save_Options | |||
proc View_Save_Window_Appearance | |||
proc View_Save_Window_Options | |||
proc View_Save_SpecialWindow_Values | |||
proc View_Save_Windows_Values | |||
proc View_Save_Interface_Values | |||
proc View_Save_Solver_Params | |||
proc View_Save_Solvers_Params | |||
proc View_Source_Option_Files | |||
proc View_Source_Params_Files | |||
proc View_Help | |||
</source> | </source> | ||
|- | |- | ||
! style="background:#bfffbf;" | main.tcl | ! style="background:#bfffbf;" | main.tcl | ||
| <source lang="tcl" style="margin:0px; background:#cfffcf;"> | | <source lang="tcl" style="margin:0px; background:#cfffcf;"> | ||
global env | |||
global xfLoadPath | |||
global xfLoadInfo | |||
global tcl_platform | |||
global argc | |||
global argv | |||
global auto_path | |||
global xfLoadPath | |||
global xfShowWindow.browser | |||
global xfShowWindow.display | |||
global xfShowWindow.library | |||
global xfShowWindow.probe | |||
global xfShowWindow.script | |||
global xfShowWindow.sims | |||
global xfShowWindow.solver | |||
global xfShowWindow.toolbox | |||
global xfShowWindow.util | |||
global xfShowWindow.units | |||
proc ShowWindow. | |||
proc StartupSrc. | |||
proc EndSrc. | |||
proc XFLocalIncludeModule | |||
proc XFLocalParseAppDefs | |||
proc XFLocalLoadAppDefs | |||
proc XFLocalSetAppDefs | |||
proc InitGlobals | |||
</source> | </source> | ||
|} | |} | ||
=== ascend/tcltk/interface === | === ascend/tcltk/interface === | ||
{| class="infobox wikitable" style="margin-left:1em;" | {| class="infobox wikitable" style="margin-left:1em;" | ||
|- | |- | ||
! style="background:#bfffbf;" | main.c | ! style="background:#bfffbf;" | main.c | ||
| <source lang="c" style="margin:0px; background:#ffcfcf;"> | | <source lang="c" style="margin:0px; background:#ffcfcf;"> | ||
int main(int argc, CONST char *argv[]) | |||
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, | |||
LPSTR lpszCmdLine, int nCmdShow) | |||
static void setargv(int *argcPtr, char ***argvPtr) | |||
</source> | </source> | ||
|- | |- | ||
! style="background:#bfffbf;" | Commands.c | ! style="background:#bfffbf;" | Commands.c | ||
| <source lang="c" style="margin:0px; background:#cfffcf;"> | | <source lang="c" style="margin:0px; background:#cfffcf;"> | ||
void Asc_AddCommand(Tcl_Interp *interp, char *cmdName, Tcl_CmdProc *proc, | |||
ClientData cdata, Tcl_CmdDeleteProc *deleteProc, | |||
CONST char *group, CONST char *usage, | |||
CONST char *shorth, HLFunc longh) | |||
void Asc_CreateCommands(Tcl_Interp *interp) | |||
</source> | </source> | ||
|- | |- | ||
! style="background:#bfffbf;" | Driver.c | ! style="background:#bfffbf;" | Driver.c | ||
| <source lang="c" style="margin:0px; background:#cfffcf;"> | | <source lang="c" style="margin:0px; background:#cfffcf;"> | ||
extern int Tktable_Init(Tcl_Interp*) | |||
static void AscTrap(int) | |||
static void AscCheckEnvironVars(Tcl_Interp*,const char *progname) | |||
static void AscPrintHelpExit(CONST char *) | |||
static int AscProcessCommandLine(Tcl_Interp*, int, CONST char **) | |||
static int AscSetStartupFile(Tcl_Interp*) | |||
static void StdinProc(ClientData, int) | |||
static void InitDebugMalloc(void) | |||
</source> | </source> | ||
|} | |} | ||
| Line 213: | Line 355: | ||
still having these error messages: | still having these error messages: | ||
Error calling set_Library_Defaults; invalid command name "libr_query (in NoteboxProc.tcl) | Error calling set_Library_Defaults; invalid command name "libr_query (in NoteboxProc.tcl) -> Library.tcl | ||
Error calling set_Probe_Defaults; invalid command name "__probe" (in ProbeProc.tcl) | Error calling set_Probe_Defaults; invalid command name "__probe" (in ProbeProc.tcl) | ||
| Line 249: | Line 391: | ||
This array defines the expected file extensions for parsable ascend MODEL/ATOM/unit code. Files are not limited to these, however. Interfaces that see a trailing .* where * is other than these should enquire as to the user intent: the user may have made a mistake. | This array defines the expected file extensions for parsable ascend MODEL/ATOM/unit code. Files are not limited to these, however. Interfaces that see a trailing .* where * is other than these should enquire as to the user intent: the user may have made a mistake. | ||
Definition at line 58 of file ascend/module/compiler/ | Definition at line 58 of file ascend/compiler/module.h | ||
Recursively going through all files where a symbol is defined on which the previous generated shared library depends on and make a shared library of it and package it via pkgIndex.tcl in the respective folder. | |||
Stuck with "couldn't find procedure Color_Init". And I can't find it myself in which file this procedure ought to be. | |||
Searching through the whole trunk branch gives no results: | |||
$ grep -Ril Color_Init * | |||
== References == | |||
<references/> | |||
http://ascend4.org/Saving_and_restoring_model_state#Wrapping_the_old_Tcl_functionality | |||
"The old Tcl/C code uses C code to traverse the model tree and output a text file containing essentially a Tcl script that, when run, does the job of reinserting values into the instance tree by looking up identifiers one-by-one using the 'qlfdid' routines. This approach to restoring model values is possibly not particular efficient, but does currently work. The hazards of using the Tcl interpreter from within Python are a bit scary, however, and it would be nicer to keep language 'cleanness' in the Python code. " | |||
http://ascend4.org/ComponentizingAscend#Older_content_from_this_page... | |||
"Have moved qlfdid stuff into compiler. Not convinced it was really worth it though. -- User:Jpye" | |||
https://matplotlib.org/gallery/user_interfaces/embedding_in_tk_sgskip.html | |||
Latest revision as of 21:56, 28 January 2019
This is a guide how you can check out the oldschool 90s tcl/tk interface of ASCEND which is part of engineering history and worth conserving.
The TkInter wrapper is used to call the tcl legacy code:
https://wiki.python.org/moin/TkInter
https://en.wikipedia.org/wiki/Tkinter
Here are notes which are going to be formulated in detail over time:
Python script to wrap the legacy tcl code with TkInter
Environment variables have to be set in the Python script.
See http://ascend4.org/Environment_variables_for_ASCEND for more information.
Locate the following script in the ascend/tcltk/tk/ folder and call it from the command line.
import tkinter gui = tkinter.Tk() #Variables ASCENDTK = tkinter.StringVar() ASCENDTK.set("./") ASCENDBITMAPS = tkinter.StringVar() ASCENDBITMAPS.set("./bitmaps") ASCENDDIST = tkinter.StringVar() ASCENDDIST.set("../../") TKTABLE_LIBRARY = tkinter.StringVar() TKTABLE_LIBRARY.set("/usr/lib/tcltk/x86_64-linux-gnu/Tktable2.10") asc_swap_del_backspace = tkinter.StringVar() asc_swap_del_backspace.set("1") # for UNIX systems argc = tkinter.IntVar() argc.set(0) #Evaluation gui.tk.eval('lappend auto_path {%s}' % './') gui.tk.eval('lappend auto_path {%s}' % '../interface') gui.tk.eval('lappend auto_path {%s}' % '../../ascend/compiler') gui.tk.eval('lappend auto_path {%s}' % '../../ascend/general') gui.tk.eval('lappend auto_path {%s}' % '../../ascend/system') gui.tk.eval('lappend auto_path {%s}' % '../../ascend/utilities') gui.tk.eval('package require color 1.0') #in ../../ascend/general/ gui.tk.eval('package require block 1.0') #in ../../ascend/system/ gui.tk.eval('package require error 1.0') #in ../../ascend/utilities/ gui.tk.eval('package require module 1.0') #in ../../ascend/compiler/ gui.tk.eval('package require LibraryProc 1.0') #in ../interface/ gui.tk.eval('set env(ASCENDTK) %s' % (ASCENDTK.get())) gui.tk.eval('set env(ASCENDBITMAPS) %s' % (ASCENDBITMAPS.get())) gui.tk.eval('set env(ASCENDDIST) %s' % (ASCENDDIST.get())) gui.tk.eval('set asc_swap_del_backspace %s' % (asc_swap_del_backspace.get())) gui.tk.eval('set argc %s' % (argc.get())) #gui.tk.eval('package require Tktable') gui.tk.eval('source {ascend.tcl}') #Mainloop gui.mainloop()
The GUI starts if one comments all the lines loading the packages out (package require) and see the Notes section below what to change in the codebase.
Shared libraries can be compiled and then provided as a package via pkgIndex.tcl in the respective folder for the shared libraries.
Example for ascend/tcltk/interface/LibraryProc.c:
$ gcc -fPIC -shared -DUSE_TCL_STUBS -I /usr/include/tcl8.5/ -I ../../ -o LibraryProc.so LibraryProc.c -L /usr/share/tcltk/tcl8.5 -ltclstub8.5
Create pkgIndex.tcl (case-sensitive!) in the same folder:
package ifneeded LibraryProc 1.0 \ [list load [file join $dir LibraryProc[info sharedlibextension]]]
ascend/tcltk/tk/
| AscendRC | global env tcl_platform global asc_swap_del_backspace proc user_shutdown |
|---|---|
| ascend.tcl | global env global ascSourceVect errorInfo global tcl_platform tk_version global ascGlobalVect proc AscGnuButton proc Help proc asc_source proc trace_var proc trace_log proc load_Templates proc mcgraw_notice proc balloon_notice |
| GlobalProc.tcl | proc ascsetdebug proc asc_catch proc awin proc asc_fixiconnames proc Redraw proc set_cmuBindings proc asctk_textCut proc asctk_textCopy proc asctk_textPaste proc asc_export_selection proc set_Global_Defaults proc set_Template_defaults proc Glob_do_GNU proc ascShowInfo proc Global_Dismiss_Forever |
| View.tcl | global ascViewWindowVect proc setpos proc getpos proc sanegeometry proc osgpos proc ospos proc gospos proc Browser proc Debugger proc Display proc Global proc Library proc Matrix proc Probe proc Script proc Simulations proc Solver proc SolverGeneral proc Toolbox proc Units proc AscPlot proc Environment proc Set_ViewVect_Values proc Set_View_Option_Values proc View_Options proc View_Appearance proc View_Get_Proc_Name proc View_Save_Values proc View_InitDialog proc View_WindowInitDialog proc View_Set_Save_Options proc View_Save_Window_Appearance proc View_Save_Window_Options proc View_Save_SpecialWindow_Values proc View_Save_Windows_Values proc View_Save_Interface_Values proc View_Save_Solver_Params proc View_Save_Solvers_Params proc View_Source_Option_Files proc View_Source_Params_Files proc View_Help |
| main.tcl | global env global xfLoadPath global xfLoadInfo global tcl_platform global argc global argv global auto_path global xfLoadPath global xfShowWindow.browser global xfShowWindow.display global xfShowWindow.library global xfShowWindow.probe global xfShowWindow.script global xfShowWindow.sims global xfShowWindow.solver global xfShowWindow.toolbox global xfShowWindow.util global xfShowWindow.units proc ShowWindow. proc StartupSrc. proc EndSrc. proc XFLocalIncludeModule proc XFLocalParseAppDefs proc XFLocalLoadAppDefs proc XFLocalSetAppDefs proc InitGlobals |
ascend/tcltk/interface
| main.c | int main(int argc, CONST char *argv[]) int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow) static void setargv(int *argcPtr, char ***argvPtr) |
|---|---|
| Commands.c | void Asc_AddCommand(Tcl_Interp *interp, char *cmdName, Tcl_CmdProc *proc, ClientData cdata, Tcl_CmdDeleteProc *deleteProc, CONST char *group, CONST char *usage, CONST char *shorth, HLFunc longh) void Asc_CreateCommands(Tcl_Interp *interp) |
| Driver.c | extern int Tktable_Init(Tcl_Interp*) static void AscTrap(int) static void AscCheckEnvironVars(Tcl_Interp*,const char *progname) static void AscPrintHelpExit(CONST char *) static int AscProcessCommandLine(Tcl_Interp*, int, CONST char **) static int AscSetStartupFile(Tcl_Interp*) static void StdinProc(ClientData, int) static void InitDebugMalloc(void) |
Changes made to the codebase to get the GUI up and running with TkInter
There was an issue with tktable which I couldn't fix and also found this bug report which might actually not be resolved: http://bugs.ascend4.org/view.php?id=254 see also:
https://github.com/nbro/tktable/issues/3
https://github.com/nbro/tktable/issues/1
Also the trunk branch was missing the interval.c and interval.h files in ascend/compiler/.
I copied the files over from the Python3 branch and then the issue was solved
In line 138 in solver.tcl the - bitmap {feet} and -bitmap{stop} options couldn't find the bitmaps in ascend/tcltk/tk/bitmaps.
See the Notes section for other changes to get the tcl/tk interface working.
Notes
ASC_IMPORT:
Definition at line 124 of file ascend/general/platform.h
asc_swap_del_backspace:
set to "1" for unix systems (done in Python script)
__userdata_init:
comment out
argc:
set argument counter argc to 0 (done in Python script)
tktable missing:
- install via sudo apt-get install tk-table
- ascend still can't find tktable
- install tcl8.5-dev, tk8.5-dev, libxft-dev, libfontconfig1-dev, libfreetype6-dev, libpng-dev
- error: if {[catch {package require Tktable 2.8} err]} in ascend.tcl
- http://bugs.ascend4.org/view.php?id=254
- https://github.com/nbro/tktable/issues/3
- The plot window and the solver window require the
- TkTable exension package by Roland King mthomas 98.05.07: require 1.8 until we debug the memory errors in 2.0
- comment the if clause block starting with line 225 in ascend.tcl out
- Issue not yet resolved
error because interval.c and interval.h files were missing (trunk branch) in ascend/compiler/:
copy both files from Python3 branch into the trunk branch folder
bitmap "feet" not defined:
- ascend.tcl line 259: awin all
- awin is in GlobalProc.tcl
- ShowWindow.solver in line 108 in GlobalProc.tcl
- line 138 in solver.tcl
- option -bitmap {feet} was removed because it couldn't be located
- option -bitmap {stop} was removed
Ascend starts with main GUI! Some windows or buttons still don't work.
still having these error messages:
Error calling set_Library_Defaults; invalid command name "libr_query (in NoteboxProc.tcl) -> Library.tcl
Error calling set_Probe_Defaults; invalid command name "__probe" (in ProbeProc.tcl)
Error calling set_Solver_Defaults; invalid command name "slv_available" (in SolverProc.tcl)
Error calling set_Units_Defaults invalid command name "u_dim2num" (in UnitsProc.tcl)
The commands aren't found because the C code isn't compiled as a shared library (extension). See this link to build the extensions in ascend/tcltk/interface:
https://wiki.tcl-lang.org/page/Hello+World+as+a+C+extension
https://www.tcl.tk/man/tcl8.4/TclLib/InitStubs.htm:
see also: https://www.tcl.tk/doc/howto/stubs.html
Change to interface directory and compile to shared libraries:
$ gcc -fPIC -shared -DUSE_TCL_STUBS -I /usr/include/tcl8.5/ -I ../../ -o LibraryProc.so LibraryProc.c -L /usr/share/tcltk/tcl8.5 -ltclstub8.5
But getting this error then when trying to load the shared library in the tcl shell (tclsh):
$tclsh
% load LibraryProc.so
% couldn't load file "LibraryProc.so": LibraryProc.so: undefined symbol: g_alt_ending
So the global variable g_alt_ending can't be found:
http://ascend4.org/Global_variables
ASC_DLLSPEC CONST char* g_alt_ending[MOD_FILE_EXTS]
This array defines the expected file extensions for parsable ascend MODEL/ATOM/unit code. Files are not limited to these, however. Interfaces that see a trailing .* where * is other than these should enquire as to the user intent: the user may have made a mistake.
Definition at line 58 of file ascend/compiler/module.h
Recursively going through all files where a symbol is defined on which the previous generated shared library depends on and make a shared library of it and package it via pkgIndex.tcl in the respective folder.
Stuck with "couldn't find procedure Color_Init". And I can't find it myself in which file this procedure ought to be.
Searching through the whole trunk branch gives no results:
$ grep -Ril Color_Init *
References
http://ascend4.org/Saving_and_restoring_model_state#Wrapping_the_old_Tcl_functionality
"The old Tcl/C code uses C code to traverse the model tree and output a text file containing essentially a Tcl script that, when run, does the job of reinserting values into the instance tree by looking up identifiers one-by-one using the 'qlfdid' routines. This approach to restoring model values is possibly not particular efficient, but does currently work. The hazards of using the Tcl interpreter from within Python are a bit scary, however, and it would be nicer to keep language 'cleanness' in the Python code. "
http://ascend4.org/ComponentizingAscend#Older_content_from_this_page... "Have moved qlfdid stuff into compiler. Not convinced it was really worth it though. -- User:Jpye"
https://matplotlib.org/gallery/user_interfaces/embedding_in_tk_sgskip.html
