1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: SWIG interface for the owner-drawn combobox classes
7 // Created: 11-Nov-2006
9 // Copyright: (c) 2006 by Total Control Software
10 // Licence: wxWindows license
11 /////////////////////////////////////////////////////////////////////////////
14 "ComboCtrl class that can have any type of popup widget, and also an
15 owner-drawn combobox control."
18 %module(package="wx", docstring=DOCSTRING) combo
21 #include "wx/wxPython/wxPython.h"
22 #include "wx/wxPython/pyclasses.h"
25 #include <wx/odcombo.h>
28 //---------------------------------------------------------------------------
31 %pythoncode { wx = _core }
32 %pythoncode { __docfilter__ = wx.__DocFilter(globals()) }
34 //---------------------------------------------------------------------------
37 MAKE_CONST_WXSTRING_NOSWIG(ComboBoxNameStr);
38 MAKE_CONST_WXSTRING_NOSWIG(EmptyString);
41 const wxArrayString wxPyEmptyStringArray;
46 // Button is preferred outside the border (GTK style)
47 wxCC_BUTTON_OUTSIDE_BORDER = 0x0001,
48 // Show popup on mouse up instead of mouse down (which is the Windows style)
49 wxCC_POPUP_ON_MOUSE_UP = 0x0002,
50 // All text is not automatically selected on click
51 wxCC_NO_TEXT_AUTO_SELECT = 0x0004,
55 // Flags used by PreprocessMouseEvent and HandleButtonMouseEvent
58 wxCC_MF_ON_BUTTON = 0x0001, // cursor is on dropbutton area
59 wxCC_MF_ON_CLICK_AREA = 0x0002 // cursor is on dropbutton or other area
60 // that can be clicked to show the popup.
64 // Namespace for wxComboCtrl feature flags
65 struct wxComboCtrlFeatures
69 MovableButton = 0x0001, // Button can be on either side of control
70 BitmapButton = 0x0002, // Button may be replaced with bitmap
71 ButtonSpacing = 0x0004, // Button can have spacing from the edge
73 TextIndent = 0x0008, // SetTextIndent can be used
74 PaintControl = 0x0010, // Combo control itself can be custom painted
75 PaintWritable = 0x0020, // A variable-width area in front of writable
76 // combo control's textctrl can be custom
78 Borderless = 0x0040, // wxNO_BORDER window style works
80 // There are no feature flags for...
81 // PushButtonBitmapBackground - if its in wxRendererNative, then it should be
82 // not an issue to have it automatically under the bitmap.
84 All = MovableButton|BitmapButton|
85 ButtonSpacing|TextIndent|
86 PaintControl|PaintWritable|
91 //---------------------------------------------------------------------------
93 // C++ implemetation of Python aware wxComboCtrl
95 class wxPyComboCtrl : public wxComboCtrl
97 DECLARE_ABSTRACT_CLASS(wxPyComboCtrl)
99 wxPyComboCtrl() : wxComboCtrl() {}
100 wxPyComboCtrl(wxWindow *parent,
101 wxWindowID id = wxID_ANY,
102 const wxString& value = wxEmptyString,
103 const wxPoint& pos = wxDefaultPosition,
104 const wxSize& size = wxDefaultSize,
106 const wxValidator& validator = wxDefaultValidator,
107 const wxString& name = wxPyComboBoxNameStr)
108 : wxComboCtrl(parent, id, value, pos, size, style, validator, name)
111 void DoSetPopupControl(wxComboPopup* popup)
114 wxPyBlock_t blocked = wxPyBeginBlockThreads();
115 if ((found = wxPyCBH_findCallback(m_myInst, "DoSetPopupControl"))) {
116 PyObject* obj = wxPyConstructObject(popup, wxT("wxComboPopup"), false);
117 wxPyCBH_callCallback(m_myInst, Py_BuildValue("(O)",obj));
120 wxPyEndBlockThreads(blocked);
122 wxComboCtrl::DoSetPopupControl(popup);
127 ShowBelow = 0x0000, // Showing popup below the control
128 ShowAbove = 0x0001, // Showing popup above the control
129 CanDeferShow = 0x0002 // Can only return true from AnimateShow if this is set
133 DEC_PYCALLBACK_VOID_(OnButtonClick);
134 DEC_PYCALLBACK__RECTINT(DoShowPopup);
135 DEC_PYCALLBACK_BOOL_RECTINT(AnimateShow);
140 IMPLEMENT_ABSTRACT_CLASS(wxPyComboCtrl, wxComboCtrl);
142 IMP_PYCALLBACK_VOID_(wxPyComboCtrl, wxComboCtrl, OnButtonClick);
143 IMP_PYCALLBACK__RECTINT(wxPyComboCtrl, wxComboCtrl, DoShowPopup);
144 IMP_PYCALLBACK_BOOL_RECTINT(wxPyComboCtrl, wxComboCtrl, AnimateShow);
150 // Now declare wxPyComboCtrl for Python
151 MustHaveApp(wxPyComboCtrl);
152 %rename(ComboCtrl) wxPyComboCtrl;
154 class wxPyComboCtrl : public wxControl
157 %pythonAppend wxPyComboCtrl "self._setOORInfo(self);" setCallbackInfo(ComboCtrl)
158 %pythonAppend wxPyComboCtrl() "";
160 wxPyComboCtrl(wxWindow *parent,
161 wxWindowID id = wxID_ANY,
162 const wxString& value = wxEmptyString,
163 const wxPoint& pos = wxDefaultPosition,
164 const wxSize& size = wxDefaultSize,
166 const wxValidator& validator = wxDefaultValidator,
167 const wxString& name = wxPyComboBoxNameStr);
169 %RenameCtor(PreComboCtrl, wxPyComboCtrl());
171 void _setCallbackInfo(PyObject* self, PyObject* _class);
173 // show/hide popup window
174 virtual void ShowPopup();
175 virtual void HidePopup();
177 // Override for totally custom combo action
178 virtual void OnButtonClick();
180 // return true if the popup is currently shown
181 bool IsPopupShown() const;
184 // set interface class instance derived from wxComboPopup
185 // NULL popup can be used to indicate default in a derived class
186 %disownarg(wxPyComboPopup* popup);
187 void SetPopupControl( wxPyComboPopup* popup );
188 %cleardisown(wxPyComboPopup* popup);
191 // get interface class instance derived from wxComboPopup
192 wxPyComboPopup* GetPopupControl();
194 // get the popup window containing the popup control
195 wxWindow *GetPopupWindow() const;
197 // Get the text control which is part of the combobox.
198 wxTextCtrl *GetTextCtrl() const;
200 // get the dropdown button which is part of the combobox
201 // note: its not necessarily a wxButton or wxBitmapButton
202 wxWindow *GetButton() const;
204 // forward these methods to all subcontrols
205 virtual bool Enable(bool enable = true);
206 virtual bool Show(bool show = true);
207 virtual bool SetFont(const wxFont& font);
209 // wxTextCtrl methods - for readonly combo they should return
211 virtual wxString GetValue() const;
212 virtual void SetValue(const wxString& value);
215 virtual void Paste();
216 virtual void SetInsertionPoint(long pos);
217 virtual void SetInsertionPointEnd();
218 virtual long GetInsertionPoint() const;
219 virtual long GetLastPosition() const;
220 virtual void Replace(long from, long to, const wxString& value);
221 virtual void Remove(long from, long to);
224 %Rename(SetMark, void , SetSelection(long from, long to));
226 // This method sets the text without affecting list selection
227 // (ie. wxComboPopup::SetStringValue doesn't get called).
228 void SetText(const wxString& value);
230 // This method sets value and also optionally sends EVT_TEXT
231 // (needed by combo popups)
232 void SetValueWithEvent(const wxString& value, bool withEvent = true);
235 // Popup customization methods
238 // Sets minimum width of the popup. If wider than combo control, it will
239 // extend to the left.
241 // * Value -1 indicates the default.
242 // * Custom popup may choose to ignore this (wxOwnerDrawnComboBox does not).
243 void SetPopupMinWidth( int width );
245 // Sets preferred maximum height of the popup.
247 // * Value -1 indicates the default.
248 // * Custom popup may choose to ignore this (wxOwnerDrawnComboBox does not).
249 void SetPopupMaxHeight( int height );
251 // Extends popup size horizontally, relative to the edges of the combo control.
253 // * Popup minimum width may override extLeft (ie. it has higher precedence).
254 // * Values 0 indicate default.
255 // * Custom popup may not take this fully into account (wxOwnerDrawnComboBox takes).
256 void SetPopupExtents( int extLeft, int extRight );
258 // Set width, in pixels, of custom paint area in writable combo.
259 // In read-only, used to indicate area that is not covered by the
260 // focus rectangle (which may or may not be drawn, depending on the
262 void SetCustomPaintWidth( int width );
263 int GetCustomPaintWidth() const;
265 // Set side of the control to which the popup will align itself.
266 // Valid values are wxLEFT, wxRIGHT and 0. The default value 0 means
267 // that the side of the button will be used.
268 void SetPopupAnchor( int anchorSide );
270 // Set position of dropdown button.
271 // width: button width. <= 0 for default.
272 // height: button height. <= 0 for default.
273 // side: wxLEFT or wxRIGHT, indicates on which side the button will be placed.
274 // spacingX: empty space on sides of the button. Default is 0.
276 // There is no spacingY - the button will be centered vertically.
277 void SetButtonPosition( int width = -1,
282 // Returns current size of the dropdown button.
283 wxSize GetButtonSize();
286 // Sets dropbutton to be drawn with custom bitmaps.
288 // bmpNormal: drawn when cursor is not on button
289 // pushButtonBg: Draw push button background below the image.
290 // NOTE! This is usually only properly supported on platforms with appropriate
291 // method in wxRendererNative.
292 // bmpPressed: drawn when button is depressed
293 // bmpHover: drawn when cursor hovers on button. This is ignored on platforms
294 // that do not generally display hover differently.
295 // bmpDisabled: drawn when combobox is disabled.
296 void SetButtonBitmaps( const wxBitmap& bmpNormal,
297 bool pushButtonBg = false,
298 const wxBitmap& bmpPressed = wxNullBitmap,
299 const wxBitmap& bmpHover = wxNullBitmap,
300 const wxBitmap& bmpDisabled = wxNullBitmap );
303 // This will set the space in pixels between left edge of the control and the
304 // text, regardless whether control is read-only (ie. no wxTextCtrl) or not.
305 // Platform-specific default can be set with value-1.
307 // * This method may do nothing on some native implementations.
308 void SetTextIndent( int indent );
310 // Returns actual indentation in pixels.
311 wxCoord GetTextIndent() const;
313 // Returns area covered by the text field.
314 const wxRect& GetTextRect() const;
316 // Call with enable as true to use a type of popup window that guarantees ability
317 // to focus the popup control, and normal function of common native controls.
318 // This alternative popup window is usually a wxDialog, and as such it's parent
319 // frame will appear as if the focus has been lost from it.
320 void UseAltPopupWindow( bool enable = true );
322 // Call with false to disable popup animation, if any.
323 void EnablePopupAnimation( bool enable = true );
326 // Utilies needed by the popups or native implementations
329 // Returns true if given key combination should toggle the popup.
330 // NB: This is a separate from other keyboard handling because:
331 // 1) Replaceability.
332 // 2) Centralized code (otherwise it'd be split up between
333 // wxComboCtrl key handler and wxVListBoxComboPopup's
335 virtual bool IsKeyPopupToggle(const wxKeyEvent& event) const;
337 // Prepare background of combo control or an item in a dropdown list
338 // in a way typical on platform. This includes painting the focus/disabled
339 // background and setting the clipping region.
340 // Unless you plan to paint your own focus indicator, you should always call this
341 // in your wxComboPopup::PaintComboControl implementation.
342 // In addition, it sets pen and text colour to what looks good and proper
343 // against the background.
344 // flags: wxRendererNative flags: wxCONTROL_ISSUBMENU: is drawing a list item instead of combo control
345 // wxCONTROL_SELECTED: list item is selected
346 // wxCONTROL_DISABLED: control/item is disabled
347 virtual void PrepareBackground( wxDC& dc, const wxRect& rect, int flags ) const;
349 // Returns true if focus indicator should be drawn in the control.
350 bool ShouldDrawFocus() const;
352 // These methods return references to appropriate dropbutton bitmaps
353 const wxBitmap& GetBitmapNormal() const;
354 const wxBitmap& GetBitmapPressed() const;
355 const wxBitmap& GetBitmapHover() const;
356 const wxBitmap& GetBitmapDisabled() const;
358 // Return internal flags
359 wxUint32 GetInternalFlags() const;
361 // Return true if Create has finished
362 bool IsCreated() const;
364 // common code to be called on popup hide/dismiss
365 void OnPopupDismiss();
376 bool IsPopupWindowState( int state ) const;
378 int GetPopupWindowState() const;
380 // Set value returned by GetMainWindowOfCompositeControl
381 void SetCtrlMainWnd( wxWindow* wnd );
383 static int GetFeatures();
386 // Flags for DoShowPopup and AnimateShow
389 ShowBelow = 0x0000, // Showing popup below the control
390 ShowAbove = 0x0001, // Showing popup above the control
391 CanDeferShow = 0x0002 // Can only return true from AnimateShow if this is set
394 // Shows and positions the popup.
395 virtual void DoShowPopup( const wxRect& rect, int flags );
397 // Implement in derived class to create a drop-down animation.
398 // Return true if finished immediately. Otherwise popup is only
399 // shown when the derived class call DoShowPopup.
400 // Flags are same as for DoShowPopup.
401 virtual bool AnimateShow( const wxRect& rect, int flags );
405 //---------------------------------------------------------------------------
409 // C++ implemetation of Python aware wxComboCtrl
411 class wxPyComboPopup : public wxComboPopup
414 wxPyComboPopup() : wxComboPopup() {}
418 DEC_PYCALLBACK_VOID_(Init);
419 DEC_PYCALLBACK_BOOL_WXWIN_pure(Create);
420 DEC_PYCALLBACK_VOID_(OnPopup);
421 DEC_PYCALLBACK_VOID_(OnDismiss);
422 DEC_PYCALLBACK__STRING(SetStringValue);
423 DEC_PYCALLBACK_STRING__constpure(GetStringValue);
424 DEC_PYCALLBACK_VOID_(OnComboDoubleClick);
425 DEC_PYCALLBACK_BOOL_(LazyCreate);
427 virtual wxWindow *GetControl()
429 wxWindow* rval = NULL;
430 const char* errmsg = "GetControl should return an object derived from wx.Window.";
431 wxPyBlock_t blocked = wxPyBeginBlockThreads();
432 if (wxPyCBH_findCallback(m_myInst, "GetControl")) {
434 ro = wxPyCBH_callCallbackObj(m_myInst, Py_BuildValue("()"));
436 if (!wxPyConvertSwigPtr(ro, (void**)&rval, wxT("wxWindow")))
437 PyErr_SetString(PyExc_TypeError, errmsg);
442 PyErr_SetString(PyExc_TypeError, errmsg);
443 wxPyEndBlockThreads(blocked);
448 virtual void PaintComboControl( wxDC& dc, const wxRect& rect )
451 wxPyBlock_t blocked = wxPyBeginBlockThreads();
452 if ((found = wxPyCBH_findCallback(m_myInst, "PaintComboControl"))) {
453 PyObject* odc = wxPyMake_wxObject(&dc,false);
454 PyObject* orect = wxPyConstructObject((void*)&rect, wxT("wxRect"), 0);
455 wxPyCBH_callCallback(m_myInst, Py_BuildValue("(OO)", odc, orect));
459 wxPyEndBlockThreads(blocked);
461 wxComboPopup::PaintComboControl(dc, rect);
465 virtual void OnComboKeyEvent( wxKeyEvent& event )
468 wxPyBlock_t blocked = wxPyBeginBlockThreads();
469 if ((found = wxPyCBH_findCallback(m_myInst, "OnComboKeyEvent"))) {
470 PyObject* oevt = wxPyConstructObject((void*)&event, wxT("wxKeyEvent"), 0);
471 wxPyCBH_callCallback(m_myInst, Py_BuildValue("(O)", oevt));
474 wxPyEndBlockThreads(blocked);
476 wxComboPopup::OnComboKeyEvent(event);
480 virtual wxSize GetAdjustedSize( int minWidth, int prefHeight, int maxHeight )
482 const char* errmsg = "GetAdjustedSize should return a wx.Size or a 2-tuple of integers.";
485 wxSize* rptr = &rval;
486 wxPyBlock_t blocked = wxPyBeginBlockThreads();
487 if ((found = wxPyCBH_findCallback(m_myInst, "GetAdjustedSize"))) {
489 ro = wxPyCBH_callCallbackObj(
490 m_myInst, Py_BuildValue("(iii)", minWidth, prefHeight, maxHeight));
492 if (! wxSize_helper(ro, &rptr))
493 PyErr_SetString(PyExc_TypeError, errmsg);
499 wxPyEndBlockThreads(blocked);
501 rval = wxComboPopup::GetAdjustedSize(minWidth, prefHeight, maxHeight);
505 wxComboCtrl* GetCombo() { return (wxComboCtrl*)m_combo; }
511 IMP_PYCALLBACK_VOID_(wxPyComboPopup, wxComboPopup, Init);
512 IMP_PYCALLBACK_BOOL_WXWIN_pure(wxPyComboPopup, wxComboPopup, Create);
513 IMP_PYCALLBACK_VOID_(wxPyComboPopup, wxComboPopup, OnPopup);
514 IMP_PYCALLBACK_VOID_(wxPyComboPopup, wxComboPopup, OnDismiss);
515 IMP_PYCALLBACK__STRING(wxPyComboPopup, wxComboPopup, SetStringValue);
516 IMP_PYCALLBACK_STRING__constpure(wxPyComboPopup, wxComboPopup, GetStringValue);
517 IMP_PYCALLBACK_VOID_(wxPyComboPopup, wxComboPopup, OnComboDoubleClick);
518 IMP_PYCALLBACK_BOOL_(wxPyComboPopup, wxComboPopup, LazyCreate);
524 // Now declare wxPyComboCtrl for Python
525 MustHaveApp(wxPyComboPopup);
526 %rename(ComboPopup) wxPyComboPopup;
531 %pythonAppend wxPyComboPopup setCallbackInfo(ComboPopup);
536 void _setCallbackInfo(PyObject* self, PyObject* _class);
538 // This is called immediately after construction finishes. m_combo member
539 // variable has been initialized before the call.
540 // NOTE: It is not in constructor so the derived class doesn't need to redefine
541 // a default constructor of its own.
544 // Create the popup child control.
545 // Return true for success.
546 virtual bool Create(wxWindow* parent);
548 // We must have an associated control which is subclassed by the combobox.
549 virtual wxWindow *GetControl();
551 // Called immediately after the popup is shown
552 virtual void OnPopup();
554 // Called when popup is dismissed
555 virtual void OnDismiss();
557 // Called just prior to displaying popup.
558 // Default implementation does nothing.
559 virtual void SetStringValue( const wxString& value );
561 // Gets displayed string representation of the value.
562 virtual wxString GetStringValue() const;
564 // This is called to custom paint in the combo control itself (ie. not the popup).
565 // Default implementation draws value as string.
566 virtual void PaintComboControl( wxDC& dc, const wxRect& rect );
568 // Receives key events from the parent wxComboCtrl.
569 // Events not handled should be skipped, as usual.
570 virtual void OnComboKeyEvent( wxKeyEvent& event );
572 // Implement if you need to support special action when user
573 // double-clicks on the parent wxComboCtrl.
574 virtual void OnComboDoubleClick();
576 // Return final size of popup. Called on every popup, just prior to OnPopup.
577 // minWidth = preferred minimum width for window
578 // prefHeight = preferred height. Only applies if > 0,
579 // maxHeight = max height for window, as limited by screen size
580 // and should only be rounded down, if necessary.
581 virtual wxSize GetAdjustedSize( int minWidth, int prefHeight, int maxHeight );
583 // Return true if you want delay call to Create until the popup is shown
584 // for the first time. It is more efficient, but note that it is often
585 // more convenient to have the control created immediately.
586 // Default returns false.
587 virtual bool LazyCreate();
596 // Returns true if Create has been called.
597 bool IsCreated() const;
599 // Default PaintComboControl behaviour
600 static void DefaultPaintComboControl( wxComboCtrlBase* combo,
602 const wxRect& rect );
604 wxPyComboCtrl* GetCombo();
610 //---------------------------------------------------------------------------
615 wxODCB_DCLICK_CYCLES,
616 wxODCB_STD_CONTROL_PAINT,
617 wxODCB_PAINTING_CONTROL,
618 wxODCB_PAINTING_SELECTED
623 // C++ implemetation of Python aware wxOwnerDrawnComboBox
625 class wxPyOwnerDrawnComboBox : public wxOwnerDrawnComboBox
628 wxPyOwnerDrawnComboBox() : wxOwnerDrawnComboBox() {}
629 wxPyOwnerDrawnComboBox(wxWindow *parent,
631 const wxString& value,
634 const wxArrayString& choices,
636 const wxValidator& validator = wxDefaultValidator,
637 const wxString& name = wxPyComboBoxNameStr)
638 : wxOwnerDrawnComboBox(parent, id, value, pos, size, choices, style,
642 DEC_PYCALLBACK__DCRECTINTINT_const(OnDrawItem);
643 DEC_PYCALLBACK_COORD_SIZET_const(OnMeasureItem);
644 DEC_PYCALLBACK_COORD_SIZET_const(OnMeasureItemWidth);
645 DEC_PYCALLBACK__DCRECTINTINT_const(OnDrawBackground);
651 IMP_PYCALLBACK__DCRECTINTINT_const(wxPyOwnerDrawnComboBox, wxOwnerDrawnComboBox, OnDrawItem);
652 IMP_PYCALLBACK_COORD_SIZET_const(wxPyOwnerDrawnComboBox, wxOwnerDrawnComboBox, OnMeasureItem);
653 IMP_PYCALLBACK_COORD_SIZET_const(wxPyOwnerDrawnComboBox, wxOwnerDrawnComboBox, OnMeasureItemWidth);
654 IMP_PYCALLBACK__DCRECTINTINT_const(wxPyOwnerDrawnComboBox, wxOwnerDrawnComboBox, OnDrawBackground);
660 // Now declare wxPyComboCtrl for Python
661 MustHaveApp(wxPyOwnerDrawnComboBox);
662 %rename(OwnerDrawnComboBox) wxPyOwnerDrawnComboBox;
664 class wxPyOwnerDrawnComboBox : public wxPyComboCtrl,
665 public wxItemContainer
668 %pythonAppend wxPyOwnerDrawnComboBox "self._setOORInfo(self);" setCallbackInfo(OwnerDrawnComboBox)
669 %pythonAppend wxPyOwnerDrawnComboBox() "";
671 wxPyOwnerDrawnComboBox(wxWindow *parent,
673 const wxString& value = wxPyEmptyString,
674 const wxPoint& pos = wxDefaultPosition,
675 const wxSize& size = wxDefaultSize,
676 const wxArrayString& choices = wxPyEmptyStringArray,
678 const wxValidator& validator = wxDefaultValidator,
679 const wxString& name = wxPyComboBoxNameStr);
681 %RenameCtor(PreOwnerDrawnComboBox, wxPyOwnerDrawnComboBox());
684 bool Create(wxWindow *parent,
686 const wxString& value = wxPyEmptyString,
687 const wxPoint& pos = wxDefaultPosition,
688 const wxSize& size = wxDefaultSize,
689 const wxArrayString& choices = wxPyEmptyStringArray,
691 const wxValidator& validator = wxDefaultValidator,
692 const wxString& name = wxPyComboBoxNameStr);
694 // Return the widest item width (recalculating it if necessary)
695 virtual int GetWidestItemWidth();
697 // Return the index of the widest item (recalculating it if necessary)
698 virtual int GetWidestItem();
700 void SetSelection(int n);
701 %Rename(SetMark, void , SetSelection(long from, long to));
705 //---------------------------------------------------------------------------
708 // Map renamed classes back to their common name for OOR
709 wxPyPtrTypeMap_Add("wxComboCtrl", "wxPyComboCtrl");
710 wxPyPtrTypeMap_Add("wxComboPopup", "wxPyComboPopup");
712 //---------------------------------------------------------------------------