| 1 | # Learn how to write your own widget demonstration. |
| 2 | |
| 3 | use vars qw/$TOP/; |
| 4 | |
| 5 | sub TEMPLATE { |
| 6 | my($demo) = @_; |
| 7 | $TOP = $MW->WidgetDemo( |
| 8 | -name => $demo, |
| 9 | -text => 'Learn how to write a widget demonstration!', |
| 10 | -geometry_manager => 'grid', |
| 11 | -title => 'WidgetDemo Example', |
| 12 | -iconname => 'WidgetDemo', |
| 13 | ); |
| 14 | $TOP->Label(-text => 'Click "See Code".')->grid; |
| 15 | } |
| 16 | __END__ |
| 17 | |
| 18 | The template code above specifies how user contributed widget demonstrations |
| 19 | can be written. |
| 20 | |
| 21 | widget looks in the directory specified on the command line to load user |
| 22 | contributed demonstrations. If no directory name is specified when widget is |
| 23 | invoked and the environment variable WIDTRIB is defined then demonstrations |
| 24 | are loaded from the WIDTRIB directory. If WIDTRIB is undefined then widget |
| 25 | defaults to the released user contributed directory. |
| 26 | |
| 27 | The first line of the file is the DDD (Demonstration Description Data), which |
| 28 | briefly describes the purpose of the demonstration. The widget program reads |
| 29 | this line and uses it when building its interface. |
| 30 | |
| 31 | Demonstrations may have a unique subroutine which is the same as the filename |
| 32 | with .pl stripped off. When widget calls your subroutine it's passed one |
| 33 | argument, the demonstration name. So file TEMPLATE.pl contains subroutine |
| 34 | TEMPLATE(). But a demo can actually be an entire program - read on! |
| 35 | |
| 36 | For consistency your demonstration should use the WidgetDemo widget. This is |
| 37 | a toplevel widget with three frames. The top frame contains descriptive |
| 38 | demonstration text. The bottom frame contains the "Dismiss" and "See Code" |
| 39 | buttons. The middle frame is the demonstration container, which can be |
| 40 | managed by either the pack or grid geometry manager. |
| 41 | |
| 42 | Since your subroutine can "see" all of widget's global variables, you |
| 43 | use $MW (the main window reference) to create the WidgetDemo toplevel; be sure |
| 44 | to pass at least the -name and -text parameters. -geometry_manager defaults |
| 45 | to "pack". The call to WidgetDemo() returns a reference to the containing |
| 46 | frame for your demonstration, so treat it as if it were the MainWindow, the |
| 47 | top-most window of your widget hierarchy. |
| 48 | |
| 49 | Alternatively the .pl file make contain typical Perl/Tk code of the form: |
| 50 | |
| 51 | # Demonstration Description Data |
| 52 | |
| 53 | use Tk; |
| 54 | my $top = MainWindow->new; |
| 55 | $top->Label(-text => 'Whatever'); |
| 56 | MainLoop; |
| 57 | __END__ |
| 58 | |
| 59 | widget has re-defined normal MainWindow to actually create a WidgetDemo |
| 60 | on your code's behalf. MainLoop is optional in a demo (it will immediately |
| 61 | return as MainLoop is already active). |
| 62 | |
| 63 | Other consideration: |
| 64 | |
| 65 | . widget global variables are all uppercase, like $MW - be careful not |
| 66 | to stomp on them! |
| 67 | |
| 68 | . Demo files should really be run in private packages to avoid those |
| 69 | problems. |
| 70 | |
| 71 | . Don't subvert the inheritance mechanism by calling Tk::MainWindow |
| 72 | in your demo code. |
| 73 | |
| 74 | . The description should really be extracted from POD documentation |
| 75 | in the .pl file rather than a magic comment. |
| 76 | |
| 77 | . If your demonstration has a Quit button change it to ring the bell |
| 78 | and use the builtin Dismiss instead. In particular destroying a |
| 79 | MainWindow is acceptable, but exit will shut down widget itself! |
| 80 | |
| 81 | . Be sure $TOP is declared in a "use vars" statement and not as a |
| 82 | lexical my() in the subroutine (see below). |
| 83 | |
| 84 | . If you're wrapping an existing main program in a subroutine be very |
| 85 | alert for closure bugs. Lexicals inside a subroutine become closed |
| 86 | so you may run into initialization problems on the second and |
| 87 | subsequent invokations of the demonstration. The npuz and plop |
| 88 | demonstrations show how to work around this. Essentially, remove |
| 89 | all "global" my() variables and place them within a "use vars". |
| 90 | This practice is prone to subtle bugs and is not recommended! |
| 91 | |
| 92 | |