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