File Coverage

blib/lib/FBP/Perl.pm
Criterion Covered Total %
statement 1336 1466 91.1
branch 365 470 77.6
condition 24 41 58.5
subroutine 165 178 92.7
pod 0 170 0.0
total 1890 2325 81.2


line stmt bran cond sub pod time code
1             package FBP::Perl;
2              
3             =pod
4              
5             =head1 NAME
6              
7             FBP::Perl - Generate Perl GUI code from wxFormBuilder .fbp files
8              
9             =head1 SYNOPSIS
10              
11             my $fbp = FBP->new;
12             $fbp->parse_file( 'MyProject.fbp' );
13            
14             my $generator = FBP::Perl->new(
15             project => $fbp->project
16             );
17            
18             open( FILE, '>', 'MyDialog.pm');
19             print $generator->flatten(
20             $generator->dialog_class(
21             $fbp->dialog('MyDialog')
22             )
23             );
24             close FILE;
25              
26             =head1 DESCRIPTION
27              
28             B is a cross-platform Perl code generator for the cross-platform
29             L GUI designer application.
30              
31             Used with the L module for parsing native wxFormBuilder save files, it
32             allows the production of complete standalone classes representing a complete
33             L dialog, frame or panel as it appears in wxFormBuilder.
34              
35             As code generators go, the Wx code produced by B is remarkebly
36             readable. The produced code can be used either as a starter template which
37             you modify, or as a pristine class which you subclass in order to customise.
38              
39             Born from the L Perl IDE project, the code generation API provided by
40             B is also extremely amenable to being itself subclassed.
41              
42             This allows you to relatively easily write customised code generators that
43             produce output more closely tailored to your large Wx-based application, or
44             to automatically integrate Perl Tidy or other beautifiers into your workflow.
45              
46             =head1 METHODS
47              
48             TO BE COMPLETED
49              
50             =cut
51              
52 11     11   413294 use 5.008005;
  11         45  
  11         476  
53 11     11   64 use strict;
  11         51  
  11         548  
54 11     11   72 use warnings;
  11         22  
  11         341  
55 11     11   76 use B ();
  11         45  
  11         224  
56 11     11   59 use Scalar::Util 1.19 ();
  11         345  
  11         267  
57 11     11   13364 use Params::Util 1.00 ();
  11         69660  
  11         349  
58 11     11   10826 use FBP 0.41 ();
  11         2930776  
  11         173149  
59              
60             our $VERSION = '0.78';
61             our $COMPATIBLE = '0.67';
62              
63             # Event Macro Binding Table
64             our %MACRO = (
65             # Common low level events
66             OnEraseBackground => [ 1, 'EVT_ERASE_BACKGROUND' ],
67             OnPaint => [ 1, 'EVT_PAINT' ],
68             OnUpdateUI => [ 2, 'EVT_UPDATE_UI' ],
69              
70             # wxActivateEvent
71             OnActivate => [ 1, 'EVT_ACTIVATE' ],
72             OnActivateApp => [ 1, 'EVT_ACTIVATE_APP' ],
73              
74             # wxCalendar
75             OnCalendar => [ 2, 'EVT_CALENDAR' ],
76             OnCalendarSelChanged => [ 2, 'EVT_CALENDAR_SEL_CHANGED' ],
77             OnCalendarDay => [ 2, 'EVT_CALENDAR_DAY' ],
78             OnCalendarMonth => [ 2, 'EVT_CALENDAR_MONTH' ],
79             OnCalendarYear => [ 2, 'EVT_CALENDAR_YEAR' ],
80             OnCalendarWeekDayClicked => [ 2, 'EVT_CALENDAR_WEEKDAY_CLICKED' ],
81              
82             # wxChoicebook
83             OnChoicebookPageChanged => [ 2, 'EVT_CHOICEBOOK_PAGE_CHANGED' ],
84             OnChoicebookPageChanging => [ 2, 'EVT_CHOICEBOOK_PAGE_CHANGING' ],
85              
86             # wxCommandEvent
87             OnButtonClick => [ 2, 'EVT_BUTTON' ],
88             OnToggleButton => [ 2, 'EVT_TOGGLEBUTTON' ],
89             OnCheckBox => [ 2, 'EVT_CHECKBOX' ],
90             OnChoice => [ 2, 'EVT_CHOICE' ],
91             OnCombobox => [ 2, 'EVT_COMBOBOX' ],
92             OnListBox => [ 2, 'EVT_LISTBOX' ],
93             OnListBoxDClick => [ 2, 'EVT_LISTBOX_DCLICK' ],
94             OnText => [ 2, 'EVT_TEXT' ],
95             OnTextEnter => [ 2, 'EVT_TEXT_ENTER' ],
96             OnMenu => [ 2, 'EVT_MENU' ],
97              
98             # wxColourPickerCtrl
99             OnColourChanged => [ 2, 'EVT_COLOURPICKER_CHANGED' ],
100              
101             # wxCloseEvent
102             OnClose => [ 1, 'EVT_CLOSE' ],
103              
104             # wxDatePickerCtrl
105             OnDateChanged => [ 2, 'EVT_DATE_CHANGED' ],
106              
107             # wxFilePickerCtrl
108             OnFileChanged => [ 2, 'EVT_FILEPICKER_CHANGED' ],
109              
110             # wxFocusEvent
111             OnKillFocus => [ 1, 'EVT_KILL_FOCUS' ],
112             OnSetFocus => [ 1, 'EVT_SET_FOCUS' ],
113              
114             # wxFontPickerCtrl
115             OnFontChanged => [ 2, 'EVT_FONTPICKER_CHANGED' ],
116              
117             # wxGrid
118             OnGridCellLeftClick => [ 1, 'EVT_GRID_CELL_LEFT_CLICK' ],
119             OnGridCellRightClick => [ 1, 'EVT_GRID_CELL_RIGHT_CLICK' ],
120             OnGridCellLeftDClick => [ 1, 'EVT_GRID_CELL_LEFT_DCLICK' ],
121             OnGridCellRightDClick => [ 1, 'EVT_GRID_CELL_RIGHT_DCLICK' ],
122             OnGridLabelLeftClick => [ 1, 'EVT_GRID_LABEL_LEFT_CLICK' ],
123             OnGridLabelRightClick => [ 1, 'EVT_GRID_LABEL_RIGHT_CLICK' ],
124             OnGridLabelLeftDClick => [ 1, 'EVT_GRID_LABEL_LEFT_DCLICK' ],
125             OnGridLabelRightDClick => [ 1, 'EVT_GRID_LABEL_RIGHT_DCLICK' ],
126             OnGridCellChange => [ 1, 'EVT_GRID_CELL_CHANGE' ],
127             OnGridSelectCell => [ 1, 'EVT_GRID_SELECT_CELL' ],
128             OnGridEditorHidden => [ 1, 'EVT_GRID_EDITOR_HIDDEN' ],
129             OnGridEditorShown => [ 1, 'EVT_GRID_EDITOR_SHOWN' ],
130             OnGridColSize => [ 1, 'EVT_GRID_COL_SIZE' ],
131             OnGridRowSize => [ 1, 'EVT_GRID_ROW_SIZE' ],
132             OnGridRangeSelect => [ 1, 'EVT_GRID_RANGE_SELECT' ],
133             OnGridEditorCreated => [ 1, 'EVT_GRID_EDITOR_CREATED' ],
134              
135             # Not sure why wxFormBuilder makes these grid event duplicates
136             # so we just slavishly cargo cult what they do in the C code.
137             OnGridCmdCellLeftClick => [ 1, 'EVT_GRID_CELL_LEFT_CLICK' ],
138             OnGridCmdCellRightClick => [ 1, 'EVT_GRID_CELL_RIGHT_CLICK' ],
139             OnGridCmdCellLeftDClick => [ 1, 'EVT_GRID_CELL_LEFT_DCLICK' ],
140             OnGridCmdCellRightDClick => [ 1, 'EVT_GRID_CELL_RIGHT_DCLICK' ],
141             OnGridCmdLabelLeftClick => [ 1, 'EVT_GRID_LABEL_LEFT_CLICK' ],
142             OnGridCmdLabelRightClick => [ 1, 'EVT_GRID_LABEL_RIGHT_CLICK' ],
143             OnGridCmdLabelLeftDClick => [ 1, 'EVT_GRID_LABEL_LEFT_DCLICK' ],
144             OnGridCmdLabelRightDClick => [ 1, 'EVT_GRID_LABEL_RIGHT_DCLICK' ],
145             OnGridCmdCellChange => [ 1, 'EVT_GRID_CELL_CHANGE' ],
146             OnGridCmdSelectCell => [ 1, 'EVT_GRID_SELECT_CELL' ],
147             OnGridCmdEditorHidden => [ 1, 'EVT_GRID_EDITOR_HIDDEN' ],
148             OnGridCmdEditorShown => [ 1, 'EVT_GRID_EDITOR_SHOWN' ],
149             OnGridCmdColSize => [ 1, 'EVT_GRID_COL_SIZE' ],
150             OnGridCmdRowSize => [ 1, 'EVT_GRID_ROW_SIZE' ],
151             OnGridCmdRangeSelect => [ 1, 'EVT_GRID_RANGE_SELECT' ],
152             OnGridCmdEditorCreated => [ 1, 'EVT_GRID_EDITOR_CREATED' ],
153              
154             # wxHtmlWindow
155             OnHtmlCellClicked => [ 2, 'EVT_HTML_CELL_CLICKED' ],
156             OnHtmlCellHover => [ 2, 'EVT_HTML_CELL_HOVER' ],
157             OnHtmlLinkClicked => [ 2, 'EVT_HTML_LINK_CLICKED' ],
158              
159             # wxIconizeEvent
160             OnIconize => [ 1, 'EVT_ICONIZE' ],
161              
162             # wxIdleEvent
163             OnIdle => [ 1, 'EVT_IDLE' ],
164              
165             # wxInitDialogEvent
166             OnInitDialog => [ 1, 'EVT_INIT_DIALOG' ],
167              
168             # wxKeyEvent
169             OnChar => [ 1, 'EVT_CHAR' ],
170             OnKeyDown => [ 1, 'EVT_KEY_DOWN' ],
171             OnKeyUp => [ 1, 'EVT_KEY_UP' ],
172              
173             # wxListEvent
174             OnListBeginDrag => [ 2, 'EVT_LIST_BEGIN_DRAG' ],
175             OnListBeginRDrag => [ 2, 'EVT_LIST_BEGIN_RDRAG' ],
176             OnListBeginLabelEdit => [ 2, 'EVT_LIST_BEGIN_LABEL_EDIT' ],
177             OnListCacheHint => [ 2, 'EVT_LIST_CACHE_HINT' ],
178             OnListEndLabelEdit => [ 2, 'EVT_LIST_END_LABEL_EDIT' ],
179             OnListDeleteItem => [ 2, 'EVT_LIST_DELETE_ITEM' ],
180             OnListDeleteAllItems => [ 2, 'EVT_LIST_DELETE_ALL_ITEMS' ],
181             OnListInsertItem => [ 2, 'EVT_LIST_INSERT_ITEM' ],
182             OnListItemActivated => [ 2, 'EVT_LIST_ITEM_ACTIVATED' ],
183             OnListItemSelected => [ 2, 'EVT_LIST_ITEM_SELECTED' ],
184             OnListItemDeselected => [ 2, 'EVT_LIST_ITEM_DESELECTED' ],
185             OnListItemFocused => [ 2, 'EVT_LIST_ITEM_FOCUSED' ],
186             OnListItemMiddleClick => [ 2, 'EVT_LIST_MIDDLE_CLICK' ],
187             OnListItemRightClick => [ 2, 'EVT_LIST_RIGHT_CLICK' ],
188             OnListKeyDown => [ 2, 'EVT_LIST_KEY_DOWN' ],
189             OnListColClick => [ 2, 'EVT_LIST_COL_CLICK' ],
190             OnListColRightClick => [ 2, 'EVT_LIST_COL_RIGHT_CLICK' ],
191             OnListColBeginDrag => [ 2, 'EVT_LIST_COL_BEGIN_DRAG' ],
192             OnListColDragging => [ 2, 'EVT_LIST_COL_DRAGGING' ],
193             OnListColEndDrag => [ 2, 'EVT_LIST_COL_END_DRAG' ],
194              
195             # wxMenuEvent
196             OnMenuSelection => [ 2, 'EVT_MENU' ],
197              
198             # wxMouseEvent
199             OnEnterWindow => [ 1, 'EVT_ENTER_WINDOW' ],
200             OnLeaveWindow => [ 1, 'EVT_LEAVE_WINDOW' ],
201             OnLeftDClick => [ 1, 'EVT_LEFT_DCLICK' ],
202             OnLeftDown => [ 1, 'EVT_LEFT_DOWN' ],
203             OnLeftUp => [ 1, 'EVT_LEFT_UP' ],
204             OnMiddleDClick => [ 1, 'EVT_MIDDLE_DCLICK' ],
205             OnMiddleDown => [ 1, 'EVT_MIDDLE_DOWN' ],
206             OnMiddleUp => [ 1, 'EVT_MIDDLE_UP' ],
207             OnMotion => [ 1, 'EVT_MOTION' ],
208             OnMouseEvents => [ 1, 'EVT_MOUSE_EVENTS' ],
209             OnMouseWheel => [ 1, 'EVT_MOUSEWHEEL' ],
210             OnRightDClick => [ 1, 'EVT_RIGHT_DCLICK' ],
211             OnRightDown => [ 1, 'EVT_RIGHT_DOWN' ],
212             OnRightUp => [ 1, 'EVT_RIGHT_UP' ],
213              
214             # wxNotebookEvent
215             OnNotebookPageChanging => [ 2, 'EVT_NOTEBOOK_PAGE_CHANGING' ],
216             OnNotebookPageChanged => [ 2, 'EVT_NOTEBOOK_PAGE_CHANGED' ],
217              
218             # wxRadioBox
219             OnRadioBox => [ 2, 'EVT_RADIOBOX' ],
220              
221             # wxRadioButton
222             OnRadioButton => [ 2, 'EVT_RADIOBUTTON' ],
223              
224             # wxSizeEvent
225             OnSize => [ 1, 'EVT_SIZE' ],
226              
227             # wxStdDialogButtonSizer (placeholders)
228             OnOKButtonClick => [ ],
229             OnYesButtonClick => [ ],
230             OnSaveButtonClick => [ ],
231             OnApplyButtonClick => [ ],
232             OnNoButtonClick => [ ],
233             OnCancelButtonClick => [ ],
234             OnHelpButtonClick => [ ],
235             OnContextTextButtonClick => [ ],
236              
237             # wxSearchCtrl
238             OnSearchButton => [ 2, 'EVT_SEARCHCTRL_SEARCH_BTN' ],
239             OnCancelButton => [ 2, 'EVT_SEARCHCTRL_CANCEL_BTN' ],
240              
241             # wxSpinButton
242             OnSpin => [ 1, 'EVT_SCROLL_THUMBTRACK' ],
243             OnSpinUp => [ 1, 'EVT_SCROLL_LINEUP' ],
244             OnSpinDown => [ 1, 'EVT_SCROLL_LINEDOWN' ],
245              
246             # wxSplitterEvent
247             OnSplitterSashPosChanging => [ 2, 'EVT_SPLITTER_SASH_POS_CHANGING' ],
248             OnSplitterSashPosChanged => [ 2, 'EVT_SPLITTER_SASH_POS_CHANGED' ],
249             OnSplitterUnsplit => [ 2, 'EVT_SPLITTER_UNSPLIT' ],
250             OnSplitterDClick => [ 2, 'EVT_SPLITTER_DCLICK' ],
251              
252             # wxToolbar events
253             OnToolClicked => [ 2, 'EVT_TOOL' ],
254             OnToolRClicked => [ 2, 'EVT_TOOL_RCLICKED' ],
255             OnToolEnter => [ 2, 'EVT_TOOL_ENTER' ],
256              
257             # wxTreeCtrl events
258             OnTreeGetInfo => [ 2, 'EVT_TREE_GET_INFO' ],
259             OnTreeSetInfo => [ 2, 'EVT_TREE_SET_INFO' ],
260             OnTreeItemGetTooltip => [ 2, 'EVT_TREE_ITEM_GETTOOLTIP' ],
261             OnTreeStateImageClick => [ 2, 'EVT_TREE_STATE_IMAGE_CLICK' ],
262             OnTreeBeginDrag => [ 2, 'EVT_TREE_BEGIN_DRAG' ],
263             OnTreeBeginRDrag => [ 2, 'EVT_TREE_BEGIN_RDRAG' ],
264             OnTreeEndDrag => [ 2, 'EVT_TREE_END_DRAG' ],
265             OnTreeBeginLabelEdit => [ 2, 'EVT_TREE_BEGIN_LABEL_EDIT' ],
266             OnTreeEndLabelEdit => [ 2, 'EVT_TREE_END_LABEL_EDIT' ],
267             OnTreeItemActivated => [ 2, 'EVT_TREE_ITEM_ACTIVATED' ],
268             OnTreeItemCollapsed => [ 2, 'EVT_TREE_ITEM_COLLAPSED' ],
269             OnTreeItemCollapsing => [ 2, 'EVT_TREE_ITEM_COLLAPSING' ],
270             OnTreeItemExpanded => [ 2, 'EVT_TREE_ITEM_EXPANDED' ],
271             OnTreeItemExpanding => [ 2, 'EVT_TREE_ITEM_EXPANDING' ],
272             OnTreeItemRightClick => [ 2, 'EVT_TREE_ITEM_RIGHT_CLICK' ],
273             OnTreeItemMiddleClick => [ 2, 'EVT_TREE_ITEM_MIDDLE_CLICK' ],
274             OnTreeSelChanged => [ 2, 'EVT_TREE_SEL_CHANGED' ],
275             OnTreeSelChanging => [ 2, 'EVT_TREE_SEL_CHANGING' ],
276             OnTreeKeyDown => [ 2, 'EVT_TREE_KEY_DOWN' ],
277             OnTreeItemMenu => [ 2, 'EVT_TREE_ITEM_MENU' ],
278             );
279              
280             # Event Connect Binding Table
281             our %CONNECT = (
282             # Common low level events
283             # OnEraseBackground => 'wxEVT_ERASE_BACKGROUND',
284             # OnPaint => 'wxEVT_PAINT',
285             # OnUpdateUI => 'wxEVT_UPDATE_UI',
286              
287             # # wxActivateEvent
288             # OnActivate => 'wxEVT_ACTIVATE',
289             # OnActivateApp => 'wxEVT_ACTIVATE_APP',
290              
291             # # wxCalendar
292             # OnCalendar => 'wxEVT_CALENDAR_DOUBLECLICKED',
293             # OnCalendarSelChanged => 'wxEVT_CALENDAR_SEL_CHANGED',
294             # OnCalendarDay => 'wxEVT_CALENDAR_DAY_CHANGED',
295             # OnCalendarMonth => 'wxEVT_CALENDAR_MONTH_CHANGED',
296             # OnCalendarYear => 'wxEVT_CALENDAR_YEAR_CHANGED',
297             # OnCalendarWeekDayClicked => 'wxEVT_CALENDAR_WEEKDAY_CLICKED',
298              
299             # # wxChoicebook
300             # OnChoicebookPageChanged => 'wxEVT_COMMAND_CHOICEBOOK_PAGE_CHANGED',
301             # OnChoicebookPageChanging => 'wxEVT_COMMAND_CHOICEBOOK_PAGE_CHANGING',
302              
303             # # wxCommandEvent
304             # OnButtonClick => 'wxEVT_COMMAND_BUTTON_CLICKED',
305             # OnCheckBox => 'wxEVT_COMMAND_CHECKBOX_CLICKED',
306             # OnChoice => 'wxEVT_COMMAND_CHOICE_SELECTED',
307             # OnCombobox => 'wxEVT_COMMAND_COMBOBOX_SELECTED',
308             # OnListBox => 'wxEVT_COMMAND_LISTBOX_SELECTED',
309             # OnListBoxDClick => 'wxEVT_COMMAND_LISTBOX_DOUBLECLICKED',
310             # OnText => 'wxEVT_COMMAND_TEXT_UPDATED',
311             # OnTextEnter => 'wxEVT_COMMAND_TEXT_ENTER',
312             # OnMenu => 'wxEVT_COMMAND_MENU_SELECTED',
313              
314             # # wxColourPickerCtrl
315             # OnColourChanged => 'wxEVT_COLOURPICKER_CHANGED',
316              
317             # # wxCloseEvent
318             # OnClose => 'wxEVT_CLOSE_WINDOW',
319              
320             # # wxDatePickerCtrl
321             # OnDateChanged => 'wxEVT_DATE_CHANGED',
322              
323             # # wxFilePickerCtrl
324             # OnFileChanged => 'wxEVT_FILEPICKER_CHANGED',
325              
326             # # wxFocusEvent
327             # OnKillFocus => 'wxEVT_KILL_FOCUS',
328             # OnSetFocus => 'wxEVT_SET_FOCUS',
329              
330             # # wxFontPickerCtrl
331             # OnFontChanged => 'wxEVT_FONTPICKER_CHANGED',
332             );
333              
334              
335              
336              
337              
338             ######################################################################
339             # Constructor
340              
341             sub new {
342 10     10 0 30112378 my $class = shift;
343 10         91 my $self = bless { @_ }, $class;
344              
345             # Check params and apply defaults
346 10 50       57 unless ( Params::Util::_INSTANCE($self->project, 'FBP::Project') ) {
347 0         0 die "Missing or invalid 'project' param";
348             }
349 10 50       50 unless ( defined $self->version ) {
350 0         0 $self->{version} = '0.01';
351             }
352 10 50       38 unless ( defined Params::Util::_STRING($self->version) ) {
353 0         0 die "Missing or invalid 'version' param";
354             }
355 10 100       57 unless ( defined $self->prefix ) {
356 7         23 $self->{prefix} = 0;
357             }
358 10 50       40 unless ( defined Params::Util::_NONNEGINT($self->prefix) ) {
359 0         0 die "Missing of invalid 'prefix' param";
360             }
361 10 100       163 unless ( defined $self->i18n ) {
362 9         36 $self->{i18n} = $self->project->internationalize;
363             }
364 10 100       49 unless ( defined $self->i18n_trim ) {
365 9         30 $self->{i18n_trim} = 0;
366             }
367 10 100       57 $self->{i18n_trim} = $self->i18n_trim ? 1 : 0;
368 10 100       46 unless ( defined $self->nocritic ) {
369 3         7 $self->{nocritic} = 0;
370             }
371 10 100       42 $self->{nocritic} = $self->nocritic ? 1 : 0;
372 10 100       45 $self->{shim} = $self->shim ? 1 : 0;
373 10 100       48 $self->{shim_deep} = $self->shim_deep ? 1 : 0;
374 10 100       36 $self->{shim_deep} = 0 unless $self->shim;
375              
376 10         38 return $self;
377             }
378              
379             sub project {
380 176     176 0 1307 $_[0]->{project};
381             }
382              
383             sub version {
384 29     29 0 211 $_[0]->{version};
385             }
386              
387             sub prefix {
388 365     365 0 1470 $_[0]->{prefix};
389             }
390              
391             sub i18n {
392 87     87 0 2409 $_[0]->{i18n};
393             }
394              
395             sub i18n_trim {
396 81     81 0 299 $_[0]->{i18n_trim};
397             }
398              
399             sub nocritic {
400 29     29 0 132 $_[0]->{nocritic};
401             }
402              
403             sub shim {
404 33     33 0 153 $_[0]->{shim};
405             }
406              
407             sub shim_deep {
408 10     10 0 54 $_[0]->{shim_deep};
409             }
410              
411              
412              
413              
414              
415             ######################################################################
416             # Project Wide Generators
417              
418             sub project_header {
419 9     9 0 19 my $self = shift;
420 9         22 my $lines = [];
421              
422             # If the code is being generated for use in a project that uses
423             # Perl::Critic then we could generate all kinds of critic warnings the
424             # maintainer can't do anything about it. So we nocritic the whole file.
425 9 100       29 if ( $self->nocritic ) {
426 6         16 push @$lines, (
427             "## no critic",
428             );
429             }
430              
431             # Add an extra spacer line if needed
432 9 100       42 if ( @$lines ) {
433 6         13 push @$lines, "";
434             }
435              
436 9         27 return $lines;
437             }
438              
439             sub project_pragma {
440 9     9 0 48 my $self = shift;
441 9         52 my $perl = $self->project_perl;
442             return [
443 9 50       48 "use $perl;",
444             ( $self->project_utf8 ? "use utf8;" : () ),
445             "use strict;",
446             "use warnings;",
447             ]
448             }
449              
450             sub project_version {
451 9     9 0 19 my $self = shift;
452 9         36 my $version = $self->version;
453              
454             return [
455 9         50 "our \$VERSION = '$version';",
456             ];
457             }
458              
459             sub project_perl {
460 9     9 0 21 my $self = shift;
461 9 50       40 return $self->project_utf8 ? '5.008005' : '5.008';
462             }
463              
464             sub project_utf8 {
465 133     133 0 186 my $self = shift;
466 133         295 return $self->project->encoding eq 'UTF-8';
467             }
468              
469              
470              
471              
472              
473             ######################################################################
474             # Launch Script Generator
475              
476             sub script_app {
477 1     1 0 1259 my $self = shift;
478 1         6 my $header = $self->script_header;
479 1         5 my $pragma = $self->script_pragma;
480 1         6 my $package = $self->app_package;
481 1         5 my $version = $self->script_version;
482              
483             return [
484 1         13 "#!/usr/bin/perl",
485             "",
486             @$header,
487             @$pragma,
488             "use $package ();",
489             "",
490             @$version,
491             "",
492             "$package->run;",
493             "",
494             "exit(0);",
495             ];
496             }
497              
498             sub script_header {
499 1     1 0 52 shift->project_header(@_);
500             }
501              
502             sub script_pragma {
503 1     1 0 5 shift->project_pragma(@_);
504             }
505              
506             sub script_version {
507 1     1 0 5 $_[0]->project_version;
508             }
509              
510              
511              
512              
513              
514             ######################################################################
515             # Wx::App Generators
516              
517             sub app_class {
518 1     1 0 768 my $self = shift;
519 1         8 my $package = $self->app_package;
520 1         7 my $header = $self->app_header;
521 1         5 my $pragma = $self->app_pragma;
522 1         5 my $wx = $self->app_wx;
523 1         6 my $forms = $self->app_forms;
524 1         5 my $version = $self->app_version;
525 1         5 my $isa = $self->app_isa;
526              
527             # Find the first frame, our default top frame
528 1         4 my $frame = $self->project->find_first( isa => 'FBP::Frame' );
529 1 50       11495 my $require = $self->shim
530             ? $self->shim_package($frame)
531             : $self->form_package($frame);
532              
533             return [
534 1         18 "package $package;",
535             "",
536             @$header,
537             @$pragma,
538             @$wx,
539             # @$forms,
540             "",
541             @$version,
542             @$isa,
543             "",
544             "sub run {",
545             $self->indent(
546             "my \$class = shift;",
547             "my \$self = \$class->new(\@_);",
548             "return \$self->MainLoop;",
549             ),
550             "}",
551             "",
552             "sub OnInit {",
553             $self->indent(
554             "my \$self = shift;",
555             "",
556             "# Create the primary frame",
557             "require $require;",
558             "\$self->SetTopWindow( $require->new );",
559             "",
560             "# Don't flash frames on the screen in tests",
561             "unless ( \$ENV{HARNESS_ACTIVE} ) {",
562             $self->indent(
563             "\$self->GetTopWindow->Show(1);",
564             ),
565             "}",
566             "",
567             "return 1;",
568             ),
569             "}",
570             "",
571             "1;"
572             ];
573             }
574              
575             # For the time being just use the plain name
576             sub app_package {
577 5     5 0 59 my $self = shift;
578              
579             # Use the C++ namespace setting if we can
580 5 100       19 if ( $self->project->namespace ) {
581 3         10 return join '::', $self->list( $self->project->namespace );
582             }
583              
584             # Fall back to the plain name
585 2         7 return $self->project->name;
586             }
587              
588             sub app_header {
589 1     1 0 8 shift->project_header(@_);
590             }
591              
592             sub app_pragma {
593 1     1 0 6 shift->project_pragma(@_);
594             }
595              
596             sub app_wx {
597 1     1 0 2 my $self = shift;
598 1         4 my $project = $self->project;
599 1         4 my @lines = (
600             "use Wx 0.98 ':everything';",
601             );
602 1 50       5 if ( $project->find_first( isa => 'FBP::HtmlWindow' ) ) {
603 1         3489 push @lines, "use Wx::Html ();";
604             }
605 1 50       5 if ( $project->find_first( isa => 'FBP::DatePickerCtrl' ) ) {
606 0         0 push @lines, "use Wx::DateTime ();";
607             }
608 1 50       12932 if ( $self->i18n ) {
609 1         4 push @lines, "use Wx::Locale ();";
610             }
611 1         7 return \@lines;
612             }
613              
614             sub app_forms {
615 1     1 0 4 my $self = shift;
616 1         7 my @forms = $self->project->forms;
617 0         0 my @names = $self->shim
618 3         10 ? ( map { $self->shim_package($_) } @forms )
619 1 50       170 : ( map { $self->form_package($_) } @forms );
620              
621             return [
622 3         15 map {
623 1         5 "use $_ ();"
624             } @names
625             ];
626             }
627              
628             sub app_version {
629 1     1 0 6 shift->project_version(@_);
630             }
631              
632             sub app_isa {
633 1     1 0 4 my $self = shift;
634 1         5 return $self->ourisa(
635             $self->app_super(@_)
636             );
637             }
638              
639             sub app_super {
640 1     1 0 8 return 'Wx::App';
641             }
642              
643              
644              
645              
646              
647             ######################################################################
648             # Shim Generators
649              
650             sub shim_class {
651 0     0 0 0 my $self = shift;
652 0         0 my $form = shift;
653 0         0 my $package = $self->shim_package($form);
654 0         0 my $header = $self->shim_header($form);
655 0         0 my $pragma = $self->shim_pragma($form);
656 0         0 my $more = $self->shim_more($form);
657 0         0 my $version = $self->shim_version($form);
658 0         0 my $isa = $self->shim_isa($form);
659              
660             return [
661 0         0 "package $package;",
662             "",
663             @$header,
664             @$pragma,
665             @$more,
666             "",
667             @$version,
668             @$isa,
669             "",
670             "1;",
671             ];
672             }
673              
674             sub shim_package {
675 0     0 0 0 my $self = shift;
676 0         0 my $form = shift;
677 0         0 my $name = $form->name;
678              
679             # If the project has a namespace nest the name inside it
680 0 0       0 if ( $self->project->namespace ) {
681 0 0       0 if ( $self->shim_deep ) {
682 0         0 my $type = Scalar::Util::blessed($form);
683 0         0 $type =~ s/^.*?(\w+)$/$1/;
684 0         0 $name = join '::', $type, $name;
685             }
686 0         0 $name = join '::', $self->app_package, $name;
687             }
688              
689             # Otherwise the name is the full namespace
690 0         0 return $name;
691             }
692              
693             sub shim_header {
694 0     0 0 0 shift->project_header(@_);
695             }
696              
697             sub shim_pragma {
698 0     0 0 0 shift->project_pragma(@_);
699             }
700              
701             sub shim_more {
702 0     0 0 0 my $self = shift;
703 0         0 my $form = shift;
704              
705             # We only need to load our super class
706 0         0 my $super = $self->form_package($form);
707              
708             return [
709 0         0 "use $super ();",
710             ];
711             }
712              
713             sub shim_version {
714 0     0 0 0 my $self = shift;
715 0         0 my $form = shift;
716              
717             # Ignore the form and inherit from the parent project
718 0         0 return $self->project_version;
719             }
720              
721             sub shim_isa {
722 0     0 0 0 my $self = shift;
723 0         0 return $self->ourisa(
724             $self->shim_super(@_)
725             );
726             }
727              
728             sub shim_super {
729 0     0 0 0 shift->form_package(@_);
730             }
731              
732              
733              
734              
735              
736             ######################################################################
737             # Form Generators
738              
739             sub form_class {
740 7     7 0 4747 my $self = shift;
741 7         72 my $form = shift;
742 7         192 my $package = $self->form_package($form);
743 7         34 my $header = $self->form_header($form);
744 7         34 my $pragma = $self->form_pragma($form);
745 7         39 my $wx = $self->form_wx($form);
746 7         36 my $more = $self->form_custom($form);
747 7         113 my $version = $self->form_version($form);
748 7         50 my $isa = $self->form_isa($form);
749 7         37 my $new = $self->form_new($form);
750 7         245 my $methods = $self->form_methods($form);
751              
752             return [
753 7         529 "package $package;",
754             "",
755             @$header,
756             @$pragma,
757             @$wx,
758             @$more,
759             "",
760             @$version,
761             @$isa,
762             "",
763             @$new,
764             @$methods,
765             "",
766             "1;",
767             ];
768             }
769              
770             sub dialog_class {
771 2     2 0 1452 shift->form_class(@_);
772             }
773              
774             sub frame_class {
775 1     1 0 1686 shift->form_class(@_);
776             }
777              
778             sub panel_class {
779 1     1 0 1298 shift->form_class(@_);
780             }
781              
782             sub form_package {
783 11     11 0 23 my $self = shift;
784 11         22 my $form = shift;
785              
786 11 100       39 unless ( $self->project->namespace ) {
787             # A simple standalone full namespace
788 8 50       24 if ( $self->shim ) {
789 0         0 return join '::', $form->name, 'FBP';
790             } else {
791 8         54 return $form->name;
792             }
793             }
794              
795             # Nest the name inside the project namespace
796 3 100       12 if ( $self->shim ) {
797 2         11 return join(
798             '::',
799             $self->app_package,
800             'FBP',
801             $form->name,
802             );
803             } else {
804 1         6 return join(
805             '::',
806             $self->app_package,
807             $form->name,
808             );
809             }
810             }
811              
812             sub form_header {
813 7     7 0 33 shift->project_header(@_);
814             }
815              
816             sub form_pragma {
817 7     7 0 34 shift->project_pragma(@_);
818             }
819              
820             sub form_wx {
821 7     7 0 14 my $self = shift;
822 7         12 my $topic = shift;
823 7         21 my $lines = [
824             "use Wx 0.98 ':everything';",
825             ];
826 7 50       37 if ( $self->find_plain( $topic => 'FBP::HtmlWindow' ) ) {
827 0         0 push @$lines, "use Wx::Html ();";
828             }
829 7 100       5009 if ( $self->find_plain( $topic => 'FBP::Grid' ) ) {
830 1         5 push @$lines, "use Wx::Grid ();";
831             }
832 7 100       4325 if ( $self->find_plain( $topic => 'FBP::CalendarCtrl' ) ) {
    50          
833 1         5 push @$lines, "use Wx::Calendar ();";
834 1         4 push @$lines, "use Wx::DateTime ();";
835             } elsif ( $self->find_plain( $topic => 'FBP::DatePickerCtrl' ) ) {
836 0         0 push @$lines, "use Wx::DateTime ();";
837             }
838 7 100       4504 if ( $self->find_plain( $topic => 'FBP::RichTextCtrl' ) ) {
839 1         6 push @$lines, "use Wx::RichText ();";
840             }
841 7         4585 return $lines;
842             }
843              
844             sub form_custom {
845 7     7 0 16 my $self = shift;
846 7         15 my $form = shift;
847              
848             # Search for all the custom classes and load them
849 7         20 my %seen = ();
850             return [
851 3         17 map {
852 3         43 "use $_ ();"
853             } sort grep {
854 90         18621 not $seen{$_}++
855             } map {
856 7         41 $_->header
857             } $form->find( isa => 'FBP::Window' )
858             ];
859             }
860              
861             sub form_version {
862 7     7 0 17 my $self = shift;
863 7         14 my $form = shift;
864              
865             # Ignore the form and inherit from the parent project
866 7         35 return $self->project_version;
867             }
868              
869             sub form_isa {
870 7     7 0 17 my $self = shift;
871 7         35 return $self->ourisa(
872             $self->form_super(@_)
873             );
874             }
875              
876             sub form_super {
877 7     7 0 14 my $self = shift;
878 7         19 my $form = shift;
879 7 100       92 if ( $form->isa('FBP::Dialog') ) {
    100          
    50          
880 1         6 return 'Wx::Dialog';
881             } elsif ( $form->isa('FBP::Frame') ) {
882 4         23 return 'Wx::Frame';
883             } elsif ( $form->isa('FBP::Panel') ) {
884 2         14 return 'Wx::Panel';
885             } else {
886 0         0 die "Unsupported form " . ref($form);
887             }
888             }
889              
890             sub form_new {
891 7     7 0 14 my $self = shift;
892 7         15 my $form = shift;
893 7         31 my $super = $self->form_supernew($form);
894 7         41 my @windows = $self->children_create($form);
895 7         49 my @sizers = $self->form_sizers($form);
896 7         55 my $status = $form->find_first( isa => 'FBP::StatusBar' );
897              
898 7         12439 my @lines = ();
899 7 50       38 if ( $self->form_setsizehints($form) ) {
900 0         0 my $minsize = $self->wxsize($form->minimum_size);
901 0         0 my $maxsize = $self->wxsize($form->maximum_size);
902 0         0 push @lines, "\$self->SetSizeHints( $minsize, $maxsize );";
903             }
904 7 100       43 if ( $status ) {
905 1         5 my $statusbar = $self->statusbar_create($status, $form);
906 1         5 push @lines, @$statusbar;
907             }
908              
909             # Add common modifications
910 7         31 push @lines, $self->window_changes($form);
911 7         31 push @lines, $self->object_bindings($form);
912              
913 92         404 return $self->nested(
914             "sub new {",
915             "my \$class = shift;",
916             "my \$parent = shift;",
917             "",
918             $super,
919             @lines,
920             "",
921 92         130 ( map { @$_, "" } grep { scalar @$_ } @windows ),
  52         184  
922 7         85 ( map { @$_, "" } grep { scalar @$_ } @sizers ),
  52         80  
923             "return \$self;",
924             "}",
925             );
926             }
927              
928             sub form_supernew {
929 7     7 0 14 my $self = shift;
930 7         15 my $form = shift;
931 7         15 my $lines = undef;
932              
933 7 100       79 if ( $form->isa('FBP::Dialog') ) {
    100          
    50          
934 1         5 $lines = $self->dialog_supernew($form);
935             } elsif ( $form->isa('FBP::Frame') ) {
936 4         23 $lines = $self->frame_supernew($form);
937             } elsif ( $form->isa('FBP::Panel') ) {
938 2         10 $lines = $self->panel_supernew($form);
939             } else {
940 0         0 die "Unsupported top class " . ref($form);
941             }
942              
943 7         28 return $lines;
944             }
945              
946             sub dialog_supernew {
947 1     1 0 4 my $self = shift;
948 1         3 my $dialog = shift;
949 1         6 my $id = $self->object_id($dialog);
950 1         9 my $title = $self->text( $dialog->title );
951 1         6 my $position = $self->object_position($dialog);
952 1         5 my $size = $self->object_wxsize($dialog);
953              
954 1         11 return $self->nested(
955             "my \$self = \$class->SUPER::new(",
956             "\$parent,",
957             "$id,",
958             "$title,",
959             "$position,",
960             "$size,",
961             $self->window_style($dialog, 'wxDEFAULT_DIALOG_STYLE'),
962             ");",
963             );
964             }
965              
966             sub frame_supernew {
967 4     4 0 7 my $self = shift;
968 4         6 my $frame = shift;
969 4         19 my $id = $self->object_id($frame);
970 4         29 my $title = $self->text( $frame->title );
971 4         21 my $position = $self->object_position($frame);
972 4         18 my $size = $self->object_wxsize($frame);
973              
974 4         35 return $self->nested(
975             "my \$self = \$class->SUPER::new(",
976             "\$parent,",
977             "$id,",
978             "$title,",
979             "$position,",
980             "$size,",
981             $self->window_style($frame, 'wxDEFAULT_FRAME_STYLE'),
982             ");",
983             );
984             }
985              
986             sub panel_supernew {
987 2     2 0 6 my $self = shift;
988 2         5 my $panel = shift;
989 2         11 my $id = $self->object_id($panel);
990 2         11 my $position = $self->object_position($panel);
991 2         11 my $size = $self->object_wxsize($panel);
992              
993 2         16 return $self->nested(
994             "my \$self = \$class->SUPER::new(",
995             "\$parent,",
996             "$id,",
997             "$position,",
998             "$size,",
999             $self->window_style($panel),
1000             ");",
1001             );
1002             }
1003              
1004             sub form_sizers {
1005 7     7 0 37 my $self = shift;
1006 7         20 my $form = shift;
1007 7         31 my $sizer = $self->form_rootsizer($form);
1008 7         25 my $variable = $self->object_variable($sizer);
1009 7         41 my @children = $self->sizer_pack($sizer);
1010 7         42 my $setsize = $self->window_setsize($form);
1011              
1012             return (
1013 7         65 @children,
1014             [
1015             "\$self->$setsize($variable);",
1016             "\$self->Layout;",
1017             ]
1018             );
1019             }
1020              
1021             sub form_rootsizer {
1022 7     7 0 14 my $self = shift;
1023 7         15 my $form = shift;
1024 7         14 my @sizers = grep { $_->isa('FBP::Sizer') } @{$form->children};
  10         59  
  7         36  
1025 7 50       43 unless ( @sizers ) {
1026 0         0 die "Form does not contain any sizers";
1027             }
1028 7 50       60 unless ( @sizers == 1 ) {
1029 0         0 die "Form contains more than one root sizer";
1030             }
1031 7         22 return $sizers[0];
1032             }
1033              
1034             sub form_setsizehints {
1035 7     7 0 23 my $self = shift;
1036 7         14 my $form = shift;
1037              
1038             # Only dialogs and frames can resize
1039 7 100 100     192 if ( $form->isa('FBP::Dialog') or $form->isa('FBP::Frame') ) {
1040             # If the dialog has size hints, we do need them
1041 5 50       142 if ( $self->size($form->minimum_size) ) {
1042 0         0 return 1;
1043             }
1044 5 50       46 if ( $self->size($form->maximum_size) ) {
1045 0         0 return 1;
1046             }
1047             }
1048              
1049 7         35 return 0;
1050             }
1051              
1052             sub form_methods {
1053 7     7 0 43 my $self = shift;
1054 7         14 my $form = shift;
1055 7         50 my @objects = (
1056             $form,
1057             $form->find( isa => 'FBP::Window' ),
1058             $form->find( isa => 'FBP::MenuItem' ),
1059             $form->find( isa => 'FBP::StdDialogButtonSizer' ),
1060             );
1061 7         37876 my %seen = ();
1062 7         17 my %done = ();
1063 7         28 my @methods = ();
1064              
1065             # Add the accessor methods
1066 7         18 foreach my $object ( @objects ) {
1067 100 50       338 next unless $object->can('name');
1068 100 50       403 next unless $object->can('permission');
1069 100 100       325 next unless $object->permission eq 'public';
1070              
1071             # Protect against duplicates
1072 1         5 my $name = $object->name;
1073 1 50       8 if ( $seen{$name}++ ) {
1074 0         0 die "Duplicate method '$name' detected";
1075             }
1076              
1077 1         11 push @methods, $self->object_accessor($object);
1078             }
1079              
1080             # Add the event handler methods
1081 7         21 foreach my $object ( @objects ) {
1082 100         8451 foreach my $event ( sort keys %MACRO ) {
1083 15100 100       43338 next unless $object->can($event);
1084              
1085 2420         4576 my $name = $object->name;
1086 2420         4946 my $method = $object->$event();
1087 2420 100       5140 next unless defined $method;
1088 28 50       170 next unless length $method;
1089              
1090             # Protect against duplicates
1091 28 50       87 if ( $seen{$method} ) {
1092 0         0 die "Duplicate method '$method' detected";
1093             }
1094 28 100       136 next if $done{$method}++;
1095              
1096 26         126 push @methods, $self->object_event($object, $event);
1097             }
1098             }
1099              
1100             # Convert back to a single block of lines
1101             return [
1102 7         28 map { ( "", @$_ ) } grep { scalar @$_ } @methods
  27         134  
  27         48  
1103             ];
1104             }
1105              
1106              
1107              
1108              
1109              
1110             ######################################################################
1111             # Window and Control Generators
1112              
1113             sub children_create {
1114 154     154 0 201 my $self = shift;
1115 154         173 my $object = shift;
1116 154         169 my $parent = shift;
1117 154         260 my @windows = ();
1118              
1119 154         197 foreach my $child ( @{$object->children} ) {
  154         542  
1120             # Skip elements we create outside the main recursion
1121 226 100       1569 next if $child->isa('FBP::StatusBar');
1122              
1123 225 100       1323 if ( $child->isa('FBP::Window') ) {
    100          
1124 89         270 push @windows, $self->window_create($child, $parent);
1125             } elsif ( $child->isa('FBP::StdDialogButtonSizer') ) {
1126 1         6 push @windows, $self->stddialogbuttonsizer_create($child, $parent);
1127             }
1128              
1129             # Descend to child windows
1130 225 100       737 next unless $child->does('FBP::Children');
1131 147 100       5781 if ( $object->isa('FBP::Window') ) {
1132 36         144 push @windows, $self->children_create($child, $object);
1133             } else {
1134 111         343 push @windows, $self->children_create($child, $parent);
1135             }
1136             }
1137              
1138 154         6607 return @windows;
1139             }
1140              
1141             sub window_create {
1142 89     89 0 107 my $self = shift;
1143 89         96 my $window = shift;
1144 89         96 my $parent = shift;
1145 89         114 my $lines = undef;
1146              
1147 89 100       7402 if ( $window->isa('FBP::AnimationCtrl') ) {
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    50          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    50          
    100          
    100          
    100          
    50          
1148 1         6 $lines = $self->animationctrl_create($window, $parent);
1149             } elsif ( $window->isa('FBP::BitmapButton') ) {
1150 1         7 $lines = $self->bitmapbutton_create($window, $parent);
1151             } elsif ( $window->isa('FBP::Button') ) {
1152 9         47 $lines = $self->button_create($window, $parent);
1153             } elsif ( $window->isa('FBP::CalendarCtrl') ) {
1154 1         8 $lines = $self->calendarctrl_create($window, $parent);
1155             } elsif ( $window->isa('FBP::CheckBox') ) {
1156 4         11 $lines = $self->checkbox_create($window, $parent);
1157             } elsif ( $window->isa('FBP::Choice') ) {
1158 1         5 $lines = $self->choice_create($window, $parent);
1159             } elsif ( $window->isa('FBP::Choicebook') ) {
1160 1         7 $lines = $self->choicebook_create($window, $parent);
1161             } elsif ( $window->isa('FBP::ComboBox') ) {
1162 1         6 $lines = $self->combobox_create($window, $parent);
1163             } elsif ( $window->isa('FBP::ColourPickerCtrl') ) {
1164 2         10 $lines = $self->colourpickerctrl_create($window, $parent);
1165             } elsif ( $window->isa('FBP::CustomControl' ) ) {
1166 1         6 $lines = $self->customcontrol_create($window, $parent);
1167             } elsif ( $window->isa('FBP::DatePickerCtrl') ) {
1168 0         0 die "Wx::DatePickerCtrl is not supported by Wx.pm";
1169 0         0 $lines = $self->datepickerctrl_create($window, $parent);
1170             } elsif ( $window->isa('FBP::DirPickerCtrl') ) {
1171 1         7 $lines = $self->dirpickerctrl_create($window, $parent);
1172             } elsif ( $window->isa('FBP::FilePickerCtrl') ) {
1173 1         21 $lines = $self->filepickerctrl_create($window, $parent);
1174             } elsif ( $window->isa('FBP::FontPickerCtrl') ) {
1175 1         5 $lines = $self->fontpickerctrl_create($window, $parent);
1176             } elsif ( $window->isa('FBP::Gauge') ) {
1177 1         6 $lines = $self->gauge_create($window, $parent);
1178             } elsif ( $window->isa('FBP::GenericDirCtrl') ) {
1179 1         6 $lines = $self->genericdirctrl_create($window, $parent);
1180             } elsif ( $window->isa('FBP::Grid') ) {
1181 1         6 $lines = $self->grid_create($window, $parent);
1182             } elsif ( $window->isa('FBP::HtmlWindow') ) {
1183 1         4 $lines = $self->htmlwindow_create($window, $parent);
1184             } elsif ( $window->isa('FBP::HyperlinkCtrl') ) {
1185 1         7 $lines = $self->hyperlink_create($window, $parent);
1186             } elsif ( $window->isa('FBP::Listbook') ) {
1187             # We emulate the creation of simple listbooks via treebooks
1188 2 100       13 if ( $window->wxclass eq 'Wx::Treebook' ) {
1189 1         36 $lines = $self->treebook_create($window, $parent);
1190             } else {
1191 1         17 $lines = $self->listbook_create($window, $parent);
1192             }
1193             } elsif ( $window->isa('FBP::ListBox') ) {
1194 1         4 $lines = $self->listbox_create($window, $parent);
1195             } elsif ( $window->isa('FBP::ListCtrl') ) {
1196 1         6 $lines = $self->listctrl_create($window, $parent);
1197             } elsif ( $window->isa('FBP::MenuBar') ) {
1198 1         7 $lines = $self->menubar_create($window, $parent);
1199             } elsif ( $window->isa('FBP::Notebook') ) {
1200 1         4 $lines = $self->notebook_create($window, $parent);
1201             } elsif ( $window->isa('FBP::Panel') ) {
1202 13         58 $lines = $self->panel_create($window, $parent);
1203             } elsif ( $window->isa('FBP::RadioBox') ) {
1204 1         5 $lines = $self->radiobox_create($window, $parent);
1205             } elsif ( $window->isa('FBP::RadioButton') ) {
1206 4         13 $lines = $self->radiobutton_create($window, $parent);
1207             } elsif ( $window->isa('FBP::RichTextCtrl') ) {
1208 1         8 $lines = $self->richtextctrl_create($window, $parent);
1209             } elsif ( $window->isa('FBP::ScrollBar') ) {
1210 1         7 $lines = $self->scrollbar_create($window, $parent);
1211             } elsif ( $window->isa('FBP::ScrolledWindow') ) {
1212 1         5 $lines = $self->scrolledwindow_create($window, $parent);
1213             } elsif ( $window->isa('FBP::SearchCtrl') ) {
1214 1         6 $lines = $self->searchctrl_create($window, $parent);
1215             } elsif ( $window->isa('FBP::Slider') ) {
1216 1         5 $lines = $self->slider_create($window, $parent);
1217             } elsif ( $window->isa('FBP::SpinButton') ) {
1218 1         7 $lines = $self->spinbutton_create($window, $parent);
1219             } elsif ( $window->isa('FBP::SpinCtrl') ) {
1220 1         5 $lines = $self->spinctrl_create($window, $parent);
1221             } elsif ( $window->isa('FBP::SplitterWindow') ) {
1222 1         6 $lines = $self->splitterwindow_create($window, $parent);
1223             } elsif ( $window->isa('FBP::StaticBitmap') ) {
1224 1         5 $lines = $self->staticbitmap_create($window, $parent);
1225             } elsif ( $window->isa('FBP::StaticLine') ) {
1226 4         35 $lines = $self->staticline_create($window, $parent);
1227             } elsif ( $window->isa('FBP::StaticText') ) {
1228 17         70 $lines = $self->statictext_create($window, $parent);
1229             } elsif ( $window->isa('FBP::StatusBar') ) {
1230 0         0 $lines = $self->statusbar_create($window, $parent);
1231             } elsif ( $window->isa('FBP::TextCtrl') ) {
1232 2         9 $lines = $self->textctrl_create($window, $parent);
1233             } elsif ( $window->isa('FBP::ToggleButton') ) {
1234 1         5 $lines = $self->togglebutton_create($window, $parent);
1235             } elsif ( $window->isa('FBP::ToolBar') ) {
1236 1         7 $lines = $self->toolbar_create($window, $parent);
1237             } elsif ( $window->isa('FBP::TreeCtrl') ) {
1238 1         5 $lines = $self->treectrl_create($window, $parent);
1239             } else {
1240 0         0 die 'Cannot create constructor code for ' . ref($window);
1241             }
1242              
1243             # Add common modifications
1244 89         432 push @$lines, $self->window_changes($window);
1245 89         211 push @$lines, $self->object_bindings($window);
1246              
1247 89         867 return $lines;
1248             }
1249              
1250             sub animationctrl_create {
1251 1     1 0 2 my $self = shift;
1252 1         2 my $control = shift;
1253 1         3 my $parent = $self->object_parent(@_);
1254 1         5 my $id = $self->object_id($control);
1255 1         6 my $animation = $self->animation($control->animation);
1256 1         3 my $position = $self->object_position($control);
1257 1         4 my $size = $self->object_wxsize($control);
1258 1         3 my $variable = $self->object_variable($control);
1259 1         9 my $bitmap = $self->bitmap($control->inactive_bitmap);
1260              
1261 1         4 my $lines = $self->nested(
1262             $self->object_new($control),
1263             "$parent,",
1264             "$id,",
1265             "$animation,",
1266             "$position,",
1267             "$size,",
1268             $self->window_style($control),
1269             ");",
1270             );
1271              
1272 1 50       5 unless ( $bitmap eq $self->bitmap(undef) ) {
1273 1         5 push @$lines, $self->nested(
1274             "$variable->SetInactiveBitmap(",
1275             $bitmap,
1276             ");",
1277             );
1278             }
1279              
1280 1 50       6 if ( $control->play ) {
1281 0         0 push @$lines, "$variable->Play;";
1282             }
1283              
1284 1         2 return $lines;
1285             }
1286              
1287             sub bitmapbutton_create {
1288 1     1 0 2 my $self = shift;
1289 1         2 my $control = shift;
1290 1         4 my $parent = $self->object_parent(@_);
1291 1         3 my $id = $self->object_id($control);
1292 1         4 my $bitmap = $self->object_bitmap($control);
1293 1         5 my $position = $self->object_position($control);
1294 1         3 my $size = $self->object_wxsize($control);
1295 1         3 my $variable = $self->object_variable($control);
1296 1         5 my $disabled = $self->bitmap( $control->disabled );
1297 1         6 my $selected = $self->bitmap( $control->selected );
1298 1         5 my $hover = $self->bitmap( $control->hover );
1299 1         13 my $focus = $self->bitmap( $control->focus );
1300              
1301 1         4 my $lines = $self->nested(
1302             $self->object_new($control),
1303             "$parent,",
1304             "$id,",
1305             "$bitmap,",
1306             "$position,",
1307             "$size,",
1308             $self->window_style($control),
1309             ");",
1310             );
1311              
1312             # Set the optional images
1313 1         40 my $null = $self->bitmap(undef);
1314 1 50       4 if ( $disabled ne $null ) {
1315 1         4 push @$lines, (
1316             "$variable->SetBitmapDisabled(",
1317             "\t$disabled",
1318             ");",
1319             );
1320             }
1321 1 50       4 if ( $selected ne $null ) {
1322 1         4 push @$lines, (
1323             "$variable->SetBitmapSelected(",
1324             "\t$selected",
1325             ");",
1326             );
1327             }
1328 1 50       3 if ( $hover ne $null ) {
1329 1         4 push @$lines, (
1330             "$variable->SetBitmapHover(",
1331             "\t$hover",
1332             ");",
1333             );
1334             }
1335 1 50       2 if ( $focus ne $null ) {
1336 1         10 push @$lines, (
1337             "$variable->SetBitmapFocus(",
1338             "\t$focus",
1339             ");",
1340             );
1341             }
1342              
1343 1 50       92 if ( $control->default ) {
1344 0         0 push @$lines, "$variable->SetDefault;";
1345             }
1346              
1347 1         4 return $lines;
1348             }
1349              
1350             sub button_create {
1351 9     9 0 17 my $self = shift;
1352 9         18 my $control = shift;
1353 9         26 my $parent = $self->object_parent(@_);
1354 9         40 my $id = $self->object_id($control);
1355 9         27 my $label = $self->object_label($control);
1356 9         30 my $position = $self->object_position($control);
1357 9         31 my $size = $self->object_wxsize($control);
1358 9         29 my $variable = $self->object_variable($control);
1359              
1360 9         45 my $lines = $self->nested(
1361             $self->object_new($control),
1362             "$parent,",
1363             "$id,",
1364             "$label,",
1365             "$position,",
1366             "$size,",
1367             $self->window_style($control),
1368             ");",
1369             );
1370              
1371 9 100       106 if ( $control->default ) {
1372 1         3 push @$lines, "$variable->SetDefault;";
1373             }
1374              
1375 9         29 return $lines;
1376             }
1377              
1378             sub calendarctrl_create {
1379 1     1 0 2 my $self = shift;
1380 1         1 my $control = shift;
1381 1         3 my $parent = $self->object_parent(@_);
1382 1         4 my $id = $self->object_id($control);
1383             # my $value = $self->wx('wxDefaultDateTime'); # NOT IMPLEMENTED
1384 1         3 my $value = 'Wx::DateTime->new'; # Believed to be equivalent
1385 1         3 my $position = $self->object_position($control);
1386 1         3 my $size = $self->object_wxsize($control);
1387              
1388 1         4 return $self->nested(
1389             $self->object_new($control),
1390             "$parent,",
1391             "$id,",
1392             "$value,",
1393             "$position,",
1394             "$size,",
1395             $self->window_style($control),
1396             ");",
1397             );
1398             }
1399              
1400             sub checkbox_create {
1401 4     4 0 5 my $self = shift;
1402 4         5 my $control = shift;
1403 4         10 my $parent = $self->object_parent(@_);
1404 4         13 my $id = $self->object_id($control);
1405 4         10 my $label = $self->object_label($control);
1406 4         15 my $position = $self->object_position($control);
1407 4         11 my $size = $self->object_wxsize($control);
1408              
1409 4         11 return $self->nested(
1410             $self->object_new($control),
1411             "$parent,",
1412             "$id,",
1413             "$label,",
1414             "$position,",
1415             "$size,",
1416             $self->window_style($control),
1417             ");",
1418             );
1419             }
1420              
1421             sub choice_create {
1422 1     1 0 3 my $self = shift;
1423 1         1 my $control = shift;
1424 1         3 my $parent = $self->object_parent(@_);
1425 1         4 my $id = $self->object_id($control);
1426 1         3 my $position = $self->object_position($control);
1427 1         4 my $size = $self->object_wxsize($control);
1428 1         5 my $items = $self->control_items($control);
1429              
1430 1         4 return $self->nested(
1431             $self->object_new($control),
1432             "$parent,",
1433             "$id,",
1434             "$position,",
1435             "$size,",
1436             $items,
1437             ");",
1438             );
1439             }
1440              
1441             sub choicebook_create {
1442 1     1 0 2 my $self = shift;
1443 1         4 my $control = shift;
1444 1         5 my $parent = $self->object_parent(@_);
1445 1         5 my $id = $self->object_id($control);
1446 1         4 my $position = $self->object_position($control);
1447 1         5 my $size = $self->object_wxsize($control);
1448              
1449 1         5 return $self->nested(
1450             $self->object_new($control),
1451             "$parent,",
1452             "$id,",
1453             "$position,",
1454             "$size,",
1455             $self->window_style($control),
1456             ");",
1457             );
1458             }
1459              
1460             sub combobox_create {
1461 1     1 0 3 my $self = shift;
1462 1         2 my $control = shift;
1463 1         5 my $parent = $self->object_parent(@_);
1464 1         4 my $id = $self->object_id($control);
1465 1         7 my $value = $self->quote( $control->value );
1466 1         14 my $position = $self->object_position($control);
1467 1         4 my $size = $self->object_wxsize($control);
1468 1         3 my $items = $self->control_items($control);
1469              
1470 1         5 return $self->nested(
1471             $self->object_new($control),
1472             "$parent,",
1473             "$id,",
1474             "$value,",
1475             "$position,",
1476             "$size,",
1477             $items,
1478             $self->window_style($control),
1479             ");",
1480             );
1481             }
1482              
1483             sub colourpickerctrl_create {
1484 2     2 0 3 my $self = shift;
1485 2         2 my $control = shift;
1486 2         6 my $parent = $self->object_parent(@_);
1487 2         7 my $id = $self->object_id($control);
1488 2         12 my $colour = $self->colour( $control->colour );
1489 2         8 my $position = $self->object_position($control);
1490 2         7 my $size = $self->object_wxsize($control);
1491              
1492             # Wx::ColourPickerCtrl does not support defaulting null colours.
1493             # Use an explicit black instead until we find a better option.
1494 2 50       8 if ( $colour eq 'undef' ) {
1495 0         0 $colour = $self->colour('0,0,0');
1496             }
1497              
1498 2         7 return $self->nested(
1499             $self->object_new($control),
1500             "$parent,",
1501             "$id,",
1502             "$colour,",
1503             "$position,",
1504             "$size,",
1505             $self->window_style($control),
1506             ");",
1507             );
1508             }
1509              
1510             # Completely generic custom control
1511             sub customcontrol_create {
1512 1     1 0 1 my $self = shift;
1513 1         2 my $control = shift;
1514 1         4 my $parent = $self->object_parent(@_);
1515 1         4 my $id = $self->object_id($control);
1516              
1517 1         3 return $self->nested(
1518             $self->object_new($control),
1519             "$parent,",
1520             "$id,",
1521             ");",
1522             );
1523             }
1524              
1525             sub datepickerctrl_create {
1526 0     0 0 0 my $self = shift;
1527 0         0 my $control = shift;
1528 0         0 my $parent = $self->object_parent(@_);
1529 0         0 my $id = $self->object_id($control);
1530             # my $value = $self->wx('wxDefaultDateTime'); # NOT IMPLEMENTED
1531 0         0 my $value = 'Wx::DateTime->new'; # Believed to be equivalent
1532 0         0 my $position = $self->object_position($control);
1533 0         0 my $size = $self->object_wxsize($control);
1534              
1535 0         0 return $self->nested(
1536             $self->object_new($control),
1537             "$parent,",
1538             "$id,",
1539             "$value,",
1540             "$position,",
1541             "$size,",
1542             $self->window_style($control),
1543             ");",
1544             );
1545             }
1546              
1547             sub dirpickerctrl_create {
1548 1     1 0 2 my $self = shift;
1549 1         3 my $control = shift;
1550 1         5 my $parent = $self->object_parent(@_);
1551 1         6 my $id = $self->object_id($control);
1552 1         8 my $value = $self->quote( $control->value );
1553 1         6 my $message = $self->text( $control->message );
1554 1         5 my $position = $self->object_position($control);
1555 1         26 my $size = $self->object_wxsize($control);
1556              
1557 1         6 return $self->nested(
1558             $self->object_new($control),
1559             "$parent,",
1560             "$id,",
1561             "$value,",
1562             "$message,",
1563             "$position,",
1564             "$size,",
1565             $self->window_style($control),
1566             ");",
1567             );
1568             }
1569              
1570             sub filepickerctrl_create {
1571 1     1 0 2 my $self = shift;
1572 1         3 my $control = shift;
1573 1         4 my $parent = $self->object_parent(@_);
1574 1         7 my $id = $self->object_id($control);
1575 1         8 my $value = $self->quote( $control->value );
1576 1         7 my $message = $self->text( $control->message );
1577 1         9 my $wildcard = $self->quote( $control->wildcard );
1578 1         5 my $position = $self->object_position($control);
1579 1         5 my $size = $self->object_wxsize($control);
1580              
1581 1         6 return $self->nested(
1582             $self->object_new($control),
1583             "$parent,",
1584             "$id,",
1585             "$value,",
1586             "$message,",
1587             "$wildcard,",
1588             "$position,",
1589             "$size,",
1590             $self->window_style($control),
1591             ");",
1592             );
1593             }
1594              
1595             sub fontpickerctrl_create {
1596 1     1 0 3 my $self = shift;
1597 1         1 my $control = shift;
1598 1         4 my $variable = $self->object_variable($control);
1599 1         4 my $parent = $self->object_parent(@_);
1600 1         4 my $id = $self->object_id($control);
1601 1         8 my $font = $self->font( $control->value );
1602 1         5 my $position = $self->object_position($control);
1603 1         4 my $size = $self->object_wxsize($control);
1604              
1605 1         4 my $lines = $self->nested(
1606             $self->object_new($control),
1607             "$parent,",
1608             "$id,",
1609             "$font,",
1610             "$position,",
1611             "$size,",
1612             $self->window_style($control),
1613             ");",
1614             );
1615              
1616 1         12 my $max_point_size = $control->max_point_size;
1617 1 50       4 if ( $max_point_size ) {
1618 1         4 push @$lines, "$variable->SetMaxPointSize($max_point_size);";
1619             }
1620              
1621 1         4 return $lines;
1622             }
1623              
1624             sub gauge_create {
1625 1     1 0 4 my $self = shift;
1626 1         3 my $control = shift;
1627 1         6 my $parent = $self->object_parent(@_);
1628 1         5 my $id = $self->object_id($control);
1629 1         8 my $range = $control->range;
1630 1         5 my $position = $self->object_position($control);
1631 1         5 my $size = $self->object_wxsize($control);
1632              
1633 1         5 my $lines = $self->nested(
1634             $self->object_new($control),
1635             "$parent,",
1636             "$id,",
1637             "$range,",
1638             "$position,",
1639             "$size,",
1640             $self->window_style($control),
1641             ");",
1642             );
1643              
1644             # Set the value we are initially at
1645 1         7 my $variable = $self->object_variable($control);
1646 1         7 my $value = $control->value;
1647 1 50       5 if ( $value ) {
1648 1         6 push @$lines, "$variable->SetValue($value);";
1649             }
1650              
1651 1         4 return $lines;
1652             }
1653              
1654             sub genericdirctrl_create {
1655 1     1 0 11 my $self = shift;
1656 1         2 my $control = shift;
1657 1         4 my $parent = $self->object_parent(@_);
1658 1         5 my $id = $self->object_id($control);
1659 1         18 my $defaultfolder = $self->quote( $control->defaultfolder );
1660 1         4 my $position = $self->object_position($control);
1661 1         4 my $size = $self->object_wxsize($control);
1662 1         7 my $filter = $self->quote( $control->filter );
1663 1         6 my $defaultfilter = $control->defaultfilter;
1664              
1665 1         4 my $lines = $self->nested(
1666             $self->object_new($control),
1667             "$parent,",
1668             "$id,",
1669             "$defaultfolder,",
1670             "$position,",
1671             "$size,",
1672             $self->window_style($control, 0),
1673             "$filter,",
1674             "$defaultfilter,",
1675             ");",
1676             );
1677              
1678 1         14 my $variable = $self->object_variable($control);
1679 1         7 my $show_hidden = $control->show_hidden;
1680 1         5 push @$lines, "$variable->ShowHidden($show_hidden);";
1681              
1682 1         4 return $lines;
1683             }
1684              
1685             sub grid_create {
1686 1     1 0 3 my $self = shift;
1687 1         1 my $control = shift;
1688 1         4 my $parent = $self->object_parent(@_);
1689 1         5 my $id = $self->object_id($control);
1690 1         4 my $position = $self->object_position($control);
1691 1         4 my $size = $self->object_wxsize($control);
1692              
1693 1         5 my $lines = $self->nested(
1694             $self->object_new($control),
1695             "$parent,",
1696             "$id,",
1697             "$position,",
1698             "$size,",
1699             $self->window_style($control),
1700             ");",
1701             );
1702              
1703             # Grid
1704 1         5 my $variable = $self->object_variable($control);
1705 1         7 my $rows = $control->rows;
1706 1         7 my $cols = $control->cols;
1707 1         5 my $editing = $control->editing;
1708 1         7 my $grid_lines = $control->grid_lines;
1709 1         34 my $drag_grid_size = $control->drag_grid_size;
1710 1         6 my $margin_width = $control->margin_width;
1711 1         7 my $margin_height = $control->margin_height;
1712              
1713 1         11 push @$lines, (
1714             "$variable->CreateGrid( $rows, $cols );",
1715             "$variable->EnableEditing($editing);",
1716             "$variable->EnableGridLines($grid_lines);",
1717             );
1718 1 50       8 if ( $control->grid_line_color ) {
1719 1         16 push @$lines, $self->nested(
1720             "$variable->SetGridLineColour(",
1721             $self->colour( $control->grid_line_color ),
1722             ");",
1723             );
1724             }
1725 1         9 push @$lines, (
1726             "$variable->EnableDragGridSize($drag_grid_size);",
1727             "$variable->SetMargins( $margin_width, $margin_height );",
1728             );
1729              
1730             # Columns
1731 1         8 my $drag_col_move = $control->drag_col_move;
1732 1         5 my $drag_col_size = $control->drag_col_size;
1733 1         7 my $col_label_size = $control->col_label_size;
1734 1         6 my $col_label_horiz_alignment = $self->wx( $control->col_label_horiz_alignment );
1735 1         8 my $col_label_vert_alignment = $self->wx( $control->col_label_vert_alignment );
1736              
1737 1 50       9 if ( $control->column_sizes ) {
1738 1         23 my @sizes = split /\s*,\s*/, $control->column_sizes;
1739              
1740 5         40 push @$lines, map {
1741 1         6 "$variable->SetColSize( $_, $sizes[$_] );"
1742             } ( 0 .. $#sizes );
1743             }
1744 1 50       9 if ( $control->autosize_cols ) {
1745 1         4 push @$lines, "$variable->AutoSizeColumns;";
1746             }
1747 1         10 push @$lines, (
1748             "$variable->EnableDragColMove($drag_col_move);",
1749             "$variable->EnableDragColSize($drag_col_size);",
1750             "$variable->SetColLabelSize($col_label_size);",
1751             );
1752 1 50       7 if ( $control->col_label_values ) {
1753 5         14 my @values = map {
1754 1         9 $self->text($_)
1755             } $self->list( $control->col_label_values );
1756              
1757 5         36 push @$lines, map {
1758 1         6 "$variable->SetColLabelValue( $_, $values[$_] );"
1759             } ( 0 .. $#values );
1760             }
1761 1         7 push @$lines, "$variable->SetColLabelAlignment( $col_label_horiz_alignment, $col_label_vert_alignment );";
1762              
1763             # Rows
1764 1         7 my $drag_row_size = $control->drag_row_size;
1765 1         6 my $row_label_horiz_alignment = $self->wx( $control->row_label_horiz_alignment );
1766 1         8 my $row_label_vert_alignment = $self->wx( $control->row_label_vert_alignment );
1767              
1768 1 50       7 if ( $control->row_sizes ) {
1769 1         17 my @sizes = split /\s*,\s*/, $control->row_sizes;
1770              
1771 5         26 push @$lines, map {
1772 1         3 "$variable->SetRowSize( $_, $sizes[$_] );"
1773             } ( 0 .. $#sizes );
1774             }
1775 1 50       9 if ( $control->autosize_rows ) {
1776 1         5 push @$lines, "$variable->AutoSizeRows;";
1777             }
1778 1         6 push @$lines, "$variable->EnableDragRowSize($drag_row_size);";
1779 1 50       8 if ( $control->row_label_values ) {
1780 5         15 my @values = map {
1781 1         7 $self->text($_)
1782             } $self->list( $control->row_label_values );
1783              
1784 5         31 push @$lines, map {
1785 1         6 "$variable->SetRowLabelValue( $_, $values[$_] );"
1786             } ( 0 .. $#values );
1787             }
1788 1         9 push @$lines, "$variable->SetRowLabelAlignment( $row_label_horiz_alignment, $row_label_vert_alignment );";
1789              
1790             # Label Appearance
1791 1 50       8 if ( $control->label_bg ) {
1792 1         7 my $colour = $self->colour( $control->label_bg );
1793 1         7 push @$lines, (
1794             "$variable->SetLabelBackgroundColour(",
1795             "\t$colour",
1796             ");",
1797             );
1798             }
1799 1 50       8 if ( $control->label_font ) {
1800 1         6 my $font = $self->font( $control->label_font );
1801 1         6 push @$lines, (
1802             "$variable->SetLabelFont(",
1803             "\t$font",
1804             ");",
1805             );
1806             }
1807 1 50       7 if ( $control->label_text ) {
1808 1         7 my $colour = $self->colour( $control->label_text );
1809 1         1144 push @$lines, (
1810             "$variable->SetLabelTextColour(",
1811             "\t$colour",
1812             ");",
1813             );
1814             }
1815              
1816             # Cell Defaults
1817 1         9 my $cell_horiz_alignment = $self->wx( $control->cell_horiz_alignment );
1818 1         6 my $cell_vert_alignment = $self->wx( $control->cell_vert_alignment );
1819 1 50       7 if ( $control->cell_bg ) {
1820 1         5 my $colour = $self->colour( $control->cell_bg );
1821 1         7 push @$lines, (
1822             "$variable->SetDefaultCellBackgroundColour(",
1823             "\t$colour",
1824             ");",
1825             );
1826             }
1827 1 50       7 if ( $control->cell_font ) {
1828 0         0 my $font = $self->font( $control->cell_font );
1829 0         0 push @$lines, (
1830             "$variable->SetDefaultCellFont(",
1831             "\t$font",
1832             ");",
1833             );
1834             }
1835 1 50       9 if ( $control->cell_text ) {
1836 0         0 my $colour = $self->colour( $control->cell_text );
1837 0         0 push @$lines, (
1838             "$variable->SetDefaultCellColour(",
1839             "\t$colour",
1840             ");",
1841             );
1842             }
1843 1         6 push @$lines, "$variable->SetDefaultCellAlignment( $cell_horiz_alignment, $cell_vert_alignment );";
1844              
1845 1         6 return $lines;
1846             }
1847              
1848             sub htmlwindow_create {
1849 1     1 0 3 my $self = shift;
1850 1         1 my $control = shift;
1851 1         3 my $parent = $self->object_parent(@_);
1852 1         4 my $id = $self->object_id($control);
1853 1         4 my $position = $self->object_position($control);
1854 1         4 my $size = $self->object_wxsize($control);
1855              
1856 1         5 return $self->nested(
1857             $self->object_new($control),
1858             "$parent,",
1859             "$id,",
1860             "$position,",
1861             "$size,",
1862             $self->window_style($control),
1863             ");",
1864             );
1865             }
1866              
1867             sub hyperlink_create {
1868 1     1 0 3 my $self = shift;
1869 1         2 my $control = shift;
1870 1         5 my $parent = $self->object_parent(@_);
1871 1         6 my $id = $self->object_id($control);
1872 1         6 my $label = $self->object_label($control);
1873 1         8 my $url = $self->quote( $control->url );
1874 1         5 my $position = $self->object_position($control);
1875 1         4 my $size = $self->object_wxsize($control);
1876              
1877 1         4 my $lines = $self->nested(
1878             $self->object_new($control),
1879             "$parent,",
1880             "$id,",
1881             "$label,",
1882             "$url,",
1883             "$position,",
1884             "$size,",
1885             $self->window_style($control),
1886             ");",
1887             );
1888              
1889             # Set additional properties
1890 1         8 my $variable = $self->object_variable($control);
1891 1 50       7 if ( $control->normal_color ) {
1892 1         9 my $colour = $self->colour( $control->normal_color );
1893 1         8 push @$lines, (
1894             "$variable->SetNormalColour(",
1895             "\t$colour",
1896             ");",
1897             );
1898             }
1899 1 50       7 if ( $control->hover_color ) {
1900 1         14 my $colour = $self->colour( $control->hover_color );
1901 1         6 push @$lines, (
1902             "$variable->SetHoverColour(",
1903             "\t$colour",
1904             ");",
1905             );
1906             }
1907 1 50       6 if ( $control->visited_color ) {
1908 0         0 my $colour = $self->colour( $control->visited_color );
1909 0         0 push @$lines, (
1910             "$variable->SetVisitedColour(",
1911             "\t$colour",
1912             ");",
1913             );
1914             }
1915              
1916 1         4 return $lines;
1917             }
1918              
1919             sub listbook_create {
1920 1     1 0 2 my $self = shift;
1921 1         2 my $control = shift;
1922 1         3 my $parent = $self->object_parent(@_);
1923 1         3 my $id = $self->object_id($control);
1924 1         4 my $position = $self->object_position($control);
1925 1         8 my $size = $self->object_wxsize($control);
1926              
1927 1         5 return $self->nested(
1928             $self->object_new($control),
1929             "$parent,",
1930             "$id,",
1931             "$position,",
1932             "$size,",
1933             $self->window_style($control),
1934             ");",
1935             );
1936             }
1937              
1938             sub listbox_create {
1939 1     1 0 2 my $self = shift;
1940 1         3 my $control = shift;
1941 1         3 my $parent = $self->object_parent(@_);
1942 1         4 my $id = $self->object_id($control);
1943 1         4 my $position = $self->object_position($control);
1944 1         3 my $size = $self->object_wxsize($control);
1945 1         3 my $items = $self->control_items($control);
1946              
1947 1         4 return $self->nested(
1948             $self->object_new($control),
1949             "$parent,",
1950             "$id,",
1951             "$position,",
1952             "$size,",
1953             $items,
1954             $self->window_style($control),
1955             ");",
1956             );
1957             }
1958              
1959             sub listctrl_create {
1960 1     1 0 2 my $self = shift;
1961 1         3 my $control = shift;
1962 1         4 my $parent = $self->object_parent(@_);
1963 1         5 my $id = $self->object_id($control);
1964 1         3 my $position = $self->object_position($control);
1965 1         12 my $size = $self->object_wxsize($control);
1966              
1967 1         5 return $self->nested(
1968             $self->object_new($control),
1969             "$parent,",
1970             "$id,",
1971             "$position,",
1972             "$size,",
1973             $self->window_style($control),
1974             ");",
1975             );
1976             }
1977              
1978             sub menu_create {
1979 1     1 0 3 my $self = shift;
1980 1         2 my $menu = shift;
1981 1         3 my $scope = $self->object_scope($menu);
1982 1         5 my $variable = $self->object_variable($menu);
1983              
1984             # Generate our children
1985 1         8 my @lines = (
1986             "$scope$variable = Wx::Menu->new;",
1987             "",
1988             );
1989 1         2 foreach my $child ( @{$menu->children} ) {
  1         5  
1990 3 50       30 if ( $child->isa('FBP::Menu') ) {
    100          
1991 0         0 push @lines, @{ $self->menu_create($child, $menu) };
  0         0  
1992              
1993             } elsif ( $child->isa('FBP::MenuItem') ) {
1994 2         3 push @lines, @{ $self->menuitem_create($child, $menu) };
  2         8  
1995              
1996             } else {
1997 1         3 next;
1998             }
1999 2         9 push @lines, "";
2000             }
2001              
2002             # Fill the menu
2003 1         2 foreach my $child ( @{$menu->children} ) {
  1         5  
2004 3 50       29 if ( $child->isa('FBP::Menu') ) {
    100          
    50          
2005 0         0 push @lines, $self->nested(
2006             "$variable->Append(",
2007             $self->object_variable($_) . ',',
2008             $self->object_label($_) . ',',
2009             ");",
2010             );
2011             } elsif ( $child->isa('FBP::MenuItem') ) {
2012 2         9 push @lines, "$variable->Append( "
2013             . $self->object_variable($child)
2014             . " );";
2015             } elsif ( $child->isa('FBP::MenuSeparator') ) {
2016 1         6 push @lines, "$variable->AppendSeparator;";
2017             }
2018             }
2019              
2020 1         6 return \@lines;
2021             }
2022              
2023             sub menubar_create {
2024 1     1 0 3 my $self = shift;
2025 1         1 my $window = shift;
2026 1         6 my $parent = $self->object_parent(@_);
2027 1         5 my $scope = $self->object_scope($window);
2028 1         5 my $variable = $self->object_variable($window);
2029 1   50     9 my $style = $self->wx($window->styles || 0);
2030              
2031             # Generate our children
2032 1         6 my @children = map {
2033 1         4 $self->menu_create($_, $self)
2034 1         3 } @{$window->children};
2035              
2036             # Build the append list
2037 1         5 my @append = map {
2038 1         5 $self->nested(
2039             "$variable->Append(",
2040             $self->object_variable($_) . ',',
2041             $self->object_label($_) . ',',
2042             ");",
2043             )
2044 1         3 } @{$window->children};
2045            
2046             return [
2047 1         4 ( map { @$_, "" } @children ),
  1         20  
2048             "$scope$variable = Wx::MenuBar->new($style);",
2049             "",
2050             @append,
2051             "",
2052             "$parent->SetMenuBar( $variable );",
2053             ];
2054             }
2055              
2056             sub menuitem_create {
2057 2     2 0 4 my $self = shift;
2058 2         2 my $menu = shift;
2059 2         8 my $parent = $self->object_parent(@_);
2060 2         10 my $scope = $self->object_scope($menu);
2061 2         6 my $variable = $self->object_variable($menu);
2062 2         8 my $id = $self->object_id($menu);
2063 2         5 my $label = $self->object_label($menu);
2064 2         11 my $help = $self->text( $menu->help );
2065 2         10 my $kind = $self->wx( $menu->kind );
2066              
2067             # Create the menu item
2068 2         18 my $lines = $self->nested(
2069             "$scope$variable = Wx::MenuItem->new(",
2070             "$parent,",
2071             "$id,",
2072             "$label,",
2073             "$help,",
2074             "$kind,",
2075             ");",
2076             );
2077              
2078             # Add the event bindings
2079 2         12 push @$lines, $self->object_bindings($menu);
2080              
2081 2         30 return $lines;
2082             }
2083              
2084             sub notebook_create {
2085 1     1 0 3 my $self = shift;
2086 1         1 my $control = shift;
2087 1         4 my $parent = $self->object_parent(@_);
2088 1         3 my $id = $self->object_id($control);
2089 1         4 my $position = $self->object_position($control);
2090 1         3 my $size = $self->object_wxsize($control);
2091              
2092 1         4 return $self->nested(
2093             $self->object_new($control),
2094             "$parent,",
2095             "$id,",
2096             "$position,",
2097             "$size,",
2098             $self->window_style($control),
2099             ");",
2100             );
2101             }
2102              
2103             sub panel_create {
2104 13     13 0 21 my $self = shift;
2105 13         15 my $window = shift;
2106 13         38 my $parent = $self->object_parent(@_);
2107 13         49 my $id = $self->object_id($window);
2108 13         41 my $position = $self->object_position($window);
2109 13         31 my $size = $self->object_wxsize($window);
2110              
2111 13         33 return $self->nested(
2112             $self->object_new($window),
2113             "$parent,",
2114             "$id,",
2115             "$position,",
2116             "$size,",
2117             $self->window_style($window),
2118             ");",
2119             );
2120             }
2121              
2122             sub radiobox_create {
2123 1     1 0 2 my $self = shift;
2124 1         2 my $control = shift;
2125 1         3 my $parent = $self->object_parent(@_);
2126 1         3 my $id = $self->object_id($control);
2127 1         4 my $label = $self->object_label($control);
2128 1         4 my $position = $self->object_position($control);
2129 1         3 my $size = $self->object_wxsize($control);
2130 1         4 my $items = $self->control_items($control);
2131 1   50     12 my $major = $control->majorDimension || 1;
2132              
2133 1         7 return $self->nested(
2134             $self->object_new($control),
2135             "$parent,",
2136             "$id,",
2137             "$label,",
2138             "$position,",
2139             "$size,",
2140             $items,
2141             "$major,",
2142             $self->window_style($control),
2143             ");",
2144             );
2145             }
2146              
2147             sub radiobutton_create {
2148 4     4 0 11 my $self = shift;
2149 4         3 my $control = shift;
2150 4         9 my $parent = $self->object_parent(@_);
2151 4         10 my $id = $self->object_id($control);
2152 4         12 my $label = $self->object_label($control);
2153 4         13 my $position = $self->object_position($control);
2154 4         9 my $size = $self->object_wxsize($control);
2155              
2156 4         18 my $lines = $self->nested(
2157             $self->object_new($control),
2158             "$parent,",
2159             "$id,",
2160             "$label,",
2161             "$position,",
2162             "$size,",
2163             $self->window_style($control),
2164             ");",
2165             );
2166              
2167 4 100       21 if ( $control->value ) {
2168 2         4 my $variable = $self->object_variable($control);
2169 2         6 push @$lines, "$variable->SetValue(1);";
2170             }
2171              
2172 4         10 return $lines;
2173             }
2174              
2175             sub richtextctrl_create {
2176 1     1 0 3 my $self = shift;
2177 1         3 my $control = shift;
2178 1         4 my $parent = $self->object_parent(@_);
2179 1         6 my $id = $self->object_id($control);
2180             # my $value = $self->wx('wxEmptyString'); # NOT IMPLEMENTED
2181 1         7 my $value = $self->quote('');
2182 1         4 my $position = $self->object_position($control);
2183 1         20 my $size = $self->object_wxsize($control);
2184              
2185 1         5 return $self->nested(
2186             $self->object_new($control),
2187             "$parent,",
2188             "$id,",
2189             "$value,",
2190             "$position,",
2191             "$size,",
2192             $self->window_style($control),
2193             ");",
2194             );
2195             }
2196              
2197             sub scrollbar_create {
2198 1     1 0 2 my $self = shift;
2199 1         2 my $control = shift;
2200 1         5 my $parent = $self->object_parent(@_);
2201 1         6 my $id = $self->object_id($control);
2202 1         4 my $position = $self->object_position($control);
2203 1         4 my $size = $self->object_wxsize($control);
2204              
2205 1         5 return $self->nested(
2206             $self->object_new($control),
2207             "$parent,",
2208             "$id,",
2209             "$position,",
2210             "$size,",
2211             $self->window_style($control),
2212             ");",
2213             );
2214             }
2215              
2216             sub scrolledwindow_create {
2217 1     1 0 2 my $self = shift;
2218 1         2 my $window = shift;
2219 1         3 my $parent = $self->object_parent(@_);
2220 1         4 my $id = $self->object_id($window);
2221 1         4 my $position = $self->object_position($window);
2222 1         12 my $size = $self->object_wxsize($window);
2223 1         5 my $variable = $self->object_variable($window);
2224 1         5 my $scroll_x = $window->scroll_rate_x;
2225 1         4 my $scroll_y = $window->scroll_rate_y;
2226              
2227 1         2 my $lines = $self->nested(
2228             $self->object_new($window),
2229             "$parent,",
2230             "$id,",
2231             "$position,",
2232             "$size,",
2233             $self->wx('wxHSCROLL|wxVSCROLL,'),
2234             ");",
2235             );
2236              
2237             # Set the scroll rate for the window
2238 1         6 push @$lines, "$variable->SetScrollRate( $scroll_x, $scroll_y );";
2239              
2240 1         3 return $lines;
2241             }
2242              
2243             sub searchctrl_create {
2244 1     1 0 10 my $self = shift;
2245 1         2 my $control = shift;
2246 1         5 my $parent = $self->object_parent(@_);
2247 1         5 my $id = $self->object_id($control);
2248 1         7 my $value = $self->quote( $control->value );
2249 1         12 my $position = $self->object_position($control);
2250 1         5 my $size = $self->object_wxsize($control);
2251              
2252 1         14 my $lines = $self->nested(
2253             $self->object_new($control),
2254             "$parent,",
2255             "$id,",
2256             "$value,",
2257             "$position,",
2258             "$size,",
2259             $self->window_style($control),
2260             ");",
2261             );
2262              
2263             # Control which optional features we show
2264 1         6 my $platform = $self->wx('wxMAC');
2265 1         4 my $variable = $self->object_variable($control);
2266 1         6 my $search_button = $control->search_button;
2267 1         5 my $cancel_button = $control->cancel_button;
2268 1         20 push @$lines, (
2269             "unless ( $platform ) {",
2270             "\t$variable->ShowSearchButton($search_button);",
2271             "}",
2272             "$variable->ShowCancelButton($cancel_button);",
2273             );
2274              
2275 1         8 return $lines;
2276             }
2277              
2278             sub slider_create {
2279 1     1 0 3 my $self = shift;
2280 1         2 my $window = shift;
2281 1         3 my $variable = $self->object_variable($window);
2282 1         4 my $parent = $self->object_parent(@_);
2283 1         4 my $id = $self->object_id($window);
2284 1         6 my $value = $window->value;
2285 1         6 my $minimum = $window->minValue;
2286 1         4 my $maximum = $window->maxValue;
2287 1         3 my $position = $self->object_position($window);
2288 1         4 my $size = $self->object_wxsize($window);
2289              
2290 1         4 return $self->nested(
2291             $self->object_new($window),
2292             "$parent,",
2293             "$id,",
2294             "$value,",
2295             "$minimum,",
2296             "$maximum,",
2297             "$position,",
2298             "$size,",
2299             $self->window_style($window),
2300             ");",
2301             );
2302             }
2303              
2304             sub spinbutton_create {
2305 1     1 0 2 my $self = shift;
2306 1         1 my $control = shift;
2307 1         3 my $parent = $self->object_parent(@_);
2308 1         4 my $id = $self->object_id($control);
2309 1         5 my $position = $self->object_position($control);
2310 1         5 my $size = $self->object_wxsize($control);
2311              
2312 1         9 return $self->nested(
2313             $self->object_new($control),
2314             "$parent,",
2315             "$id,",
2316             "$position,",
2317             "$size,",
2318             $self->window_style($control),
2319             ");",
2320             );
2321             }
2322              
2323             sub spinctrl_create {
2324 1     1 0 2 my $self = shift;
2325 1         2 my $control = shift;
2326 1         3 my $variable = $self->object_variable($control);
2327 1         5 my $parent = $self->object_parent(@_);
2328 1         3 my $id = $self->object_id($control);
2329 1         6 my $value = $self->quote( $control->value );
2330 1         24 my $position = $self->object_position($control);
2331 1         4 my $size = $self->object_wxsize($control);
2332 1         7 my $style = $self->wx( $control->styles );
2333 1         6 my $min = $control->min;
2334 1         4 my $max = $control->max;
2335 1         3 my $initial = $control->initial;
2336              
2337 1         4 return $self->nested(
2338             $self->object_new($control),
2339             "$parent,",
2340             "$id,",
2341             "$value,",
2342             "$position,",
2343             "$size,",
2344             "$style,",
2345             "$min,",
2346             "$max,",
2347             "$initial,",
2348             ");",
2349             );
2350             }
2351              
2352             sub splitterwindow_create {
2353 1     1 0 2 my $self = shift;
2354 1         2 my $window = shift;
2355 1         3 my $variable = $self->object_variable($window);
2356 1         4 my $parent = $self->object_parent(@_);
2357 1         3 my $id = $self->object_id($window);
2358 1         3 my $position = $self->object_position($window);
2359 1         4 my $size = $self->object_wxsize($window);
2360              
2361             # Object constructor
2362 1         4 my $lines = $self->nested(
2363             $self->object_new($window),
2364             "$parent,",
2365             "$id,",
2366             "$position,",
2367             "$size,",
2368             $self->window_style($window),
2369             ");",
2370             );
2371              
2372             # Optional settings
2373 1         6 my $sashsize = $window->sashsize;
2374 1         5 my $sashgravity = $window->sashgravity;
2375 1         4 my $min_pane_size = $window->min_pane_size;
2376 1 50 33     21 if ( length $sashgravity and $sashgravity >= 0 ) {
2377 1         4 push @$lines, "$variable->SetSashGravity($sashgravity);";
2378             }
2379 1 50 33     8 if ( length $sashsize and $sashsize >= 0 ) {
2380 0         0 push @$lines, "$variable->SetSashSize($sashsize);";
2381             }
2382 1 50 33     6 if ( $min_pane_size and $min_pane_size > 0 ) {
2383 1         4 push @$lines, "$variable->SetMinimumPaneSize($min_pane_size);";
2384             }
2385              
2386 1         3 return $lines;
2387             }
2388              
2389             sub staticbitmap_create {
2390 1     1 0 2 my $self = shift;
2391 1         2 my $window = shift;
2392 1         13 my $parent = $self->object_parent(@_);
2393 1         4 my $id = $self->object_id($window);
2394 1         4 my $bitmap = $self->object_bitmap($window);
2395 1         4 my $position = $self->object_position($window);
2396 1         4 my $size = $self->object_wxsize($window);
2397              
2398 1         45 return $self->nested(
2399             $self->object_new($window),
2400             "$parent,",
2401             "$id,",
2402             "$bitmap,",
2403             "$position,",
2404             "$size,",
2405             $self->window_style($window),
2406             ");",
2407             );
2408             }
2409              
2410             sub staticline_create {
2411 4     4 0 11 my $self = shift;
2412 4         7 my $control = shift;
2413 4         14 my $parent = $self->object_parent(@_);
2414 4         15 my $id = $self->object_id($control);
2415 4         16 my $position = $self->object_position($control);
2416 4         15 my $size = $self->object_wxsize($control);
2417              
2418 4         15 return $self->nested(
2419             $self->object_new($control),
2420             "$parent,",
2421             "$id,",
2422             "$position,",
2423             "$size,",
2424             $self->window_style($control),
2425             ");",
2426             );
2427             }
2428              
2429             sub statictext_create {
2430 17     17 0 28 my $self = shift;
2431 17         25 my $control = shift;
2432 17         112 my $parent = $self->object_parent(@_);
2433 17         47 my $id = $self->object_id($control);
2434 17         58 my $label = $self->object_label($control);
2435              
2436 17         67 return $self->nested(
2437             $self->object_new($control),
2438             "$parent,",
2439             "$id,",
2440             "$label,",
2441             ");",
2442             );
2443             }
2444              
2445             sub statusbar_create {
2446 1     1 0 2 my $self = shift;
2447 1         1 my $object = shift;
2448 1         10 my $variable = $self->object_variable($object);
2449 1         6 my $parent = $self->object_parent(@_);
2450 1         7 my $fields = $object->fields;
2451 1         6 my $style = $self->window_style($object, 0);
2452 1         5 my $id = $self->object_id($object);
2453              
2454             # If the status bar is not stored for later reference,
2455             # don't create the variable at all to avoid perlcritic'ism
2456 1 50       5 if ( $self->object_lexical($object) ) {
2457 1         3 $variable = "";
2458             } else {
2459 0         0 $variable = "$variable = ";
2460             }
2461              
2462             return [
2463 1         10 "$variable$parent->CreateStatusBar( $fields, $style $id );",
2464             ];
2465             }
2466              
2467 11         111671 use constant STDDIALOGBUTTONS => qw{
2468             OK Yes Save Apply No Cancel Help ContextHelp
2469 11     11   184 };
  11         71  
2470              
2471             sub stddialogbuttonsizer_create {
2472 1     1 0 2 my $self = shift;
2473 1         3 my $sizer = shift;
2474 1         4 my $parent = $self->object_parent(@_);
2475 1         4 my @windows = ();
2476              
2477             # We don't create the sizer here, but we do create the buttons
2478 1         6 foreach my $button ( $self->stddialogbuttonsizer_buttons($sizer) ) {
2479 3         9 my $id = $self->object_id($button);
2480              
2481 3         9 my $lines = $self->nested(
2482             $self->object_new($button),
2483             "$parent,",
2484             "$id,",
2485             ");",
2486             );
2487              
2488 3         11 push @$lines, $self->object_bindings($button);
2489 3         33 push @windows, $lines;
2490             }
2491              
2492 1         16 return @windows;
2493             }
2494              
2495             sub stddialogbuttonsizer_buttons {
2496 2     2 0 5 my $self = shift;
2497 2         4 my $sizer = shift;
2498 6         17 return map {
2499 16         92 $self->stddialogbuttonsizer_button($sizer, $_)
2500             } grep {
2501 2         6 $sizer->$_()
2502             } STDDIALOGBUTTONS;
2503             }
2504              
2505             sub stddialogbuttonsizer_button {
2506 6     6 0 8 my $self = shift;
2507 6         8 my $sizer = shift;
2508 6         7 my $type = shift;
2509 6         33 my $name = $sizer->name . '_' . lc($type);
2510 6         14 my $id = 'wxID_' . uc($type);
2511 6         12 my $click = 'On' . $type . 'ButtonClick';
2512 6         20 my $event = $sizer->$click();
2513 6 100       187 return FBP::Button->new(
2514             name => $name,
2515             id => $id,
2516             permission => $sizer->permission,
2517             ( $event ? ( OnButtonClick => $event ) : () ),
2518             );
2519             }
2520              
2521             sub textctrl_create {
2522 2     2 0 3 my $self = shift;
2523 2         4 my $control = shift;
2524 2         7 my $parent = $self->object_parent(@_);
2525 2         8 my $id = $self->object_id($control);
2526 2         13 my $value = $self->quote( $control->value );
2527 2         8 my $position = $self->object_position($control);
2528 2         6 my $size = $self->object_wxsize($control);
2529              
2530 2         9 my $lines = $self->nested(
2531             $self->object_new($control),
2532             "$parent,",
2533             "$id,",
2534             "$value,",
2535             "$position,",
2536             "$size,",
2537             $self->window_style($control),
2538             ");",
2539             );
2540              
2541 2         14 my $maxlength = $control->maxlength;
2542 2 100       7 if ( $maxlength ) {
2543 1         4 my $variable = $self->object_variable($control);
2544 1         7 push @$lines, "$variable->SetMaxLength($maxlength);";
2545             }
2546              
2547 2         7 return $lines;
2548             }
2549              
2550             sub togglebutton_create {
2551 1     1 0 3 my $self = shift;
2552 1         1 my $control = shift;
2553 1         12 my $parent = $self->object_parent(@_);
2554 1         4 my $id = $self->object_id($control);
2555 1         4 my $label = $self->object_label($control);
2556 1         4 my $position = $self->object_position($control);
2557 1         3 my $size = $self->object_wxsize($control);
2558              
2559 1         3 my $lines = $self->nested(
2560             $self->object_new($control),
2561             "$parent,",
2562             "$id,",
2563             "$label,",
2564             "$position,",
2565             "$size,",
2566             $self->window_style($control),
2567             ");",
2568             );
2569              
2570 1 50       8 if ( $control->value ) {
2571 1         25 my $variable = $self->object_variable($control);
2572 1         4 push @$lines, "$variable->SetValue(1);";
2573             }
2574              
2575 1         5 return $lines;
2576             }
2577              
2578             sub tool_create {
2579 2     2 0 4 my $self = shift;
2580 2         4 my $tool = shift;
2581 2         6 my $parent = $self->object_parent(@_);
2582 2         8 my $id = $self->object_id($tool);
2583 2         6 my $label = $self->object_label($tool);
2584 2         8 my $bitmap = $self->object_bitmap($tool);
2585 2         11 my $tooltip = $self->text( $tool->tooltip );
2586 2         8 my $kind = $self->wx( $tool->kind );
2587              
2588 2         18 return $self->nested(
2589             "$parent->AddTool(",
2590             "$id,",
2591             "$label,",
2592             "$bitmap,",
2593             "$tooltip,",
2594             "$kind,",
2595             ");",
2596             );
2597             }
2598              
2599             sub toolbar_create {
2600 1     1 0 3 my $self = shift;
2601 1         2 my $window = shift;
2602 1         6 my $parent = $self->object_parent(@_);
2603 1         15 my $scope = $self->object_scope($window);
2604 1         5 my $variable = $self->object_variable($window);
2605 1   50     9 my $style = $self->wx($window->styles || 0);
2606 1         5 my $id = $self->object_id($window);
2607              
2608             # Generate child constructor code
2609 3 100       27 my @children = map {
2610 1         5 $_->isa('FBP::Tool')
2611             ? $self->tool_create($_, $window)
2612             : "$variable->AddSeparator;"
2613 1         3 } @{$window->children};
2614              
2615             return [
2616 3 100       27 "$scope$variable = $parent->CreateToolBar( $style, $id );",
2617 1         8 ( map { ref $_ ? @$_ : $_ } @children ),
2618             "$variable->Realize;",
2619             ];
2620             }
2621              
2622             sub treebook_create {
2623 1     1 0 2 my $self = shift;
2624 1         3 my $control = shift;
2625 1         4 my $parent = $self->object_parent(@_);
2626 1         5 my $id = $self->object_id($control);
2627 1         4 my $position = $self->object_position($control);
2628 1         4 my $size = $self->object_wxsize($control);
2629 0         0 my $style = $self->wx(
2630             # Strip listbook-specific styles
2631 1         6 join ' | ', grep { ! /^wxLB_/ } split /\s*\|\s*/, $control->styles
2632             );
2633              
2634 1 50       5 return $self->nested(
2635             $self->object_new($control),
2636             "$parent,",
2637             "$id,",
2638             "$position,",
2639             "$size,",
2640             ( $style ? "$style," : () ),
2641             ");",
2642             );
2643             }
2644              
2645             sub treectrl_create {
2646 1     1 0 2 my $self = shift;
2647 1         10 my $control = shift;
2648 1         4 my $parent = $self->object_parent(@_);
2649 1         9 my $id = $self->object_id($control);
2650 1         4 my $position = $self->object_position($control);
2651 1         3 my $size = $self->object_wxsize($control);
2652              
2653 1         4 return $self->nested(
2654             $self->object_new($control),
2655             "$parent,",
2656             "$id,",
2657             "$position,",
2658             "$size,",
2659             $self->window_style($control),
2660             ");",
2661             );
2662             }
2663              
2664              
2665              
2666              
2667              
2668             ######################################################################
2669             # Sizer Generators
2670              
2671             sub children_pack {
2672 31     31 0 191 my $self = shift;
2673 31         36 my $object = shift;
2674 31         49 my @children = ();
2675              
2676 31         94 foreach my $item ( @{$object->children} ) {
  31         114  
2677 98         4633 my $child = $item->children->[0];
2678 98 100       2300 if ( $child->isa('FBP::Sizer') ) {
    100          
    100          
    100          
    100          
    100          
    100          
    50          
2679 7         35 push @children, $self->sizer_pack($child);
2680             } elsif ( $child->isa('FBP::Choicebook') ) {
2681 1         5 push @children, $self->choicebook_pack($child);
2682             } elsif ( $child->isa('FBP::Listbook') ) {
2683 2         8 push @children, $self->listbook_pack($child);
2684             } elsif ( $child->isa('FBP::Notebook') ) {
2685 1         6 push @children, $self->notebook_pack($child);
2686             } elsif ( $child->isa('FBP::Panel') ) {
2687 13         33 push @children, $self->panel_pack($child);
2688             } elsif ( $child->isa('FBP::SplitterWindow') ) {
2689 1         7 push @children, $self->splitterwindow_pack($child);
2690             } elsif ( $child->isa('FBP::ScrolledWindow') ) {
2691 1         5 push @children, $self->scrolledwindow_pack($child);
2692             } elsif ( $child->does('FBP::Children') ) {
2693 0 0       0 if ( @{$child->children} ) {
  0         0  
2694 0         0 die "Unsupported parent " . ref($child);
2695             }
2696             }
2697             }
2698              
2699 31         1577 return @children;
2700             }
2701              
2702             sub sizer_pack {
2703 27     27 0 38 my $self = shift;
2704 27         42 my $sizer = shift;
2705              
2706 27 100       555 if ( $sizer->isa('FBP::GridBagSizer') ) {
    100          
    100          
    100          
    100          
    50          
2707 2         10 return $self->gridbagsizer_pack($sizer);
2708             } elsif ( $sizer->isa('FBP::FlexGridSizer') ) {
2709 1         7 return $self->flexgridsizer_pack($sizer);
2710             } elsif ( $sizer->isa('FBP::GridSizer') ) {
2711 1         12 return $self->gridsizer_pack($sizer);
2712             } elsif ( $sizer->isa('FBP::StaticBoxSizer') ) {
2713 1         7 return $self->staticboxsizer_pack($sizer);
2714             } elsif ( $sizer->isa('FBP::BoxSizer') ) {
2715 21         152 return $self->boxsizer_pack($sizer);
2716             } elsif ( $sizer->isa('FBP::StdDialogButtonSizer') ) {
2717 1         5 return $self->stddialogbuttonsizer_pack($sizer);
2718             } else {
2719 0         0 die "Unsupported sizer " . ref($sizer);
2720             }
2721             }
2722              
2723             # Packing for Listbook, Notebook and Treebook
2724             sub book_pack {
2725 4     4 0 9 my $self = shift;
2726 4         7 my $book = shift;
2727 4         10 my $variable = $self->object_variable($book);
2728              
2729             # Generate fragments for our child panels
2730 4         18 my @children = $self->children_pack($book);
2731              
2732             # Add each of our child pages
2733 4         8 my @lines = ();
2734 4         9 foreach my $item ( @{$book->children} ) {
  4         19  
2735 11         32 my $child = $item->children->[0];
2736 11 50       41 if ( $child->isa('FBP::Panel') ) {
2737 11 100       28 my $params = join(
2738             ', ',
2739             $self->object_variable($child),
2740             $self->object_label($item),
2741             $item->select ? 1 : 0,
2742             );
2743 11         54 push @lines, "$variable->AddPage( $params );";
2744              
2745             } else {
2746 0         0 die "Unknown or unsupported book child " . ref($child);
2747             }
2748             }
2749              
2750 4         46 return ( @children, \@lines );
2751             }
2752              
2753             sub boxsizer_pack {
2754 21     21 0 32 my $self = shift;
2755 21         28 my $sizer = shift;
2756 21         59 my $scope = $self->object_scope($sizer);
2757 21         61 my $variable = $self->object_variable($sizer);
2758 21         108 my $orient = $self->wx( $sizer->orient );
2759              
2760             # Add the content for all our child sizers
2761 21         114 my @children = $self->children_pack($sizer);
2762              
2763             # Add the content for this sizer
2764 21         125 my @lines = (
2765             "$scope$variable = Wx::BoxSizer->new($orient);",
2766             $self->object_minimum_size($sizer),
2767             );
2768 21         42 foreach my $item ( @{$sizer->children} ) {
  21         82  
2769 67         194 my $child = $item->children->[0];
2770 67 100       366 if ( $child->isa('FBP::Spacer') ) {
2771 2         21 my $params = join(
2772             ', ',
2773             $child->width,
2774             $child->height,
2775             $item->proportion,
2776             $self->wx( $item->flag ),
2777             $item->border,
2778             );
2779 2         11 push @lines, "$variable->Add( $params );";
2780             } else {
2781 65         154 my $params = join(
2782             ', ',
2783             $self->object_variable($child),
2784             $item->proportion,
2785             $self->wx( $item->flag ),
2786             $item->border,
2787             );
2788 65         338 push @lines, "$variable->Add( $params );";
2789             }
2790             }
2791              
2792 21         111 return ( @children, \@lines );
2793             }
2794              
2795             sub flexgridsizer_pack {
2796 1     1 0 2 my $self = shift;
2797 1         3 my $sizer = shift;
2798 1         3 my $scope = $self->object_scope($sizer);
2799 1         5 my $variable = $self->object_variable($sizer);
2800 1         9 my $direction = $self->wx( $sizer->flexible_direction );
2801 1         7 my $growmode = $self->wx( $sizer->non_flexible_grow_mode );
2802 1         16 my $params = join( ', ',
2803             $sizer->rows,
2804             $sizer->cols,
2805             $sizer->vgap,
2806             $sizer->hgap,
2807             );
2808              
2809             # Add the content for all our child sizers
2810 1         6 my @children = $self->children_pack($sizer);
2811              
2812             # Add the content for this sizer
2813 1         7 my @lines = (
2814             "$scope$variable = Wx::FlexGridSizer->new( $params );",
2815             $self->object_minimum_size($sizer),
2816             );
2817 1         8 foreach my $row ( split /\s*,\s*/, $sizer->growablerows ) {
2818 0         0 push @lines, "$variable->AddGrowableRow($row);";
2819             }
2820 1         17 foreach my $col ( split /\s*,\s*/, $sizer->growablecols ) {
2821 2         7 push @lines, "$variable->AddGrowableCol($col);";
2822             }
2823 1         3 push @lines, "$variable->SetFlexibleDirection($direction);";
2824 1         4 push @lines, "$variable->SetNonFlexibleGrowMode($growmode);";
2825 1         2 foreach my $item ( @{$sizer->children} ) {
  1         4  
2826 5         13 my $child = $item->children->[0];
2827 5 50       29 if ( $child->isa('FBP::Spacer') ) {
2828 0         0 my $params = join(
2829             ', ',
2830             $child->width,
2831             $child->height,
2832             $item->proportion,
2833             $self->wx( $item->flag ),
2834             $item->border,
2835             );
2836 0         0 push @lines, "$variable->Add( $params );";
2837             } else {
2838 5         10 my $params = join(
2839             ', ',
2840             $self->object_variable($child),
2841             $item->proportion,
2842             $self->wx( $item->flag ),
2843             $item->border,
2844             );
2845 5         27 push @lines, "$variable->Add( $params );";
2846             }
2847             }
2848              
2849 1         6 return ( @children, \@lines );
2850             }
2851              
2852             sub gridbagsizer_pack {
2853 2     2 0 4 my $self = shift;
2854 2         5 my $sizer = shift;
2855 2         6 my $scope = $self->object_scope($sizer);
2856 2         7 my $variable = $self->object_variable($sizer);
2857 2         15 my $direction = $self->wx( $sizer->flexible_direction );
2858 2         11 my $growmode = $self->wx( $sizer->non_flexible_grow_mode );
2859 2         31 my $params = join ', ', $sizer->vgap, $sizer->hgap;
2860              
2861             # Add the content for all our child sizers
2862 2         12 my @children = $self->children_pack($sizer);
2863              
2864             # Add the content for this sizer
2865 2         12 my @lines = (
2866             "$scope$variable = Wx::GridBagSizer->new( $params );",
2867             $self->object_minimum_size($sizer),
2868             );
2869 2         14 foreach my $row ( split /,/, $sizer->growablerows ) {
2870 0         0 push @lines, "$variable->AddGrowableRow($row);";
2871             }
2872 2         35 foreach my $col ( split /,/, $sizer->growablecols ) {
2873 0         0 push @lines, "$variable->AddGrowableCol($col);";
2874             }
2875 2         10 push @lines, "$variable->SetFlexibleDirection($direction);";
2876 2         15 push @lines, "$variable->SetNonFlexibleGrowMode($growmode);";
2877 2         4 foreach my $item ( @{$sizer->children} ) {
  2         9  
2878 8         43 my $child = $item->children->[0];
2879 8         27 my $row = $item->row;
2880 8         19 my $column = $item->column;
2881 8         21 my $rowspan = $item->rowspan;
2882 8         20 my $colspan = $item->colspan;
2883 8         38 my $flag = $self->wx( $item->flag );
2884 8         25 my $border = $item->border;
2885 8 100       41 if ( $child->isa('FBP::Spacer') ) {
2886 2         10 my $width = $child->width;
2887 2         9 my $height = $child->height;
2888 2         22 push @lines, $self->nested(
2889             "$variable->Add(",
2890             "$width,",
2891             "$height,",
2892             "Wx::GBPosition->new( $row, $column ),",
2893             "Wx::GBSpan->new( $rowspan, $colspan ),",
2894             "$flag,",
2895             "$border,",
2896             ");",
2897             );
2898             } else {
2899 6         20 push @lines, $self->nested(
2900             "$variable->Add(",
2901             $self->object_variable($child) . ',',
2902             "Wx::GBPosition->new( $row, $column ),",
2903             "Wx::GBSpan->new( $rowspan, $colspan ),",
2904             "$flag,",
2905             "$border,",
2906             ");",
2907             );
2908             }
2909             }
2910              
2911 2         14 return ( @children, \@lines );
2912             }
2913              
2914             sub gridsizer_pack {
2915 1     1 0 1 my $self = shift;
2916 1         3 my $sizer = shift;
2917 1         3 my $scope = $self->object_scope($sizer);
2918 1         3 my $variable = $self->object_variable($sizer);
2919 1         18 my $params = join( ', ',
2920             $sizer->rows,
2921             $sizer->cols,
2922             $sizer->vgap,
2923             $sizer->hgap,
2924             );
2925              
2926             # Add the content for all our child sizers
2927 1         3 my @children = $self->children_pack($sizer);
2928              
2929             # Add the content for this sizer
2930 1         8 my @lines = (
2931             "$scope$variable = Wx::GridSizer->new( $params );",
2932             $self->object_minimum_size($sizer),
2933             );
2934 1         3 foreach my $item ( @{$sizer->children} ) {
  1         6  
2935 4         13 my $child = $item->children->[0];
2936 4 50       27 if ( $child->isa('FBP::Spacer') ) {
2937 0         0 my $params = join(
2938             ', ',
2939             $child->width,
2940             $child->height,
2941             $item->proportion,
2942             $self->wx( $item->flag ),
2943             $item->border,
2944             );
2945 0         0 push @lines, "$variable->Add( $params );";
2946             } else {
2947 4         11 my $params = join(
2948             ', ',
2949             $self->object_variable($child),
2950             $item->proportion,
2951             $self->wx( $item->flag ),
2952             $item->border,
2953             );
2954 4         24 push @lines, "$variable->Add( $params );";
2955             }
2956             }
2957              
2958 1         6 return ( @children, \@lines );
2959             }
2960              
2961             sub stddialogbuttonsizer_pack {
2962 1     1 0 1 my $self = shift;
2963 1         2 my $sizer = shift;
2964 1         3 my $scope = $self->object_scope($sizer);
2965 1         4 my $variable = $self->object_variable($sizer);
2966              
2967             # Create the sizer (it can't have child sizers)
2968 1         3 my @lines = ();
2969 1         6 foreach my $button ( $self->stddialogbuttonsizer_buttons($sizer) ) {
2970 3         7 my $button_variable = $self->object_variable($button);
2971 3         15 push @lines, "$variable->AddButton( $button_variable );";
2972             }
2973              
2974             return [
2975 1         16 "$scope$variable = Wx::StdDialogButtonSizer->new;",
2976             $self->object_minimum_size($sizer),
2977             @lines,
2978             "$variable->Realize;",
2979             ];
2980             }
2981              
2982             sub choicebook_pack {
2983 1     1 0 4 shift->book_pack(@_);
2984             }
2985              
2986             sub listbook_pack {
2987 2     2 0 8 shift->book_pack(@_);
2988             }
2989              
2990             sub notebook_pack {
2991 1     1 0 5 shift->book_pack(@_);
2992             }
2993              
2994             sub panel_pack {
2995 13     13 0 15 my $self = shift;
2996 13         15 my $panel = shift;
2997 13 100       101 my $sizer = $panel->children->[0] or return ();
2998 12         26 my $variable = $self->object_variable($panel);
2999 12         32 my $sizervar = $self->object_variable($sizer);
3000 12         37 my $setsize = $self->window_setsize($panel);
3001              
3002             # Generate fragments for our (optional) child sizer
3003 12         36 my @children = $self->sizer_pack($sizer);
3004              
3005             # Attach the sizer to the panel
3006             return (
3007 12         102 @children,
3008             [
3009             "$variable->$setsize($sizervar);",
3010             "$variable->Layout;",
3011             ]
3012             );
3013             }
3014              
3015             sub scrolledwindow_pack {
3016 1     1 0 2 my $self = shift;
3017 1         2 my $window = shift;
3018 1 50       17 my $sizer = $window->children->[0] or return ();
3019 1         4 my $variable = $self->object_variable($window);
3020 1         5 my $sizervar = $self->object_variable($sizer);
3021 1         18 my $setsize = $self->window_setsize($window);
3022              
3023             # Generate fragments for our (optional) child sizer
3024 1         7 my @children = $self->sizer_pack($sizer);
3025              
3026             # Attach the sizer to the panel
3027             return (
3028 1         28 @children,
3029             [
3030             "$variable->$setsize($sizervar);",
3031             "$variable->Layout;",
3032             ],
3033             );
3034             }
3035              
3036             sub splitterwindow_pack {
3037 1     1 0 17 my $self = shift;
3038 1         3 my $window = shift;
3039 1         10 my $variable = $self->object_variable($window);
3040 1         4 my @windows = map { $_->children->[0] } @{$window->children};
  2         12  
  1         235  
3041              
3042             # Add the content for all our child sizers
3043 1         4 my @children = $self->children_pack($window);
3044              
3045 1 50       5 if ( @windows == 1 ) {
3046             # One child window
3047 0         0 my $window1 = $self->object_variable($windows[0]);
3048             return (
3049 0         0 @children,
3050             [
3051             "$variable->Initialize(",
3052             "\t$window1,",
3053             ");",
3054             ],
3055             );
3056             }
3057              
3058 1 50       4 if ( @windows == 2 ) {
3059             # Two child windows
3060 1         6 my $sashpos = $window->sashpos;
3061 1         4 my $window1 = $self->object_variable($windows[0]);
3062 1         7 my $window2 = $self->object_variable($windows[1]);
3063 1 50       8 my $method = $window->splitmode eq 'wxSPLIT_HORIZONTAL'
3064             ? 'SplitHorizontally'
3065             : 'SplitVertically';
3066             return (
3067 1 50       16 @children,
3068             [
3069             "$variable->$method(",
3070             "\t$window1,",
3071             "\t$window2,",
3072             ( $sashpos ? "\t$sashpos," : () ),
3073             ");",
3074             ],
3075             );
3076             }
3077              
3078 0         0 die "Unexpected number of splitterwindow children";
3079             }
3080              
3081             sub staticboxsizer_pack {
3082 1     1 0 3 my $self = shift;
3083 1         2 my $sizer = shift;
3084 1         3 my $scope = $self->object_scope($sizer);
3085 1         4 my $variable = $self->object_variable($sizer);
3086 1         5 my $label = $self->object_label($sizer);
3087 1         10 my $orient = $self->wx( $sizer->orient );
3088              
3089             # Add the content for all our child sizers
3090 1         4 my @children = $self->children_pack($sizer);
3091              
3092             # Add the content for this sizer
3093 1         10 my @lines = (
3094             "$scope$variable = Wx::StaticBoxSizer->new(",
3095             "\tWx::StaticBox->new(",
3096             "\t\t\$self,",
3097             "\t\t-1,",
3098             "\t\t$label,",
3099             "\t),",
3100             "\t$orient,",
3101             ");",
3102             $self->object_minimum_size($sizer),
3103             );
3104 1         2 foreach my $item ( @{$sizer->children} ) {
  1         5  
3105 1         5 my $child = $item->children->[0];
3106 1 50       8 if ( $child->isa('FBP::Spacer') ) {
3107 0         0 my $params = join(
3108             ', ',
3109             $child->width,
3110             $child->height,
3111             $item->proportion,
3112             $self->wx( $item->flag ),
3113             $item->border,
3114             );
3115 0         0 push @lines, "$variable->Add( $params );";
3116             } else {
3117 1         3 my $params = join(
3118             ', ',
3119             $self->object_variable($child),
3120             $item->proportion,
3121             $self->wx( $item->flag ),
3122             $item->border,
3123             );
3124 1         15 push @lines, "$variable->Add( $params );";
3125             }
3126             }
3127              
3128 1         6 return ( @children, \@lines );
3129             }
3130              
3131              
3132              
3133              
3134              
3135             ######################################################################
3136             # Window Statement Fragments
3137              
3138             sub window_changes {
3139 96     96 0 131 my $self = shift;
3140 96         120 my $window = shift;
3141 96         143 my @lines = ();
3142              
3143 96         221 push @lines, $self->window_selection($window);
3144 96         233 push @lines, $self->object_minimum_size($window);
3145 96         206 push @lines, $self->object_maximum_size($window);
3146 96         224 push @lines, $self->window_fg($window);
3147 96         214 push @lines, $self->window_bg($window);
3148 96         223 push @lines, $self->window_font($window);
3149 96         212 push @lines, $self->window_tooltip($window);
3150 96         215 push @lines, $self->window_disable($window);
3151 96         210 push @lines, $self->window_hide($window);
3152              
3153 96         178 return @lines;
3154             }
3155              
3156             sub window_selection {
3157 96     96 0 110 my $self = shift;
3158 96         112 my $window = shift;
3159              
3160 96 100       788 if ( $window->can('selection') ) {
3161 2         5 my $variable = $self->object_variable($window);
3162 2   100     15 my $selection = $window->selection || 0;
3163             return (
3164 2         9 "$variable->SetSelection($selection);",
3165             );
3166             }
3167              
3168 94         182 return;
3169             }
3170              
3171             sub window_fg {
3172 96     96 0 119 my $self = shift;
3173 96         121 my $window = shift;
3174              
3175 96 100       524 if ( $window->fg ) {
3176 1         4 my $variable = $self->object_variable($window);
3177 1         6 my $colour = $self->colour( $window->fg );
3178             return (
3179 1         6 "$variable->SetForegroundColour(",
3180             "\t$colour",
3181             ");",
3182             );
3183             };
3184              
3185 95         140 return;
3186             }
3187              
3188             sub window_bg {
3189 96     96 0 127 my $self = shift;
3190 96         98 my $window = shift;
3191              
3192 96 100       569 if ( $window->bg ) {
3193 3         11 my $variable = $self->object_variable($window);
3194 3         20 my $colour = $self->colour( $window->bg );
3195             return (
3196 3         19 "$variable->SetBackgroundColour(",
3197             "\t$colour",
3198             ");",
3199             );
3200             };
3201              
3202 93         139 return;
3203             }
3204              
3205             sub window_font {
3206 96     96 0 128 my $self = shift;
3207 96         102 my $window = shift;
3208              
3209 96 100       551 if ( $window->font ) {
3210 1         4 my $variable = $self->object_variable($window);
3211 1         8 my $font = $self->font( $window->font );
3212             return (
3213 1         6 "$variable->SetFont(",
3214             "\t$font",
3215             ");",
3216             );
3217             }
3218              
3219 95         169 return;
3220             }
3221              
3222             sub window_tooltip {
3223 96     96 0 105 my $self = shift;
3224 96         106 my $window = shift;
3225              
3226 96 100       544 if ( $window->tooltip ) {
3227 3         8 my $variable = $self->object_variable($window);
3228 3         13 my $tooltip = $self->text( $window->tooltip );
3229             return (
3230 3         14 "$variable->SetToolTip(",
3231             "\t$tooltip",
3232             ");",
3233             );
3234             }
3235              
3236 93         147 return;
3237             }
3238              
3239             sub window_disable {
3240 96     96 0 115 my $self = shift;
3241 96         99 my $window = shift;
3242              
3243 96 100       507 unless ( $window->enabled ) {
3244 2         24 my $variable = $self->object_variable($window);
3245             return (
3246 2         7 "$variable->Disable;",
3247             );
3248             }
3249              
3250 94         136 return;
3251             }
3252              
3253             sub window_hide {
3254 96     96 0 119 my $self = shift;
3255 96         98 my $window = shift;
3256              
3257 96 100       537 if ( $window->hidden ) {
3258 1         3 my $variable = $self->object_variable($window);
3259             return (
3260 1         3 "$variable->Hide;",
3261             );
3262             }
3263              
3264 95         168 return;
3265             }
3266              
3267             sub object_bindings {
3268 101     101 0 138 my $self = shift;
3269 101         117 my $object = shift;
3270 28 50       152 return map {
3271 15251 100       92010 $CONNECT{$_}
3272             ? $self->object_connect( $object, $_ )
3273             : $self->object_macro( $object, $_ )
3274             } grep {
3275 101         9512 $object->can($_) and $object->$_()
3276             } sort keys %MACRO;
3277             }
3278              
3279             sub object_macro {
3280 28     28 0 45 my $self = shift;
3281 28         40 my $object = shift;
3282 28         39 my $attribute = shift;
3283 28         88 my $variable = $self->object_variable($object);
3284 28 50       163 my $method = $object->$attribute() or return;
3285              
3286             # Add the binding for it
3287 28         79 my $args = $MACRO{$attribute}->[0];
3288 28         55 my $macro = $MACRO{$attribute}->[1];
3289 28 100       87 if ( $args == 2 ) {
3290             return (
3291 16         214 "",
3292             "Wx::Event::$macro(",
3293             "\t\$self,",
3294             "\t$variable,",
3295             "\tsub {",
3296             "\t\tshift->$method(\@_);",
3297             "\t},",
3298             ");",
3299             );
3300             }
3301 12 100       42 if ( $variable eq '$self' ) {
3302             return (
3303 10         106 "",
3304             "Wx::Event::$macro(",
3305             "\t\$self,",
3306             "\tsub {",
3307             "\t\tshift->$method(\@_);",
3308             "\t},",
3309             ");",
3310             );
3311             }
3312              
3313             # Using $self here is a cop out but ok for now
3314             return (
3315 2         17 "",
3316             "Wx::Event::$macro(",
3317             "\t$variable,",
3318             "\tsub {",
3319             "\t\t\$self->$method(\$_[1]);",
3320             "\t},",
3321             ");",
3322             );
3323             }
3324              
3325             sub object_minimum_size {
3326 123     123 0 157 my $self = shift;
3327 123         125 my $object = shift;
3328 123         573 my $minimum = $object->minimum_size;
3329              
3330 123 100 66     348 if ( $minimum and $self->size($minimum) ) {
3331 1         4 my $variable = $self->object_variable($object);
3332 1         5 my $size = $self->wxsize($minimum);
3333             return (
3334 1         8 "$variable->SetMinSize( $size );",
3335             );
3336             }
3337              
3338 122         227 return;
3339             }
3340              
3341             sub object_maximum_size {
3342 96     96 0 116 my $self = shift;
3343 96         96 my $object = shift;
3344 96         457 my $maximum = $object->maximum_size;
3345              
3346 96 50 33     237 if ( $maximum and $self->size($maximum) ) {
3347 0         0 my $variable = $self->object_variable($object);
3348 0         0 my $size = $self->wxsize($maximum);
3349             return (
3350 0         0 "$variable->SetMaxSize( $size );",
3351             );
3352             }
3353              
3354 96         135 return;
3355             }
3356              
3357             sub object_connect {
3358 0     0 0 0 my $self = shift;
3359 0         0 my $object = shift;
3360 0         0 my $attribute = shift;
3361 0         0 my $variable = $self->object_variable($object);
3362 0 0       0 my $method = $object->$attribute() or return;
3363 0 0       0 my $constant = $CONNECT{$attribute} or return;
3364              
3365             return (
3366 0         0 "",
3367             "\$self->Connect(",
3368             "\t$variable,",
3369             "\t-1,",
3370             "\tWx::$constant,",
3371             "\tsub {",
3372             "\t\tshift->$method(\@_);",
3373             "\t},",
3374             ");",
3375             );
3376             }
3377              
3378              
3379              
3380              
3381              
3382             ######################################################################
3383             # Window Fragment Generators
3384              
3385             sub object_lexical {
3386 493     493 0 31652 $_[1]->permission !~ /^(?:protected|public)\z/;
3387             }
3388              
3389             sub object_label {
3390 54     54 0 303 $_[0]->text( $_[1]->label );
3391             }
3392              
3393             sub object_scope {
3394 122     122 0 150 my $self = shift;
3395 122         119 my $object = shift;
3396 122 100       220 if ( $self->object_lexical($object) ) {
3397 28         70 return 'my ';
3398             } else {
3399 94         217 return '';
3400             }
3401             }
3402              
3403             sub object_variable {
3404 382     382 0 465 my $self = shift;
3405 382         430 my $object = shift;
3406 382 100       1133 if ( $object->does('FBP::Form') ) {
    100          
3407 12         456 return '$self';
3408             } elsif ( $self->object_lexical($object) ) {
3409 59         318 return '$' . $object->name;
3410             } else {
3411 311         2080 return '$self->{' . $object->name . '}';
3412             }
3413             }
3414              
3415             sub object_parent {
3416 95     95 0 129 my $self = shift;
3417 95         114 my $object = shift;
3418 95 100 100     548 if ( $object and not $object->does('FBP::Form') ) {
3419 54         4480 return $self->object_variable($object);
3420             } else {
3421 41         1553 return '$self';
3422             }
3423             }
3424              
3425             sub object_position {
3426 76     76 0 113 my $self = shift;
3427 76         76 my $object = shift;
3428 76         450 my $position = $object->pos;
3429 76 50       158 unless ( $position ) {
3430 76         152 return $self->wx('wxDefaultPosition');
3431             }
3432 0         0 $position =~ s/,/, /;
3433 0         0 return "[ $position ]";
3434             }
3435              
3436             sub object_wxsize {
3437 76     76 0 162 my $self = shift;
3438 76         83 my $object = shift;
3439 76         491 return $self->wxsize($object->size);
3440             }
3441              
3442             # Is an object a top level project asset.
3443             # i.e. A Dialog, Frame or top level Panel
3444             sub object_top {
3445 0     0 0 0 my $self = shift;
3446 0         0 my $object = shift;
3447 0 0       0 return 1 if $object->isa('FBP::Dialog');
3448 0 0       0 return 1 if $object->isa('FBP::Frame');
3449 0         0 return 0;
3450             }
3451              
3452             sub object_new {
3453 90     90 0 133 my $self = shift;
3454 90         115 my $object = shift;
3455 90         184 my $scope = $self->object_scope($object);
3456 90         204 my $variable = $self->object_variable($object);
3457 90         549 my $wxclass = $object->wxclass;
3458 90         1867 return "$scope$variable = $wxclass->new(";
3459             }
3460              
3461             sub window_new {
3462 0     0 0 0 my $self = shift;
3463 0         0 my $window = shift;
3464 0         0 my $parent = $self->object_parent(@_);
3465 0         0 my $id = $self->object_id($window);
3466             return (
3467 0         0 $self->object_new($window),
3468             "$parent,",
3469             "$id,",
3470             );
3471             }
3472              
3473             sub window_style {
3474 73     73 0 100 my $self = shift;
3475 73         97 my $window = shift;
3476 73         172 my $default = shift;
3477 73   66     399 my $styles = $window->styles || $default;
3478              
3479 73 100 66     1915 if ( defined $styles and length $styles ) {
3480 50         120 return $self->wx($styles) . ',';
3481             }
3482              
3483 23         130 return;
3484             }
3485              
3486             sub window_setsize {
3487 20     20 0 35 my $self = shift;
3488 20         28 my $window = shift;
3489 20 100       104 return 'SetSizer' if $self->size( $window->size );
3490 16         37 return 'SetSizerAndFit';
3491             }
3492              
3493             sub object_id {
3494 103     103 0 159 my $self = shift;
3495 103         113 my $object = shift;
3496 103         709 return $self->wx( $object->id );
3497             }
3498              
3499             sub object_accessor {
3500 1     1 0 3 my $self = shift;
3501 1         2 my $object = shift;
3502 1         5 my $name = $object->name;
3503              
3504 1         15 return $self->nested(
3505             "sub $name {",
3506             "\$_[0]->{$name};",
3507             "}",
3508             );
3509             }
3510              
3511             sub object_bitmap {
3512 4     4 0 9 my $self = shift;
3513 4         8 my $object = shift;
3514 4         28 return $self->bitmap( $object->bitmap );
3515             }
3516              
3517             sub object_event {
3518 26     26 0 53 my $self = shift;
3519 26         34 my $window = shift;
3520 26         37 my $event = shift;
3521 26         79 my $name = $window->name;
3522 26         75 my $method = $window->$event();
3523              
3524 26         214 return $self->nested(
3525             "sub $method {",
3526             "warn 'Handler method $method for event $name.$event not implemented';",
3527             "}",
3528             );
3529             }
3530              
3531             sub control_items {
3532 4     4 0 6 my $self = shift;
3533 4         4 my $control = shift;
3534 4         28 my @items = $control->items;
3535 4 100       105 unless ( @items ) {
3536 2         4 return '[],';
3537             }
3538              
3539 8         16 return $self->nested(
3540             '[',
3541 2         5 ( map { $self->quote($_) . ',' } @items ),
3542             '],',
3543             );
3544             }
3545              
3546              
3547              
3548              
3549              
3550             ######################################################################
3551             # Support Methods
3552              
3553             sub list {
3554 5     5 0 13 my $self = shift;
3555 5         79 my @list = $_[0] =~ /" ( (?: \\. | . )+? ) "/xg;
3556 5         17 foreach ( @list ) {
3557 16         34 s/\\(.)/$1/g;
3558             }
3559 5         52 return @list;
3560             }
3561              
3562             sub ourisa {
3563 8     8 0 18 my $self = shift;
3564              
3565             # Complex inheritance
3566 8 50       39 if ( @_ > 1 ) {
3567             return [
3568 0         0 "our \@ISA = qw{",
3569 0         0 ( map { "\t$_" } @_ ),
3570             "};",
3571             ];
3572             }
3573              
3574             # Simple inheritance
3575 8 50       45 if ( @_ ) {
3576             return [
3577 8         49 "our \@ISA = '$_[0]';",
3578             ];
3579             }
3580              
3581             # No inheritance
3582 0         0 return [ ];
3583             }
3584              
3585             sub wx {
3586 447     447 0 669 my $self = shift;
3587 447         564 my $string = shift;
3588 447 100       938 return 0 if $string eq '';
3589 445 100       966 return -1 if $string eq 'wxID_ANY';
3590              
3591             # Apply constant prefix policy
3592 345 100       674 if ( $self->prefix ) {
3593             # The capture here keeps Wx::WXK_KEYNAME sane
3594 54         445 $string =~ s/\b(wx[A-Z])/Wx::$1/g;
3595             } else {
3596             # For a limited group of constants we must be explicit
3597 291         504 $string =~ s/\bwxMAC\b/Wx::wxMAC/;
3598             }
3599              
3600             # Tidy a collection of multiple constants
3601 345         731 $string =~ s/\s*\|\s*/ | /g;
3602              
3603 345         1554 return $string;
3604             }
3605              
3606             sub text {
3607 78     78 0 111 my $self = shift;
3608 78         163 my $string = shift;
3609 78 100 66     458 unless ( defined $string and length $string ) {
3610 4         10 return "''";
3611             }
3612              
3613             # Handle the simple boring case
3614 74 100       199 unless ( $self->i18n ) {
3615 15         38 return $self->quote($string);
3616             }
3617              
3618             # Trim off leading and trailing punctuation
3619 59         120 my $leading = '';
3620 59         87 my $trailing = '';
3621 59 100       134 if ( $self->i18n_trim ) {
3622 4 50       22 if ( $string =~ /^[ :]+\z/ ) {
3623 0         0 return $self->quote($string);
3624             }
3625 4 100       17 if ( $string =~ s/^([ :]+)//s ) {
3626 1         6 $leading = $self->quote("$1");
3627             }
3628 4 100       40 if ( $string =~ s/(\s*\.\.\.)\z//s ) {
    100          
3629 1         6 $trailing = $self->quote("$1");
3630             } elsif ( $string =~ s/([ :]+)\z//s ) {
3631 2         8 $trailing = $self->quote("$1");
3632             }
3633             }
3634              
3635             # Translate the remaining part of the string
3636 59         190 $string = $self->quote($string);
3637 59         171 $string = "Wx::gettext($string)";
3638              
3639             # Put leading and trailing punctuation back on
3640 59 100       135 if ( length $leading ) {
3641 1         3 $string = "$leading . $string";
3642             }
3643 59 100       128 if ( length $trailing ) {
3644 3         7 $string = "$string . $trailing";
3645             }
3646              
3647 59         237 return $string;
3648             }
3649              
3650             # This gets tricky if you ever hit weird characters
3651             # or Unicode, so hand off to an expert.
3652             # The only reason this is a standalone method is so that
3653             # specialised subclasses can change it if desired.
3654             sub quote {
3655 115     115 0 6948 my $self = shift;
3656 115         165 my $string = shift;
3657 115         779 my $code = B::perlstring($string);
3658 115 50       321 return $code unless $self->project_utf8;
3659              
3660             # Attempt to convert the escaped string into unicode
3661 115         204 my $unicode = $code;
3662 115         904 my $found = $unicode =~ s/
3663             ( \\\\ | (?: \\x\{[0-9a-f]{3,}\} )+ )
3664             /
3665 15 100       675 length($1) > 2 ? eval("\"$1\"") : $1
3666             /gex;
3667              
3668 115 100       548 return $code unless utf8::is_utf8($unicode);
3669 5         19 return $unicode;
3670             }
3671              
3672             sub wxsize {
3673 77     77 0 97 my $self = shift;
3674 77         165 my $string = $self->size(shift);
3675 77 100       262 return $self->wx('wxDefaultSize') unless $string;
3676 7         43 $string =~ s/,/, /;
3677 7         28 return "[ $string ]";
3678             }
3679              
3680             sub size {
3681 108     108 0 137 my $self = shift;
3682 108         156 my $string = shift;
3683 108 50       247 return '' unless defined $string;
3684 108 100       278 return '' if $string eq '-1,-1';
3685 100         287 return $string;
3686             }
3687              
3688             sub colour {
3689 12     12 0 24 my $self = shift;
3690 12         29 my $string = shift;
3691              
3692             # Default colour
3693 12 50       54 unless ( length $string ) {
3694 0         0 return 'undef';
3695             }
3696              
3697             # Explicit colour
3698 12 100       95 if ( $string =~ /^\d/ ) {
3699 8         108 $string =~ s/,(\d)/, $1/g; # Space the numbers a bit
3700 8         52 return "Wx::Colour->new( $string )";
3701             }
3702              
3703             # System colour
3704 4 50       25 if ( $string =~ /^wx/ ) {
3705 4         12 my $string = $self->wx($string);
3706 4         19 return "Wx::SystemSettings::GetColour( $string )";
3707             }
3708              
3709 0         0 die "Invalid or unsupported colour '$string'";
3710             }
3711              
3712             sub font {
3713 3     3 0 6 my $self = shift;
3714 3         6 my $string = shift;
3715              
3716             # Default font
3717 3 100       9 unless ( length $string ) {
3718 1         53 return $self->wx('wxNullFont');
3719             }
3720              
3721             # Generate a font from the overcompact FBP format.
3722             # It will probably look something like ",90,92,-1,70,0"
3723 2         15 my @font = split /,/, $string;
3724 2 50       9 if ( @font == 6 ) {
3725 2         4 my $point_size = $font[3];
3726 2         4 my $family = $font[4];
3727 2         3 my $style = $font[1];
3728 2         4 my $weight = $font[2];
3729 2         3 my $underlined = $font[5];
3730 2         4 my $face_name = $font[0];
3731 2         8 my $params = join( ', ',
3732             $self->points($point_size),
3733             $family,
3734             $style,
3735             $weight,
3736             $underlined,
3737             $self->quote($face_name),
3738             );
3739 2         12 return "Wx::Font->new( $params )";
3740             }
3741              
3742 0         0 die "Invalid or unsupported font '$string'";
3743             }
3744              
3745             sub points {
3746 2     2 0 2 my $self = shift;
3747 2         5 my $size = shift;
3748 2 50 33     18 if ( $size and $size > 0 ) {
3749 0         0 return $size;
3750             }
3751 2         4 $self->wx('wxNORMAL_FONT') . '->GetPointSize';
3752             }
3753              
3754             sub bitmap {
3755 11     11 0 18 my $self = shift;
3756 11         28 my $file = $self->file(shift);
3757 11 100       29 unless ( defined $file ) {
3758 3         10 return $self->wx('wxNullBitmap');
3759             }
3760              
3761             # Use the file path exactly as is for now
3762 8         19 my $type = $self->wx('wxBITMAP_TYPE_ANY');
3763 8         29 return "Wx::Bitmap->new( $file, $type )";
3764             }
3765              
3766             sub animation {
3767 1     1 0 2 my $self = shift;
3768 1         2 my $string = shift;
3769 1 50       7 unless ( Params::Util::_STRING($string) ) {
3770 1         3 return $self->wx('wxNullAnimation');
3771             }
3772              
3773             ### To be completed
3774 0         0 return $self->wx('wxNullAnimation');
3775             }
3776              
3777             sub file {
3778 11     11 0 14 my $self = shift;
3779 11         25 my $string = shift;
3780 11 100       49 return undef unless Params::Util::_STRING($string);
3781 8 50       58 return undef unless $string =~ s/; Load From File$//;
3782 8         24 return $self->quote($string);
3783             }
3784              
3785             sub indent {
3786 16 100       112 map { /\S/ ? "\t$_" : $_ } (
  0         0  
3787 3 50   3 0 16 ref($_[1]) ? @{$_[1]} : @_[1..$#_]
3788             );
3789             }
3790              
3791             # Indent except for the first and last lines.
3792             # Return as an array reference.
3793             sub nested {
3794 148     148 0 265 my $self = shift;
3795 148 100       246 my @lines = map { ref $_ ? @$_ : $_ } @_;
  2233         4411  
3796 148         308 my $top = shift @lines;
3797 148         197 my $bottom = pop @lines;
3798             return [
3799 2051 100       12849 $top,
3800 148         225 ( map { /\S/ ? "\t$_" : $_ } @lines ),
3801             $bottom,
3802             ];
3803             }
3804              
3805             sub flatten {
3806 0     0 0 0 join '', map { "$_\n" } @{$_[1]};
  0         0  
  0         0  
3807             }
3808              
3809             # Are there any FBP objects of a particular type in a FBP tree
3810             # that do NOT use a custom subclass.
3811             sub find_plain {
3812 34     34 0 4721 my $self = shift;
3813 34         49 my $topic = shift;
3814 34         48 my $plain = shift;
3815              
3816             # Search for all objects of that type
3817 4         35988 return !! scalar grep {
3818 34         125 not $_->subclass
3819             } $topic->find( isa => $plain );
3820             }
3821              
3822             1;
3823              
3824             =pod
3825              
3826             =head1 SUPPORT
3827              
3828             Bugs should be reported via the CPAN bug tracker at
3829              
3830             L
3831              
3832             For other issues, or commercial enhancement or support, contact the author.
3833              
3834             =head1 AUTHOR
3835              
3836             Adam Kennedy Eadamk@cpan.orgE
3837              
3838             =head1 COPYRIGHT
3839              
3840             Copyright 2010 - 2012 Adam Kennedy.
3841              
3842             This program is free software; you can redistribute
3843             it and/or modify it under the same terms as Perl itself.
3844              
3845             The full text of the license can be found in the
3846             LICENSE file included with this module.
3847              
3848             =cut