]> git.saurik.com Git - wxWidgets.git/blame - wxPython/wx/lib/masked/combobox.py
wxCheckListBox doesn't require wxUSE_OWNER_DRAWN when using WXUNIVERSAL
[wxWidgets.git] / wxPython / wx / lib / masked / combobox.py
CommitLineData
c878ceea
RD
1#----------------------------------------------------------------------------
2# Name: masked.combobox.py
3# Authors: Will Sadkin
4# Email: wsadkin@nameconnector.com
5# Created: 02/11/2003
6# Copyright: (c) 2003 by Will Sadkin, 2003
7# RCS-ID: $Id$
8# License: wxWidgets license
9#----------------------------------------------------------------------------
10#
11# This masked edit class allows for the semantics of masked controls
12# to be applied to combo boxes.
13#
14#----------------------------------------------------------------------------
15
f54a36bb
RD
16"""
17Provides masked edit capabilities within a ComboBox format, as well as
18a base class from which you can derive masked comboboxes tailored to a specific
19function. See maskededit module overview for how to configure the control.
20"""
21
22import wx, types, string
c878ceea
RD
23from wx.lib.masked import *
24
25# jmg 12/9/03 - when we cut ties with Py 2.2 and earlier, this would
26# be a good place to implement the 2.3 logger class
27from wx.tools.dbg import Logger
f54a36bb 28##dbg = Logger()
281c1054 29##dbg(enable=1)
c878ceea
RD
30
31## ---------- ---------- ---------- ---------- ---------- ---------- ----------
32## Because calling SetSelection programmatically does not fire EVT_COMBOBOX
33## events, we have to do it ourselves when we auto-complete.
34class MaskedComboBoxSelectEvent(wx.PyCommandEvent):
f54a36bb
RD
35 """
36 Because calling SetSelection programmatically does not fire EVT_COMBOBOX
37 events, the derived control has to do it itself when it auto-completes.
38 """
c878ceea
RD
39 def __init__(self, id, selection = 0, object=None):
40 wx.PyCommandEvent.__init__(self, wx.wxEVT_COMMAND_COMBOBOX_SELECTED, id)
41
42 self.__selection = selection
43 self.SetEventObject(object)
44
45 def GetSelection(self):
46 """Retrieve the value of the control at the time
47 this event was generated."""
48 return self.__selection
49
50
51class BaseMaskedComboBox( wx.ComboBox, MaskedEditMixin ):
52 """
f54a36bb
RD
53 Base class for generic masked edit comboboxes; allows auto-complete of values.
54 It is not meant to be instantiated directly, but rather serves as a base class
55 for any subsequent refinements.
c878ceea
RD
56 """
57 def __init__( self, parent, id=-1, value = '',
58 pos = wx.DefaultPosition,
59 size = wx.DefaultSize,
60 choices = [],
61 style = wx.CB_DROPDOWN,
62 validator = wx.DefaultValidator,
63 name = "maskedComboBox",
64 setupEventHandling = True, ## setup event handling by default):
65 **kwargs):
66
67
c878ceea
RD
68 kwargs['choices'] = choices ## set up maskededit to work with choice list too
69
70 ## Since combobox completion is case-insensitive, always validate same way
71 if not kwargs.has_key('compareNoCase'):
72 kwargs['compareNoCase'] = True
73
74 MaskedEditMixin.__init__( self, name, **kwargs )
75
76 self._choices = self._ctrl_constraints._choices
77## dbg('self._choices:', self._choices)
78
79 if self._ctrl_constraints._alignRight:
80 choices = [choice.rjust(self._masklength) for choice in choices]
81 else:
82 choices = [choice.ljust(self._masklength) for choice in choices]
83
84 wx.ComboBox.__init__(self, parent, id, value='',
85 pos=pos, size = size,
86 choices=choices, style=style|wx.WANTS_CHARS,
87 validator=validator,
88 name=name)
c878ceea
RD
89 self.controlInitialized = True
90
339983ff
RD
91 self._PostInit(style=style, setupEventHandling=setupEventHandling,
92 name=name, value=value, **kwargs)
93
94
95 def _PostInit(self, style=wx.CB_DROPDOWN,
96 setupEventHandling = True, ## setup event handling by default):
97 name = "maskedComboBox", value='', **kwargs):
98
99 # This is necessary, because wxComboBox currently provides no
100 # method for determining later if this was specified in the
101 # constructor for the control...
102 self.__readonly = style & wx.CB_READONLY == wx.CB_READONLY
103
104 if not hasattr(self, 'controlInitialized'):
105
106 self.controlInitialized = True ## must have been called via XRC, therefore base class is constructed
107 if not kwargs.has_key('choices'):
108 choices=[]
109 kwargs['choices'] = choices ## set up maskededit to work with choice list too
110 self._choices = []
111
112 ## Since combobox completion is case-insensitive, always validate same way
113 if not kwargs.has_key('compareNoCase'):
114 kwargs['compareNoCase'] = True
115
116 MaskedEditMixin.__init__( self, name, **kwargs )
117
118 self._choices = self._ctrl_constraints._choices
119## dbg('self._choices:', self._choices)
120
121 if self._ctrl_constraints._alignRight:
122 choices = [choice.rjust(self._masklength) for choice in choices]
123 else:
124 choices = [choice.ljust(self._masklength) for choice in choices]
125 wx.ComboBox.Clear(self)
126 wx.ComboBox.AppendItems(self, choices)
127
128
c878ceea
RD
129 # Set control font - fixed width by default
130 self._setFont()
131
132 if self._autofit:
133 self.SetClientSize(self._CalcSize())
339983ff
RD
134 width = self.GetSize().width
135 height = self.GetBestSize().height
5193b348 136 self.SetBestFittingSize((width, height))
339983ff 137
c878ceea
RD
138
139 if value:
140 # ensure value is width of the mask of the control:
141 if self._ctrl_constraints._alignRight:
142 value = value.rjust(self._masklength)
143 else:
144 value = value.ljust(self._masklength)
145
146 if self.__readonly:
147 self.SetStringSelection(value)
148 else:
149 self._SetInitialValue(value)
150
151
f54a36bb
RD
152 self._SetKeycodeHandler(wx.WXK_UP, self._OnSelectChoice)
153 self._SetKeycodeHandler(wx.WXK_DOWN, self._OnSelectChoice)
c878ceea
RD
154
155 if setupEventHandling:
156 ## Setup event handlers
157 self.Bind(wx.EVT_SET_FOCUS, self._OnFocus ) ## defeat automatic full selection
158 self.Bind(wx.EVT_KILL_FOCUS, self._OnKillFocus ) ## run internal validator
159 self.Bind(wx.EVT_LEFT_DCLICK, self._OnDoubleClick) ## select field under cursor on dclick
160 self.Bind(wx.EVT_RIGHT_UP, self._OnContextMenu ) ## bring up an appropriate context menu
161 self.Bind(wx.EVT_CHAR, self._OnChar ) ## handle each keypress
f54a36bb 162 self.Bind(wx.EVT_KEY_DOWN, self._OnKeyDownInComboBox ) ## for special processing of up/down keys
c878ceea
RD
163 self.Bind(wx.EVT_KEY_DOWN, self._OnKeyDown ) ## for processing the rest of the control keys
164 ## (next in evt chain)
165 self.Bind(wx.EVT_TEXT, self._OnTextChange ) ## color control appropriately & keep
166 ## track of previous value for undo
167
168
169
170 def __repr__(self):
171 return "<MaskedComboBox: %s>" % self.GetValue()
172
173
174 def _CalcSize(self, size=None):
175 """
176 Calculate automatic size if allowed; augment base mixin function
177 to account for the selector button.
178 """
179 size = self._calcSize(size)
180 return (size[0]+20, size[1])
181
182
339983ff
RD
183 def SetFont(self, *args, **kwargs):
184 """ Set the font, then recalculate control size, if appropriate. """
185 wx.ComboBox.SetFont(self, *args, **kwargs)
186 if self._autofit:
f54a36bb 187## dbg('calculated size:', self._CalcSize())
339983ff
RD
188 self.SetClientSize(self._CalcSize())
189 width = self.GetSize().width
190 height = self.GetBestSize().height
f54a36bb 191## dbg('setting client size to:', (width, height))
5193b348 192 self.SetBestFittingSize((width, height))
339983ff
RD
193
194
c878ceea
RD
195 def _GetSelection(self):
196 """
197 Allow mixin to get the text selection of this control.
198 REQUIRED by any class derived from MaskedEditMixin.
199 """
281c1054 200## dbg('MaskedComboBox::_GetSelection()')
c878ceea
RD
201 return self.GetMark()
202
203 def _SetSelection(self, sel_start, sel_to):
204 """
205 Allow mixin to set the text selection of this control.
206 REQUIRED by any class derived from MaskedEditMixin.
207 """
281c1054 208## dbg('MaskedComboBox::_SetSelection: setting mark to (%d, %d)' % (sel_start, sel_to))
c878ceea
RD
209 return self.SetMark( sel_start, sel_to )
210
211
212 def _GetInsertionPoint(self):
281c1054
RD
213## dbg('MaskedComboBox::_GetInsertionPoint()', indent=1)
214## ret = self.GetInsertionPoint()
215 # work around new bug in 2.5, in which the insertion point
216 # returned is always at the right side of the selection,
217 # rather than the start, as is the case with TextCtrl.
218 ret = self.GetMark()[0]
219## dbg('returned', ret, indent=0)
220 return ret
c878ceea
RD
221
222 def _SetInsertionPoint(self, pos):
281c1054 223## dbg('MaskedComboBox::_SetInsertionPoint(%d)' % pos)
c878ceea
RD
224 self.SetInsertionPoint(pos)
225
226
227 def _GetValue(self):
228 """
229 Allow mixin to get the raw value of the control with this function.
230 REQUIRED by any class derived from MaskedEditMixin.
231 """
232 return self.GetValue()
233
234 def _SetValue(self, value):
235 """
236 Allow mixin to set the raw value of the control with this function.
237 REQUIRED by any class derived from MaskedEditMixin.
238 """
239 # For wxComboBox, ensure that values are properly padded so that
240 # if varying length choices are supplied, they always show up
241 # in the window properly, and will be the appropriate length
242 # to match the mask:
243 if self._ctrl_constraints._alignRight:
244 value = value.rjust(self._masklength)
245 else:
246 value = value.ljust(self._masklength)
247
248 # Record current selection and insertion point, for undo
249 self._prevSelection = self._GetSelection()
250 self._prevInsertionPoint = self._GetInsertionPoint()
251 wx.ComboBox.SetValue(self, value)
252 # text change events don't always fire, so we check validity here
253 # to make certain formatting is applied:
254 self._CheckValid()
255
256 def SetValue(self, value):
257 """
258 This function redefines the externally accessible .SetValue to be
259 a smart "paste" of the text in question, so as not to corrupt the
260 masked control. NOTE: this must be done in the class derived
261 from the base wx control.
262 """
263 if not self._mask:
264 wx.ComboBox.SetValue(value) # revert to base control behavior
265 return
266 # else...
267 # empty previous contents, replacing entire value:
268 self._SetInsertionPoint(0)
269 self._SetSelection(0, self._masklength)
270
271 if( len(value) < self._masklength # value shorter than control
272 and (self._isFloat or self._isInt) # and it's a numeric control
273 and self._ctrl_constraints._alignRight ): # and it's a right-aligned control
274 # try to intelligently "pad out" the value to the right size:
275 value = self._template[0:self._masklength - len(value)] + value
276## dbg('padded value = "%s"' % value)
277
278 # For wxComboBox, ensure that values are properly padded so that
279 # if varying length choices are supplied, they always show up
280 # in the window properly, and will be the appropriate length
281 # to match the mask:
282 elif self._ctrl_constraints._alignRight:
283 value = value.rjust(self._masklength)
284 else:
285 value = value.ljust(self._masklength)
286
287
288 # make SetValue behave the same as if you had typed the value in:
289 try:
5f280eaa 290 value, replace_to = self._Paste(value, raise_on_invalid=True, just_return_value=True)
c878ceea
RD
291 if self._isFloat:
292 self._isNeg = False # (clear current assumptions)
293 value = self._adjustFloat(value)
294 elif self._isInt:
295 self._isNeg = False # (clear current assumptions)
296 value = self._adjustInt(value)
297 elif self._isDate and not self.IsValid(value) and self._4digityear:
298 value = self._adjustDate(value, fixcentury=True)
299 except ValueError:
300 # If date, year might be 2 digits vs. 4; try adjusting it:
301 if self._isDate and self._4digityear:
302 dateparts = value.split(' ')
303 dateparts[0] = self._adjustDate(dateparts[0], fixcentury=True)
304 value = string.join(dateparts, ' ')
305## dbg('adjusted value: "%s"' % value)
306 value = self._Paste(value, raise_on_invalid=True, just_return_value=True)
307 else:
308 raise
309
310 self._SetValue(value)
5f280eaa
RD
311#### dbg('queuing insertion after .SetValue', replace_to)
312 wx.CallAfter(self._SetInsertionPoint, replace_to)
313 wx.CallAfter(self._SetSelection, replace_to, replace_to)
c878ceea
RD
314
315
316 def _Refresh(self):
317 """
318 Allow mixin to refresh the base control with this function.
319 REQUIRED by any class derived from MaskedEditMixin.
320 """
321 wx.ComboBox.Refresh(self)
322
323 def Refresh(self):
324 """
325 This function redefines the externally accessible .Refresh() to
326 validate the contents of the masked control as it refreshes.
327 NOTE: this must be done in the class derived from the base wx control.
328 """
329 self._CheckValid()
330 self._Refresh()
331
332
333 def _IsEditable(self):
334 """
335 Allow mixin to determine if the base control is editable with this function.
336 REQUIRED by any class derived from MaskedEditMixin.
337 """
338 return not self.__readonly
339
340
341 def Cut(self):
342 """
343 This function redefines the externally accessible .Cut to be
344 a smart "erase" of the text in question, so as not to corrupt the
345 masked control. NOTE: this must be done in the class derived
346 from the base wx control.
347 """
348 if self._mask:
349 self._Cut() # call the mixin's Cut method
350 else:
351 wx.ComboBox.Cut(self) # else revert to base control behavior
352
353
354 def Paste(self):
355 """
356 This function redefines the externally accessible .Paste to be
357 a smart "paste" of the text in question, so as not to corrupt the
358 masked control. NOTE: this must be done in the class derived
359 from the base wx control.
360 """
361 if self._mask:
362 self._Paste() # call the mixin's Paste method
363 else:
364 wx.ComboBox.Paste(self) # else revert to base control behavior
365
366
367 def Undo(self):
368 """
369 This function defines the undo operation for the control. (The default
370 undo is 1-deep.)
371 """
372 if self._mask:
373 self._Undo()
374 else:
375 wx.ComboBox.Undo() # else revert to base control behavior
376
c878ceea
RD
377 def Append( self, choice, clientData=None ):
378 """
f54a36bb
RD
379 This base control function override is necessary so the control can keep track
380 of any additions to the list of choices, because wx.ComboBox doesn't have an
381 accessor for the choice list. The code here is the same as in the
382 SetParameters() mixin function, but is done for the individual value
383 as appended, so the list can be built incrementally without speed penalty.
c878ceea
RD
384 """
385 if self._mask:
386 if type(choice) not in (types.StringType, types.UnicodeType):
387 raise TypeError('%s: choices must be a sequence of strings' % str(self._index))
388 elif not self.IsValid(choice):
389 raise ValueError('%s: "%s" is not a valid value for the control as specified.' % (str(self._index), choice))
390
391 if not self._ctrl_constraints._choices:
392 self._ctrl_constraints._compareChoices = []
393 self._ctrl_constraints._choices = []
394 self._hasList = True
395
396 compareChoice = choice.strip()
397
398 if self._ctrl_constraints._compareNoCase:
399 compareChoice = compareChoice.lower()
400
401 if self._ctrl_constraints._alignRight:
402 choice = choice.rjust(self._masklength)
403 else:
404 choice = choice.ljust(self._masklength)
405 if self._ctrl_constraints._fillChar != ' ':
406 choice = choice.replace(' ', self._fillChar)
407## dbg('updated choice:', choice)
408
409
410 self._ctrl_constraints._compareChoices.append(compareChoice)
411 self._ctrl_constraints._choices.append(choice)
412 self._choices = self._ctrl_constraints._choices # (for shorthand)
413
414 if( not self.IsValid(choice) and
415 (not self._ctrl_constraints.IsEmpty(choice) or
416 (self._ctrl_constraints.IsEmpty(choice) and self._ctrl_constraints._validRequired) ) ):
417 raise ValueError('"%s" is not a valid value for the control "%s" as specified.' % (choice, self.name))
418
419 wx.ComboBox.Append(self, choice, clientData)
420
421
339983ff
RD
422 def AppendItems( self, choices ):
423 """
424 AppendItems() is handled in terms of Append, to avoid code replication.
425 """
426 for choice in choices:
427 self.Append(choice)
428
c878ceea
RD
429
430 def Clear( self ):
431 """
f54a36bb
RD
432 This base control function override is necessary so the derived control can
433 keep track of any additions to the list of choices, because wx.ComboBox
434 doesn't have an accessor for the choice list.
c878ceea
RD
435 """
436 if self._mask:
437 self._choices = []
438 self._ctrl_constraints._autoCompleteIndex = -1
439 if self._ctrl_constraints._choices:
440 self.SetCtrlParameters(choices=[])
441 wx.ComboBox.Clear(self)
442
443
444 def _OnCtrlParametersChanged(self):
445 """
f54a36bb
RD
446 This overrides the mixin's default OnCtrlParametersChanged to detect
447 changes in choice list, so masked.Combobox can update the base control:
c878ceea
RD
448 """
449 if self.controlInitialized and self._choices != self._ctrl_constraints._choices:
450 wx.ComboBox.Clear(self)
451 self._choices = self._ctrl_constraints._choices
452 for choice in self._choices:
453 wx.ComboBox.Append( self, choice )
454
455
b0f3dd44
RD
456 # Not all wx platform implementations have .GetMark, so we make the following test,
457 # and fall back to our old hack if they don't...
458 #
459 if not hasattr(wx.ComboBox, 'GetMark'):
460 def GetMark(self):
461 """
462 This function is a hack to make up for the fact that wx.ComboBox has no
463 method for returning the selected portion of its edit control. It
464 works, but has the nasty side effect of generating lots of intermediate
465 events.
466 """
467## dbg(suspend=1) # turn off debugging around this function
468## dbg('MaskedComboBox::GetMark', indent=1)
469 if self.__readonly:
470## dbg(indent=0)
471 return 0, 0 # no selection possible for editing
472## sel_start, sel_to = wxComboBox.GetMark(self) # what I'd *like* to have!
473 sel_start = sel_to = self.GetInsertionPoint()
474## dbg("current sel_start:", sel_start)
475 value = self.GetValue()
476## dbg('value: "%s"' % value)
c878ceea 477
b0f3dd44 478 self._ignoreChange = True # tell _OnTextChange() to ignore next event (if any)
c878ceea 479
b0f3dd44
RD
480 wx.ComboBox.Cut(self)
481 newvalue = self.GetValue()
482## dbg("value after Cut operation:", newvalue)
c878ceea 483
b0f3dd44
RD
484 if newvalue != value: # something was selected; calculate extent
485## dbg("something selected")
486 sel_to = sel_start + len(value) - len(newvalue)
487 wx.ComboBox.SetValue(self, value) # restore original value and selection (still ignoring change)
488 wx.ComboBox.SetInsertionPoint(self, sel_start)
489 wx.ComboBox.SetMark(self, sel_start, sel_to)
c878ceea 490
b0f3dd44 491 self._ignoreChange = False # tell _OnTextChange() to pay attn again
c878ceea 492
b0f3dd44
RD
493## dbg('computed selection:', sel_start, sel_to, indent=0, suspend=0)
494 return sel_start, sel_to
281c1054
RD
495 else:
496 def GetMark(self):
497## dbg('MaskedComboBox::GetMark()', indent = 1)
498 ret = wx.ComboBox.GetMark(self)
499## dbg('returned', ret, indent=0)
500 return ret
c878ceea
RD
501
502
503 def SetSelection(self, index):
504 """
f54a36bb 505 Necessary override for bookkeeping on choice selection, to keep current value
c878ceea
RD
506 current.
507 """
508## dbg('MaskedComboBox::SetSelection(%d)' % index)
509 if self._mask:
510 self._prevValue = self._curValue
511 self._curValue = self._choices[index]
512 self._ctrl_constraints._autoCompleteIndex = index
513 wx.ComboBox.SetSelection(self, index)
514
515
f54a36bb 516 def _OnKeyDownInComboBox(self, event):
c878ceea
RD
517 """
518 This function is necessary because navigation and control key
519 events do not seem to normally be seen by the wxComboBox's
520 EVT_CHAR routine. (Tabs don't seem to be visible no matter
521 what... {:-( )
522 """
523 if event.GetKeyCode() in self._nav + self._control:
524 self._OnChar(event)
525 return
526 else:
527 event.Skip() # let mixin default KeyDown behavior occur
528
529
f54a36bb 530 def _OnSelectChoice(self, event):
c878ceea
RD
531 """
532 This function appears to be necessary, because the processing done
533 on the text of the control somehow interferes with the combobox's
534 selection mechanism for the arrow keys.
535 """
536## dbg('MaskedComboBox::OnSelectChoice', indent=1)
537
538 if not self._mask:
539 event.Skip()
540 return
541
542 value = self.GetValue().strip()
543
544 if self._ctrl_constraints._compareNoCase:
545 value = value.lower()
546
547 if event.GetKeyCode() == wx.WXK_UP:
548 direction = -1
549 else:
550 direction = 1
551 match_index, partial_match = self._autoComplete(
552 direction,
553 self._ctrl_constraints._compareChoices,
554 value,
555 self._ctrl_constraints._compareNoCase,
556 current_index = self._ctrl_constraints._autoCompleteIndex)
557 if match_index is not None:
558## dbg('setting selection to', match_index)
559 # issue appropriate event to outside:
560 self._OnAutoSelect(self._ctrl_constraints, match_index=match_index)
561 self._CheckValid()
562 keep_processing = False
563 else:
564 pos = self._adjustPos(self._GetInsertionPoint(), event.GetKeyCode())
565 field = self._FindField(pos)
566 if self.IsEmpty() or not field._hasList:
567## dbg('selecting 1st value in list')
568 self._OnAutoSelect(self._ctrl_constraints, match_index=0)
569 self._CheckValid()
570 keep_processing = False
571 else:
572 # attempt field-level auto-complete
573## dbg(indent=0)
574 keep_processing = self._OnAutoCompleteField(event)
575## dbg('keep processing?', keep_processing, indent=0)
576 return keep_processing
577
578
579 def _OnAutoSelect(self, field, match_index):
580 """
581 Override mixin (empty) autocomplete handler, so that autocompletion causes
582 combobox to update appropriately.
583 """
584## dbg('MaskedComboBox::OnAutoSelect', field._index, indent=1)
585## field._autoCompleteIndex = match_index
586 if field == self._ctrl_constraints:
587 self.SetSelection(match_index)
588## dbg('issuing combo selection event')
589 self.GetEventHandler().ProcessEvent(
590 MaskedComboBoxSelectEvent( self.GetId(), match_index, self ) )
591 self._CheckValid()
592## dbg('field._autoCompleteIndex:', match_index)
593## dbg('self.GetSelection():', self.GetSelection())
5f280eaa
RD
594 end = self._goEnd(getPosOnly=True)
595## dbg('scheduling set of end position to:', end)
596 # work around bug in wx 2.5
597 wx.CallAfter(self.SetInsertionPoint, 0)
598 wx.CallAfter(self.SetInsertionPoint, end)
c878ceea
RD
599## dbg(indent=0)
600
601
602 def _OnReturn(self, event):
603 """
f54a36bb 604 For wx.ComboBox, it seems that if you hit return when the dropdown is
c878ceea 605 dropped, the event that dismisses the dropdown will also blank the
f54a36bb
RD
606 control, because of the implementation of wxComboBox. So this function
607 examines the selection and if it is -1, and the value according to
608 (the base control!) is a value in the list, then it schedules a
c878ceea 609 programmatic wxComboBox.SetSelection() call to pick the appropriate
f54a36bb 610 item in the list. (and then does the usual OnReturn bit.)
c878ceea
RD
611 """
612## dbg('MaskedComboBox::OnReturn', indent=1)
613## dbg('current value: "%s"' % self.GetValue(), 'current index:', self.GetSelection())
614 if self.GetSelection() == -1 and self.GetValue().lower().strip() in self._ctrl_constraints._compareChoices:
615 wx.CallAfter(self.SetSelection, self._ctrl_constraints._autoCompleteIndex)
616
617 event.m_keyCode = wx.WXK_TAB
618 event.Skip()
619## dbg(indent=0)
620
621
622class ComboBox( BaseMaskedComboBox, MaskedEditAccessorsMixin ):
623 """
f54a36bb
RD
624 The "user-visible" masked combobox control, this class is
625 identical to the BaseMaskedComboBox class it's derived from.
626 (This extra level of inheritance allows us to add the generic
627 set of masked edit parameters only to this class while allowing
628 other classes to derive from the "base" masked combobox control,
629 and provide a smaller set of valid accessor functions.)
630 See BaseMaskedComboBox for available methods.
c878ceea
RD
631 """
632 pass
633
634
339983ff
RD
635class PreMaskedComboBox( BaseMaskedComboBox, MaskedEditAccessorsMixin ):
636 """
f54a36bb 637 This class exists to support the use of XRC subclassing.
339983ff
RD
638 """
639 # This should really be wx.EVT_WINDOW_CREATE but it is not
640 # currently delivered for native controls on all platforms, so
641 # we'll use EVT_SIZE instead. It should happen shortly after the
642 # control is created as the control is set to its "best" size.
643 _firstEventType = wx.EVT_SIZE
644
645 def __init__(self):
646 pre = wx.PreComboBox()
647 self.PostCreate(pre)
648 self.Bind(self._firstEventType, self.OnCreate)
649
650
651 def OnCreate(self, evt):
652 self.Unbind(self._firstEventType)
653 self._PostInit()
654
f54a36bb 655__i = 0
339983ff
RD
656## CHANGELOG:
657## ====================
b0f3dd44
RD
658## Version 1.3
659## 1. Made definition of "hack" GetMark conditional on base class not
660## implementing it properly, to allow for migration in wx code base
661## while taking advantage of improvements therein for some platforms.
662##
f54a36bb
RD
663## Version 1.2
664## 1. Converted docstrings to reST format, added doc for ePyDoc.
665## 2. Renamed helper functions, vars etc. not intended to be visible in public
666## interface to code.
667##
339983ff
RD
668## Version 1.1
669## 1. Added .SetFont() method that properly resizes control
670## 2. Modified control to support construction via XRC mechanism.
671## 3. Added AppendItems() to conform with latest combobox.