TkInter wrapper for tcl/tk GUI

From ASCEND
Jump to: navigation, search

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.

Ascend tcltk GUI.png

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