1.2.1 Projects and applications
2.2 Define project's properties
4. Implementing Perl/Tk applications from
scratch
5. Upgrading perl/Tk applications
6. Implementing Perl/Tk composites
8. Control the clickTk session flow
10.2 Callbacks (subroutines or methods)
10.5 Coding the command options (message to
callbacks)
10.7.1 Projects of type subroutine
10.7.2 Projects of type composite or package
11.1 Build several versions of the same project
clickTk is a graphical editor that helps
Perl/Tk programmers to create Perl/Tk applications consisting of several more
or less sophisticated dialogs.
The main goal is to
generate Perl/Tk code in form of scripts, subroutines and classes which can be
embedded in the application with or without minor manual interventions.
Once the dialog flow is designed and
the individual dialogs have been sketched, clickTk can be used to
generate the corresponding Perl/Tk source code.
Moreover, it can be used on
the one hand to easily create some different versions of a dialog flow and on
the other hand to refine the chosen version to its ultimate state.
The ability to generate
additional run code to the dialog definitions itself allows the programmer to
already do some unit tests during the development session, with the advantage
that the exported code has already been tested, when it will run in the
application environment.
Therefore, clickTk
considerably reduces the extremely tedious and error prone coding of complex
widget definitions on the one hand assisting the input of options with
preformatted dialogs and on the other hand allowing the use of templates.
Further, clickTk allows to
separate the code related to the presentation's functionality from the
application logic.
In consequence, it is easier to develop specialized widgets, a fact that
simplifies the application's code and significantly increases the quality of
the application's design.
The clickTk world consists
mainly of projects, which may be grouped into applications.
Thus, each project of an application
contains the definitions of its application. Of course, projects of an
application may be grouped into a subdir underneath the clickTk project
folder.
Nevertheless, projects must not be assigned to an application, especially then
when they are shared among many applications (i.e. composite widgets) or by
contrast they are not related to other scripts.
A clickTk
session processes one project at a time. Thereby the following means are used:
The main functions of a clickTk
session are:
application
An
application consists of one or more main scripts which instantiate several
dialogs to communicate with the user. Actually, the application is an optional
property of a project (name , folder and libraries).
widget
Instance
of type widget class.
order
Snipped of
Perl code inserted just after its widget constructor code.
widget class
Class
based on legal Tk base classes and may be a standard,
composite or derived widget.
non visual
Class that
is not Tk-compliant. Usually, these classes implement the application's objects.
dialog
Assembly
of widgets, which may run modal or non modal.
properties
Set of
resources which define the nature of the dialog and finally the content of the
target. Dialog properties or code properties are equivalent expressions to
properties.
project
GUI dialog
with its related Perl code (callbacks).
work
The
persistent version of a project at a specific time of the session.
target
Code that
is generated while saving a project. It may be a
script, a subroutine, a composite widget, or a derived widget (or package).
It is always a Perl script.
template
'Work'
with a basic set of widgets and code which may be used as a starting structure
to implement dialogs with the same basic structure.
export
Process
that takes over a project into the application environment according to its
kind. Thereby it gets rid of any test code.
import
Process
that does the opposite of the export process. It takes over a script, possibly
exported earlier, into a project with (usually) the same name.
clickTk applies the application model of single
document processing as far as possible. Therefore, basic functionalities like
new, save and undo are not explained.
A clickTk session is started
entering the command
ctk_w.pl [options] [file]
|
-c |
"cold
start", do not restore last used project resp work |
|
-h |
show this
help |
|
-? |
show this
help |
|
-d |
set debug
mode on |
|
-r |
restore
work from given workfile or noname |
|
-u |
userid |
|
file |
name of
the file to be load or name of the work to be restored |
Examples:
1. Start clickTk session and
load last used project
ctk_w.pl
2. Start clickTk session and
load project tx.pl
ctk_w tx.pl
3. Start clickTk session and
restore saved work tx.pl
ctk_w.pl -r tx.pl
4. Start clickTk session and
restore saved work and set debug mode
ctk_w.pl -d -r tx.pl
5. Start clickTk session and
restore last not saved job
ctk_w.pl -r
Properties are defined at creation
time of a project, but may also be basically redefined at any time.
Project's properties define
Widgets may be inserted before or
after the selected widget, whereby either a subwidget (that means a child) or a
sibling widget can be inserted.
Selected widget may be modified:
After that the modal dialog to enter
the options appears.
See screenshot
Entering <right click> on the selected widget in the tree view allows to
execute the following functions:
Insert Before After Subwidget Order Options All options View all options View default options Context help Cut Copy Paste Rename Delete Replace hide widget view packInfo
This function loads a previously
saved project for further developments. Thereby the target is parsed to
reconstruct the clickTk internal project structure.
At any time of the session the state
of the project can be saved persistently as a 'work'. Thereby only the internal
state of the project is dumped to the persistent clickTk work folder.
The process 'save' implies the process 'save work' Several saved works may
exist, because a 'work' may have any name.
Projects are always persistently
saved in the form of a target into the clickTk project folder.
At any time of the session the
target may be checked against possible syntax error mainly in callback-code.
At any time of the session the
target may be executed. Of course this function implies that the project has
been saved before.
Some options to customize clickTk
may be:
·
Add
supported widgets classes.
The implementation of a Perl/Tk
application consists of several steps which seldom happen straight forward. Most
times, these steps must be repeated many times in order to find the final
implementation.
Nevertheless, usually the development cycle consists of the following steps:
Usually, a Perl/Tk application consists
of a main script and several dialogs, which may be implemented either as composite
widgets or as required scripts, where the TK code is embedded in a subroutine.
The main script usually hosts the menu, the main loop and the application code,
that means the callbacks.
Therefore, the application' s structure may look like this:
All these components can be
developed with clickTk.
Composite widgets usually implement
lot of functionality and are mostly shared among many applications.
After their development with clickTk, they may be exported to the
application's library, or even Perl library, and then registered as widget
class to clickTk.
The use of templates may avoid
wasting time entering several time the same things, may prevent peoples to
reinvent the wheel over and over again and finally may help to give an uniform design
and feeling to the different applications.
Using clickTk the individual
dialogs are set up as projects. Thus, the main structure of the application is
done. Although the application's logic is not yet implemented, the design and
feeling of the application can be presented.
See details in chapter 10. Enter the dialog data.
Callback code may be added in order
to allow the dialog flow to work. An important task in this phase is the
implementation of non visual widgets and orders. Non visual widgets provide
means to control the application flow (i.e. timer, events, state machine and
much more) while orders allow to send messages to widget instances after the
constructor message.
Code developed with clickTk
always contains a minimum of test code in order to make it executable. The
application logic must be included explicitly by means of non-visual classes
though. Further, the access to the application's libraries may be done
specifying the property 'libraries' which generates a set of 'use lib'
statements. So unit tests done out of clickTk sessions may get very
close to the reality of the application.
Convert the individual dialogs to
its final form for the implementation in the application:
clickTk assists you also in this task, because the project's
properties may have changed before a save.
Export the projects into the
application test environment and implement the required adaptations.
Although clickTk eliminates its test code, most of the times the
callbacks coded dering the design phase must be adapted to the real
application's environment.
Sometimes it is more useful to copy and paste the generated Perl/Tk comands
from the project into the application's script. Especially targets of type
'subroutine' are suitable to this way of use.
Existing Perl/Tk applications may be
upgraded using clickTk. This applies both to applications developed with
clickTk as well as to applications implemented by hand. In the first
case, dialogs may be simply imported, in the latter case the dialog definitions
should be first be isolated manually into a file which acts as an exported
project and then imported .
Dialogs can be imported from the application's
location into the clickTk project folder. Of course, problems may arise
when the project has been heavily changed manually.
Projects remain in the project
folder until they are explicitly deleted. Thus, they may be reused for further
developments.
Composite widgets are developed the
same way as dialogs whereby clickTk automatically generates the required
OO-code. The focus of this development is on the coding of the methods which is
done entering menu item /file/properties/methods.
The project automatically contains test code to run unit tests and may also
contains callbacks entered via /file/properties/callback .
clickTk edits the widget options using registered
widget class definitions. Any composite or derived widget may be registered.
In order to do that the menu item '/tools/add widget class' definition may be
used.
Run time options influence the flow
of the session.
The target code is the most
important part of a project.
The generated target code consists of
The target code is divided into
sections delimited by control information. These lines should not be removed
because the clickTk parser uses them to locate the individual parts of
the target code.
A wide set of properties control the generation of the target code.
Properties of a project are:
Widget definitions are inserted
following the dialog's hierarchical structure:
Note :
For each widget the following steps
should be done:
For targets of type script and
subroutines the subroutines may be entered during the clickTk session using the
function ‘File/Code properties/callbacks’.
For targets of type package and
composite the methods of the
widgets may be entered while the clickTk session using the function ‘File/ Code
properties /methods’.
Orders are snipped of Perl code
which usually contains messages to widgets. A good example is the use of the
widget Balloon: the widget gets inserted as a standard widget at the end of the
widget tree. Then an order is added to the widget definition to define its
attach-messages. To do that the following procedure may be applied:
·
enter
the non-visual classes .
Supported callback option formats
are
- \&callback_name- [\callback_name, args]- ['callback_name',args]- sub { callback(args) }
whereby callback_name is any valid subroutine name while args must be a scalar variable i.e.
$self .
Reserved callback’s names are
- Subroutine _init- Subroutines test_*, i.e. sub test_01 { } sub test_xyz { }
It is recommended to explicitly
define all involved variables using the menu item 'file/Code
properties/variables'
Variables may be
clickTk is able to extract variables from the specified
widget options and assign them to the local variable scope or to the global
variable scope depending on the actual code properties. Of course, these
properties may be changed during a session, even many times, a fact that forces
clickTk to reassign the extracted variables according to the changed
property values.
Note: Switching the code property 'extract variable to local' forces clickTk
to refresh the variable assignments regardless the actual assignment, which may
or even may not reflect the old state of the property. This fact may be
relevant in those cases where individual variables get moved from local to
global in order to do specific unit tests while the clickTk session. By
contrast, those variables that are not extracted are also not affected by this
refresh process.
Of course, programmers can avoid all these problems by switching off the auto
extraction. This could be a good idea working on little projects!
Projects of type subroutine may
select the way to pass arguments to the subroutine code by means of:
clickTk provides automatically an hash named %args
which gets generated when the field 'argList' in the dialog entered through 'File/code
properties/Options' contains its coding as an hash.
The scope assigned to %args depends on the code options about variables, i.e.
option 'extracted variable becomes local' , and may even be changed manually by
means of the variable's dialog entered through 'File/code
properties/variables'.
This fact may be important when widgets refer items of argument list %args. It is a good
practice to use an argument list and limit the use of global as far as
possible.
The argument list %args is passed to
the constructor.
0 File 0 Open (command) 1 Open previous (command) 2 New (command) 3 Save (command) 4 Save As (command) 5 --- (separator) 6 Save work (command) 7 Restore work (command) 8 --- (separator) 9 Save template (command) 9 Save template (command) 10 --- (separator) 11 Set application (command) 12 Code Properties (cascade) 0 === X (tearoff) 1 Options (command) 2 Variables (command) 3 --- (separator) 4 Libraries (command) 5 --- (separator) 6 Callbacks (command) 7 Methods (command) 8 General code (command) 9 --- (separator) 10 Pod section (command) 13 --- (separator) 14 Import (command) 15 Export (command) 16 --- (separator) 17 Quit (command) 1 Edit 0 Widget Options (command) 1 --- (separator) 2 Undo (command) 3 Redo (command) 4 --- (separator) 5 Cut (command) 6 Copy (command) 7 Paste (command) 8 --- (separator) 9 Rename (command) 10 Delete (command) 11 Replace (command) 2 Insert 0 Before (command) 1 After (command) 2 Sub-widget (command) 3 Order (command) 3 View 0 Repaint (command) 1 Code (command) 2 pick color (command) 3 Re-color myself (command) 4 view widget structure (command) 5 list bindings (command) 6 view ctk Logfile (command) 4 Tools 0 Edit code (command) 1 --- (separator)2 Check syntax (command)
3 Run code (command) 4 Gen Font code (command) 5 Tk variables (command)6 --- (separator)
7 Add widget class definition (command) 8 Update widget class definition (command) 9 Delete widget class definition (command) 5 Options 0 Use Toplevel for the preview (checkbutton) 1 Show widget balloons (checkbutton) 2 Blink widget on selection (checkbutton) 3 Show mouse pointer X,Y coordinates (checkbutton) 4 Isolate geometry messages (checkbutton) 5 Ask for widget ident (checkbutton) 6 Gen test code (checkbutton) 7 Gen modal dialog by default (checkbutton) 8 Copy/paste parent and children (checkbutton) 9 Use specialized color picker (checkbutton) 10 Debug mode (checkbutton) 6 Help 0 === X (tearoff) 1 ctk help (command) 2 Context help (command) 3 Perl/Tk manuals (cascade) 0 === X (tearoff) 1 Overview (command) 2 Standard options (command) 3 Base class widget (command) 4 Option handling (command)5 Tk variables (command)
6 Grab manipulation (command)7 Binding (command)
8 Bind tags (command) 9 Callbacks (command) 10 Events (command) 11 Composite widgets (command) 12 Mega widgets (command) 13 ConfigSpecs (command) 14 Derived (command) 4 About (command)(triggered by <right click> on
selected widget definition)
0 X (tearoff)
1 Insert (cascade)
0 Before (command)
1 After (command)
2 Subwidget (command)
3 Order (command)
2 Options (command)
3 All options
(command)
4 View all options
(command)
5 View default
options (command)
6 Context help
(command)
7 Cut (command)
8 Copy (command)
9 Paste (command)
10 Rename (command)
11 Delete (command)
12 Replace (command)
13 hide widget
(command)
14 view packInfo
(command)
$rDef = { 'icon' => 'default','geom' => '1',
'file' => 'xLabel', 'attr' => { '-pady' => 'int+', '-background' => 'color', '-foreground' => 'color', '-bg' => 'color', '-width' => 'int+', '-height' => 'int+', '-borderwidth' => 'int+', '-text' => 'text', '-relief' => 'relief', '-textvariable' => 'variable', '-bitmap' => 'variable','-padx' => 'int+'
},
'classname' => 'xLabel', 'use' => 'test::xLabel', 'nonVisual' => '0', 'defaultgeometrymanager' => 'pack', 'balloon' => undef, 'defaultgeometryoptions' => undef, 'defaultwidgetoptions' => undef};(file ctkConfigOptions.txt)
$rOptions = { 'isolate_geom' => 0, 'opt_copyChildren' => 1, 'geomMgr' => [ 'pack', 'grid', 'place', 'form' ], 'popupmenuTearoff' => 1,'initialGeometry' => '=600x500+20+20',
'templateFolder' => 'templates', 'opt_colorPicker' => 0, 'opt_modalDialog' => 0, 'HListDefaultHeight' => 30, 'HListSelectMode' => 'single', 'opt_useToplevel' => 0, 'applName' => 'test', 'ctkC' => '## ctk:', 'cacheLogSize' => 2048, 'imageFolder' => 'images', 'MSWin32_editor' => 'Notepad', 'initialGeometryPreview' => '=400x400+420+10', 'HListDefaultWidth' => 32, 'opt_fileHistory' => 10, 'tempFolder' => 'temp', 'noname' => 'noname.pl', 'userid' => 'Tkadmin', 'subroutineName' => 'thisDialog', 'opt_autoSave' => 1, 'sessionFileNamePrefix' => 'ctk_session', 'opt_dialogClassName' => 'DialogBox', 'defaultGeometryManager' => 'pack', 'xterm' => 'xterm', 'widgetFolder' => 'widgets', 'toolbarFolder' => 'toolbar', 'projectFolder' => 'project', 'MW' => 'mw', 'editingCodeProperties' => 0, 'workFolder' => 'work', 'ctkTitle' => 'clickTk', 'identPrefix' => 'wr_', 'ctkLogFileName' => 'ctk_w_log.txt', 'aix_editor' => 'nedit', 'opt_defaultButtons' => '[qw(Ok Cancel)]', 'autoEdit' => 1, 'opt_autoRestore' => 0, 'opt_askIdent' => 1, 'opt_TestCode' => 1, 'applFolder' => 'test', 'UNIX_editor' => 'vi'};
#!C:\Perl\bin\perl.exe
## ctk: description
## ctk: title
## ctk: application Test c:\Dokumente
## ctk: strict 0## ctk: code 0## ctk: subroutineName thisDialog
## ctk: autoExtractVariables 1## ctk: autoExtract2Local 1## ctk: modal 0
## ctk: version 3.095
## ctk: onDeleteWindow sub{1}## ctk: Toplevel 1## ctk: 2006 10 27 - 02:07:35 ## ctk: uselib start ## ctk: uselib end use Tk;use Tk::Button;use Tk::Frame;use Tk::LabEntry; $mw=MainWindow->new(-title=>'');## ctk: Globalvars## ctk: Globalvars end&main::init();&main::thisDialog($mw,-title => '', -buttons => [qw(Ok Cancel)]);MainLoop; sub thisDialog {my $hwnd = shift;my (%args) = @_;my $rv;#### ctk: Localvars my ($w1,$w2); ## ctk: Localvars end##my $mw = $hwnd->Toplevel();$mw->configure(-title=> (exists $args{-title})? $args{-title}:'');$mw->protocol('WM_DELETE_WINDOW',sub{1}); ## ctk: code generated by ctk_w version '3.095' ## ctk: instantiate and display widgets $wr_001 = $mw -> LabEntry ( -background , '#ffffff' , -justify , 'left' , -label , 'Name' , -relief , 'sunken' , -labelPack , [-side=>left,-anchor=>n] , -textvariable , \$w1 , -state , 'normal' ) -> pack(-side=>'top', -anchor=>'nw', -pady=>5, -fill=>'x', -expand=>1, -padx=>5); $wr_003 = $mw -> Frame ( -relief , 'solid' ) -> pack(-side=>'top', -anchor=>'nw', -pady=>5, -fill=>'x', -expand=>1, -padx=>5); $wr_002 = $wr_003 -> LabEntry ( -background , '#ffffff' , -justify , 'left' , -label , 'Folder name' , -relief , 'sunken' , -labelPack , [-side=>left,-anchor=>n] , -textvariable , \$w2 , -state , 'normal' ) -> pack(-side=>'left', -anchor=>'nw', -pady=>5, -fill=>'x', -expand=>1, -padx=>5); $wr_005 = $wr_003 -> Button ( -anchor , 'nw' , -background , '#ffffff' , -state , 'normal' , -relief , 'raised' , -text , 'Browse' ) -> pack(-anchor=>'nw', -side=>'left', -pady=>5, -padx=>5); ## ctk: end of gened Tk-code return $rv; } ## end of thisDialog ## ctk: end of dialog code## ctk: callbackssub init { 1 }## ctk: other code## ctk: eof 2006 10 27 - 02:07:351; ## make perl compiler happy...
$rDescriptor = { 'wr_001' => bless( { 'parent' => 'mw', 'geom' => 'pack(-fill, x, -expand, 1, -anchor, nw, -pady, 5, -side, top, -padx, 5)', 'order' => undef, 'id' => 'wr_001', 'type' => 'LabEntry', 'opt' => '-background , \'#ffffff\' , -label , \'Name\' , -justify , \'left\' , -labelPack , [-side=>\'left\',-anchor=>\'n\'] , -relief , \'sunken\' , -textvariable , \\$w1 , -state , \'normal\' ' }, 'ctkDescriptor' ), 'mw' => bless( { 'parent' => undef, 'geom' => undef,'order' => undef,
'id' => 'mw', 'type' => 'Frame', 'opt' => undef }, 'ctkDescriptor' ), 'wr_005' => bless( { 'parent' => 'wr_003', 'geom' => 'pack(-anchor=>nw, -side=>left, -pady=>5, -padx=>5)', 'order' => undef, 'id' => 'wr_005', 'type' => 'Button', 'opt' => '-anchor , nw , -background , #ffffff , -state , normal , -relief , raised , -text , Browse' }, 'ctkDescriptor' ), 'wr_002' => bless( { 'parent' => 'wr_003', 'geom' => 'pack(-side=>left, -anchor=>nw, -pady=>5, -fill=>x, -expand=>1, -padx=>5)', 'order' => undef, 'id' => 'wr_002', 'type' => 'LabEntry', 'opt' => '-background , #ffffff , -justify , left , -label , \'Folder name\' , -relief , sunken , -labelPack , [-side=>left,-anchor=>n] , -textvariable , \\$w2 , -state , normal' }, 'ctkDescriptor' ), 'wr_003' => bless( { 'parent' => 'mw', 'geom' => 'pack(-side=>top, -anchor=>nw, -pady=>5, -fill=>x, -expand=>1, -padx=>5)', 'order' => undef, 'id' => 'wr_003', 'type' => 'Frame', 'opt' => '-relief , solid' }, 'ctkDescriptor' )};$rTree = [ 'mw', 'mw.wr_001', 'mw.wr_003', 'mw.wr_003.wr_002', 'mw.wr_003.wr_005'];$rUser_subroutines = [ 'sub init { 1 }'];
$rUser_methods_code = [];
$rUser_gcode = [];$rOther_code = [];$rUser_pod = [];$rUser_auto_vars = [];$rUser_local_vars = ['$w1',
'$w2'];$rFile_opt = { 'modal' => '0','subWidgets' => [],
'autoExtractVariables' => '1', 'subroutineName' => 'thisDialog', 'description' => '', 'autoExtract2Local' => '1', 'baseClass' => '', 'strict' => '0', 'Toplevel' => '1', 'title' => '', 'code' => '0', 'onDeleteWindow' => 'sub{1}'};
$rLastfile = \'t7.pl';
$rIsolate_geom = \'0';$rHiddenWidgets = [];$rLibraries = [];
## ctk: description
## ctk: title
## ctk: application Test c:\Dokumente
## ctk: strict 0## ctk: code 0## ctk: subroutineName thisDialog
## ctk: autoExtractVariables 1## ctk: autoExtract2Local 1## ctk: modal 0
## ctk: version 3.095
## ctk: onDeleteWindow sub{1}## ctk: Toplevel 1## ctk: 2006 10 27 - 17:44:32 use Tk;use Tk::Button;use Tk::Frame;use Tk::LabEntry;sub thisDialog {my $hwnd = shift;my (%args) = @_;my $rv;#### ctk: Localvars my ($w1,$w2); ## ctk: Localvars end##my $mw = $hwnd->Toplevel();$mw->configure(-title=> (exists $args{-title})? $args{-title}:'');$mw->protocol('WM_DELETE_WINDOW',sub{1}); ## ctk: code generated by ctk_w version '3.095' ## ctk: instantiate and display widgets $wr_001 = $mw -> LabEntry ( -background , '#ffffff' , -justify , 'left' , -label , 'Name' , -relief , 'sunken' , -labelPack , [-side=>left,-anchor=>n] , -textvariable , \$w1 , -state , 'normal' ) -> pack(-anchor=>'nw', -side=>'top', -pady=>5, -fill=>'x', -expand=>1, -padx=>5); $wr_003 = $mw -> Frame ( -relief , 'solid' ) -> pack(-anchor=>'nw', -side=>'top', -pady=>5, -fill=>'x', -expand=>1, -padx=>5); $wr_002 = $wr_003 -> LabEntry ( -background , '#ffffff' , -justify , 'left' , -label , 'Folder name' , -relief , 'sunken' , -labelPack , [-side=>left,-anchor=>n] , -textvariable , \$w2 , -state , 'normal' ) -> pack(-anchor=>'nw', -side=>'left', -pady=>5, -fill=>'x', -expand=>1, -padx=>5); $wr_005 = $wr_003 -> Button ( -anchor , 'nw' , -background , '#ffffff' , -state , 'normal' , -relief , 'raised' , -text , 'Browse' ) -> pack(-side=>'left', -anchor=>'nw', -pady=>5, -padx=>5); ## ctk: end of gened Tk-code return $rv; } ## end of thisDialog ## ctk: end of dialog code## ctk: callbackssub init { 1 }## ctk: other code## ctk: eof 2006 10 27 - 17:44:321; ## make perl compiler happy...