00001
00002
00003
00004
00005
00007
00008
00009
00010
00011
00012
00013
00014
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include <wx/wx.h>
00026
00027 #include "combo.h"
00028 #if wxXTRA_COMBOCTRL
00029
00030 #include <wx/renderer.h>
00031 #include <wx/tooltip.h>
00032
00033
00034
00035
00036
00037
00038 #define DOUBLE_CLICK_CONVERSION_TRESHOLD 500
00039
00040 #define DEFAULT_DROPBUTTON_WIDTH 19
00041
00042 #define BMP_BUTTON_MARGIN 4
00043
00044 #define DEFAULT_POPUP_HEIGHT 200
00045
00046 #define DEFAULT_TEXT_INDENT 3
00047
00048 #define COMBO_MARGIN 2 // spacing right of wxTextCtrl
00049
00050
00051 #if defined(__WXMSW__)
00052
00053 #define USE_TRANSIENT_POPUP 1 // Use wxPopupWindowTransient (preferred, if it works properly on platform)
00054
00055
00056
00057
00058 #elif defined(__WXGTK__)
00059
00060 #define USE_TRANSIENT_POPUP 1 // Use wxPopupWindowTransient (preferred, if it works properly on platform)
00061
00062 #elif defined(__WXMAC__)
00063
00064 #define USE_TRANSIENT_POPUP 0 // Use wxPopupWindowTransient (preferred, if it works properly on platform)
00065
00066 #else
00067
00068 #define USE_TRANSIENT_POPUP 0 // Use wxPopupWindowTransient (preferred, if it works properly on platform)
00069
00070 #endif
00071
00072
00073
00074
00075
00076 #if (!defined(__WXMSW__) && !defined(__WXGTK__)) || defined(__WXWINCE__)
00077 #undef wxUSE_POPUPWIN
00078 #define wxUSE_POPUPWIN 0
00079 #endif
00080
00081
00082 #if wxUSE_POPUPWIN
00083 #include "wx/popupwin.h"
00084 #else
00085 #undef USE_TRANSIENT_POPUP
00086 #define USE_TRANSIENT_POPUP 0
00087 #endif
00088
00089
00090 #if USE_TRANSIENT_POPUP
00091
00092 #define wxComboPopupWindowBase wxPopupTransientWindow
00093 #define INSTALL_TOPLEV_HANDLER 0
00094
00095 #elif wxUSE_POPUPWIN
00096
00097 #define wxComboPopupWindowBase wxPopupWindow
00098 #define INSTALL_TOPLEV_HANDLER 1
00099
00100 #else
00101
00102 #define wxComboPopupWindowBase wxDialog
00103 #define INSTALL_TOPLEV_HANDLER 0 // Doesn't need since can monitor active event
00104
00105 #endif
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120 #if INSTALL_TOPLEV_HANDLER
00121
00122
00123
00124
00125
00126
00127 class wxComboFrameEventHandler : public wxEvtHandler
00128 {
00129 public:
00130 wxComboFrameEventHandler( wxComboCtrlBase* pCb );
00131 ~wxComboFrameEventHandler();
00132
00133 void OnPopup();
00134
00135 void OnIdle( wxIdleEvent& event );
00136 void OnMouseEvent( wxMouseEvent& event );
00137 void OnActivate( wxActivateEvent& event );
00138 void OnResize( wxSizeEvent& event );
00139 void OnMove( wxMoveEvent& event );
00140 void OnMenuEvent( wxMenuEvent& event );
00141 void OnClose( wxCloseEvent& event );
00142
00143 protected:
00144 wxWindow* m_focusStart;
00145 wxComboCtrlBase* m_combo;
00146
00147 private:
00148 DECLARE_EVENT_TABLE()
00149 };
00150
00151 BEGIN_EVENT_TABLE(wxComboFrameEventHandler, wxEvtHandler)
00152 EVT_IDLE(wxComboFrameEventHandler::OnIdle)
00153 EVT_LEFT_DOWN(wxComboFrameEventHandler::OnMouseEvent)
00154 EVT_RIGHT_DOWN(wxComboFrameEventHandler::OnMouseEvent)
00155 EVT_SIZE(wxComboFrameEventHandler::OnResize)
00156 EVT_MOVE(wxComboFrameEventHandler::OnMove)
00157 EVT_MENU_HIGHLIGHT(wxID_ANY,wxComboFrameEventHandler::OnMenuEvent)
00158 EVT_MENU_OPEN(wxComboFrameEventHandler::OnMenuEvent)
00159 EVT_ACTIVATE(wxComboFrameEventHandler::OnActivate)
00160 EVT_CLOSE(wxComboFrameEventHandler::OnClose)
00161 END_EVENT_TABLE()
00162
00163 wxComboFrameEventHandler::wxComboFrameEventHandler( wxComboCtrlBase* combo )
00164 : wxEvtHandler()
00165 {
00166 m_combo = combo;
00167 }
00168
00169 wxComboFrameEventHandler::~wxComboFrameEventHandler()
00170 {
00171 }
00172
00173 void wxComboFrameEventHandler::OnPopup()
00174 {
00175 m_focusStart = ::wxWindow::FindFocus();
00176 }
00177
00178 void wxComboFrameEventHandler::OnIdle( wxIdleEvent& event )
00179 {
00180 wxWindow* winFocused = ::wxWindow::FindFocus();
00181
00182 wxWindow* popup = m_combo->GetPopupControl();
00183 wxWindow* winpopup = m_combo->GetPopupWindow();
00184
00185 if (
00186 winFocused != m_focusStart &&
00187 winFocused != popup &&
00188 winFocused->GetParent() != popup &&
00189 winFocused != winpopup &&
00190 winFocused->GetParent() != winpopup &&
00191 winFocused != m_combo &&
00192 winFocused != m_combo->GetButton()
00193 )
00194 {
00195 m_combo->HidePopup();
00196 }
00197
00198 event.Skip();
00199 }
00200
00201 void wxComboFrameEventHandler::OnMenuEvent( wxMenuEvent& event )
00202 {
00203 m_combo->HidePopup();
00204 event.Skip();
00205 }
00206
00207 void wxComboFrameEventHandler::OnMouseEvent( wxMouseEvent& event )
00208 {
00209 m_combo->HidePopup();
00210 event.Skip();
00211 }
00212
00213 void wxComboFrameEventHandler::OnClose( wxCloseEvent& event )
00214 {
00215 m_combo->HidePopup();
00216 event.Skip();
00217 }
00218
00219 void wxComboFrameEventHandler::OnActivate( wxActivateEvent& event )
00220 {
00221 m_combo->HidePopup();
00222 event.Skip();
00223 }
00224
00225 void wxComboFrameEventHandler::OnResize( wxSizeEvent& event )
00226 {
00227 m_combo->HidePopup();
00228 event.Skip();
00229 }
00230
00231 void wxComboFrameEventHandler::OnMove( wxMoveEvent& event )
00232 {
00233 m_combo->HidePopup();
00234 event.Skip();
00235 }
00236
00237 #endif // INSTALL_TOPLEV_HANDLER
00238
00239
00240
00241
00242
00243
00244 class wxComboPopupWindow : public wxComboPopupWindowBase
00245 {
00246 public:
00247
00248 wxComboPopupWindow( wxComboCtrlBase *parent, int style = wxBORDER_NONE );
00249
00250 #if USE_TRANSIENT_POPUP
00251 virtual bool ProcessLeftDown(wxMouseEvent& event);
00252 #endif
00253
00254 void OnKeyEvent(wxKeyEvent& event);
00255
00256 void OnMouseEvent( wxMouseEvent& event );
00257 #if !wxUSE_POPUPWIN
00258 void OnActivate( wxActivateEvent& event );
00259 #endif
00260
00261 protected:
00262
00263 #if USE_TRANSIENT_POPUP
00264 virtual void OnDismiss();
00265 #endif
00266
00267 private:
00268 DECLARE_EVENT_TABLE()
00269 };
00270
00271
00272 BEGIN_EVENT_TABLE(wxComboPopupWindow, wxComboPopupWindowBase)
00273 EVT_MOUSE_EVENTS(wxComboPopupWindow::OnMouseEvent)
00274 #if !wxUSE_POPUPWIN
00275 EVT_ACTIVATE(wxComboPopupWindow::OnActivate)
00276 #endif
00277 EVT_KEY_DOWN(wxComboPopupWindow::OnKeyEvent)
00278 EVT_KEY_UP(wxComboPopupWindow::OnKeyEvent)
00279 END_EVENT_TABLE()
00280
00281
00282 wxComboPopupWindow::wxComboPopupWindow( wxComboCtrlBase *parent,
00283 int style )
00284 #if wxUSE_POPUPWIN
00285 : wxComboPopupWindowBase(parent,style)
00286 #else
00287 : wxComboPopupWindowBase(parent,
00288 wxID_ANY,
00289 wxEmptyString,
00290 wxPoint(-21,-21),
00291 wxSize(20,20),
00292 style)
00293 #endif
00294 {
00295 }
00296
00297 void wxComboPopupWindow::OnKeyEvent( wxKeyEvent& event )
00298 {
00299
00300
00301 wxWindowList children = GetChildren();
00302 wxWindowList::iterator node = children.begin();
00303 wxWindow* child = (wxWindow*)*node;
00304 child->AddPendingEvent(event);
00305 }
00306
00307 void wxComboPopupWindow::OnMouseEvent( wxMouseEvent& event )
00308 {
00309 event.Skip();
00310 }
00311
00312 #if !wxUSE_POPUPWIN
00313 void wxComboPopupWindow::OnActivate( wxActivateEvent& event )
00314 {
00315 if ( !event.GetActive() )
00316 {
00317
00318 wxComboCtrl* combo = (wxComboCtrl*) GetParent();
00319 wxASSERT( combo );
00320 wxASSERT( combo->IsKindOf(CLASSINFO(wxComboCtrl)) );
00321
00322 combo->HidePopup();
00323
00324 event.Skip();
00325 }
00326 }
00327 #endif
00328
00329 #if USE_TRANSIENT_POPUP
00330 bool wxComboPopupWindow::ProcessLeftDown(wxMouseEvent& event )
00331 {
00332 return wxComboPopupWindowBase::ProcessLeftDown(event);
00333 }
00334 #endif
00335
00336 #if USE_TRANSIENT_POPUP
00337
00338 void wxComboPopupWindow::OnDismiss()
00339 {
00340 wxComboCtrlBase* combo = (wxComboCtrlBase*) GetParent();
00341 wxASSERT_MSG( combo->IsKindOf(CLASSINFO(wxComboCtrlBase)),
00342 wxT("parent might not be wxComboCtrl, but check IMPLEMENT_DYNAMIC_CLASS(2) macro for correctness") );
00343
00344 combo->OnPopupDismiss();
00345 }
00346 #endif
00347
00348
00349
00350
00351
00352
00353 wxComboPopup::~wxComboPopup()
00354 {
00355 }
00356
00357 void wxComboPopup::OnPopup()
00358 {
00359 }
00360
00361 void wxComboPopup::OnDismiss()
00362 {
00363 }
00364
00365 wxSize wxComboPopup::GetAdjustedSize( int minWidth,
00366 int prefHeight,
00367 int WXUNUSED(maxHeight) )
00368 {
00369 return wxSize(minWidth,prefHeight);
00370 }
00371
00372 void wxComboPopup::DefaultPaintComboControl( wxComboCtrlBase* combo,
00373 wxDC& dc, const wxRect& rect )
00374 {
00375 if ( combo->GetWindowStyle() & wxCB_READONLY )
00376 {
00377 combo->DrawFocusBackground(dc,rect,0);
00378
00379 dc.DrawText( combo->GetValue(),
00380 rect.x + combo->GetTextIndent(),
00381 (rect.height-dc.GetCharHeight())/2 + rect.y );
00382 }
00383 }
00384
00385 void wxComboPopup::PaintComboControl( wxDC& dc, const wxRect& rect )
00386 {
00387 DefaultPaintComboControl(m_combo,dc,rect);
00388 }
00389
00390 void wxComboPopup::OnComboKeyEvent( wxKeyEvent& event )
00391 {
00392 event.Skip();
00393 }
00394
00395 void wxComboPopup::OnComboDoubleClick()
00396 {
00397 }
00398
00399 void wxComboPopup::SetStringValue( const wxString& WXUNUSED(value) )
00400 {
00401 }
00402
00403 bool wxComboPopup::LazyCreate()
00404 {
00405 return false;
00406 }
00407
00408 void wxComboPopup::Dismiss()
00409 {
00410 m_combo->HidePopup();
00411 }
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421 class wxComboBoxExtraInputHandler : public wxEvtHandler
00422 {
00423 public:
00424
00425 wxComboBoxExtraInputHandler( wxComboCtrlBase* combo )
00426 : wxEvtHandler()
00427 {
00428 m_combo = combo;
00429 }
00430 ~wxComboBoxExtraInputHandler() { }
00431 void OnKey(wxKeyEvent& event);
00432 void OnFocus(wxFocusEvent& event);
00433
00434 protected:
00435 wxComboCtrlBase* m_combo;
00436
00437 private:
00438 DECLARE_EVENT_TABLE()
00439 };
00440
00441
00442 BEGIN_EVENT_TABLE(wxComboBoxExtraInputHandler, wxEvtHandler)
00443 EVT_KEY_DOWN(wxComboBoxExtraInputHandler::OnKey)
00444 EVT_SET_FOCUS(wxComboBoxExtraInputHandler::OnFocus)
00445 END_EVENT_TABLE()
00446
00447
00448 void wxComboBoxExtraInputHandler::OnKey(wxKeyEvent& event)
00449 {
00450 int keycode = event.GetKeyCode();
00451
00452 if ( keycode == WXK_TAB && !m_combo->IsPopupShown() )
00453 {
00454 wxNavigationKeyEvent evt;
00455 evt.SetFlags(wxNavigationKeyEvent::FromTab|
00456 (!event.ShiftDown()?wxNavigationKeyEvent::IsForward:
00457 wxNavigationKeyEvent::IsBackward));
00458 evt.SetEventObject(m_combo);
00459 m_combo->GetParent()->GetEventHandler()->AddPendingEvent(evt);
00460 return;
00461 }
00462
00463 if ( m_combo->IsPopupShown() )
00464 {
00465
00466 m_combo->GetPopupControl()->GetControl()->AddPendingEvent(event);
00467 }
00468 else
00469 {
00470 int comboStyle = m_combo->GetWindowStyle();
00471 wxComboPopup* popupInterface = m_combo->GetPopupControl();
00472
00473 if ( !popupInterface )
00474 {
00475 event.Skip();
00476 return;
00477 }
00478
00479 if ( (comboStyle & wxCB_READONLY) ||
00480 ( keycode != WXK_RIGHT && keycode != WXK_LEFT )
00481 )
00482 {
00483 popupInterface->OnComboKeyEvent(event);
00484 }
00485 else
00486 event.Skip();
00487 }
00488 }
00489
00490 void wxComboBoxExtraInputHandler::OnFocus(wxFocusEvent& event)
00491 {
00492
00493
00494 if ( !(m_combo->GetInternalFlags() & wxCC_NO_TEXT_AUTO_SELECT) )
00495 {
00496 if ( m_combo->GetTextCtrl() )
00497 m_combo->GetTextCtrl()->SelectAll();
00498 else
00499 m_combo->SetSelection(-1,-1);
00500 }
00501
00502 if ( event.GetId() != m_combo->GetId() )
00503 {
00504
00505
00506
00507 wxFocusEvent evt2(wxEVT_SET_FOCUS,m_combo->GetId());
00508 evt2.SetEventObject(m_combo);
00509 m_combo->GetEventHandler()->ProcessEvent(evt2);
00510 }
00511 else
00512 event.Skip();
00513
00514 event.Skip();
00515 }
00516
00517
00518
00519
00520
00521
00522 class wxComboPopupExtraEventHandler : public wxEvtHandler
00523 {
00524 public:
00525
00526 wxComboPopupExtraEventHandler( wxComboCtrlBase* combo )
00527 : wxEvtHandler()
00528 {
00529 m_combo = combo;
00530 m_beenInside = false;
00531 }
00532 ~wxComboPopupExtraEventHandler() { }
00533
00534 void OnMouseEvent( wxMouseEvent& event );
00535
00536
00537 void OnPopupDismiss()
00538 {
00539 m_beenInside = false;
00540 }
00541
00542 protected:
00543 wxComboCtrlBase* m_combo;
00544
00545 bool m_beenInside;
00546
00547 private:
00548 DECLARE_EVENT_TABLE()
00549 };
00550
00551
00552 BEGIN_EVENT_TABLE(wxComboPopupExtraEventHandler, wxEvtHandler)
00553 EVT_MOUSE_EVENTS(wxComboPopupExtraEventHandler::OnMouseEvent)
00554 END_EVENT_TABLE()
00555
00556
00557 void wxComboPopupExtraEventHandler::OnMouseEvent( wxMouseEvent& event )
00558 {
00559 wxPoint pt = event.GetPosition();
00560 wxSize sz = m_combo->GetPopupControl()->GetControl()->GetClientSize();
00561 int evtType = event.GetEventType();
00562 bool isInside = pt.x >= 0 && pt.y >= 0 && pt.x < sz.x && pt.y < sz.y;
00563
00564 if ( evtType == wxEVT_MOTION ||
00565 evtType == wxEVT_LEFT_DOWN ||
00566 evtType == wxEVT_RIGHT_DOWN )
00567 {
00568
00569 if ( !isInside )
00570 {
00571 event.Skip(false);
00572 return;
00573 }
00574 }
00575 else if ( evtType == wxEVT_LEFT_UP )
00576 {
00577
00578 if ( evtType == wxEVT_LEFT_DOWN )
00579 {
00580 if ( !isInside )
00581 return;
00582 }
00583
00584 if ( !m_beenInside )
00585 {
00586 if ( isInside )
00587 {
00588 m_beenInside = true;
00589 }
00590 else
00591 {
00592
00593
00594
00595
00596
00597 wxWindow* btn = m_combo->GetButton();
00598 if ( btn )
00599 btn->GetEventHandler()->AddPendingEvent(event);
00600 else
00601 m_combo->GetEventHandler()->AddPendingEvent(event);
00602
00603 return;
00604 }
00605
00606 event.Skip();
00607 }
00608 }
00609
00610 event.Skip();
00611 }
00612
00613
00614
00615
00616
00617
00618 BEGIN_EVENT_TABLE(wxComboCtrlBase, wxControl)
00619 EVT_TEXT(wxID_ANY,wxComboCtrlBase::OnTextCtrlEvent)
00620 EVT_SIZE(wxComboCtrlBase::OnSizeEvent)
00621 EVT_SET_FOCUS(wxComboCtrlBase::OnFocusEvent)
00622 EVT_KILL_FOCUS(wxComboCtrlBase::OnFocusEvent)
00623
00624 EVT_TEXT_ENTER(wxID_ANY,wxComboCtrlBase::OnTextCtrlEvent)
00625 EVT_SYS_COLOUR_CHANGED(wxComboCtrlBase::OnSysColourChanged)
00626 END_EVENT_TABLE()
00627
00628
00629 IMPLEMENT_ABSTRACT_CLASS(wxComboCtrlBase, wxControl)
00630
00631
00632 static wxBitmap* gs_doubleBuffer = (wxBitmap*) NULL;
00633
00634 void wxComboCtrlBase::Init()
00635 {
00636 m_winPopup = (wxWindow *)NULL;
00637 m_popup = (wxWindow *)NULL;
00638 m_isPopupShown = false;
00639 m_btn = (wxWindow*) NULL;
00640 m_text = (wxTextCtrl*) NULL;
00641 m_popupInterface = (wxComboPopup*) NULL;
00642
00643 m_extraEvtHandler = (wxEvtHandler*) NULL;
00644 m_popupExtraHandler = (wxEvtHandler*) NULL;
00645 m_textEvtHandler = (wxEvtHandler*) NULL;
00646
00647 #if INSTALL_TOPLEV_HANDLER
00648 m_toplevEvtHandler = (wxEvtHandler*) NULL;
00649 #endif
00650
00651 m_heightPopup = -1;
00652 m_widthMinPopup = -1;
00653 m_anchorSide = 0;
00654 m_widthCustomPaint = 0;
00655 m_widthCustomBorder = 0;
00656
00657 m_btnState = 0;
00658 m_btnWidDefault = 0;
00659 m_blankButtonBg = false;
00660 m_btnWid = m_btnHei = -1;
00661 m_btnSide = wxRIGHT;
00662 m_btnSpacingX = 0;
00663
00664 m_extLeft = 0;
00665 m_extRight = 0;
00666 m_absIndent = -1;
00667 m_iFlags = 0;
00668 m_downReceived = false;
00669 m_timeCanAcceptClick = 0;
00670 }
00671
00672 bool wxComboCtrlBase::Create(wxWindow *parent,
00673 wxWindowID id,
00674 const wxString& value,
00675 const wxPoint& pos,
00676 const wxSize& size,
00677 long style,
00678 const wxValidator& validator,
00679 const wxString& name)
00680 {
00681 if ( !wxControl::Create(parent,
00682 id,
00683 pos,
00684 size,
00685 style | wxWANTS_CHARS,
00686 validator,
00687 name) )
00688 return false;
00689
00690 m_valueString = value;
00691
00692
00693 OnThemeChange();
00694 m_absIndent = GetNativeTextIndent();
00695
00696 m_iFlags |= wxCC_IFLAG_CREATED;
00697
00698
00699
00700 if ( size.x > 0 && size.y > 0 )
00701 {
00702 wxSizeEvent evt(size,GetId());
00703 GetEventHandler()->AddPendingEvent(evt);
00704 }
00705
00706 return true;
00707 }
00708
00709 void wxComboCtrlBase::InstallInputHandlers( bool alsoTextCtrl )
00710 {
00711 if ( m_text && alsoTextCtrl )
00712 {
00713 m_textEvtHandler = new wxComboBoxExtraInputHandler(this);
00714 m_text->PushEventHandler(m_textEvtHandler);
00715 }
00716
00717 wxComboBoxExtraInputHandler* inputHandler = new wxComboBoxExtraInputHandler(this);
00718 PushEventHandler(inputHandler);
00719 m_extraEvtHandler = inputHandler;
00720 }
00721
00722 void
00723 wxComboCtrlBase::CreateTextCtrl(int style, const wxValidator& validator)
00724 {
00725 if ( !(m_windowStyle & wxCB_READONLY) )
00726 {
00727
00728
00729
00730
00731 style |= wxTE_PROCESS_TAB;
00732
00733 if ( HasFlag(wxTE_PROCESS_ENTER) )
00734 style |= wxTE_PROCESS_ENTER;
00735
00736 m_text = new wxTextCtrl(this, wxID_ANY, m_valueString,
00737 wxDefaultPosition, wxDefaultSize,
00738 style, validator);
00739
00740
00741 m_text->SetSizeHints(2,4);
00742 }
00743 }
00744
00745 void wxComboCtrlBase::OnThemeChange()
00746 {
00747 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
00748 }
00749
00750 wxComboCtrlBase::~wxComboCtrlBase()
00751 {
00752 if ( HasCapture() )
00753 ReleaseMouse();
00754
00755 delete gs_doubleBuffer;
00756 gs_doubleBuffer = (wxBitmap*) NULL;
00757
00758 #if INSTALL_TOPLEV_HANDLER
00759 delete ((wxComboFrameEventHandler*)m_toplevEvtHandler);
00760 m_toplevEvtHandler = (wxEvtHandler*) NULL;
00761 #endif
00762
00763 DestroyPopup();
00764
00765 RemoveEventHandler(m_extraEvtHandler);
00766
00767 if ( m_text )
00768 m_text->RemoveEventHandler(m_textEvtHandler);
00769
00770 delete m_textEvtHandler;
00771 delete m_extraEvtHandler;
00772 }
00773
00774
00775
00776
00777
00778
00779
00780 void wxComboCtrlBase::CalculateAreas( int btnWidth )
00781 {
00782 wxSize sz = GetClientSize();
00783 int customBorder = m_widthCustomBorder;
00784 int btnBorder;
00785
00786
00787
00788
00789 if ( ( (m_iFlags & wxCC_BUTTON_OUTSIDE_BORDER) ||
00790 (m_bmpNormal.Ok() && m_blankButtonBg) ) &&
00791 m_btnSpacingX == 0 &&
00792 m_btnHei <= 0 )
00793 {
00794 m_iFlags |= wxCC_IFLAG_BUTTON_OUTSIDE;
00795 btnBorder = 0;
00796 }
00797 else
00798 {
00799 m_iFlags &= ~(wxCC_IFLAG_BUTTON_OUTSIDE);
00800 btnBorder = customBorder;
00801 }
00802
00803
00804 if ( m_absIndent < 0 )
00805 m_absIndent = GetNativeTextIndent();
00806
00807 int butWidth = btnWidth;
00808
00809 if ( butWidth <= 0 )
00810 butWidth = m_btnWidDefault;
00811 else
00812 m_btnWidDefault = butWidth;
00813
00814 if ( butWidth <= 0 )
00815 return;
00816
00817 int butHeight = sz.y - btnBorder*2;
00818
00819
00820 if ( m_btnWid > 0 )
00821 butWidth = m_btnWid;
00822 else
00823 {
00824
00825
00826 int bestHeight = GetBestSize().y;
00827 int height = GetSize().y;
00828
00829 if ( height < bestHeight )
00830 {
00831
00832
00833
00834 if ( height > 18 )
00835 butWidth = (height*butWidth)/bestHeight;
00836 else
00837 butWidth = butHeight;
00838 }
00839 }
00840
00841
00842 if ( m_btnHei > 0 )
00843 butHeight = m_btnHei;
00844
00845
00846
00847
00848
00849 if ( m_bmpNormal.Ok() )
00850 {
00851 int bmpReqWidth = m_bmpNormal.GetWidth();
00852 int bmpReqHeight = m_bmpNormal.GetHeight();
00853
00854
00855 if ( m_blankButtonBg )
00856 {
00857 bmpReqWidth += BMP_BUTTON_MARGIN*2;
00858 bmpReqHeight += BMP_BUTTON_MARGIN*2;
00859 }
00860
00861 if ( butWidth < bmpReqWidth || ( m_btnWid == 0 && !m_blankButtonBg ) )
00862 butWidth = bmpReqWidth;
00863 if ( butHeight < bmpReqHeight || ( m_btnHei == 0 && !m_blankButtonBg ) )
00864 butHeight = bmpReqHeight;
00865
00866
00867 if ( (sz.y-(customBorder*2)) < butHeight && btnWidth == 0 )
00868 {
00869 int newY = butHeight+(customBorder*2);
00870 SetClientSize(wxDefaultCoord,newY);
00871 sz.y = newY;
00872 }
00873 }
00874
00875 int butAreaWid = butWidth + (m_btnSpacingX*2);
00876
00877 m_btnSize.x = butWidth;
00878 m_btnSize.y = butHeight;
00879
00880 m_btnArea.x = ( m_btnSide==wxRIGHT ? sz.x - butAreaWid - btnBorder : btnBorder );
00881 m_btnArea.y = btnBorder;
00882 m_btnArea.width = butAreaWid;
00883 m_btnArea.height = sz.y - (btnBorder*2);
00884
00885 m_tcArea.x = ( m_btnSide==wxRIGHT ? 0 : butAreaWid ) + customBorder;
00886 m_tcArea.y = customBorder;
00887 m_tcArea.width = sz.x - butAreaWid - (customBorder*2);
00888 m_tcArea.height = sz.y - (customBorder*2);
00889
00890
00891
00892
00893
00894
00895
00896
00897 }
00898
00899 void wxComboCtrlBase::PositionTextCtrl( int textCtrlXAdjust, int textCtrlYAdjust )
00900 {
00901 if ( !m_text )
00902 return;
00903
00904 wxSize sz = GetClientSize();
00905 int customBorder = m_widthCustomBorder;
00906
00907 if ( (m_text->GetWindowStyleFlag() & wxBORDER_MASK) == wxNO_BORDER )
00908 {
00909
00910 int tcSizeY = m_text->GetBestSize().y;
00911 int diff = sz.y - tcSizeY;
00912 int y = textCtrlYAdjust + (diff/2);
00913
00914 if ( y < customBorder )
00915 y = customBorder;
00916
00917 m_text->SetSize( m_tcArea.x + m_widthCustomPaint + m_absIndent + textCtrlXAdjust,
00918 y,
00919 m_tcArea.width - COMBO_MARGIN -
00920 (textCtrlXAdjust + m_widthCustomPaint + m_absIndent),
00921 -1 );
00922
00923
00924 wxSize tsz = m_text->GetSize();
00925 diff = (y + tsz.y) - (sz.y - customBorder);
00926 if ( diff >= 0 )
00927 {
00928 tsz.y = tsz.y - diff - 1;
00929 m_text->SetSize(tsz);
00930 }
00931 }
00932 else
00933 {
00934 m_text->SetSize( m_tcArea.x,
00935 0,
00936 sz.x - m_btnArea.x - m_widthCustomPaint - customBorder,
00937 sz.y );
00938 }
00939 }
00940
00941 wxSize wxComboCtrlBase::DoGetBestSize() const
00942 {
00943 wxSize sizeText(150,0);
00944
00945 if ( m_text )
00946 sizeText = m_text->GetBestSize();
00947
00948
00949
00950 int fhei;
00951 if ( m_font.Ok() )
00952 fhei = (m_font.GetPointSize()*2) + 5;
00953 else if ( wxNORMAL_FONT->Ok() )
00954 fhei = (wxNORMAL_FONT->GetPointSize()*2) + 5;
00955 else
00956 fhei = sizeText.y + 4;
00957
00958
00959 int btnSizeY = m_btnSize.y;
00960 if ( m_bmpNormal.Ok() && fhei < btnSizeY )
00961 fhei = btnSizeY;
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977 #ifdef __WXGTK__
00978 fhei += 1;
00979 #endif
00980
00981 wxSize ret(sizeText.x + COMBO_MARGIN + DEFAULT_DROPBUTTON_WIDTH,
00982 fhei);
00983
00984 CacheBestSize(ret);
00985 return ret;
00986 }
00987
00988 void wxComboCtrlBase::OnSizeEvent( wxSizeEvent& event )
00989 {
00990 if ( !IsCreated() )
00991 return;
00992
00993
00994 OnResize();
00995
00996 event.Skip();
00997 }
00998
00999
01000
01001
01002
01003 bool wxComboCtrlBase::Enable(bool enable)
01004 {
01005 if ( !wxControl::Enable(enable) )
01006 return false;
01007
01008 if ( m_btn )
01009 m_btn->Enable(enable);
01010 if ( m_text )
01011 m_text->Enable(enable);
01012
01013 return true;
01014 }
01015
01016 bool wxComboCtrlBase::Show(bool show)
01017 {
01018 if ( !wxControl::Show(show) )
01019 return false;
01020
01021 if (m_btn)
01022 m_btn->Show(show);
01023
01024 if (m_text)
01025 m_text->Show(show);
01026
01027 return true;
01028 }
01029
01030 bool wxComboCtrlBase::SetFont ( const wxFont& font )
01031 {
01032 if ( !wxControl::SetFont(font) )
01033 return false;
01034
01035 if (m_text)
01036 m_text->SetFont(font);
01037
01038 return true;
01039 }
01040
01041 #if wxUSE_TOOLTIPS
01042 void wxComboCtrlBase::DoSetToolTip(wxToolTip *tooltip)
01043 {
01044 wxControl::DoSetToolTip(tooltip);
01045
01046
01047 if ( tooltip )
01048 {
01049 const wxString &tip = tooltip->GetTip();
01050 if ( m_text ) m_text->SetToolTip(tip);
01051 if ( m_btn ) m_btn->SetToolTip(tip);
01052 }
01053 else
01054 {
01055 if ( m_text ) m_text->SetToolTip( (wxToolTip*) NULL );
01056 if ( m_btn ) m_btn->SetToolTip( (wxToolTip*) NULL );
01057 }
01058 }
01059 #endif // wxUSE_TOOLTIPS
01060
01061
01062
01063
01064
01065
01066 void wxComboCtrlBase::DrawFocusBackground( wxDC& dc, const wxRect& rect, int flags ) const
01067 {
01068 wxSize sz = GetClientSize();
01069 bool isEnabled;
01070 bool isFocused;
01071
01072
01073 int focusSpacingX;
01074 int focusSpacingY;
01075
01076 if ( !(flags & wxCONTROL_ISSUBMENU) )
01077 {
01078
01079 isEnabled = IsEnabled();
01080 isFocused = ShouldDrawFocus();
01081
01082
01083 focusSpacingX = isEnabled ? 2 : 1;
01084 focusSpacingY = sz.y > (GetCharHeight()+2) && isEnabled ? 2 : 1;
01085 }
01086 else
01087 {
01088
01089 isEnabled = true;
01090 isFocused = flags & wxCONTROL_SELECTED ? true : false;
01091
01092 focusSpacingX = 0;
01093 focusSpacingY = 0;
01094 }
01095
01096
01097 wxRect selRect(rect);
01098 selRect.y += focusSpacingY;
01099 selRect.height -= (focusSpacingY*2);
01100
01101 int wcp = 0;
01102
01103 if ( !(flags & wxCONTROL_ISSUBMENU) )
01104 wcp += m_widthCustomPaint;
01105
01106 selRect.x += wcp + focusSpacingX;
01107 selRect.width -= wcp + (focusSpacingX*2);
01108
01109 wxColour bgCol;
01110
01111 if ( isEnabled )
01112 {
01113
01114
01115 if ( isFocused )
01116 {
01117 dc.SetTextForeground( wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT) );
01118 bgCol = wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT);
01119 }
01120 else
01121 {
01122 dc.SetTextForeground( wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT) );
01123 bgCol = GetBackgroundColour();
01124 }
01125 }
01126 else
01127 {
01128 dc.SetTextForeground( wxSystemSettings::GetColour(wxSYS_COLOUR_GRAYTEXT) );
01129 bgCol = GetBackgroundColour();
01130 }
01131
01132 dc.SetBrush( bgCol );
01133 dc.SetPen( bgCol );
01134 dc.DrawRectangle( selRect );
01135 }
01136
01137 void wxComboCtrlBase::DrawButton( wxDC& dc, const wxRect& rect, bool paintBg )
01138 {
01139 int drawState = m_btnState;
01140
01141 #ifdef __WXGTK__
01142 if ( m_isPopupShown )
01143 drawState |= wxCONTROL_PRESSED;
01144 #endif
01145
01146 wxRect drawRect(rect.x+m_btnSpacingX,
01147 rect.y+((rect.height-m_btnSize.y)/2),
01148 m_btnSize.x,
01149 m_btnSize.y);
01150
01151
01152 if ( drawRect.y < rect.y )
01153 drawRect.y = rect.y;
01154 if ( drawRect.height > rect.height )
01155 drawRect.height = rect.height;
01156
01157 bool enabled = IsEnabled();
01158
01159 if ( !enabled )
01160 drawState |= wxCONTROL_DISABLED;
01161
01162 if ( !m_bmpNormal.Ok() )
01163 {
01164
01165 if ( paintBg )
01166 {
01167 wxColour bgCol;
01168
01169 if ( m_iFlags & wxCC_IFLAG_BUTTON_OUTSIDE )
01170 bgCol = GetParent()->GetBackgroundColour();
01171 else
01172 bgCol = GetBackgroundColour();
01173
01174 dc.SetBrush(bgCol);
01175 dc.SetPen(bgCol);
01176 dc.DrawRectangle(rect);
01177 }
01178
01179
01180 wxRendererNative::Get().DrawComboBoxDropButton(this,
01181 dc,
01182 drawRect,
01183 drawState);
01184 }
01185 else
01186 {
01187
01188
01189 wxBitmap* pBmp;
01190
01191 if ( !enabled )
01192 pBmp = &m_bmpDisabled;
01193 else if ( m_btnState & wxCONTROL_PRESSED )
01194 pBmp = &m_bmpPressed;
01195 else if ( m_btnState & wxCONTROL_CURRENT )
01196 pBmp = &m_bmpHover;
01197 else
01198 pBmp = &m_bmpNormal;
01199
01200 if ( m_blankButtonBg )
01201 {
01202
01203
01204 if ( paintBg )
01205 {
01206 wxColour bgCol = GetParent()->GetBackgroundColour();
01207
01208 dc.SetPen(bgCol);
01209 dc.SetBrush(bgCol);
01210 dc.DrawRectangle(rect);
01211 }
01212 #if 0
01213 wxRendererNative::Get().DrawPushButton(this,
01214 dc,
01215 drawRect,
01216 drawState);
01217 #endif
01218 }
01219 else
01220
01221 {
01222
01223
01224 if ( paintBg )
01225 dc.DrawRectangle(rect);
01226 }
01227
01228
01229 dc.DrawBitmap(*pBmp,
01230 drawRect.x + (drawRect.width-pBmp->GetWidth())/2,
01231 drawRect.y + (drawRect.height-pBmp->GetHeight())/2,
01232 true);
01233 }
01234 }
01235
01236 void wxComboCtrlBase::RecalcAndRefresh()
01237 {
01238 if ( IsCreated() )
01239 {
01240 wxSizeEvent evt(GetSize(),GetId());
01241 GetEventHandler()->ProcessEvent(evt);
01242 Refresh();
01243 }
01244 }
01245
01246 wxBitmap& wxComboCtrlBase::GetBufferBitmap( const wxSize& sz ) const
01247 {
01248
01249 if ( !gs_doubleBuffer ||
01250 sz.x > gs_doubleBuffer->GetWidth() ||
01251 sz.y > gs_doubleBuffer->GetHeight() )
01252 {
01253 delete gs_doubleBuffer;
01254 gs_doubleBuffer = new wxBitmap(sz.x+25,sz.y);
01255 }
01256 return *gs_doubleBuffer;
01257 }
01258
01259
01260
01261
01262
01263 void wxComboCtrlBase::OnTextCtrlEvent(wxCommandEvent& event)
01264 {
01265
01266 event.SetId(GetId());
01267 wxString s = event.GetString();
01268 event.SetEventObject(this);
01269 event.SetString(s);
01270 event.Skip();
01271 }
01272
01273
01274 bool wxComboCtrlBase::HandleButtonMouseEvent( wxMouseEvent& event,
01275 int flags )
01276 {
01277 int type = event.GetEventType();
01278
01279 if ( type == wxEVT_MOTION )
01280 {
01281 if ( flags & wxCC_MF_ON_BUTTON )
01282 {
01283 if ( !(m_btnState & wxCONTROL_CURRENT) )
01284 {
01285
01286 m_btnState |= wxCONTROL_CURRENT;
01287 if ( HasCapture() )
01288 m_btnState |= wxCONTROL_PRESSED;
01289 Refresh();
01290 }
01291 }
01292 else if ( (m_btnState & wxCONTROL_CURRENT) )
01293 {
01294
01295 m_btnState &= ~(wxCONTROL_CURRENT|wxCONTROL_PRESSED);
01296 Refresh();
01297 }
01298 }
01299 else if ( type == wxEVT_LEFT_DOWN )
01300 {
01301
01302
01303 {
01304
01305 if ( flags & wxCC_MF_ON_BUTTON )
01306 {
01307 m_btnState |= wxCONTROL_PRESSED;
01308 Refresh();
01309
01310 if ( !(m_iFlags & wxCC_POPUP_ON_MOUSE_UP) )
01311 OnButtonClick();
01312 else
01313
01314 CaptureMouse();
01315 }
01316 }
01317
01318
01319
01320
01321 }
01322 else if ( type == wxEVT_LEFT_UP )
01323 {
01324
01325
01326 if ( HasCapture() )
01327 ReleaseMouse();
01328
01329 if ( m_btnState & wxCONTROL_PRESSED )
01330 {
01331
01332 if ( m_iFlags & wxCC_POPUP_ON_MOUSE_UP )
01333 {
01334 if ( flags & wxCC_MF_ON_BUTTON )
01335 OnButtonClick();
01336 }
01337
01338 m_btnState &= ~(wxCONTROL_PRESSED);
01339 Refresh();
01340 }
01341 }
01342 else if ( type == wxEVT_LEAVE_WINDOW )
01343 {
01344 if ( m_btnState & (wxCONTROL_CURRENT|wxCONTROL_PRESSED) )
01345 {
01346 m_btnState &= ~(wxCONTROL_CURRENT);
01347
01348
01349 if ( !m_isPopupShown )
01350 {
01351 m_btnState &= ~(wxCONTROL_PRESSED);
01352 Refresh();
01353 }
01354 }
01355 }
01356 else
01357 return false;
01358
01359 return true;
01360 }
01361
01362
01363
01364
01365 bool wxComboCtrlBase::PreprocessMouseEvent( wxMouseEvent& event,
01366 int flags )
01367 {
01368 wxLongLong t = ::wxGetLocalTimeMillis();
01369 int evtType = event.GetEventType();
01370
01371
01372
01373
01374 if ( (m_windowStyle & wxCC_SPECIAL_DCLICK) &&
01375 !m_isPopupShown &&
01377 !(flags & wxCC_MF_ON_BUTTON) )
01378 {
01379 if ( evtType == wxEVT_LEFT_DOWN )
01380 {
01381
01382 m_downReceived = true;
01383 }
01384 else if ( evtType == wxEVT_LEFT_DCLICK )
01385 {
01386
01387
01388 event.SetEventType(0);
01389 return true;
01390 }
01391 else if ( evtType == wxEVT_LEFT_UP )
01392 {
01393 if ( m_downReceived || m_timeLastMouseUp == 1 )
01394 {
01395 wxLongLong timeFromLastUp = (t-m_timeLastMouseUp);
01396
01397 if ( timeFromLastUp < DOUBLE_CLICK_CONVERSION_TRESHOLD )
01398 {
01399
01400 event.SetEventType(wxEVT_LEFT_DCLICK);
01401 m_timeLastMouseUp = 1;
01402 }
01403 else
01404 {
01405 m_timeLastMouseUp = t;
01406 }
01407
01408
01409 }
01410 }
01411 }
01412
01413
01414 if ( evtType == wxEVT_LEFT_DOWN && t < m_timeCanAcceptClick )
01415 {
01416 event.SetEventType(0);
01417 return true;
01418 }
01419
01420 return false;
01421 }
01422
01423 void wxComboCtrlBase::HandleNormalMouseEvent( wxMouseEvent& event )
01424 {
01425 int evtType = event.GetEventType();
01426
01427 if ( (evtType == wxEVT_LEFT_DOWN || evtType == wxEVT_LEFT_DCLICK) &&
01428 (m_windowStyle & wxCB_READONLY) )
01429 {
01430 if ( m_isPopupShown )
01431 {
01432 #if !wxUSE_POPUPWIN
01433
01434 #elif !USE_TRANSIENT_POPUP
01435
01436 HidePopup();
01437 #endif
01438 }
01439 else
01440 {
01441 if ( !(m_windowStyle & wxCC_SPECIAL_DCLICK) )
01442 {
01443
01444
01445 OnButtonClick();
01446 }
01447 else if ( evtType == wxEVT_LEFT_DCLICK )
01448 {
01449
01450
01451 if ( m_popupInterface )
01452 m_popupInterface->OnComboDoubleClick();
01453 }
01454 }
01455 }
01456 else
01457 if ( m_isPopupShown )
01458 {
01459
01460 if ( evtType == wxEVT_MOUSEWHEEL )
01461 m_popup->AddPendingEvent(event);
01462 }
01463 else if ( evtType )
01464 event.Skip();
01465 }
01466
01467 void wxComboCtrlBase::OnFocusEvent( wxFocusEvent& )
01468 {
01469
01470
01471
01472
01473 m_timeLastMouseUp = ::wxGetLocalTimeMillis();
01474
01475 if ( m_text )
01476 {
01477 m_text->SetFocus();
01478 }
01479 else
01480
01481
01482
01483 Refresh();
01484 }
01485
01486 void wxComboCtrlBase::OnSysColourChanged(wxSysColourChangedEvent& WXUNUSED(event))
01487 {
01488 OnThemeChange();
01489
01490 if ( !(m_iFlags & wxCC_IFLAG_INDENT_SET) )
01491 m_absIndent = GetNativeTextIndent();
01492 RecalcAndRefresh();
01493 }
01494
01495
01496
01497
01498
01499
01500 void wxComboCtrlBase::CreatePopup()
01501 {
01502 wxComboPopup* popupInterface = m_popupInterface;
01503 wxWindow* popup;
01504
01505 if ( !m_winPopup )
01506 m_winPopup = new wxComboPopupWindow( this, wxNO_BORDER );
01507
01508 popupInterface->Create(m_winPopup);
01509 m_popup = popup = popupInterface->GetControl();
01510
01511 m_popupExtraHandler = new wxComboPopupExtraEventHandler(this);
01512 popup->PushEventHandler( m_popupExtraHandler );
01513
01514
01515
01516
01517 m_winPopup->Hide();
01518
01519 popupInterface->m_iFlags |= wxCP_IFLAG_CREATED;
01520 }
01521
01522
01523 void wxComboCtrlBase::DestroyPopup()
01524 {
01525 if ( m_popup )
01526 m_popup->RemoveEventHandler(m_popupExtraHandler);
01527
01528 delete m_popupExtraHandler;
01529
01530 HidePopup();
01531
01532 delete m_popupInterface;
01533
01534 if ( m_winPopup )
01535 m_winPopup->Destroy();
01536
01537 m_popupExtraHandler = (wxEvtHandler*) NULL;
01538 m_popupInterface = (wxComboPopup*) NULL;
01539 m_winPopup = (wxWindow*) NULL;
01540 m_popup = (wxWindow*) NULL;
01541 }
01542
01543 void wxComboCtrlBase::DoSetPopupControl(wxComboPopup* iface)
01544 {
01545 wxCHECK_RET( iface, wxT("no popup interface set for wxComboCtrl") );
01546
01547 DestroyPopup();
01548
01549 iface->InitBase(this);
01550 iface->Init();
01551
01552 m_popupInterface = iface;
01553
01554 if ( !iface->LazyCreate() )
01555 {
01556 CreatePopup();
01557 }
01558 else
01559 {
01560 m_popup = (wxWindow*) NULL;
01561 }
01562
01563
01564 if ( m_valueString.length() )
01565 {
01566 iface->SetStringValue(m_valueString);
01567
01568 }
01569 }
01570
01571
01572 void wxComboCtrlBase::EnsurePopupControl()
01573 {
01574 if ( !m_popupInterface )
01575 SetPopupControl(NULL);
01576 }
01577
01578 void wxComboCtrlBase::OnButtonClick()
01579 {
01580
01581
01582 ShowPopup();
01583 }
01584
01585 void wxComboCtrlBase::ShowPopup()
01586 {
01587 EnsurePopupControl();
01588 wxCHECK_RET( !IsPopupShown(), wxT("popup window already shown") );
01589
01590 SetFocus();
01591
01592
01593 int screenHeight;
01594 wxPoint scrPos;
01595 int spaceAbove;
01596 int spaceBelow;
01597 int maxHeightPopup;
01598 wxSize ctrlSz = GetSize();
01599
01600 screenHeight = wxSystemSettings::GetMetric( wxSYS_SCREEN_Y );
01601 scrPos = GetParent()->ClientToScreen(GetPosition());
01602
01603 spaceAbove = scrPos.y;
01604 spaceBelow = screenHeight - spaceAbove - ctrlSz.y;
01605
01606 maxHeightPopup = spaceBelow;
01607 if ( spaceAbove > spaceBelow )
01608 maxHeightPopup = spaceAbove;
01609
01610
01611 int widthPopup = ctrlSz.x + m_extLeft + m_extRight;
01612
01613 if ( widthPopup < m_widthMinPopup )
01614 widthPopup = m_widthMinPopup;
01615
01616 wxWindow* winPopup = m_winPopup;
01617 wxWindow* popup;
01618
01619
01620
01621
01622
01623
01624
01625
01626 wxWindow* parent = GetParent();
01627 int parentFlags = parent->GetWindowStyle();
01628 if ( parentFlags & wxTAB_TRAVERSAL )
01629 {
01630 parent->SetWindowStyle( parentFlags & ~(wxTAB_TRAVERSAL) );
01631 m_iFlags |= wxCC_IFLAG_PARENT_TAB_TRAVERSAL;
01632 }
01633
01634 if ( !winPopup )
01635 {
01636 CreatePopup();
01637 winPopup = m_winPopup;
01638 popup = m_popup;
01639 }
01640 else
01641 {
01642 popup = m_popup;
01643 }
01644
01645 wxASSERT( !m_popup || m_popup == popup );
01646
01647 wxSize adjustedSize = m_popupInterface->GetAdjustedSize(widthPopup,
01648 m_heightPopup<=0?DEFAULT_POPUP_HEIGHT:m_heightPopup,
01649 maxHeightPopup);
01650
01651 popup->SetSize(adjustedSize);
01652 popup->Move(0,0);
01653 m_popupInterface->OnPopup();
01654
01655
01656
01657
01658
01659 wxSize szp = popup->GetSize();
01660
01661 int popupX;
01662 int popupY = scrPos.y + ctrlSz.y;
01663
01664
01665 int anchorSide = m_anchorSide;
01666 if ( !anchorSide )
01667 anchorSide = wxLEFT;
01668
01669 int rightX = scrPos.x + ctrlSz.x + m_extRight - szp.x;
01670 int leftX = scrPos.x - m_extLeft;
01671 int screenWidth = wxSystemSettings::GetMetric( wxSYS_SCREEN_X );
01672
01673
01674
01675 if ( anchorSide == wxRIGHT )
01676 {
01677 if ( rightX < 0 )
01678 {
01679 if ( (leftX+szp.x) < screenWidth )
01680 anchorSide = wxLEFT;
01681 else
01682 anchorSide = 0;
01683 }
01684 }
01685 else
01686 {
01687 if ( (leftX+szp.x) >= screenWidth )
01688 {
01689 if ( rightX >= 0 )
01690 anchorSide = wxRIGHT;
01691 else
01692 anchorSide = 0;
01693 }
01694 }
01695
01696
01697 if ( anchorSide == wxRIGHT )
01698 popupX = rightX;
01699 else if ( anchorSide == wxLEFT )
01700 popupX = leftX;
01701 else
01702 popupX = 0;
01703
01704 if ( spaceBelow < szp.y )
01705 {
01706 popupY = scrPos.y - szp.y;
01707 }
01708
01709
01710
01711
01712
01713
01714 winPopup->SetSize( szp.x, szp.y );
01715 winPopup->Move( popupX, popupY );
01716
01717
01718
01719 m_popup = popup;
01720
01721
01722 if ( m_text )
01723 {
01724 if ( !(m_iFlags & wxCC_NO_TEXT_AUTO_SELECT) )
01725 m_text->SelectAll();
01726
01727 m_popupInterface->SetStringValue( m_text->GetValue() );
01728 }
01729 else
01730 {
01731
01732 Refresh();
01733 }
01734
01735
01736 m_isPopupShown = true;
01737
01738
01739 #if USE_TRANSIENT_POPUP
01740 ((wxPopupTransientWindow*)winPopup)->Popup(popup);
01741 #else
01742 winPopup->Show();
01743 #endif
01744
01745 #if INSTALL_TOPLEV_HANDLER
01746
01747 if ( !m_toplevEvtHandler )
01748 m_toplevEvtHandler = new wxComboFrameEventHandler(this);
01749
01750 wxWindow* toplev = ::wxGetTopLevelParent( this );
01751 wxASSERT( toplev );
01752 ((wxComboFrameEventHandler*)m_toplevEvtHandler)->OnPopup();
01753 toplev->PushEventHandler( m_toplevEvtHandler );
01754 #endif
01755
01756 }
01757
01758 void wxComboCtrlBase::OnPopupDismiss()
01759 {
01760
01761 if ( !m_isPopupShown )
01762 return;
01763
01764
01765 m_isPopupShown = false;
01766
01767
01768 m_popupInterface->OnDismiss();
01769
01770 if ( m_popupExtraHandler )
01771 ((wxComboPopupExtraEventHandler*)m_popupExtraHandler)->OnPopupDismiss();
01772
01773 #if INSTALL_TOPLEV_HANDLER
01774
01775 if ( m_toplevEvtHandler )
01776 {
01777 wxWindow* toplev = ::wxGetTopLevelParent( this );
01778 if ( toplev )
01779 toplev->RemoveEventHandler( m_toplevEvtHandler );
01780 }
01781 #endif
01782
01783 m_timeCanAcceptClick = ::wxGetLocalTimeMillis() + 150;
01784
01785
01786
01787 if ( !m_btnArea.Inside(ScreenToClient(::wxGetMousePosition())) )
01788 m_btnState = 0;
01789
01790
01791
01792 if ( m_iFlags & wxCC_IFLAG_PARENT_TAB_TRAVERSAL )
01793 {
01794 wxWindow* parent = GetParent();
01795 parent->SetWindowStyle( parent->GetWindowStyle() | wxTAB_TRAVERSAL );
01796 m_iFlags &= ~(wxCC_IFLAG_PARENT_TAB_TRAVERSAL);
01797 }
01798
01799
01800 Refresh();
01801
01802 #if !wxUSE_POPUPWIN
01803 SetFocus();
01804 #endif
01805
01806 }
01807
01808 void wxComboCtrlBase::HidePopup()
01809 {
01810
01811
01812 if ( !m_isPopupShown )
01813 return;
01814
01815
01816 SetValue( m_popupInterface->GetStringValue() );
01817
01818 #if USE_TRANSIENT_POPUP
01819 ((wxPopupTransientWindow*)m_winPopup)->Dismiss();
01820 #else
01821 m_winPopup->Hide();
01822 #endif
01823
01824 OnPopupDismiss();
01825 }
01826
01827
01828
01829
01830
01831 void wxComboCtrlBase::SetButtonPosition( int width, int height,
01832 int side, int spacingX )
01833 {
01834 m_btnWid = width;
01835 m_btnHei = height;
01836 m_btnSide = side;
01837 m_btnSpacingX = spacingX;
01838
01839 RecalcAndRefresh();
01840 }
01841
01842 wxSize wxComboCtrlBase::GetButtonSize()
01843 {
01844 if ( m_btnSize.x > 0 )
01845 return m_btnSize;
01846
01847 wxSize retSize(m_btnWid,m_btnHei);
01848
01849
01850
01851 if ( retSize.x <= 0 || retSize.y <= 0)
01852 {
01853 OnResize();
01854
01855 retSize = m_btnSize;
01856 }
01857
01858 return retSize;
01859 }
01860
01861 void wxComboCtrlBase::SetButtonBitmaps( const wxBitmap& bmpNormal,
01862 bool blankButtonBg,
01863 const wxBitmap& bmpPressed,
01864 const wxBitmap& bmpHover,
01865 const wxBitmap& bmpDisabled )
01866 {
01867 m_bmpNormal = bmpNormal;
01868 m_blankButtonBg = blankButtonBg;
01869
01870 if ( bmpPressed.Ok() )
01871 m_bmpPressed = bmpPressed;
01872 else
01873 m_bmpPressed = bmpNormal;
01874
01875 if ( bmpHover.Ok() )
01876 m_bmpHover = bmpHover;
01877 else
01878 m_bmpHover = bmpNormal;
01879
01880 if ( bmpDisabled.Ok() )
01881 m_bmpDisabled = bmpDisabled;
01882 else
01883 m_bmpDisabled = bmpNormal;
01884
01885 RecalcAndRefresh();
01886 }
01887
01888 void wxComboCtrlBase::SetCustomPaintWidth( int width )
01889 {
01890 if ( m_text )
01891 {
01892
01893 wxRect r = m_text->GetRect();
01894 int inc = width - m_widthCustomPaint;
01895 r.x += inc;
01896 r.width -= inc;
01897 m_text->SetSize( r );
01898 }
01899
01900 m_widthCustomPaint = width;
01901
01902 RecalcAndRefresh();
01903 }
01904
01905 void wxComboCtrlBase::SetTextIndent( int indent )
01906 {
01907 if ( indent < 0 )
01908 {
01909 m_absIndent = GetNativeTextIndent();
01910 m_iFlags &= ~(wxCC_IFLAG_INDENT_SET);
01911 }
01912 else
01913 {
01914 m_absIndent = indent;
01915 m_iFlags |= wxCC_IFLAG_INDENT_SET;
01916 }
01917
01918 RecalcAndRefresh();
01919 }
01920
01921 wxCoord wxComboCtrlBase::GetNativeTextIndent() const
01922 {
01923 return DEFAULT_TEXT_INDENT;
01924 }
01925
01926
01927
01928
01929
01930 wxString wxComboCtrlBase::GetValue() const
01931 {
01932 if ( m_text )
01933 return m_text->GetValue();
01934 return m_valueString;
01935 }
01936
01937 void wxComboCtrlBase::SetValue(const wxString& value)
01938 {
01939 if ( m_text )
01940 {
01941 m_text->SetValue(value);
01942 if ( !(m_iFlags & wxCC_NO_TEXT_AUTO_SELECT) )
01943 m_text->SelectAll();
01944 }
01945
01946 m_valueString = value;
01947
01948 Refresh();
01949
01950
01951
01952 if ( m_valueString != value && m_popupInterface )
01953 {
01954 m_popupInterface->SetStringValue(value);
01955 }
01956 }
01957
01958
01959 void wxComboCtrlBase::SetText(const wxString& value)
01960 {
01961
01962
01963 EnsurePopupControl();
01964
01965 m_valueString = value;
01966
01967 Refresh();
01968 }
01969
01970 void wxComboCtrlBase::Copy()
01971 {
01972 if ( m_text )
01973 m_text->Copy();
01974 }
01975
01976 void wxComboCtrlBase::Cut()
01977 {
01978 if ( m_text )
01979 m_text->Cut();
01980 }
01981
01982 void wxComboCtrlBase::Paste()
01983 {
01984 if ( m_text )
01985 m_text->Paste();
01986 }
01987
01988 void wxComboCtrlBase::SetInsertionPoint(long pos)
01989 {
01990 if ( m_text )
01991 m_text->SetInsertionPoint(pos);
01992 }
01993
01994 void wxComboCtrlBase::SetInsertionPointEnd()
01995 {
01996 if ( m_text )
01997 m_text->SetInsertionPointEnd();
01998 }
01999
02000 long wxComboCtrlBase::GetInsertionPoint() const
02001 {
02002 if ( m_text )
02003 return m_text->GetInsertionPoint();
02004
02005 return 0;
02006 }
02007
02008 long wxComboCtrlBase::GetLastPosition() const
02009 {
02010 if ( m_text )
02011 return m_text->GetLastPosition();
02012
02013 return 0;
02014 }
02015
02016 void wxComboCtrlBase::Replace(long from, long to, const wxString& value)
02017 {
02018 if ( m_text )
02019 m_text->Replace(from, to, value);
02020 }
02021
02022 void wxComboCtrlBase::Remove(long from, long to)
02023 {
02024 if ( m_text )
02025 m_text->Remove(from, to);
02026 }
02027
02028 void wxComboCtrlBase::SetSelection(long from, long to)
02029 {
02030 if ( m_text )
02031 m_text->SetSelection(from, to);
02032 }
02033
02034 void wxComboCtrlBase::Undo()
02035 {
02036 if ( m_text )
02037 m_text->Undo();
02038 }
02039
02040 #endif // wxUSE_COMBOCONTROL