File Coverage

blib/lib/Tcl/pTk.pm
Criterion Covered Total %
statement 4 6 66.6
branch n/a
condition n/a
subroutine 2 2 100.0
pod n/a
total 6 8 75.0


line stmt bran cond sub pod time code
1             package Tcl::pTk;
2              
3             our ($VERSION) = ('0.85');
4              
5 113     113   624665 use strict;
  113         263  
  113         5912  
6 113     113   424478 use Tcl;
  0            
  0            
7             use Exporter ('import');
8             use Scalar::Util (qw /blessed/); # Used only for it's blessed function
9             use vars qw(@EXPORT @EXPORT_OK %EXPORT_TAGS $platform @cleanup_refs $cleanup_queue_maxsize $cleanupPending);
10              
11             # Wait till we have 100 things to delete before we do cleanup
12             $cleanup_queue_maxsize = 50;
13              
14             # Set the platform global variable, based on the OS we are running under
15             BEGIN{
16             if($^O eq 'cygwin')
17             {
18             $platform = 'MSWin32'
19             }
20             else
21             {
22             $platform = ($^O eq 'MSWin32') ? $^O : 'unix';
23             }
24             };
25              
26              
27             use Tcl::pTk::Widget;
28             use Tcl::pTk::MainWindow;
29             use Tcl::pTk::DialogBox;
30             use Tcl::pTk::Dialog;
31             use Tcl::pTk::LabEntry;
32             use Tcl::pTk::ROText;
33             use Tcl::pTk::Listbox;
34             use Tcl::pTk::Balloon;
35             use Tcl::pTk::Menu;
36             use Tcl::pTk::Menubutton;
37             use Tcl::pTk::Optionmenu;
38             use Tcl::pTk::Canvas;
39             use Tcl::pTk::Font;
40              
41              
42             # Tcl::pTk::libary variable: Translation from perl/tk Tk.pm
43             {($Tcl::pTk::library) = __FILE__ =~ /^(.*)\.pm$/;}
44             $Tcl::pTk::library = Tk->findINC('.') unless (defined($Tcl::pTk::library) && -d $Tcl::pTk::library);
45              
46              
47             # Global vars used by this package
48              
49             our ( %W, $Wint, $Wpath, $Wdata, $DEBUG, $inMainLoop );
50              
51              
52             # For debugging, we use Sub::Name to name anonymous subs, this makes tracing the program
53             # much easier (using perl -d:DProf or other tools)
54             $DEBUG =0 unless defined($DEBUG);
55             if($DEBUG){
56             require Sub::Name;
57             import Sub::Name;
58             }
59              
60              
61             @Tcl::pTk::ISA = qw(Tcl);
62              
63              
64             sub WIDGET_CLEANUP() {1}
65              
66             $Tcl::pTk::DEBUG ||= 0;
67              
68             sub _DEBUG {
69             # Allow for optional debug level and message to be passed in.
70             # If level is passed in, return true only if debugging is at
71             # that level.
72             # If message is passed in, output that message if the level
73             # is appropriate (with any extra args passed to output).
74             my $lvl = shift;
75             return $Tcl::pTk::DEBUG unless defined $lvl;
76             my $msg = shift;
77             if (defined($msg) && ($Tcl::pTk::DEBUG >= $lvl)) { print STDERR $msg, @_; }
78             return ($Tcl::pTk::DEBUG >= $lvl);
79             }
80              
81              
82             =head1 NAME
83              
84             Tcl::pTk - Interface to Tcl/Tk with Perl/Tk compatible sytax
85              
86             =head1 SYNOPSIS
87              
88             B
89              
90             use Tcl::pTk;
91              
92             my $mw = MainWindow->new();
93             my $lab = $mw->Label(-text => "Hello world")->pack;
94             my $btn = $mw->Button(-text => "test", -command => sub {
95             $lab->configure(-text=>"[". $lab->cget('-text')."]");
96             })->pack;
97             MainLoop;
98              
99             Or B
100              
101             use Tcl::pTk;
102             my $int = new Tcl::pTk;
103             $int->Eval(<<'EOS');
104             # pure-tcl code to create widgets (e.g. generated by some GUI builder)
105             entry .e
106             button .inc -text {increment by Perl}
107             pack .e .inc
108             EOS
109             my $btn = $int->widget('.inc'); # get .inc button into play
110             my $e = $int->widget('.e'); # get .e entry into play
111             $e->configure(-textvariable=>\(my $var='aaa'));
112             $btn->configure(-command=>sub{$var++});
113             $int->MainLoop;
114              
115             =head1 DESCRIPTION
116              
117             C interfaces perl to an existing Tcl/Tk
118             installation on your computer. It has fully perl/tk (See L) compatible syntax for running existing
119             perl/tk scripts, as well as direct-tcl syntax for using any other Tcl/Tk features.
120              
121             Using this module an interpreter object is created, which
122             then provides access to all the installed Tcl libraries (Tk, Tix,
123             BWidgets, BLT, etc) and existing features (for example native-looking
124             widgets using the C package).
125              
126             B
127              
128             =over
129              
130             =item *
131              
132             Perl/Tk compatible syntax.
133              
134             =item *
135              
136             Pure perl megawidgets work just like in perl/tk. See the test case t/slideMegaWidget.t in the source distribution
137             for a simple example.
138              
139             =item *
140              
141             All the perl/tk widget demos work with minimal changes. Typically the only changes needed are just changing the "Use Tk;"
142             to "Use Tcl::pTk" at the top of the file. See the I demo script included in the source distribution to run the demos.
143              
144             =item *
145              
146             Built-in local drag-drop support, compatible with perl/tk drag-drop coding syntax.
147              
148             =item *
149              
150             L package supplied which enables Tcl::pTk to be used with existing Tk Scripts.
151              
152             =item *
153              
154             Similar interface approach to Tcl/Tk that other dynamic languages use (e.g. ruby, python). Because of this approach,
155             upgrades to Tcl/Tk shouldn't require much coding changes (if any) in L.
156              
157             =item *
158              
159             L package supplied, which provides a quick way of using the new better-looking Tile/ttk widgets in existing code.
160              
161             =item *
162              
163             TableMatrix (spreadsheet/grid Tktable widget, built to emulate the perl/tk L interface ) built into the package
164             (as long as you have the Tktable Tcl/Tk extension installed).
165              
166             =item *
167              
168             Extensive test suite.
169              
170             =item *
171              
172             Compatible with Tcl/Tk 8.4+
173              
174             =back
175              
176             =head2 Examples
177              
178             There are many examples in the I script (This is very simlar to the I demo installed with
179             perl/tk). After installing the L package, type I on the command line to run.
180              
181             The test cases in the I directory of the source distribution also is a good source of code examples.
182              
183             =head1 Relation to the L Package
184              
185             This package (L) is similar (and much of the code is derived from) the L package,
186             maintained by Vadim Konovalov. However it differs from the L package in some important ways:
187              
188             =over 1
189              
190             =item * L
191              
192             Emphasis is on 100% compatibility with existing perl/tk syntax.
193              
194             For developers with a perl/Tk background and an existing perl/Tk codebase to support.
195             For perl/Tk developers looking to take
196             advantage of the look/feel updates in Tcl/Tk 8.5 and above.
197              
198             =item * L
199              
200             Emphasis is on a lightweight interface to Tcl/Tk with syntax similar to (but not exactly like) perl/tk.
201              
202             For developers with some perl/Tk background, writing new code,
203             but no existing perl/Tk codebase to support.
204              
205             =back
206              
207             =head1 Basic Usage/Operation
208              
209             =head2 Creating a Tcl interpreter for Tk
210              
211             Before you start using widgets, an interpreter (at least one) should be
212             created, which will manage all things in Tcl. Creating an interpreter is created automatically
213             my the call to the C (or C) methods, but can also be created explicitly.
214              
215             B
216             For perl/tk syntax, the interpreter is created for you when you create the mainwindow.
217              
218             use Tcl::pTk;
219              
220             my $mw = MainWindow->new(); # Create Tcl::pTk interpreter and returns mainwindow widget
221             my $int = $mw->interp; # Get the intepreter that was created in the MainWindow call
222              
223             B
224              
225             use Tcl::pTk;
226              
227             my $int = new Tcl::pTk;
228              
229             Optionally a DISPLAY argument can be specified: C.
230             This creates a Tcl interpreter object $int, and creates a main toplevel
231             window. The window is created on display DISPLAY (defaulting to the display
232             named in the DISPLAY environment variable)
233              
234             =head2 Entering the main event loop
235              
236             B
237              
238             MainLoop; # Exact same syntax used as perl/Tk
239              
240             B
241              
242             $inst->MainLoop;
243              
244             =head2 Creating and using widgets
245              
246             Two different approaches are used to manipulate widgets (or to manipulate any Tcl objects that
247             act similarly to widgets).
248              
249             =over
250              
251             =item *
252              
253             Perl/Tk compatible-syntax approach. i.e. C<< $widget->method >> syntax.
254              
255             =item *
256              
257             Direct access using Eval-ed Tcl code. (e.g. using the C<< Eval >> Tcl::pTk method)
258              
259             =back
260              
261             The first way to manipulate widgets is identical to the perl/Tk calling conventions,
262             the second one uses Tcl syntax. Both ways are interchangeable in that a widget
263             created with one way can be used the another way. This interchangability enables
264             use of Tcl-code created elsewhere (e.g. by some WYSIWYG IDE).
265              
266             Usually Perl programs operate with Tcl::pTk via perl/Tk syntax, so users have no
267             need to deal with the Tcl language directly. Only some basic understanding of
268             Tcl/Tk widgets is needed.
269              
270              
271             =head3 Tcl/Tk syntax
272              
273             In order to get better understanding on usage of Tcl/Tk widgets from within
274             Perl, a bit of Tcl/Tk knowledge is needed, so we'll start from 2nd approach,
275             with Tcl's Eval (C<< $int->Eval('...') >>) and then smoothly move to first
276             approach with perl/Tk syntax.
277              
278             =over
279              
280             =item * The Tcl Interpreter
281              
282             The Tcl interpreter is used to process Tcl/Tk widgets; within C you
283             create it with C, and given any widget object, you can retreive it by the
284             C<< $widget->interp >> method. ( Within pure Tcl/Tk the interpreter already exists,
285             you don't need to create it explicitly. )
286              
287             =item * The Widget Path
288              
289             The Widget path is a string starting with a dot and consisting of several
290             names separated by dots. These names are individual widget-names that comprise
291             a widget's hierarchy. As an example, if there exists a frame with a path
292             C<.fram>, and you want to create a button on it and name it C, then
293             you should specify name C<.fram.butt>. Widget paths are also refered in
294             other miscellaneous widget operations, like geometry management.
295              
296             At any time a widget's path can be retreived with C<< $widget->path; >>
297             within C.
298              
299             =item * The Widget Path as a Tcl/Tk command
300              
301             When a widget is created in Tcl/Tk, a special command is created that is the name of the
302             widget's path. For example, a button created in a frame has a path and command-name C<.fr.b>. This
303             command also has subcommands which manipulate the widget. That is why
304             C<< $int->Eval('.fr.b configure -text {new text}'); >> makes sense.
305             Note that using perl/tk syntax C<< $button->configure(-text=>'new text'); >> does exactly the same thing,
306             if C<$button> corresponds to C<.fr.b> widget.
307              
308              
309             =back
310              
311              
312             The C statement not only creates the C package, but also creates the
313             C package, which is responsible for widgets. Each widget ( an object
314             blessed to C, or any of its subclasses )
315             behaves in such a way that its method will result in calling it's path on the
316             interpreter.
317              
318             =head3 Perl/Tk syntax
319              
320             C fully supports perl/Tk widget syntax of the L package, which has been used for many years. This means that any C widget
321             has a number of methods like C
322             on, and invoking those methods will create an appropriate child widget.
323             C will generate an unique path-name for a newly created widget.
324              
325             To demonstrate this concept, the perl/Tk syntax:
326              
327             my $label = $frame->Label(-text => "Hello world");
328              
329             executes the command
330              
331             $int->call("label", ".l", "-text", "Hello world");
332              
333             and this command similar to
334              
335             $int->Eval("label .l -text {Hello world}");
336              
337             This way Tcl::pTk widget commands are translated to Tcl syntax and directed to
338             the Tcl interpreter. This translation that occurs from perl/Tk syntax to Tcl calls is why the two approaches for
339             dealing with widgets are interchangeable.
340              
341             The newly created widget C<$label> will be blessed to package C
342             which is isa-C (i.e. C is a subclass of C).
343              
344              
345             =head1 Categories of Tcl::pTk Widgets
346              
347             C Widgets fall into the following basic categories, based on how they are implemented in the C package.
348              
349             =over 1
350              
351             =item Direct auto-wrapped widgets
352              
353             These types of widgets (for example the Entry, Button, Scrollbar, and Label widgets) have no special code written for them
354             in C. Their creation and method calls (e.g. C<$button->configure(-text => 'ButtonText')> ) are handled
355             by the wrapping code in the base Tcl::pTk::Widget package.
356              
357             =item Auto-wrapped widgets, with compatibility code
358              
359             These types of widgets are similar to the Direct auto-wraped widgets, but have additional code written to be completely
360             compatibile with the perl/Tk syntax. Examples of this type of widget are the Text, Frame, Menu, and Menubutton widgets.
361              
362             =item Megawidgets
363              
364             These are widgets that are composed of one-or-more other base widget types. Pure-perl megawidgets are supported in Tcl::pTk,
365             just like they are in perl/Tk. Examples of these types of widgets are ProgressBar, LabEntry, BrowseEntry, and SlideSwitch (one of the test cases in the source distribution).
366              
367             =item Derived Widgets
368              
369             Derived widgets are sub-classes of existing widgets that provide some additional functions. Derived widgets are created in
370             Tcl::pTk using very similar syntax to perl/Tk (i.e. using the Tcl::pTk::Derived package, similar to the Tk::Derived package).
371             Examples of these types of widgets are Tree, TextEdit, TextUndo, ROText, and DirTree.
372              
373             =back
374              
375             =head1 A behind-the-scenes look at auto-wrapped widgets
376              
377             All widgets in C are objects, and have an inheritance hierarchy that derives from the C
378             parent class. Megawidgets and derived widgets are handled very similar (if not exactly) the same as in perl/tk.
379              
380             Auto-wrapped widgets (like the Entry, Button, Scrollbar, etc.) are handled differently.
381             The object system for these types of widgets is dynamic. Classes and/or methods are created when they are
382             first used or needed.
383              
384             The following describes how methods are called for the two different categories of auto-wrapped widgets
385              
386             =over 1
387              
388             =item Direct auto-wrapped widget example
389              
390             Here is an example of a Entry widget, a direct auto-wrapped widget:
391              
392             my $entry = $mw->Entry->pack; # Create an entry widget and pack it
393             $entry->insert('end', -text=>'text'); # Insert some text into the Entry
394             my $entryText = $entry->get(); # Get the entry's text
395              
396             Internally, the following mechanics come into play:
397             The I method creates an I widget (known as C in the Tcl/Tk environment).
398             When this creation method is invoked the first time, a package
399             C is created, which sets up the class hierarchy for any
400             further Entry widgets. The newly-created C class is be
401             a direct subclass of C.
402              
403             The second code line above calls the C method of the C<$entry> object.
404             When invoked first time, a method (i.e. subref) C is
405             created in package C, which will end-up calling
406             calling the C method on the Tcl/Tk interpreter (i.e.
407             C<$entry->interp()->invoke($entry, 'insert', -text, 'text')
408              
409             The first time C is called, the C method does not exist, so AUTOLOAD
410             comes into play and creates the method. The second time C is called, the already-created
411             method is called directly (i.e. not created again), thus saving execution time.
412              
413             =item Auto-wrapped widgets, with compatibility code
414              
415             Here is an example of a Text widget, which is an auto-wrapped widget with extra
416             code added for compatibility with the perl/tk Text widget.
417              
418             my $text = $mw->Text->pack; # Create an text widget and pack it
419             $text->insert('end', -text=>'text'); # Insert some text into the Text
420             @names = $text->markNames; # Get a list of the marks set in the
421             # Text widget
422              
423             Internally, following mechanics come into play:
424             The I method creates an I widget (known as C in Tcl/Tk environment).
425             Because a C package already exists, a new package is not created
426             at runtime like the case above.
427              
428             The second code line above calls the C of the C<$text> object of type
429             C. This C method is already defined in the C package,
430             so it is called directly.
431              
432             The third code line above calls the C method on the C<$text> object. This method
433             is not defined in the C package, so the first time when C is called,
434             AUTOLOAD in the L package comes into play and creates the method.
435             The second time C is called, the already-created
436             method is called directly (i.e. not created again), thus saving execution time.
437              
438             =back
439              
440             =head2 Description of an auto-wrapped method call
441              
442             Suppose C<$widget> isa C, its path is C<.path>, and method
443             C invoked on it with a list of parameters, C<@parameters>:
444              
445             $widget->method(@parameters);
446              
447             In this case all C<@parameters> will be preprocessed by performing the following actions:
448              
449             =over
450              
451             =item 1.
452              
453             For each variable reference, a Tcl variable will be created and tied to it, so changes in the perl variable
454             will be reflected in the Tcl variable, and changes in the Tcl variable will show up in the perl variable.
455              
456             =item 2.
457              
458             For each perl code-reference, a Tcl command will be created that calls this perl code-ref.
459              
460             =item 3.
461              
462             Each array reference will considered a callback, and proper actions will be taken.
463              
464             =back
465              
466             After processing of C<@parameters>, the Tcl/Tk interpreter will be requested to
467             perform following operation:
468              
469             =over
470              
471             =item if C<$method> is all lowercase (e.g. C), C
472              
473             C<.path method parameter1 parameter2> I<....>
474              
475             =item if C<$method> contains exactly one capital letter inside the method name (e.g. C), C
476              
477             C<.path method submethod parameter1 parameter2> I<....>
478              
479             =item if C<$method> contains several capital letter inside the method name, C
480              
481             C<.path method submeth subsubmeth parameter1 parameter2> I<....>
482              
483             =back
484              
485             =head2 Fast method invocation for auto-wrapped widgets
486              
487             If you are sure that preprocessing of C<@parameters> in a method call aren't required
488             (i.e. no parameters are Perl references to scalars, subroutines or arrays), then
489             the preprocessing step described above can be skipped by calling the method with
490             an underscore C<_> prepended to the name. (e.g call C<$text->_markNames()>, instead of
491             C<$text->markNames()>). Calling the method this way means you are using an internal
492             method that executes faster, but normally you should use a "public" (i.e. non-underscore) method, which includes all preprocessing.
493              
494             Example:
495              
496             # Can't use the faster method-call here, because \$var must be
497             # preprocessed for Tcl/Tk:
498             $button->configure(-textvariable=>\$var);
499              
500             # Faster version of insert method for the "Text" widget
501             $text->_insert('end','text to insert','tag');
502            
503             # This line does exactly same thing as previous line:
504             $text->_insertEnd('text to insert','tag');
505              
506             When doing many inserts to a text widget, the faster version can help speed things up.
507              
508              
509             =head1 Using any Tcl/Tk feature from Tcl::pTk
510              
511             In addition to the standard widgets (e.g. Entry, Button, Menu, etc), the C module
512             lets you use any other widget from the Tcl/Tk widget library. This can be done with either
513             Tcl syntax (via the C method), or with regular perl/tk syntax.
514              
515             To interface to a new Tcl/Tk widget using perl/tk syntax, a C method call
516             is made on an already-created widget, or on the C interpreter object itself.
517              
518             Syntax is
519            
520             # Calling Declare on a widget object:
521             $widget->Declare('perlTk_widget_method_name','tcl/tk-widget_method_name',
522             @options);
523              
524             or, exactly the same,
525            
526             # Calling Declare on a the Tcl::pTk Interpreter object:
527             $interp->Declare('perlTk_widget_method_name','tcl/tk-widget_method_name',
528             @options);
529            
530             Options are:
531              
532             -require => 'tcl-package-name'
533             -prefix => 'some-prefix'
534              
535             The I<-require> option specifies the new Tcl/Tk widget requires a Tcl package to be loaded with a name
536             of 'tcl-package-name';
537              
538             The I<-prefix> option used to specify the prefix of the autogenerated widget path-name. This option is
539             normally used when the Tcl/Tk widget name contains non-alphabetic characters (e.g. ':'). If not specified, the
540             prefix will be generated from the package-name.
541              
542             A typical example of using the C method:
543              
544             $mw->Declare('BLTNoteBook','blt::tabnotebook',-require=>'BLT',-prefix=>'bltnbook');
545              
546             After this call, C will create a widget creation method for this new package to make it an
547             auto-wrapped widget (See the definition of auto-wrapped widgets above).
548              
549             This means
550              
551             my $tab = $mw->BLTNoteBook;
552              
553             will create blt::tabnotebook widget. Effectively, this is equavalent to the following
554             Tcl/Tk code:
555              
556             package require BLT # but invoked only once
557             blt::tabnotebook .bltnbook1
558              
559             After the above example code, the variable C<$tab> is a B that behaves in
560             the usual way, for example:
561              
562             $tab->insert('end', -text=>'text');
563             $tab->tabConfigure(0, -window=>$tab->Label(-text=>'text of label'));
564              
565             These two lines are the Tcl/Tk equivalent of:
566              
567             .bltnbook1 insert end -text {text}
568             .bltnbook1 tab configure 0 -window [label .bltnbook1.lab1 -text {text of label}]
569              
570             You can also intermix the perl/tk and Tcl/Tk syntax like this:
571              
572             $interp->Eval('package require BLT;blt::tabnotebook .bltnbook1');
573             $tab = $interp->widget('.bltnbook1');
574             $tab->tabConfigure(0, -window=>$tab->Label(-text=>'text of label'));
575              
576             =head1 How to read Tcl/Tk widget docs when using in C
577              
578             For the documentation of standard perl/tk widgets (like Button, Entry, Menu, etc), you can refer
579             to the the perl/tk docs L (We may move a copy of the perl/tk docs to Tcl::pTk in the future). For non-standard
580             widgets (like the BLTNotebook widget example above) you have to use the Tcl docs on the widget for the widget documentation. (Most Tcl/Tk
581             docs can be found at http://www.tcl.tk/ )
582              
583             When reading Tcl/Tk widget documentation about widgets, you can apply the following guidelines to determine how
584             to use the widget in C using perl/tk syntax.
585              
586             Suppose the Tcl/Tk docs say:
587              
588             pathName method-name optional-parameters
589             (some description)
590            
591             This means the widget has a has method C and you can
592             invoke it in C like
593              
594             $widget->method-name(optional-parameters);
595              
596             The C<$widget> variable in C is like the I in the Tcl/Tk docs.
597              
598             Sometimes the Tcl/Tk method-name consists of two words (verb1 verb2). In this
599             case there are two equivalent ways to invoke it, C< $widget->verb1('verb2',...); > or
600             C< $widget->verb1Verb2(...)>;
601              
602             Widget options are used just like they are shown in the Tcl/Tk docs. There is no special translation needed
603             for the widget options described in the Tcl/Tk docs for use in C.
604              
605             =head1 Miscellaneous methods
606              
607             =head2 C<< $int->widget( path, widget-type ) >>
608              
609             When widgets are created in C they are stored internally and can and can be retreived
610             by the C method, which takes widget path as first parameter, and optionally
611             the widget type (such as Button, or Text etc.). For Example:
612              
613             # this will retrieve widget, and then call configure on it
614             widget(".fram.butt")->configure(-text=>"new text");
615              
616             # this will retrieve widget as Button (Tcl::pTk::Button object)
617             my $button = widget(".fram.butt", 'Button');
618            
619             # same but retrieved widget considered as general widget, without
620             # specifying its type. This will make it a generic Tcl::pTk::Widget object
621             my $button = widget(".fram.butt");
622              
623             Please note that this method will return to you a widget object even if it was
624             not created within C. A check is not performed to see if a
625             widget with given path name exists. This enables the use of widgets created elsewhere
626             in Tcl/Tk to be treated like C widgets.
627              
628             =head2 C
629              
630             If you need to associate any data with particular widget, you can do this with
631             C method of either interpreter or widget object itself. This method
632             returns same anonymous hash and it should be used to hold any keys/values pairs.
633              
634             Examples:
635              
636             $interp->widget_data('.fram1.label2')->{var} = 'value';
637             $label->widget_data()->{var} = 'value';
638            
639             B
640              
641             Use of this method has largely been superceded by the perl/tk-compatible C widget method.
642              
643              
644              
645             =head2 C<< $widget->tooltip("text") >>
646              
647             Any widget accepts the C method, accepting any text as parameter, which
648             will be used as floating help text explaining the widget. The widget itself
649             is returned, so to provide convenient way of chaining:
650              
651             $mw->Button(-text=>"button 1")->tooltip("This is a button, m-kay")->pack;
652             $mw->Entry(-textvariable=>\my $e)->tooltip("enter the text here, m-kay")->pack;
653              
654             The C method uses the C package, which is a part of C within
655             Tcl/Tk, so be sure you have that Tcl/Tk package installed.
656              
657             Note: The perl/tk-compatible B widget is also available for installing tool-tips on widgets
658             and widget-elements.
659              
660              
661             =head1 Terminology
662              
663             In the documentation and comments for this package, I, I, I, I, and I are used. These terms have the
664             following meanings in the context of this package.
665              
666             =over 1
667              
668             =item perl/Tk
669              
670             The traditional perl interface to the Tk GUI libraries. i.e the perl package occupying the L namespace on CPAN.
671              
672             =item Tcl/Tk
673              
674             The Tcl/Tk package with tcl-code and associated libraries (e.g. Tcl.so or Tcl.dll and associated tcl-code). See http://www.tcl.tk/
675              
676             =item Tcl::pTk
677              
678             This package, which provides a perl interface into the Tcl/Tk GUI libraries.
679              
680             =item Tcl.pm
681              
682             The L perl package, which provides a simple interface from perl to Tcl/Tk. L interpreter objects are subclassed
683             from the L package.
684              
685             =item Tcl
686              
687             The I programming language.
688              
689             =back
690              
691              
692             =head1 BUGS
693              
694             Currently work is in progress, and some features could change in future
695             versions.
696              
697             =head1 AUTHORS
698              
699             =over
700              
701             =item Malcolm Beattie.
702              
703             =item Vadim Konovalov, vadim_tcltk@vkonovalov.ru 19 May 2003.
704              
705             =item Jeff Hobbs, jeffh _a_ activestate com, February 2004.
706              
707             =item Gisle Aas, gisle _a_ activestate . com, 14 Apr 2004.
708              
709             =item John Cerney, john.cerney _a_ gmail . com, 29 Sep 2009.
710              
711             =back
712              
713             =head1 COPYRIGHT
714              
715             This program is free software; you can redistribute it and/or modify it
716             under the same terms as Perl itself.
717              
718             See http://www.perl.com/perl/misc/Artistic.html
719              
720             =cut
721              
722             my @misc = qw( after destroy focus grab lower option place raise
723             image font
724             selection tk grid tkwait update winfo wm);
725             my @perlTk = qw( MainWindow MainLoop DoOneEvent tkinit update Ev Exists);
726              
727             # Flags for supplying to DoOneEvent
728             my @eventFlags = qw(DONT_WAIT WINDOW_EVENTS FILE_EVENTS
729             TIMER_EVENTS IDLE_EVENTS ALL_EVENTS);
730              
731             @EXPORT = (@perlTk, @eventFlags);
732             @EXPORT_OK = (@misc );
733             %EXPORT_TAGS = (widgets => [], misc => \@misc, perlTk => \@perlTk,
734             eventtypes => [@eventFlags],
735             );
736              
737             ## TODO -- module's private $tkinterp should go away!
738             my $tkinterp = undef; # this gets defined when "new" is done
739              
740             # Hash to keep track of all created widgets and related instance data
741             # Tcl::pTk will maintain PATH (Tk widget pathname) and INT (Tcl interp)
742             # and the user can create other info.
743             %W = (
744             INT => {}, # Hash of mainwindowID or pathname => Tcl::pTk Interpreter Reference
745             PATH => {}, # Hash of pathname => pathname (or mainwindow id)
746             RPATH => {}, # Hash of pathname => widget reference
747             DATA => {}, # Hash of widget data (used by the widget_data methods)
748             );
749             # few shortcuts for %W to be faster
750             $Wint = $W{INT};
751             $Wpath = $W{PATH};
752             $Wdata = $W{DATA};
753              
754              
755              
756             # hash to keep track on preloaded Tcl/Tk modules, such as Tix, BWidget
757             my %preloaded_tk; # (interpreter independent thing. is this right?)
758              
759             #
760             sub new {
761             my ($class, $display) = @_;
762             Carp::croak 'Usage: $interp = new Tcl::pTk([$display])'
763             if @_ > 1;
764             my @argv;
765             if (defined($display)) {
766             push(@argv, -display => $display);
767             } else {
768             $display = $ENV{DISPLAY} || '';
769             }
770             my $i = new Tcl;
771             bless $i, $class;
772             $i->SetVar2("env", "DISPLAY", $display, Tcl::GLOBAL_ONLY);
773             $i->SetVar("argv", [@argv], Tcl::GLOBAL_ONLY);
774             $i->SetVar("tcl_interactive", 0, Tcl::GLOBAL_ONLY);
775             $i->SUPER::Init();
776             $i->pkg_require('Tk', $i->GetVar('tcl_version'));
777              
778             my $mwid = $i->invoke('winfo','id','.');
779             $W{PATH}->{$mwid} = '.';
780             $W{INT}->{$mwid} = $i;
781             $W{mainwindow}->{"$i"} = bless({ winID => $mwid }, 'Tcl::pTk::MainWindow');
782              
783             # When mainwindow goes away, delete entry from the $W{mainwindow} global hash:
784             $i->call('trace', 'add', 'command', '.', 'delete',
785             sub { delete $W{mainwindow}{"$i"} }
786             );
787             $i->ResetResult();
788              
789             $Tcl::pTk::TK_VERSION = $i->GetVar("tk_version");
790             # Only do this for DEBUG() ?
791             $Tk::VERSION = $Tcl::pTk::TK_VERSION;
792             $Tk::VERSION =~ s/^(\d)\.(\d)/${1}0$2/;
793             unless (defined $tkinterp) {
794             # first call, create command-helper in TCL to trace widget destruction
795             $i->CreateCommand("::perl::w_del", \&widget_deletion_watcher);
796            
797             # Create command-helper in TCL to perform the actual widget cleanup
798             # (deferred in a afterIdle call )
799             $i->CreateCommand("::perl::w_cleanup", \&widget_cleanup);
800             }
801             $tkinterp = $i;
802             return $i;
803             }
804              
805             sub mainwindow {
806             # this is a window with path '.'
807             my $interp = shift;
808            
809            
810             return $W{mainwindow}->{"$interp"};
811             }
812             sub tkinit {
813             my $interp = Tcl::pTk->new(@_);
814             $interp->mainwindow;
815             }
816              
817             sub MainWindow {
818             my $interp = Tcl::pTk->new(@_);
819              
820             # Load Tile Widgets, if the tcl version is > 8.5
821             my $patchlevel = $interp->icall('info', 'patchlevel');
822             my (@patchElems) = split('\.', $patchlevel);
823             my $versionNumber = $patchElems[0] + $patchElems[1]/1000 + $patchElems[2]/100e3; # convert version to number
824             if( $versionNumber >= 8.005 ){
825             require Tcl::pTk::Tile;
826             Tcl::pTk::Tile::_declareTileWidgets($interp);
827             }
828            
829             # Load palette commands, so $interp->invoke can be used with them later, for speed.
830             $interp->call('auto_load', 'tk_setPalette');
831              
832            
833             # Declare auto-widgets, so subclasses of auto-created widgets will work correctly.
834             Tcl::pTk::Widget::declareAutoWidget($interp);
835            
836              
837             $interp->mainwindow;
838             }
839              
840              
841             ## Front-End for fileevent that can be called using Tcl::pTk->fileevent, instead of the normal
842             # $widget->filevent syntax. This is provided for compatibility with perl/tk
843             #
844             sub fileevent{
845             my $firstArg = shift;
846             my $int = ( ref($firstArg) ? $firstArg : $tkinterp ); # Get default interp, unless supplied
847             my $mw = $int->mainwindow(); # Get the mainwindow for this interpreter
848            
849             # Call the normal fileevent
850             $mw->fileevent(@_);
851             }
852            
853             sub MainLoop {
854             # This perl-based mainloop differs from Tk_MainLoop in that it
855             # relies on the traced deletion of '.' instead of using the
856             # Tk_GetNumMainWindows C API.
857             # This could optionally be implemented with 'vwait' on a specially
858             # named variable that gets set when '.' is destroyed.
859             unless ($inMainLoop){ # Don't recursivly enter into a mainloop
860             local $inMainLoop = 1;
861             my $int = (ref $_[0]?shift:$tkinterp);
862             my $mainwindow = $W{mainwindow};
863             while ( %$mainwindow ) { # Keep calling DoOneEvent until all mainwindows go away
864             $int->DoOneEvent(0);
865             }
866             }
867             }
868              
869             # timeofday function for compatibility with Tk::timeofday
870             sub timeofday {
871             # This perl-based mainloop differs from Tk_MainLoop in that it
872             # relies on the traced deletion of '.' instead of using the
873             # Tk_GetNumMainWindows C API.
874             # This could optionally be implemented with 'vwait' on a specially
875             # named variable that gets set when '.' is destroyed.
876             my $int = (ref $_[0]?shift:$tkinterp);
877             my $t = $int->invoke("clock", "microseconds");
878             $t = $t/1e6;
879             }
880              
881              
882             # DoOneEvent for compatibility with perl/tk
883             sub DoOneEvent{
884             my $int = (ref $_[0]?shift:$tkinterp);
885             my $flags = shift;
886             $int->Tcl::DoOneEvent($flags);
887             }
888              
889             # After wrapper for compatibility with perl/tk (So that Tcl::pTk->after(delay) calls work
890             sub after{
891             my $int = shift;
892             $int = (ref($int) ? $int : $tkinterp ); # if interpreter not supplied use $tkinterp
893             my $ms = shift;
894             my $callback = shift;
895            
896             $ms = int($ms) if( $ms =~ /\d/ ); # Make into an integer to keep tk from complaining
897            
898             if( defined($callback)){
899             # Turn into callback, if not one already
900             unless( blessed($callback) and $callback->isa('Tcl::pTk::Callback')){
901             $callback = Tcl::pTk::Callback->new($callback);
902             }
903            
904             my $sub = sub{ $callback->Call()};
905             #print "Tcl::pTk::after: setting after on $sub\n";
906             my $ret = $int->call('after', $ms, $sub );
907             return $int->declare_widget($ret);
908             }
909             else{ # No Callback defined, just do a sleep
910             return $int->call('after', $ms );
911             }
912            
913             return($int->call('after', $ms));
914             }
915              
916              
917             # create_widget Method
918             # This is used as a front-end to the declare_widget method, so that -command and -variable configuration
919             # options supplied at widget-creation will be properly stored as Tcl::pTk::Callback objects (for perltk
920             # compatibility).
921             # This is done by issuing the -command or -variable type option after widget creation, where the callback object can be
922             # stored with the widget
923             sub create_widget{
924             my $int = shift; # Interperter
925             my $parent = shift; # Parent widget
926             my $id = shift; # unique id for the new widget
927             my $ttktype = shift; # Name of widget, in tcl/tk
928             my $widget_class = shift || 'Tcl::pTk::Widget';
929              
930             my @args = @_;
931            
932             my @filteredArgs; # args, filtered of any -command type options
933             my @commandOptions; # any command options needed to be issued after widget creation.
934            
935             # Go thru each arg and look for callback (i.e -command ) args
936             my $lastArg;
937             foreach my $arg(@args){
938            
939             if( defined($lastArg) && !ref($lastArg) && ( $lastArg =~ /^-\w+/ ) ){
940             if( $lastArg =~ /command|cmd$/ && defined($arg) ) { # Check for last arg something like -command
941            
942             #print "Found command arg $lastArg => $arg\n";
943            
944             # Save this option for issuing after widget creation
945             push @commandOptions, $lastArg, $arg;
946            
947             # Remove the lastArg from the current arg queue, since we will be handling
948             # it using @commandOptions
949             pop @filteredArgs;
950            
951             $lastArg = undef;
952             next;
953             }
954             if( $lastArg =~ /variable$/ ){ # Check for last arg something like -textvariable
955             # Save this option for issuing after widget creation
956             push @commandOptions, $lastArg, $arg;
957            
958             # Remove the lastArg from the current arg queue, since we will be handling
959             # it using @commandOptions
960             pop @filteredArgs;
961            
962             $lastArg = undef;
963             next;
964             }
965              
966             }
967            
968             $lastArg = $arg;
969            
970             push @filteredArgs, $arg;
971             }
972            
973             # Make the normal declare_widget call
974             my $widget = $int->declare_widget($parent->call($ttktype, $id, @filteredArgs), $widget_class);
975            
976             # Make configure call for any left-over commands
977             $widget->configure(@commandOptions) if(@commandOptions);
978            
979             return $widget;
980             }
981            
982            
983             #
984             # declare_widget, method of interpreter object
985             # args:
986             # - a path of existing Tcl/Tk widget to declare its existance in Tcl::pTk
987             # - (optionally) package name where this widget will be declared, default
988             # is 'Tcl::pTk::Widget', but could be 'Tcl::pTk::somewidget'
989             sub declare_widget {
990             my $int = shift;
991             my $path = shift;
992             my $widget_class = shift || 'Tcl::pTk::Widget';
993             # JH: This is all SOOO wrong, but works for the simple case.
994             # Issues that need to be addressed:
995             # 1. You can create multiple interpreters, each containing identical
996             # pathnames. This var should be better scoped.
997             # VK: mostly resolved, such interpreters with pathnames allowed now
998             # 2. There is NO cleanup going on. We should somehow detect widget
999             # destruction (trace add command delete ... in 8.4) and interp
1000             # destruction to clean up package variables.
1001             #my $id = $path=~/^\./ ? $int->invoke('winfo','id',$path) : $path;
1002             $int->invoke('trace', 'add', 'command', $path, 'delete', "::perl::w_del $path")
1003             if ( WIDGET_CLEANUP && $path !~ /\#/); # don't trace for widgets like 'after#0'
1004             my $id = $path;
1005             my $w = bless({ winID => $id}, $widget_class);
1006             Carp::confess("id is not found\n") if( !defined($id));
1007             $Wpath->{$id} = $path; # widget pathname
1008             $Wint->{$id} = $int; # Tcl interpreter
1009             $W{RPATH}->{$path} = $w;
1010            
1011            
1012             return $w;
1013             }
1014              
1015             sub widget_deletion_watcher {
1016             my (undef,$int,undef,$path) = @_;
1017             #print STDERR "[D:$path]\n";
1018            
1019             # Call the _OnDestroy method on the widget to perform cleanup on it
1020             my $w = $W{RPATH}->{$path};
1021             #print STDERR "Calling _Destroyed on $w, Ind = ".$Idelete++."\n";
1022             $w->_Destroyed();
1023            
1024             $int->delete_widget_refs($path);
1025              
1026             delete $W{RPATH}->{$path};
1027             }
1028              
1029             ###############################################
1030             # Overriden delet_ref
1031             # Instead of immediately deleting a scalar or code ref in Tcl-land,
1032             # queue the ref to be deleted in an after-idle call.
1033             # This is done, rather than deleting immediately, because an immediate delete
1034             # before a widget is completely destroyed can causes Tcl-crashes.
1035             sub delete_ref {
1036             my $interp = shift;
1037             my $rname = shift;
1038             my $ref = $interp->return_ref($rname);
1039             push @cleanup_refs, $rname;
1040            
1041             # Create an after-idle call to delete refs, if the cleanup queue is bigger
1042             # than the threshold
1043             if( !$cleanupPending and scalar(@cleanup_refs) > $cleanup_queue_maxsize ){
1044             #print STDERR "Calling after idle cleanup on ".join(", ", @cleanup_refs)."\n";
1045             $cleanupPending = 1; # Setup flag so we don't call the after idle multiple times
1046             $interp->call('after', 'idle', "::perl::w_cleanup");
1047             }
1048             return $ref;
1049             }
1050              
1051              
1052             # Sub to cleanup any que-ed commands and variables in
1053             # @cleanup_refs. This usually called from an after-idle procedure
1054             sub widget_cleanup {
1055             my (undef,$int,undef,$path) = @_;
1056              
1057             my @deleteList = @cleanup_refs;
1058            
1059             # Go thru each list and delete
1060             foreach my $rname(@deleteList){
1061             #print "Widget_Cleanup deleting $rname\n";
1062              
1063             $int->SUPER::delete_ref($rname);
1064             }
1065            
1066             # Zero-out cleanup_refs
1067             @cleanup_refs = ();
1068             $cleanupPending = 0; # Reset cleanup flag for next time
1069              
1070             }
1071              
1072             # widget_data return anonymous hash that could be used to hold any
1073             # user-specific data
1074             sub widget_data {
1075             my $int = shift;
1076             my $path = shift;
1077             $Wdata->{$path} ||= {};
1078             return $Wdata->{$path};
1079             }
1080              
1081             # subroutine awidget used to create [a]ny [widget]. Nothing complicated here,
1082             # mainly needed for keeping track of this new widget and blessing it to right
1083             # package
1084             sub awidget {
1085             my $int = (ref $_[0]?shift:$tkinterp);
1086             my $wclass = shift;
1087             # Following is a suboptimal way of autoloading, there should exist a way
1088             # to Improve it.
1089             my $sub = sub {
1090             my $int = (ref $_[0]?shift:$tkinterp);
1091             my ($path) = $int->call($wclass, @_);
1092             return $int->declare_widget($path);
1093             };
1094             unless ($wclass=~/^\w+$/) {
1095             die "widget name '$wclass' contains not allowed characters";
1096             }
1097             # create appropriate method ...
1098             no strict 'refs';
1099             *{"Tcl::pTk::$wclass"} = $sub;
1100             # ... and call it (if required)
1101             if ($#_>-1) {
1102             return $sub->($int,@_);
1103             }
1104             }
1105             sub widget($@) {
1106             my $int = (ref $_[0]?shift:$tkinterp);
1107             my $wpath = shift;
1108             my $wtype = shift || 'Tcl::pTk::Widget';
1109             if (exists $W{RPATH}->{$wpath}) {
1110             return $W{RPATH}->{$wpath};
1111             }
1112             unless ($wtype=~/^(?:Tcl::pTk)/) {
1113             Tcl::pTk::Widget::create_widget_package($wtype);
1114             $wtype = "Tcl::pTk::$wtype";
1115             }
1116             #if ($wtype eq 'Tcl::pTk::Widget') {
1117             # require Carp;
1118             # Carp::cluck("using \"widget\" without widget type is strongly discouraged");
1119             #}
1120             # We could ask Tcl about it by invoking
1121             # my @res = $int->Eval("winfo exists $wpath");
1122             # but we don't do it, as long as we allow any widget paths to
1123             # be used by user.
1124             my $w = $int->declare_widget($wpath,$wtype);
1125             return $w;
1126             }
1127              
1128             sub Exists {
1129             my $wid = shift;
1130             return 0 unless defined($wid);
1131             if (blessed($wid) && $wid->isa('Tcl::pTk::Widget') ) {
1132             my $wp = $wid->path;
1133             my $interp = $wid->interp;
1134             return 0 unless( defined $interp); # Takes care of some issues during global destruction
1135             return $interp->icall('winfo','exists',$wp);
1136             }
1137             return eval{$tkinterp->icall('winfo','exists',$wid)};
1138             }
1139              
1140             sub widgets {
1141             \%W;
1142             }
1143              
1144             sub pkg_require {
1145             # Do Tcl package require with optional version, cache result.
1146             my $int = shift;
1147             my $pkg = shift;
1148             my $ver = shift;
1149              
1150             my $id = "$int$pkg"; # to made interpreter-wise, do stringification of $int
1151              
1152             return $preloaded_tk{$id} if $preloaded_tk{$id};
1153              
1154             my @args = ("package", "require", $pkg);
1155             push(@args, $ver) if defined($ver);
1156             eval { $preloaded_tk{$id} = $int->icall(@args); };
1157             if ($@) {
1158             # Don't cache failures, as the package may become available by
1159             # changing auto_path and such.
1160             return;
1161             }
1162             return $preloaded_tk{$id};
1163             }
1164              
1165             sub need_tk {
1166             # DEPRECATED: Use pkg_require and call instead.
1167             my $int = shift;
1168             my $pkg = shift;
1169             my $cmd = shift || '';
1170             warn "DEPRECATED CALL: need_tk($pkg, $cmd), use pkg_require\n";
1171             if ($pkg eq 'ptk-Table') {
1172             require Tcl::pTk::Table;
1173             }
1174             else {
1175             # Only require the actual package once
1176             my $ver = $int->pkg_require($pkg);
1177             return 0 if !defined($ver);
1178             $int->Eval($cmd) if $cmd;
1179             }
1180             return 1;
1181             }
1182              
1183              
1184              
1185             # subroutine findINC copied from perlTk/Tk.pm
1186             sub findINC {
1187             my $file = join('/',@_); # Normal location
1188             my $fileImage = join('/', $_[0], 'images', $_[1]); # alternate location in the 'images' directory
1189             my $dir;
1190             $file =~ s,::,/,g;
1191             $fileImage =~ s,::,/,g;
1192             foreach $dir (@INC) {
1193             my $path;
1194              
1195             # check for normal location and 'images' location of the file
1196             return $path if (-e ($path = "$dir/$file") );
1197             return $path if (-e ($path = "$dir/$fileImage") );
1198              
1199             }
1200             return undef;
1201             }
1202              
1203              
1204              
1205             # sub Declare is just a dispatcher into Tcl::pTk::Widget method
1206             sub Declare {
1207             Tcl::pTk::Widget::Declare(undef,@_[1..$#_]);
1208             }
1209              
1210              
1211             #
1212             # AUTOLOAD method for Tcl::pTk interpreter object, which will bring into
1213             # existance interpreter methods
1214             sub AUTOLOAD {
1215             my $int = shift;
1216             my ($method,$package) = $Tcl::pTk::AUTOLOAD;
1217             my $method0;
1218             for ($method) {
1219             s/^(Tcl::pTk::)//
1220             or Carp::confess "weird inheritance ($method)";
1221             $package = $1;
1222             $method0 = $method;
1223             s/(?
1224             s/(?
1225             }
1226            
1227             # if someone calls $interp->_method(...) then it is considered as faster
1228             # version of method, similar to calling $interp->method(...) but via
1229             # 'invoke' instead of 'call', thus faster
1230             my $fast = '';
1231             $method =~ s/^_// and do {
1232             $fast='_';
1233             if (exists $::Tcl::pTk::{$method}) {
1234             no strict 'refs';
1235             *{"::Tcl::pTk::_$method"} = *{"::Tcl::pTk::$method"};
1236             return $int->$method(@_);
1237             }
1238             };
1239              
1240             # search for right corresponding Tcl/Tk method, and create it afterwards
1241             # (so no consequent AUTOLOAD will happen)
1242              
1243             # Check to see if it is a camelCase method. If so, split it apart.
1244             # code below will always create subroutine that calls a method.
1245             # This could be changed to create only known methods and generate error
1246             # if method is, for example, misspelled.
1247             # so following check will be like
1248             # if (exists $knows_method_names{$method}) {...}
1249             my $sub;
1250             if ($method =~ /^([a-z]+)([A-Z][a-z]+)$/) {
1251             my ($meth, $submeth) = ($1, lcfirst($2));
1252             # break into $method $submethod and call
1253             $sub = $fast ? sub {
1254             my $int = shift;
1255             $int->invoke($meth, $submeth, @_);
1256             } : sub {
1257             my $int = shift;
1258             $int->call($meth, $submeth, @_);
1259             };
1260             }
1261             else {
1262             # Default case, call as method of $int
1263             $sub = $fast ? sub {
1264             my $int = shift;
1265             $int->invoke($method, @_);
1266             } : sub {
1267             my $int = shift;
1268             $int->call($method, @_);
1269             };
1270             }
1271             no strict 'refs';
1272             *{"$package$fast$method0"} = $sub;
1273             Sub::Name::subname("$package$fast$method0", $sub) if( $Tcl::pTk::DEBUG);
1274             return $sub->($int,@_);
1275             }
1276              
1277             # Sub to support the "Ev('x'), Ev('y'), etc" syntax that perltk uses to supply event information
1278             # to bind callbacks. This sub-name is exported with the other perltk subs (like MainLoop, etc).
1279             sub Ev {
1280             my @events = @_;
1281             return bless \@events, "Tcl::pTk::Ev";
1282             }
1283              
1284             # Tcl::pTk::break, used to break out of event bindings (i.e. don't process anymore bind subs after break is called).
1285             # This is handled by the wrapper tcl code setup in Tcl::pTk::bind
1286             sub break
1287             {
1288             # Check to see if we are being called from Tcl::pTk::Callback, if so, then this is a valid 'break' call
1289             # and we will die with _TK_BREAK_
1290             my @callInfo;
1291             my $index = 0;
1292             my $callback; # Flag = 1 if this is a callback
1293             while (@callInfo = caller($index)){
1294             #print STDERR "Break Caller = ".join(", ", @callInfo)."\n";
1295             if( $callInfo[3] eq 'Tcl::pTk::Callback::BindCall'){
1296             $callback = 1;
1297             }
1298             $index++;
1299             }
1300              
1301             die "_TK_BREAK_\n" if($callback);
1302            
1303             }
1304              
1305             # Wrappers for the Event Flag subs in Tcl (for compatiblity with perl/tk code
1306             sub DONT_WAIT{ Tcl::DONT_WAIT()};
1307             sub WINDOW_EVENTS{ Tcl::WINDOW_EVENTS()};
1308             sub FILE_EVENTS{ Tcl::FILE_EVENTS()};
1309             sub TIMER_EVENTS{ Tcl::TIMER_EVENTS()};
1310             sub IDLE_EVENTS{ Tcl::IDLE_EVENTS()};
1311             sub ALL_EVENTS{ Tcl::ALL_EVENTS()};
1312              
1313             # Wrappers for the Tk color functions (for compatibility with perl/tk
1314             sub NORMAL_BG{
1315             if($^O eq 'cygwin' || $^O =~ /win32/ ){
1316             return 'systembuttonface';
1317             }
1318             elsif( $^O =~ /darwin/i ){ # MacOS
1319             return 'systemWindowBody';
1320             }
1321             else{ # Must be unix
1322             return '#d9d9d9';
1323             }
1324             }
1325              
1326             sub ACTIVE_BG{
1327             if($^O eq 'cygwin' || $^O =~ /win32/ ){
1328             return 'systembuttonface';
1329             }
1330             elsif( $^O =~ /darwin/i ){ # MacOS
1331             return 'systemButtonFacePressed';
1332             }
1333             else{ # Must be unix
1334             return '#ececec';
1335             }
1336             }
1337              
1338             sub SELECT_BG{
1339             if($^O eq 'cygwin' || $^O =~ /win32/ ){
1340             return 'SystemHighlight';
1341             }
1342             elsif( $^O =~ /darwin/i ){ # MacOS
1343             return 'systemHighlightSecondary';
1344             }
1345             else{ # Must be unix
1346             return '#c3c3c3';
1347             }
1348             }
1349              
1350              
1351             1;