Twilight GUI Documentation
Table of Contents
- 1. Importing the wrappers
- 2. Hello World
- 3. An IDE to run the examples
- 4. Callback mechanism
- 5. button widget
- 6. Widget Placement
- 7. checkbutton widget
- 8. label widget
- 9. Radio buttons
- 10. tbutton widget
- 11. textentry widget
- 12. editor widget
- 13. image widget
- 14. splitter views
- 15. listbox widget
- 16. streebox widget (static tree)
- 17. treebox widget
- 18. popup command
- 19. modal Dialog windows
- 20. Workspaces
- 21. Higher level widgets (openFile, saveFile)
At the moment, the Twilight GUI interface is minimal. Only the most basic
widgets are implemented and standard signals are connected to them.
1. Importing the wrappers
In order to use TG we have to import one of: wrap_pygtk.py,
wrap_pyqt.py, wrap_wxpython.py or
wrap_tkinter.py.
It's possible to import more than one and switch GUIs at
runtime but often one toolkit may not allow the threads of another one to
run and this should be used only for the development of TG itself.
GUI=None
try: # try to import PyQt first
import wrap_pyqt
GUI = wrap_pyqt
except ImportError:
try: # if it doesn't exist, go for PyGTK
import wrap_pygtk
GUI = wrap_pygtk
except ImportError:
try: # try for wxPython
import wrap_wxpython
GUI = wrap_wxpython
except ImportError:
try: # finally go for Tkinter
import wrap_tkinter
GUI = wrap_tkinter
except ImportError:
print "No toolkit"
|
In the future we may define a standard environemnt variable which
would set the user's preferable toolkit search order. For example something like:
TWGUI_TOOLKITS = [ 'pygtk', 'pyqt', 'wxpython', 'tkinter' ]
|
2. Hello World
The basic element of a TG application is the Window class. There are
many ways to use a window to put widgets in it, for example, inheritance,
creating a window and calling its 'widget generation functions', passing
the widget creation code as a string to the __init__ of the window, etc.
In this tutorial we'll see the method of creating a Window and
calling its 'widget creation functions':
Supposing you've imported the apropriate wrapper and set GUI=wrap_toolkit,
the simple 'hello world' example is this:
W=GUI.Window ()
W.start_construction ()
W.button (text='Click me', cmd='print "Hello world"')
W.end_construction ()
GUI.exec_loop ()
|
Widget creation code must always be included in start_construction() and end_construction().
The latter finalizes the creation and displays the window. The GUI.exec_loop() must be
executed at least once to make everything working.
3. An IDE to run the examples
Throughout this short course we will see many small examples. It is good to
have a gui to paste and run them. Here it is:
W=GUI.Window ()
if W.BaseGUI == 'pyqt': fnt = 'terminal'
else: fnt = 'Courier'
W.start_construction ()
W.open_vbox ()
W.editor (name='EDDIE', font=fnt, dims=(80,20))
W.open_hbox ()
W.button (text='Run It!', cmd='exec self.master.EDDIE.get_text () in globals (), globals ()')
W.button (text='Clear', cmd='self.master.EDDIE.set_text ("")')
W.close_box ()
W.close_box ()
W.end_construction ()
GUI.exec_loop ()
|
Run it. You can paste examples from below and click on 'Run it' to run them
and see what happens. In fact, for starters, paste the above editor text
and run it if you want. It is too an example!
4. Callback mechanism
The button and several other widgets can execute callback code. The code can be a
string or a function. In the editor example the code is a string and this string
is exec'd. If we want to use functions we would also like to make them members
of the Window instance. For that the famous transplant class is very useful:
it takes a function and makes it an instance method. Here is the editor
where this time the button's command is a function.
class transplant:
def __init__(self, method, host, method_name=None):
self.host = host
self.method = method
setattr(host, method_name or method.__name__, self)
def __call__(self, *args, **kwargs):
nargs = [self.host]
nargs.extend(args)
return apply(self.method, nargs, kwargs)
def RUNCMD (self):
exec self.EDDIE.get_text () in globals (), globals ()
W=GUI.Window ()
# make RUNCMD a method of W
transplant (RUNCMD, W)
if W.BaseGUI == 'pyqt': fnt = 'terminal'
else: fnt = 'Courier'
W.start_construction ()
W.open_vbox ()
W.EDDIE = W.editor (font=fnt, dims=(80,20))
W.open_hbox ()
W.button (text='Run It!', cmd=W.RUNCMD)
W.button (text='Clear', cmd='self.master.EDDIE.set_text ("")')
W.close_box ()
W.close_box ()
W.end_construction ()
GUI.exec_loop ()
|
It is very important to understand that in the case the code is a string,
it is executed in the namespace of the *module* and therefore it cannot
access names from the global namespace -- unlike functions. The
transplant class is part of the Window class
(Dialog, Sheet), and can be invoked like this:
5. button widget
W.button (name=None, text='', cmd=None, rclick=None)
|
Attributes:
.master
.code
.rclick
.enable()
.disable()
|
- name: is the name of the button. We give a name to a button if
we want to inspect or change its parameters from other widgets.
Also, it is possible to generate the name manually. For instance:
is the same as:
- text: is the label of the button. A button's label cannot be
changed!
- cmd: the code that will be executed when the button is clicked.
- rclick: the code to be executed when a button is right-clicked.
cmd and rclick can be functions or strings. In the case they
are strings, they will be executed in a method of the button instance.
Therefore in this case in order to access things from the Window
the member master has to be used.
An example with a button that increments a value and prints it and also
prints its code:
CMD="""
self.master.counter += 1
print self.master.counter, 'My code is:', self.code
"""
W=GUI.Window ()
W.counter = 0
W.start_construction ()
W.button (text='Inc Unlimited', cmd=CMD)
W.end_construction ()
GUI.exec_loop ()
|
6. Widget Placement
W.open_vbox (text=None)
W.open_hbox (text=None)
W.close_box ()
W.separator ()
|
vbox and hbox are vertical and horizontal placement containers.
All widgets generated between an open_[vh]box() and a close_box()
are placed inside this container. If text is passed then the
container box will have a visible outline around it and a title
which is text.
The separator is a vertical or horizontal line (depending on
the current open container) which separates elements visually.
[ separators not implemented in wx ]
An example of placing three buttons :
W=GUI.Window ()
W.start_construction ()
W.open_vbox ()
if 1:
W.open_hbox ()
if 1:
W.button (name='B1', text='Button 1', cmd='print 1')
W.button (text='Button 2', cmd='print 2')
W.close_box ()
W.button (text='Button 1', cmd='print "The code of button 1 is", self.master.B1.code')
W.close_box ()
W.end_construction ()
GUI.exec_loop ()
|
7. checkbutton widget
W.checkbutton (name=None, text='', cmd='', active=False)
|
Attributes:
.master
.cmd
.active
.set_active (state)
.enable()
.disable()
|
The command cmd will be executed each time the check button's
state is toggled. A checkbutton widget has the attributes
active and set_active (value). For example, a check button which
reports its state when it's toggled and a button which when clicked
sets the checkbutton to 'ok':
W=GUI.Window ()
W.start_construction ()
W.checkbutton (name='CB', text='Next time?', cmd='print "State:", self.active')
W.button (text='I Agree', cmd='self.master.CB.activate (1)')
W.end_construction ()
GUI.exec_loop ()
|
8. label widget
W.label (name=None, text='label')
|
Attributes:
.set_text (text)
.get_text ()
|
A label is a dummy area with a message.
W=GUI.Window ()
W.start_construction ()
W.label (name='L', text='A Label')
W.button (text='Do', cmd='self.master.L.set_text (self.master.L.get_text () + "*")')
W.end_construction ()
GUI.exec_loop ()
|
9. Radio buttons
W.open_radio (name=None, cmd=None)
W.radio (name=None, text='', active=False)
W.close_radio ()
|
Attributes:
.master
.cmd
.current
.activate (name)
.enable(name)
.disable(name)
|
Radio buttons are groupped very much like the container boxes.
The W.radio() command must be executed within an W.open_radio()
and a W.close_radio() segment. There is only one widget actually
generated and that is with the open_radio command. name is
the name of the widget and cmd the command that will be
executed each time the active radio button is changed. The
W.radio() command just adds a name-value pair to the radio
group. The user sees the 'value' part and the progammer the 'name'
part of a radio button.
W=GUI.Window ()
W.start_construction ()
W.open_radio (name='RBG', cmd='print "the active radio is", self.current')
if 1:
W.radio ('FM', "FM frequencies")
W.radio ('AM', "AM rocks", True)
W.radio ('OFF', "Turn it off")
W.close_radio ()
W.button (text="Turn Off Damn Thing", cmd="self.master.RBG.activate ('OFF')")
W.end_construction ()
GUI.exec_loop ()
|
As you will see if you execute the above example, the message "the
active radio is:" is printed each time the active radio button is
changed, even if it is changed indirectly from the button.
10. tbutton widget
W.tbutton (name=Nome, text='', cmdact=None, cmddeact=None, active=0)
|
Attributes:
.master
.cmdact
.cmddeact
.toggle ()
.isOn ()
.enable()
.disable()
|
The toggle button's cmdact will be executed each time the button
is "pressed" and the cmddeact each time it's "unpressed".
11. textentry widget
W.textentry (name=None, text='', length=0, cmd=None, label=None)
|
Attributes:
.master
.code
.text ()
.set_text (text)
.enable()
.disable()
|
This is a text entry. A goal in the next version is to create
and advanced realine. Anyway, for now, cmd is executed each time
enter is pressed. length specifies the visual length of
the entry in characters. Because characters may be non fixed
this is an approximation. A length zero means that the toolkit
is free to size the widget as it wants.
Here is an example of a button, a text entry that changes the button's
code to whatever is typed in it and another button which prints the current
code of the first button:
def ENTRY_CMD (self):
self.B1.code = self.ENT.text()
self.ENT.set_text ('')
W=GUI.Window ()
transplant (ENTRY_CMD, W)
W.start_construction ()
W.open_vbox ()
if 1:
W.open_hbox ()
if 1:
W.button (name='B1', text='CLICK ME!', cmd='print "thanks"')
W.button (text='Code of button 1', cmd='print "it is:", self.master.B1.code')
W.close_box ()
W.separator ()
W.textentry (name='ENT', label='Enter new code for B1', cmd=W.ENTRY_CMD)
W.close_box ()
W.end_construction ()
GUI.exec_loop ()
|
12. editor widget
W.editor (name=None, dims=(0,0), font=None, wrap=0, editable=True)
|
Attributes:
.master
.get_text ()
.set_text (text)
.set_editable (value)
.disable ()
.enable ()
|
That is a simple text editor/viewer.
dims: is a tuple of the desired dimensions of the editor in
characters. A value of zero means that the specific dimension
will be what the toolkit wants.
font: is kinda complex. There is no real agreement between
pygtk, pyqt and wxpython. Generally, something like 'Courier 10'
should work here. Because pygtk and wxpython share pango they
agree on most strings. pango on the other hand doesn't have
terminal fonts, so 'terminal' is a good choice for editing
with fixed size in pyqt (non-fixed fonts are for girl's
diaries afterall).
wrap: is 0 for no wrap, 1 for character wrap and 2 for word wrap
editable: tells whether the text can be edited by the user.
the text can always be altered by the code with set_text() though.
W=GUI.Window ()
if W.BaseGUI == 'pyqt': fnt = 'terminal'
else: fnt = 'Courier'
W.start_construction ()
W.open_vbox ()
W.editor (name='EDDIE', font=fnt, dims=(80,20))
W.open_hbox ()
W.button (text='Run It!', cmd='exec self.master.EDDIE.get_text () in globals (), globals ()')
W.button (text='Clear', cmd='self.master.EDDIE.set_text ("")')
W.close_box ()
W.close_box ()
W.end_construction ()
GUI.exec_loop ()
|
13. image widget
W.image (name=None, filename=None)
|
Attributes:
.load (filename)
|
That is a primitive image displayer. The load method doesn't work in qt
It's mainly used to display the Twilight GUI logo. This widget needs serious
improvements.
14. splitter views
self.hsplitter ()
self.vsplitter ()
|
The splitter is a placement command which separates two widgets by a
bar which the user can drag, consequently, making the one widget
smaller and the other bigger, as he or she whishes at the current
time they are working on their computer. The splitter applies
for the next two widgets that will be created. The splitter
DOESN'T work in wxpython yet and hbox, vbox will be used instead.
An example with three editors in splitters:
W=GUI.Window ()
W.start_construction ()
W.hsplitter ()
if 1:
W.vsplitter ()
if 1:
W.editor ()
W.editor ()
W.editor ()
W.end_construction ()
GUI.exec_loop ()
|
15. listbox widget
W.listbox (name=None, gcode=None, colnam=[''], scode=None, ecode=None, dims=(0,0), rclick=None)
|
Attributes:
.master
.row
.reload (code=None)
.enable ()
.disable ()
Listbox Creation:
.addrow (data)
|
The listbox is TG is very simple and it is used to reflect some
internal python data. A list is loaded with the gcode argument
which can be a string or a function. The code in gcode can call
the member addrow to addrows to the list, and that's it.
After that it is not possible to add extra rows or remove rows
from the list once it has been created. The list can only be
reload()ed in which case it will be emptied and the gcode will
be called again to refill the list.
colnam: is a sequence of strings which gives the names of the
columns of the list (and consequently their count)
scode: will be executed each time an element is selected.
ecode: each time an element is activated (double click or return)
rclick: each time an element is clicked with the right button
dims: specifies the dimensions of the listbox in characters.
Row data added with addrow: In lists and trees we want not only
the visible column contents but often our own extra data accossiated
with each row. For that the argument of addrow must be a
sequence whos first argument is a sequence of the values.
In the case a callback is invoked (scode, ecode or rclick), the
member self.row will be set to the entire data sequence that
was used in addrow. Ok. Example.
# make a listbox with the keys of globals() and a viewer to show their values
def MAKELIST (self):
lst = globals ().keys ()
lst.sort ()
for i in lst:
self.addrow ([[i]])
def SHOWKEY (self):
self.E.set_text (repr (globals ()[self.L.row [0][0]]))
W=GUI.Window ()
transplant (SHOWKEY, W)
W.start_construction ()
W.hsplitter ()
if 1:
W.listbox (name='L', colnam=['keys'], gcode=MAKELIST, scode=W.SHOWKEY, dims=(20,10))
W.editor (name='E', editable=False, dims = (40, 10))
W.end_construction ()
GUI.exec_loop ()
|
We should note two things: first, the list is not sorted. Actually in Qt it
is and if we click on columns we select the sort column. In pygtk and
wxpython the elements are not sorted, so we'd better sort them to be sure.
Secondly, the gcode argument is special. If a plain function is passed
to it (not a method function), it is automatically attached to
the newly generated list instance.
16. streebox widget (static tree)
W.streebox (name=None, gcode=None, colnam=[''], scode=None, ecode=None, dims=(0,0), rclick=None)
|
Attributes:
.master
.row
.reload (code=None)
.enable ()
.disable ()
Listbox Creation:
.sub ()
.addrow (data)
.unsub ()
|
A tree is just like a list in almost everything, except that the
elements of the first column can be in a tree representation.
The static tree is the one that is entirely created with gcode,
and so it's not suitable for thousands of nodes (for example
a filesystem navigator).
def MAKETREE (self):
self.addrow ([['tmp']])
self.addrow ([['home']])
self.sub ()
if 1:
self.addrow ([['johnny']])
self.addrow ([['jack']])
self.sub ()
if 1:
self.addrow ([['src']])
self.unsub ()
self.unsub ()
W=GUI.Window ()
W.start_construction ()
W.streebox (colnam=['dirs'], gcode=MAKETREE)
W.end_construction ()
GUI.exec_loop ()
|
[ in wx, the tree's GOT to have a root, (TreeListCtrl) and for that
there is an ugly '.' root for now ]
17. treebox widget
W.treebox (name=None, gcode=None, colnam=[''], scodeecode=None, dims=(0,0), rclick=None)
|
Attributes:
.master
.row
.reload (code=None)
.enable ()
.disable ()
Listbox Creation:
.addrow (data, expander=None)
|
This is the real tree. Just like the listbox, elements are
inserted with addrow from gcode. Additionally, an element that
passes code (string or function) to the expander argument
of addrow, is a parent node and the expander code is invoked to
generate the children (with addrow) each time the user clicks
to expand the node. Ok, this is fun.
A filesystem navigator:
import os
import os.path
def EXPAND_DIR (self):
self = self.L
# the hidden data is the full pathname
basedir = self.row [1]
dirs=os.listdir (basedir)
dirs.sort ()
for i in dirs:
fullname = basedir + '/' + i
if os.path.isdir (fullname):
self.addrow (((i,),fullname),self.master.EXPAND_DIR)
else:
self.addrow (((i,),))
CODE="self.addrow ((('/',),'/'), self.master.EXPAND_DIR)"
W = GUI.Window ()
transplant (EXPAND_DIR, W)
W.start_construction ()
W.treebox (name='L', colnam = ['dir'], gcode = CODE, dims=(20,10))
W.end_construction ()
GUI.exec_loop ()
|
18. popup command
W.popup (code, *args, **kwargs)
|
Menu Creation:
.item (name, code)
.sub (name)
.unsub ()
.sep ()
|
The popup menu is normally not created during the window construction, but
it 'pops up' when some event happens. So we excpect the popup creation
to happen in the code of a button or something like that. The popup
command is a method of the window instance nontheless.
The code argument which can be a string or function (in case it's a plain
function it will be attached to the popup), can invoke the members item(),
sub(), unsub() and sep() to generate menu items, submenus
and separators.
A menubar can be done with buttons that make popups on click:
def FILEMENU (self):
self.item ('New', 'print "New"')
self.item ('Open', 'print "Open"')
self.sep ()
self.sub ('Send to')
if 1:
self.item ('Floppy disk', 'print "Floppy"')
self.unsub ()
self.sep ()
self.item ('Exit', 'self.master.quit ()')
def POPUPCODE (self):
self.popup (FILEMENU)
W = GUI.Window ()
transplant (POPUPCODE, W)
W.start_construction ()
W.open_vbox ()
W.open_hbox ()
W.button (text='File', cmd=W.POPUPCODE)
W.close_box ()
W.separator ()
W.editor (dims = (80,25))
W.close_box ()
W.end_construction ()
GUI.exec_loop ()
|
Just like the tree/list generation code, the code argument of the popup,
if a global function shall be attached to the currently constucted
popup instance.
Popup menus, usually operate on some selected data. For example, in
the dir viewer example we would like to make a popup menu that does
something with the selected file. For that we need to pass values
to the popup. Any keyword arguments to popup() will be attached
as values to the instance. The dirviewer with a popup that prints
the fullname of the selected file:
import os
import os.path
def EXPAND_DIR (self):
self = self.L
# the hidden data is the full pathname
basedir = self.row [1]
dirs=os.listdir (basedir)
dirs.sort ()
for i in dirs:
fullname = basedir + '/' + i
if os.path.isdir (fullname):
self.addrow (((i,),fullname),self.master.EXPAND_DIR)
else:
self.addrow (((i,),fullname))
def FILEMENU (self):
self.item ('Print fullname', 'print "Fullname:", self.fullname')
def POPUPCODE (self):
self.popup (FILEMENU, fullname=self.L.row [1])
CODE="self.addrow ((('/',),'/'), self.master.EXPAND_DIR)"
W = GUI.Window ()
transplant (EXPAND_DIR, W)
transplant (POPUPCODE, W)
W.start_construction ()
W.treebox (name='L', colnam = ['dir'], gcode = CODE, dims=(20,10), rclick=W.POPUPCODE)
W.end_construction ()
GUI.exec_loop ()
|
(in PyGTK you have to keep the right button pressed otherwise the menu closes.
I don't know how to fix this)
19. modal Dialog windows
A dialog is a modal popup window that can be a message or a confirmation
or whatever that freezes its background window until it gets a reply.
The Dialog is a class just like Window. Here is a confirmation dialog
that appears each time we click on the 'Dangerous action button'.
def CONFIRM(self):
D = GUI.Dialog (self)
D.ok = False
D.start_construction ()
D.open_vbox ()
D.label (text='Are you 100% sure?')
D.open_hbox ()
D.button (text='ok', cmd="self.master.ok=True; self.master.close()")
D.button (text='Cancel', cmd='self.master.close()')
D.close_box ()
D.close_box ()
D.end_construction () # this fires up the dialog box
if D.ok:
print "Ok with me"
else:
print "Canceled"
W = GUI.Window ()
transplant (CONFIRM, W)
W.start_construction ()
W.button (text='Dangerous action button', cmd=W.CONFIRM)
W.end_construction ()
GUI.exec_loop ()
|
20. Workspaces
W.tabworkspace (name=None)
W.MDIworkspace (name=None)
|
The notebook and MDI workspaces are very experimental and still do not work
very well. Anyway they are workspaces inside which we can add pages (GUI
pages) at runtime. Like a small window manager inside our window. The
notebook is known as "tabs". The MDI is only supported in QT. wxPython is
supposed to support MDI but it just opens tabs in another window here.
Maybe I missed --enable-mdi or something. PyGTK doesn't have MDI and a
notebook will be used instead. Anyway.
Then we have the class Sheet which is just like Window and Dialog.
In its construction we must pass the name of the workspace where the sheet
will be added. Here is an example. *Workspaces need serious fixing*
NT="""
self.settitle ('A page')
self.button (text='butto', cmd='self.master.RR.disable ("On")')
self.button (name='B', text='boggler', cmd='self.master.disable()')
self.editor (name='E',dims=(30,10))
self.open_radio (name='RR')
self.radio ('This', "This")
self.radio ('On', "Ons", active=1)
self.close_radio ()
self.E.set_text (self.workspace.master.NT)
"""
def NEWSHEET (self):
GUI.Sheet (self.WS, NT)
return
W = GUI.Window ()
W.NT=NT
transplant (NEWSHEET, W)
W.start_construction ()
W.button (text='Make new sheet', cmd=W.NEWSHEET)
W.MDIworkspace (name='WS')
GUI.Sheet (W.WS, NT)
W.NEWSHEET ()
W.end_construction ()
GUI.exec_loop ()
|
It just works.
21. Higher level widgets
W.openFileDialog (name='')
W.saveFileDialog (name='')
|
These can be invoked from callbacks. They open custom pygtk/pyqt/wxpython
advanced dialog widgets to read or save a file. A string of the selected
filename or None is returned when these are called. PyGTK 2.4.0 has a neat
advanced fileDialog which isn't used yet. We should add wildcards and
directory here in the future...
Here is the code of the editor IDE that appears in the screenshot
of the Twilight GUI homepage. It uses openFileDialog and saveFileDialog too:
class transplant:
def __init__(self, method, host, method_name=None):
self.host = host
self.method = method
setattr(host, method_name or method.__name__, self)
def __call__(self, *args, **kwargs):
nargs = [self.host]
nargs.extend(args)
return apply(self.method, nargs, kwargs)
def readfile (fnm):
f=open (fnm, 'r')
txt = f.read()
f.close ()
return txt
def writefile (fnm, txt):
f=open (fnm, 'w')
f.write (txt)
f.close ()
def app ():
def NEWCMD(self):
self.ED.set_text('')
self.CURRENT_FILE='NewFile.py'
self.FILENAME.set_text ('NewFile.py')
def RELOADCMD(self):
self.ED.set_text (readfile (self.CURRENT_FILE))
def LOADCMD (self):
l = self.openFileDialog (name=self.CURRENT_FILE)
if l:
try:
self.ED.set_text (readfile (l))
self.FILENAME.set_text (l)
self.CURRENT_FILE = l
except IOError:
print "No such file"
def SAVEASCMD (self):
l = self.saveFileDialog (name=self.CURRENT_FILE)
if l:
try:
writefile (l, self.ED.get_text ())
self.FILENAME.set_text (l)
self.CURRENT_FILE = l
except IOError:
print "Failed save"
def SAVECMD(self):
D=self.MyGUI.Dialog (self)
D.ok = False
D.start_construction ()
D.open_vbox ()
D.label (text='Save file '+self.CURRENT_FILE+' ?')
D.open_hbox ()
D.button (text='ok', cmd="self.master.ok=True; self.master.close()")
D.button (text='Cancel', cmd='self.master.close()')
D.close_box ()
D.close_box ()
D.end_construction ()
if D.ok:
writefile (self.CURRENT_FILE, self.ED.get_text())
def RUNCMD (self):
x = self.LIBRADIO.current
print 'Running with ['+x+']'
for i in self.GUIList:
if i[0] == x:
break
xx=self.ED.get_text ()
global GUI
TMP=GUI
GUI = i[1]
exec xx in globals (), globals ()
GUI.exec_loop ()
GUI=TMP
W = GUI.Window ()
W.MyGUI = GUI
W.CURRENT_FILE = 'Editor.py'
W.GUIList = GUIList
transplant (RUNCMD, W)
transplant (NEWCMD, W)
transplant (RELOADCMD, W)
transplant (SAVECMD, W)
transplant (SAVEASCMD, W)
transplant (LOADCMD, W)
if W.BaseGUI == 'pyqt': fnt = 'terminal'
else: fnt = 'Courier'
W.start_construction ()
W.settitle ('Editor IDE in '+W.BaseGUI)
W.open_vbox ()
if 1:
W.label (name='FILENAME', text=W.CURRENT_FILE)
W.open_hbox ()
if 1:
W.editor (name='ED', dims=(78,23), font = fnt)
W.open_vbox ('Run it with')
if 1:
W.open_radio (name='LIBRADIO')
if 1:
for i in GUIList:
W.radio (name=i[0], text=i[0], active=(GUI==i[1]))
W.close_radio ()
W.button (text="Run it!", cmd=W.RUNCMD)
W.image (name='IMG', filename='tw-logo.png')
W.close_box ()
W.close_box ()
W.open_hbox ()
if 1:
W.button (text='New', cmd=W.NEWCMD)
W.button (text='Reload', cmd=W.RELOADCMD)
W.button (text='Load', cmd=W.LOADCMD)
W.button (text='Save', cmd=W.SAVECMD)
W.button (text='Save As...', cmd=W.SAVEASCMD)
W.button (text='Quit', cmd='self.master.quit ()')
W.close_box ()
W.close_box ()
W.end_construction ()
W.ED.set_text (readfile (W.CURRENT_FILE))
GUI.exec_loop ()
app ()
|