📄 odcombo.cpp
字号:
wxSize ctrl_sz = GetSize();
#if wxODC_ALLOW_FAKE_POPUP
int existing_height = 200;
if ( m_popup )
existing_height = m_popup->GetSize().y;
//wxLogDebug(wxT("Existing height: %i"),existing_height);
int screen_width;
GetParent()->GetClientSize(&screen_width,&screen_height);
screen_width -= 2;
scr_pos = GetPosition();
space_above = scr_pos.y - 2;
space_below = screen_height - space_above - ctrl_sz.y - 4;
maxHeightPopup = space_below;
if ( space_above > space_below )
maxHeightPopup = space_above;
//wxLogDebug(wxT("FakeMaxHei: %i"),maxHeightPopup);
if ( maxHeightPopup >= existing_height )
{
if ( m_winPopup && m_fakePopupUsage!=2 )
{
delete m_winPopup;
m_winPopup = (wxWindow*) NULL;
m_popup = (wxWindow*) NULL;
}
m_fakePopupUsage = 2;
}
else
{
if ( m_winPopup && m_fakePopupUsage!=1 )
{
delete m_winPopup;
m_winPopup = (wxWindow*) NULL;
m_popup = (wxWindow*) NULL;
}
m_fakePopupUsage = 1;
#else
{
#endif
screen_height = wxSystemSettings::GetMetric( wxSYS_SCREEN_Y );
scr_pos = GetParent()->ClientToScreen(GetPosition());
space_above = scr_pos.y;
space_below = screen_height - space_above - ctrl_sz.y;
maxHeightPopup = space_below;
if ( space_above > space_below )
maxHeightPopup = space_above;
//wxLogDebug(wxT("RealMaxHei: %i"),maxHeightPopup);
}
// Width
int widthPopup = ctrl_sz.x + m_extLeft + m_extRight;
wxWindow* winPopup = m_winPopup;
wxWindow* give_parent = (wxWindow*) NULL;
if ( !winPopup )
{
#if wxODC_ALLOW_FAKE_POPUP
if ( m_fakePopupUsage == 2 )
{
//wxLogDebug(wxT("Faking popup!"));
winPopup = new wxWindow();
#ifdef __WXMSW__
// Only wxMSW supports this
winPopup->Hide();
#endif
winPopup->Create( GetParent(), -1 );
}
else
#endif
{
winPopup =
new wxComboPopupWindow( this, wxNO_BORDER );
}
m_winPopup = give_parent = winPopup;
}
// Generate/resize window
wxWindow* popup = m_popupInterface->GeneratePopup( give_parent,
widthPopup, maxHeightPopup, m_heightPopup );
wxASSERT ( !m_popup || m_popup == popup ); // Consistency check.
#if wxODC_ALLOW_FAKE_POPUP
// Make sure fake popup didn't get too big
if ( m_fakePopupUsage == 2 && popup->GetSize().x > screen_width )
{
popup->SetSize(screen_width-2,popup->GetSize().y);
}
#endif
// Add interface as event handler
if ( !m_popup )
popup->PushEventHandler( m_popupInterface );
//
// Reposition and resize popup window
//
wxSize szp = popup->GetSize();
wxPoint ptp(scr_pos.x+ctrl_sz.x+m_extRight-szp.x,
scr_pos.y + ctrl_sz.y);
#if wxODC_ALLOW_FAKE_POPUP
if ( m_fakePopupUsage == 2 )
{
if ( space_below < szp.y )
{
//wxLogDebug(wxT("%i,%i"),space_below,space_above);
if ( space_above > space_below )
{
if ( szp.y > space_above )
{
popup->SetSize(szp.x,space_above);
szp.y = space_above;
}
ptp.y = scr_pos.y - szp.y;
}
else
{
if ( szp.y > space_below )
{
popup->SetSize(szp.x,space_below);
szp.y = space_below;
}
}
}
}
else
#endif
if ( space_below < szp.y )
{
ptp.y = scr_pos.y - szp.y;
}
// Move to position
//wxLogDebug(wxT("popup scheduled position1: %i,%i"),ptp.x,ptp.y);
//wxLogDebug(wxT("popup position1: %i,%i"),winPopup->GetPosition().x,winPopup->GetPosition().y);
#if defined(__WXGTK__) && (wxMINOR_VERSION < 5 || ( wxMINOR_VERSION == 5 && wxRELEASE_NUMBER < 5 ))
// Remedy for wxGTK popup resize issue
winPopup->SetSizeHints(szp.x, szp.y, szp.x, szp.y);
#endif
//winPopup->SetSize( ptp.x, ptp.y, szp.x, szp.y );
// Some platforms (GTK) may need these two to be separate
winPopup->SetSize( szp.x, szp.y );
winPopup->Move( ptp.x, ptp.y );
//wxLogDebug(wxT("popup position2: %i,%i"),winPopup->GetPosition().x,winPopup->GetPosition().y);
//wxLogDebug(wxT("popup position3: %i,%i"),winPopup->GetPosition().x,winPopup->GetPosition().y);
m_popup = popup;
((wxComboDropButton*)m_btn)->SetPopup( popup );
if ( m_text )
{
m_text->SelectAll();
// Set string selection (must be this way instead of SetStringSelection)
m_popupInterface->SetValueFromString( m_text->GetValue() );
#ifdef __WXDEBUG__
// Id confirmation
wxASSERT_MSG ( GetId() == m_text->GetId(),
wxT("You must use wxPGComboBox::SetId to set its id - calling parent class's won't do"));
#endif
}
else
{
Refresh();
}
// this must be after SetValueFromString
m_isPopupShown = 1;
// Show it
{
#if wxODC_USE_TRANSIENT_POPUP
((wxPopupTransientWindow*)winPopup)->Popup(popup);
#else
winPopup->Show();
//popup->SetFocus();
#endif
}
#if wxODC_INSTALL_TOPLEV_HANDLER
// If our real popup is wxDialog, then only install handler
// incase of fake popup.
#if !wxUSE_POPUPWIN
if ( m_fakePopupUsage == 2 )
#endif
{
// Put top level window event handler into place
if ( !m_toplevEvtHandler )
m_toplevEvtHandler = new wxComboFrameEventHandler(this);
wxWindow* toplev = ::wxGetTopLevelParent( this );
wxASSERT( toplev );
((wxComboFrameEventHandler*)m_toplevEvtHandler)->OnPopup();
toplev->PushEventHandler( m_toplevEvtHandler );
}
#endif
}
void wxPGComboBox::OnPopupDismiss()
{
//wxLogDebug(wxT("wxPGComboBox::OnPopupDismiss"));
((wxComboDropButton*)m_btn)->SetPopup( (wxWindow*) NULL );
#if wxODC_INSTALL_TOPLEV_HANDLER
// Remove top level window event handler
if ( m_toplevEvtHandler )
{
wxWindow* toplev = ::wxGetTopLevelParent( this );
if ( toplev )
toplev->RemoveEventHandler( m_toplevEvtHandler );
}
// TODO: This may be needed for transient window as well
// FIXME: This is a hack to resolve a bug wxPopupWindow+wxScrolledWindow
/*
wxSize orig_size = toplev->GetSize();
wxSize new_size = orig_size;
new_size.x += 1;
toplev->SetSize(new_size);
toplev->SetSize(orig_size);
*/
#endif
wxWindow* focus_target = this;
if ( m_text )
focus_target = m_text;
focus_target->SetFocus();
m_isPopupShown = 0;
// refresh control (necessary even if m_text)
Refresh();
}
void wxPGComboBox::HidePopup( bool sendEvent )
{
wxCHECK_RET( m_popupInterface, _T("no popup interface specified in wxPGComboBox") );
if ( m_isPopupShown < 1 )
{
//wxLogDebug(wxT("wxPGComboBox::HidePopup: Warning: trying to hide hidden popup."));
return;
}
//wxLogDebug( wxT("wxPGComboBox::HidePopup") );
// transfer value and refresh control
m_valueString = m_popupInterface->GetValueAsString();
if ( m_text )
m_text->SetValue (m_valueString);
#if wxODC_USE_TRANSIENT_POPUP
((wxPopupTransientWindow*)m_winPopup)->Dismiss();
#else
m_winPopup->Hide();
#endif
OnPopupDismiss();
if ( sendEvent )
{
// fire the event
wxCommandEvent event(wxEVT_COMMAND_COMBOBOX_SELECTED, GetId());
event.SetEventObject(this);
event.SetInt(GetSelection());
GetEventHandler()->AddPendingEvent(event);
}
}
// ----------------------------------------------------------------------------
// event handlers
// ----------------------------------------------------------------------------
void wxPGComboBox::OnButtonClick(wxCommandEvent& /*event*/ )
{
SetFocus();
//wxLogDebug(wxT("wxPGComboBox::OnButtonClick"));
// Must check exactly against 0 to allow -1 value to take effect below
if ( m_isPopupShown == 0 )
{
ShowPopup();
}
else
{
#if !wxUSE_POPUPWIN
if ( m_isPopupShown > 0 )
HidePopup( false );
m_isPopupShown++;
// Normally do nothing - evt handler should close it for us
//#if wxODC_ALLOW_FAKE_POPUP
//if ( m_fakePopupUsage == 2 )
//
//#endif
#elif !wxODC_USE_TRANSIENT_POPUP
HidePopup( false );
//m_winPopup->OnDismiss();
#else
// Why this? See wxComboPopupWindow::OnDismiss
OnPopupDismiss();
#endif
}
}
void wxPGComboBox::OnPaint( wxPaintEvent& )
{
wxPaintDC dc(this);
// paint, whatever is required, on the control
if ( m_btn && ( !m_text || m_widthCustomPaint ) )
{
wxASSERT ( m_popupInterface );
wxASSERT ( m_widthCustomPaint >= 0 );
//wxASSERT ( m_widthCustomPaint < m_btn->GetPosition().x );
wxSize sz = GetClientSize();
wxRect rect(0,0, sz.x - m_btn->GetSize().x, sz.y );
#if wxODC_BORDER_STYLE == 1
// artifical simple border around custom-drawn value
if ( m_widthCustomBorder )
{
dc.SetPen( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNSHADOW ) );
dc.SetBrush( *wxTRANSPARENT_BRUSH );
dc.DrawRectangle( rect );
rect.Deflate(m_widthCustomBorder);
}
#endif
// this is intentionally here to allow drawed rectangle's
// right edge to be hidden
if ( m_text )
rect.width = m_widthCustomPaint;
wxColour win_col = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW);
dc.SetFont( GetFont() );
dc.SetBrush ( win_col );
dc.SetPen ( win_col );
dc.DrawRectangle ( rect );
#if wxODC_SELECTION_STYLE == 0
// If popup is hidden and this control is focused,
// then draw the focus-indicator (blue background etc.).
wxWindow* cur_focus = FindFocus();
if ( m_isPopupShown < 1 && (cur_focus == this || cur_focus == m_btn) &&
!m_text
)
{
wxRect sel_rect(rect);
sel_rect.y += 1;
sel_rect.height -= 2;
sel_rect.x += m_widthCustomPaint + 1;
sel_rect.width -= m_widthCustomPaint + 2;
dc.SetTextForeground( wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT) );
DrawComboSelectionBackground( dc, sel_rect );
}
else
dc.SetTextForeground( wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT) );
#else
wxColour tx_col(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT));
// If popup is hidden and this control is focused,
// then draw the focus-indicator (blue background etc.).
wxWindow* cur_focus = FindFocus();
if ( m_isPopupShown < 1 && (cur_focus == this || cur_focus == m_btn) &&
!m_text
)
{
wxRect sel_rect(rect);
sel_rect.y += 1;
sel_rect.height -= 2;
sel_rect.x += m_widthCustomPaint + 1;
sel_rect.width -= m_widthCustomPaint + 2;
// Draw dotted edge (use sys_hilight_text colour)
wxPen pen(tx_col,1,wxDOT);
// TODO: Remove this line after CreatePen/ExtCreatePen issue fixed in main lib
pen.SetCap( wxCAP_BUTT );
dc.SetPen( pen );
dc.SetBrush( *wxTRANSPARENT_BRUSH );
dc.DrawRectangle( sel_rect );
}
dc.SetTextForeground( tx_col );
#endif
wxComboPaintCallback callback = m_popupInterface->GetCallback();
if ( !(m_windowStyle & wxODCB_STD_CONTROL_PAINT) && callback )
{
int sel = GetSelection();
((GetParent())->*m_popupInterface->GetCallback())(this,
sel,dc,rect,wxODCB_CB_PAINTING_CONTROL);
}
else if ( !m_text )
{
dc.DrawText(m_valueString,
3+wxODC_TEXTXADJUST,
(rect.height-dc.GetCharHeight())/2 );
}
}
}
void wxPGComboBox::OnMouseEvent( wxMouseEvent& event )
{
int type = event.GetEventType();
//if ( type != wxEVT_MOTION ) wxLogDebug(wxT("wxPGComboBox::OnMouseEvent"));
if ( type == wxEVT_LEFT_DOWN || type == wxEVT_LEFT_DCLICK )
{
//wxLogDebug(wxT("wxPGComboBox::OnMouseEvent"));
#if !wxODC_USE_TRANSIENT_POPUP
// Check if event occurs on the button (technically not necessary on MSW,
// but important in GTK).
// TODO: Remove this
if ( event.GetPosit
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -