wx_sugar 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,392 @@
1
+ # = WxSugar - Keyword Constructors Classes
2
+ #
3
+ # This extension defines the keyword parameters for +new+ methods for
4
+ # widgets, windows and frames. It's for use with *Keyword Constructors*
5
+ # and is no use on its own - except if you are looking for a bug or want
6
+ # to add a missing class.
7
+
8
+ # This is a dummy, this variable is not loaded until Wx init
9
+ Wx::NULL_BITMAP = nil
10
+
11
+ module WxSugar
12
+ # accepts a string unadorned name of a WxWidgets class, and block, which
13
+ # defines the constructor parameters and style flags for that class.
14
+ # If the named class exists in the available WxRuby, the block is run and
15
+ # the class may use keyword constructors. If the class is not available, the
16
+ # block is ignored.
17
+ def self.define_keyword_ctors(klass_name, &block)
18
+ begin
19
+ klass = Wx::const_get(klass_name)
20
+ rescue NameError
21
+ return nil
22
+ end
23
+ klass.module_eval { include WxSugar::KeywordConstructor }
24
+ # automatically add :id as the first argument, unless this is a
25
+ # Dialog subclass - which don't require this argument
26
+ unless klass < Wx::Dialog
27
+ klass.wx_ctor_params :id
28
+ end
29
+ klass.instance_eval(&block)
30
+ end
31
+ end
32
+
33
+ ### FRAMES
34
+ # Normal frame
35
+
36
+ # wxTopLevelWindow ABSTRACT: Any top level window, dialog or frame
37
+
38
+ # Dialog box
39
+ WxSugar.define_keyword_ctors('Dialog') do
40
+ wx_ctor_params :title => ''
41
+ wx_ctor_params :pos, :size, :style => Wx::DEFAULT_DIALOG_STYLE
42
+ wx_ctor_params :name => 'dialogBox'
43
+ end
44
+
45
+ # Normal frame
46
+ WxSugar.define_keyword_ctors('Frame') do
47
+ wx_ctor_params :title => ''
48
+ wx_ctor_params :pos, :size, :style => Wx::DEFAULT_FRAME_STYLE
49
+ wx_ctor_params :name => 'frame'
50
+ end
51
+
52
+ # MDI child frame
53
+ WxSugar.define_keyword_ctors('MDIChildFrame') do
54
+ wx_ctor_params :title => ''
55
+ wx_ctor_params :pos, :size, :style => Wx::DEFAULT_FRAME_STYLE
56
+ wx_ctor_params :name => 'frame'
57
+ end
58
+
59
+ # MDI parent frame
60
+ WxSugar.define_keyword_ctors('MDIParentFrame') do
61
+ wx_ctor_params :title => ''
62
+ wx_ctor_params :pos, :size
63
+ wx_ctor_params :style => Wx::DEFAULT_FRAME_STYLE|Wx::VSCROLL|Wx::HSCROLL
64
+ wx_ctor_params :name => 'frame'
65
+ end
66
+
67
+ # wxMiniFrame A frame with a small title bar
68
+ WxSugar.define_keyword_ctors('MiniFrame') do
69
+ wx_ctor_params :title => ''
70
+ wx_ctor_params :pos, :size
71
+ wx_ctor_params :style => Wx::DEFAULT_FRAME_STYLE
72
+ wx_ctor_params :name => 'frame'
73
+ end
74
+
75
+ # wxSplashScreen Splash screen class
76
+ # wxPropertySheetDialog Property sheet dialog
77
+ # wxTipWindow Shows text in a small window
78
+
79
+ # wxWizard A wizard dialog
80
+ WxSugar.define_keyword_ctors('Wizard') do
81
+ wx_ctor_params :title => ''
82
+ wx_ctor_params :bitmap => Wx::NULL_BITMAP
83
+ wx_ctor_params :pos, :size
84
+ wx_ctor_params :style => Wx::DEFAULT_DIALOG_STYLE
85
+ end
86
+
87
+
88
+ # MISCELLANEOUS WINDOWS
89
+
90
+ # A window whose colour changes according to current user settings
91
+ WxSugar.define_keyword_ctors('Panel') do
92
+ wx_ctor_params :pos, :size, :style => Wx::TAB_TRAVERSAL
93
+ wx_ctor_params :name => 'panel'
94
+ end
95
+
96
+ # wxScrolledWindow Window with automatically managed scrollbars
97
+ WxSugar.define_keyword_ctors('ScrolledWindow') do
98
+ wx_ctor_params :pos, :size, :style => Wx::VSCROLL|Wx::HSCROLL
99
+ wx_ctor_params :name => 'scrolledWindow'
100
+ wx_ctor_flags :h_scroll => Wx::HSCROLL,
101
+ :v_scroll => Wx::VSCROLL
102
+ end
103
+
104
+ # wxGrid A grid (table) window
105
+ WxSugar.define_keyword_ctors('Grid') do
106
+ wx_ctor_params :pos, :size, :style => Wx::WANTS_CHARS
107
+ wx_ctor_params :name => 'grid'
108
+ end
109
+
110
+ # Window which can be split vertically or horizontally
111
+ WxSugar.define_keyword_ctors('SplitterWindow') do
112
+ wx_ctor_params :pos, :size, :style => Wx::SP_3D
113
+ wx_ctor_params :name => 'splitterWindow'
114
+ end
115
+
116
+ # Implements the status bar on a frame
117
+ WxSugar.define_keyword_ctors('StatusBar') do
118
+ wx_ctor_params :style => Wx::ST_SIZEGRIP
119
+ wx_ctor_params :name => 'statusBar'
120
+ end
121
+
122
+ # Toolbar class
123
+ WxSugar.define_keyword_ctors('ToolBar') do
124
+ wx_ctor_params :pos, :size, :style => Wx::TB_HORIZONTAL|Wx::NO_BORDER
125
+ wx_ctor_params :name => 'toolBar' # not as documented in Wx 2.6.3
126
+ end
127
+
128
+ # Notebook class
129
+ WxSugar.define_keyword_ctors('Notebook') do
130
+ wx_ctor_params :pos, :size, :style, :name => 'noteBook'
131
+ end
132
+
133
+ # Similar to notebook but using list control - undocumented
134
+ WxSugar.define_keyword_ctors('Listbook') do
135
+ wx_ctor_params :pos, :size, :style, :name => 'listBook'
136
+ end
137
+
138
+ # Similar to notebook but using choice control
139
+ WxSugar.define_keyword_ctors('Choicebook') do
140
+ wx_ctor_params :pos, :size, :style, :name => 'choiceBook'
141
+ end
142
+
143
+ # wxSashWindow: Window with four optional sashes that can be dragged
144
+ WxSugar.define_keyword_ctors('SashWindow') do
145
+ wx_ctor_params :pos, :size
146
+ wx_ctor_params :style => Wx::CLIP_CHILDREN|Wx::SW_3D
147
+ wx_ctor_params :name => 'sashWindow'
148
+ end
149
+
150
+ # wxSashLayoutWindow: Window that can be involved in an IDE-like layout
151
+ # arrangement
152
+ WxSugar.define_keyword_ctors('SashWindow') do
153
+ wx_ctor_params :pos, :size
154
+ wx_ctor_params :style => Wx::CLIP_CHILDREN|Wx::SW_3D
155
+ wx_ctor_params :name => 'layoutWindow'
156
+ end
157
+
158
+ # wxVScrolledWindow: As wxScrolledWindow but supports lines of variable height
159
+
160
+ # wxWizardPage: A base class for the page in wizard dialog.
161
+ WxSugar.define_keyword_ctors('WizardPage') do
162
+ wx_ctor_params :bitmap => Wx::NULL_BITMAP
163
+ end
164
+
165
+ # wxWizardPageSimple: A page in wizard dialog.
166
+ WxSugar.define_keyword_ctors('WizardPageSimple') do
167
+ wx_ctor_params :prev, :next, :bitmap => Wx::NULL_BITMAP
168
+ end
169
+
170
+ ### DIALOGS
171
+ # wxDialog Base class for common dialogs
172
+ WxSugar.define_keyword_ctors('Dialog') do
173
+ wx_ctor_params :title => ''
174
+ wx_ctor_params :pos, :size, :style => Wx::DEFAULT_DIALOG_STYLE
175
+ wx_ctor_params :name => 'dialogBox'
176
+ end
177
+
178
+ # wxColourDialog Colour chooser dialog
179
+ WxSugar.define_keyword_ctors('ColourDialog') do
180
+ wx_ctor_params :colour_data => nil
181
+ end
182
+
183
+ # wxDirDialog Directory selector dialog
184
+ WxSugar.define_keyword_ctors('DirDialog') do
185
+ wx_ctor_params :message => 'Choose a directory'
186
+ wx_ctor_params :default_path => ''
187
+ wx_ctor_params :style, :pos, :size, :name => 'wxDirCtrl'
188
+ end
189
+
190
+ # wxFileDialog File selector dialog
191
+ WxSugar.define_keyword_ctors('FileDialog') do
192
+ wx_ctor_params :message => 'Choose a file'
193
+ wx_ctor_params :default_dir => ''
194
+ wx_ctor_params :default_file => ''
195
+ wx_ctor_params :wildcard => '*.*'
196
+ wx_ctor_params :style, :pos
197
+ end
198
+
199
+ # wxFindReplaceDialog Text search/replace dialog
200
+ WxSugar.define_keyword_ctors('FindReplaceDialog') do
201
+ wx_ctor_params :find_replace_data => Wx::FindReplaceData.new()
202
+ wx_ctor_params :title => 'findReplaceDialog'
203
+ wx_ctor_params :style
204
+ end
205
+
206
+ # wxMultiChoiceDialog Dialog to get one or more selections from a list
207
+ # wxSingleChoiceDialog Dialog to get a single selection from a list and return the string
208
+
209
+ # Dialog to get a single line of text from the user
210
+ WxSugar.define_keyword_ctors('TextEntryDialog') do
211
+ wx_ctor_params :message => ''
212
+ wx_ctor_params :caption => 'Please enter text'
213
+ wx_ctor_params :default_value => ''
214
+ wx_ctor_params :style => Wx::OK|Wx::CANCEL|Wx::CENTRE
215
+ wx_ctor_params :pos
216
+ end
217
+
218
+ # wxPasswordEntryDialog Dialog to get a password from the user
219
+ # WxSugar.define_keyword_ctors('PasswordEntryDialog') do
220
+ # wx_ctor_params :message => ''
221
+ # wx_ctor_params :caption => 'Enter password'
222
+ # wx_ctor_params :default_value => ''
223
+ # wx_ctor_params :style => Wx::OK|Wx::CANCEL|Wx::CENTRE
224
+ # wx_ctor_params :pos
225
+ # end
226
+
227
+ # wxFontDialog Font chooser dialog
228
+ # wxPageSetupDialog Standard page setup dialog
229
+ # wxPrintDialog Standard print dialog
230
+
231
+ # Simple message box dialog
232
+ WxSugar.define_keyword_ctors('MessageDialog') do
233
+ wx_ctor_params :message => ''
234
+ wx_ctor_params :caption => 'Message box'
235
+ wx_ctor_params :style => Wx::OK|Wx::CANCEL
236
+ wx_ctor_params :pos
237
+ end
238
+
239
+ ### CONTROLS
240
+
241
+ # Push button control, displaying text
242
+ WxSugar.define_keyword_ctors('Button') do
243
+ wx_ctor_params :label => ''
244
+ wx_ctor_params :pos, :size, :style
245
+ # wx_ctor_params :validator, :name => 'button'
246
+ end
247
+
248
+ # Push button control, displaying a bitmap
249
+ WxSugar.define_keyword_ctors('BitmapButton') do
250
+ wx_ctor_params :bitmap, :pos, :size, :style => Wx::BU_AUTODRAW
251
+ end
252
+
253
+ # A button which stays pressed when clicked by user.
254
+ WxSugar.define_keyword_ctors('ToggleButton') do
255
+ wx_ctor_params :label, :pos, :size, :style
256
+ # wx_ctor_params :validator, :name => 'checkBox'
257
+ end
258
+
259
+ # Control showing an entire calendar month
260
+ WxSugar.define_keyword_ctors('CalendarCtrl') do
261
+ wx_ctor_params :date => Time.now()
262
+ wx_ctor_params :pos, :size, :style => Wx::CAL_SHOW_HOLIDAYS
263
+ wx_ctor_params :name => 'calendar'
264
+ end
265
+
266
+ # Checkbox control
267
+ WxSugar.define_keyword_ctors('CheckBox') do
268
+ wx_ctor_params :label => ''
269
+ wx_ctor_params :pos, :size, :style
270
+ # wx_ctor_params :validator, :name => 'checkBox'
271
+ end
272
+
273
+ # A listbox with a checkbox to the left of each item
274
+ WxSugar.define_keyword_ctors('CheckListBox') do
275
+ wx_ctor_params :pos, :size, :choices, :style
276
+ # wx_ctor_params :validator, :name => 'listBox'
277
+ end
278
+
279
+ # wxChoice Choice control (a combobox without the editable area)
280
+ WxSugar.define_keyword_ctors('Choice') do
281
+ wx_ctor_params :pos, :size, :choices, :style
282
+ # wx_ctor_params :validator, :name => 'choice'
283
+ end
284
+
285
+ # wxComboBox A choice with an editable area
286
+ WxSugar.define_keyword_ctors('ComboBox') do
287
+ wx_ctor_params :value => ''
288
+ wx_ctor_params :pos, :size, :choices => []
289
+ wx_ctor_params :style
290
+ # wx_ctor_params :validator, :name => 'comboBox'
291
+ end
292
+
293
+ # wxDatePickerCtrl Small date picker control
294
+
295
+ # wxGauge A control to represent a varying quantity, such as time
296
+ # remaining
297
+ WxSugar.define_keyword_ctors('Gauge') do
298
+ wx_ctor_params :range, :pos, :size, :style => Wx::GA_HORIZONTAL
299
+ # wx_ctor_params :validator, :name
300
+ end
301
+
302
+ # wxGenericDirCtrl A control for displaying a directory tree
303
+ # wxHtmlListBox A listbox showing HTML content
304
+ # wxListBox A list of strings for single or multiple selection
305
+ WxSugar.define_keyword_ctors('ListBox') do
306
+ wx_ctor_params :pos, :size, :choices => []
307
+ wx_ctor_params :style
308
+ end
309
+
310
+ # wxListCtrl A control for displaying lists of strings and/or icons, plus a multicolumn report view
311
+ WxSugar.define_keyword_ctors('ListCtrl') do
312
+ wx_ctor_params :pos, :size, :style => Wx::LC_ICON
313
+ # wx_ctor_params :validator, :name => 'listCtrlNameStr'
314
+ end
315
+
316
+ # wxListView A simpler interface (facade for wxListCtrl in report mode
317
+
318
+ # wxTreeCtrl Tree (hierarchy) control
319
+ WxSugar.define_keyword_ctors('TreeCtrl') do
320
+ wx_ctor_params :pos, :size, :style => Wx::TR_HAS_BUTTONS
321
+ # wx_ctor_params :validator, :name => 'treeCtrl'
322
+ end
323
+
324
+ # wxScrollBar Scrollbar control
325
+ # wxSpinButton A spin or 'up-down' control
326
+ WxSugar.define_keyword_ctors('SpinCtrl') do
327
+ wx_ctor_params :pos, :size, :style => Wx::SP_HORIZONTAL
328
+ # wx_ctor_params :validator, :name => 'treeCtrl'
329
+ end
330
+
331
+ # wxSpinCtrl A spin control - i.e. spin button and text control
332
+ WxSugar.define_keyword_ctors('SpinCtrl') do
333
+ wx_ctor_params :pos, :size, :style => Wx::SP_ARROW_KEYS
334
+ wx_ctor_params :min => 0
335
+ wx_ctor_params :max => 100
336
+ wx_ctor_params :initial => 0
337
+ # wx_ctor_params :validator, :name => 'treeCtrl'
338
+ end
339
+
340
+ # One or more lines of non-editable text
341
+ WxSugar.define_keyword_ctors('StaticText') do
342
+ wx_ctor_params :label, :pos, :size, :style, :name => 'staticText'
343
+ end
344
+
345
+ WxSugar.define_keyword_ctors('StaticBox') do
346
+ wx_ctor_params :label, :pos, :size, :style, :name => 'staticBox'
347
+ end
348
+
349
+ WxSugar.define_keyword_ctors('StaticLine') do
350
+ wx_ctor_params :pos, :size, :style => Wx::LI_HORIZONTAL
351
+ wx_ctor_params :name => 'staticBox'
352
+ end
353
+
354
+ # wxStaticBitmap A control to display a bitmap
355
+ WxSugar.define_keyword_ctors('StaticBitmap') do
356
+ wx_ctor_params :label, :pos, :size, :style
357
+ end
358
+
359
+
360
+ # wxRadioBox A group of radio buttons
361
+ WxSugar.define_keyword_ctors('RadioBox') do
362
+ wx_ctor_params :label => ''
363
+ wx_ctor_params :pos, :size, :choices => []
364
+ wx_ctor_params :major_dimension => 0
365
+ wx_ctor_params :style => Wx::RA_SPECIFY_COLS
366
+
367
+ # wx_ctor_params :validator, :name => 'radioBox'
368
+ end
369
+
370
+
371
+ # wxRadioButton A round button to be used with others in a mutually exclusive way
372
+ WxSugar.define_keyword_ctors('RadioBox') do
373
+ wx_ctor_params :label => ''
374
+ wx_ctor_params :pos, :size, :style => 0
375
+ # wx_ctor_params :validator, :name => 'radioButton'
376
+ end
377
+
378
+ # wxSlider A slider that can be dragged by the user
379
+ WxSugar.define_keyword_ctors('Slider') do
380
+ wx_ctor_params :min_value, :max_value
381
+ wx_ctor_params :pos, :size, :style => Wx::SL_HORIZONTAL
382
+ # wx_ctor_params :validator, :name => 'radioButton'
383
+ end
384
+
385
+ # wxVListBox A listbox supporting variable height rows
386
+
387
+ # wxTextCtrl Single or multiline text editing control
388
+ WxSugar.define_keyword_ctors('TextCtrl') do
389
+ wx_ctor_params :value => ''
390
+ wx_ctor_params :pos, :size, :style
391
+ end
392
+
@@ -0,0 +1,268 @@
1
+ # = WxRuby Extensions - Keyword Constructors
2
+ #
3
+ # The *Keyword Constructors* extension allows the use of Ruby hash-style
4
+ # keyword arguments in constructors of common WxWidgets Windows, Frame,
5
+ # Dialog and Control classes.
6
+ #
7
+ # == Introduction
8
+ #
9
+ # Building a GUI in WxWidgets involves lots of calls to +new+, but
10
+ # these methods often have long parameter lists. Often the default
11
+ # values for many of these parameters are correct. For example, if
12
+ # you're using a sizer-based layout, you usually don't want to specify a
13
+ # size for widgets, but you still have to type
14
+ #
15
+ # Wx::TreeCtrl.new( parent, -1, Wx::DEFAULT_POSITION, Wx::DEFAULT_SIZE,
16
+ # Wx::NO_BUTTONS )
17
+ #
18
+ # just to create a standard TreeCtrl with the 'no buttons' style. If you
19
+ # want to specify the 'NO BUTTONS' style, you can't avoid all the typing
20
+ # of DEFAULT_POSITION etc.
21
+ #
22
+ # == Basic Keyword Constructors
23
+ #
24
+ # With keyword_constructors, you could write the above as
25
+ #
26
+ # TreeCtrl.new(parent, :style => Wx::NO_BUTTONS)
27
+ #
28
+ # And it will assume you want the default id (-1), and the default size
29
+ # and position. If you want to specify an explicit size, you can do so:
30
+ #
31
+ # TreeCtrl.new(parent, :size => Wx::Size.new(100, 300))
32
+ #
33
+ # For brevity, this module also allows you to specify positions and
34
+ # sizes using a a two-element array:
35
+ #
36
+ # TreeCtrl.new(parent, :size => [100, 300])
37
+ #
38
+ # Similarly with position:
39
+ #
40
+ # TreeCtrl.new(parent, :pos => Wx::Point.new(5, 25))
41
+ #
42
+ # TreeCtrl.new(parent, :pos => [5, 25])
43
+ #
44
+ # You can have multiple keyword arguments:
45
+ #
46
+ # TreeCtrl.new(parent, :pos => [5, 25], :size => [100, 300] )
47
+ #
48
+ # == No ID required
49
+ #
50
+ # As with position and size, you usually don't want to deal with
51
+ # assigning unique ids to every widget and frame you create - it's a C++
52
+ # hangover that often seems clunky in Ruby. The *Event Connectors*
53
+ # extension allows you to set up event handling without having to use
54
+ # ids, and if no :id argument is supplied to a constructor, the default
55
+ # (-1) will be passed.
56
+ #
57
+ # There are occasions when a specific ID does need to be used - for
58
+ # example, to tell WxWidgets that a button is a 'stock' item, so that it
59
+ # can be displayed using platform-standard text and icon. To do this,
60
+ # simply pass an :id argument to the constructor - here, the system's
61
+ # standard 'preview' button
62
+ #
63
+ # Wx::Button.new(parent, :id => Wx::ID_PREVIEW)
64
+ #
65
+ # == Class-specific arguments
66
+ #
67
+ # The arguments :size, :pos and :style are common to many WxWidgets
68
+ # window classes. The +new+ methods of these classes also have
69
+ # parameters that are specific to those classes; for example, the text
70
+ # label on a button, or the initial value of a text control.
71
+ #
72
+ # Wx::Button.new(parent, :label => 'press me')
73
+ # Wx::TextCtrl.new(parent, :value => 'type some text here')
74
+ #
75
+ # The keyword names of these arguments can be found by looking at the
76
+ # WxRuby documentation, in the relevant class's +new+ method. You can
77
+ # also get a string description of the class's +new+ method parameters
78
+ # within Ruby by doing:
79
+ #
80
+ # puts Wx::TextCtrl.describe_constructor()
81
+ #
82
+ # This will print a list of the argument names expected by the class's
83
+ # +new+ method, and the correct type for them.
84
+ #
85
+ # == Mixing positional and keyword arguments
86
+ #
87
+ # To support existing code, and to avoid forcing the use of more verbose
88
+ # keyword-style arguments where they're not desired, you can mix
89
+ # positional and keyword arguments, omitting or including +id+s as
90
+ # desired.
91
+ #
92
+ # Wx::Button.new(parent, 'press me', :style => Wx::BU_RIGHT)
93
+ #
94
+ module WxSugar
95
+ module KeywordConstructor
96
+ module ClassMethods
97
+ # Shorthand constructors
98
+ TYPEMAP = {
99
+ Wx::Size => lambda { | x | Wx::Size === x ? x : Wx::Size.new(*x) },
100
+ Wx::Point => lambda { | x | Wx::Point === x ? x : Wx::Point.new(*x) }
101
+ }
102
+
103
+ # Common Wx constructor argument keywords, with their default values.
104
+ STANDARD_DEFAULTS = {
105
+ :id => -1,
106
+ :size => Wx::DEFAULT_SIZE,
107
+ :pos => Wx::DEFAULT_POSITION,
108
+ :style => 0,
109
+ :validator => nil, # Should be Wx::DefaultValidator
110
+ :choices => [] # for Choice, ComboBox etc
111
+ }
112
+
113
+ # Provide convenient convertors for Wx::Size and Wx::Point to be
114
+ # specified as simple ruby array.
115
+ #
116
+ # instead of
117
+ # :size => Wx::Size.new(150, 225)
118
+ # just
119
+ # :size => [ 150, 225 ]
120
+ def map_type(in_obj, default)
121
+ if TYPEMAP.include?(default.class)
122
+ in_obj = TYPEMAP[default.class].call(in_obj)
123
+ end
124
+ in_obj
125
+ end
126
+
127
+ # A named parameter in a Wx constructor parameter list
128
+ Parameter = Struct.new( :name, :default )
129
+
130
+ attr_writer :param_spec
131
+ def param_spec
132
+ @param_spec ||= [ ]
133
+ end
134
+
135
+ attr_writer :param_flags
136
+ def param_flags
137
+ @param_flags ||= {}
138
+ end
139
+
140
+
141
+ # Adds a list of named parameters *params* to the parameter
142
+ # specification for this Wx class's constructor. Each parameter
143
+ # should be specified as a either a common known symbol, such as
144
+ # +:size+ or +:pos:+ or +:style:+ (corresponding to the common
145
+ # constructor arguments in WxWidgets API), or a single-key with the
146
+ # key the name of the argument, and the value a default value.
147
+ #
148
+ # Parameters should be specified in the order they occur in the Wx
149
+ # API constructor
150
+ def wx_ctor_params(*params)
151
+ self.param_spec += params.map do | param |
152
+ param.kind_of?(Hash) ? Parameter[*param.to_a.flatten] :
153
+ Parameter[param, STANDARD_DEFAULTS[param] ]
154
+ end
155
+ end
156
+
157
+ # Add a named style constructor flag.
158
+ def wx_ctor_flags(flags)
159
+ param_flags.update(flags)
160
+ end
161
+
162
+ def args_as_list(*mixed_args)
163
+ # get keyword arguments from mixed args if supplied, else empty
164
+ kwa = mixed_args.last.kind_of?(Hash) ? mixed_args.pop : {}
165
+ out_args = []
166
+ param_spec.zip(mixed_args) do | param, arg |
167
+ if arg # use the supplied list arg
168
+ out_args << map_type(arg, param.default)
169
+ elsif kwa.key?(param.name) # use the keyword arg
170
+ out_args << map_type(kwa[param.name], param.default)
171
+ else # use the default argument
172
+ out_args << param.default
173
+ end
174
+ end
175
+ out_args
176
+ rescue
177
+ Kernel.raise ArgumentError,
178
+ "Bad arg composition of #{mixed_args.inspect}"
179
+ end
180
+
181
+ def args_as_hash(*mixed_args)
182
+ kwa = mixed_args.last.kind_of?(Hash) ? mixed_args.pop : {}
183
+ param_spec.zip(mixed_args) do | param, arg |
184
+ kwa[param.name] = arg if arg
185
+ end
186
+ kwa
187
+ end
188
+
189
+ # Look through a set of keyword arguments +in_flags+ and return a
190
+ # style parameter based on the known style flags applicable to this
191
+ # widget type.
192
+ # TODO - not currently used
193
+ def style_constant(kw_args)
194
+ # get the default flag for this style parameter
195
+ base_style = kw_args[:style] ||
196
+ param_spec.find { | x | x.name == :style }.default
197
+
198
+ # go through each of the known style flags for this widget
199
+ param_flags.each do | sym, const |
200
+ next unless kw_args.key?(sym)
201
+ # add or delete flag, depending on whether true or false
202
+ kw_args[sym] ? base_style |= const : base_style &= ~const
203
+ end
204
+ base_style
205
+ end
206
+
207
+ def describe_constructor()
208
+ param_spec.inject("") do | desc, param |
209
+ desc << "#{param.name} (#{param.default.class.name})\n"
210
+ end
211
+ end
212
+ end
213
+
214
+ def self.included(klass)
215
+ klass.extend ClassMethods
216
+
217
+ klass.module_eval do
218
+ alias :pre_wx_kwctor_init :initialize
219
+
220
+ def initialize(parent, *mixed_args)
221
+ if parent and not parent.is_a?(Wx::Window)
222
+ Kernel.raise ArgumentError,
223
+ "Parent must be a Wx::Window, not #{parent.inspect}"
224
+ end
225
+
226
+ # Allow classes to ignore :id argument in positional args
227
+ unless self.class < Wx::Dialog
228
+ if not mixed_args[0].kind_of?(Fixnum)
229
+ mixed_args.unshift(-1)
230
+ end
231
+ end
232
+
233
+ real_args = [ parent ] + self.class.args_as_list(*mixed_args)
234
+
235
+
236
+ # deal with style flags
237
+ # if mixed_args.last.kind_of?(Hash)
238
+ # flags = self.class.style_constant(mixed_args.last)
239
+ # style_param = self.class.param_spec.find { | param | param.name == :style }
240
+ # real_args[ self.class.param_spec.index(style_param) + 1 ] = flags
241
+ # end
242
+
243
+ begin
244
+ pre_wx_kwctor_init(*real_args)
245
+ rescue
246
+ Kernel.raise ArgumentError, "Error initializing #{self.inspect} \n" +
247
+ "Sent paramters: #{real_args.inspect}\n" +
248
+ "correct parameters are:\n" +
249
+ self.class.describe_constructor()
250
+ end
251
+ end
252
+ end
253
+
254
+
255
+ # Any class inheriting from a class including this module must have
256
+ # its own copy of the param_spec
257
+ def klass.inherited(sub_klass)
258
+ # sub_klass.module_eval { include KeywordConstructor }
259
+ sub_klass.instance_variable_set(:@param_spec,
260
+ self.instance_variable_get(:@param_spec) )
261
+ sub_klass.instance_variable_set(:@param_flags,
262
+ self.instance_variable_get(:@param_flags) )
263
+ end
264
+ end
265
+ end
266
+ end
267
+
268
+ require 'wx_sugar/keyword_classes'