Fix wxStatusBar with field controls under wxQt
Postpone the creation of the QStatusBar fields until the first call to SetStatusText(). This is to account for any field control added by the user and also to avoid having to call UpdateFields() multiple times. wxSTB_ELLIPSIZE_XXX and wxSTB_SHOW_TIPS supports are also implemented now. The statbar sample is also updated: The OnSize() handler is removed because it doesn't do much. that is: it is defined to keep the bitmap centered in the status bar field it occupies if it is resized. but this is already done by the wxStaticBitmap control, at least under wxMSW, wxGTK3 and wxQt.
This commit is contained in:
parent
02610d5d4b
commit
5c46947c57
3 changed files with 109 additions and 40 deletions
|
|
@ -10,7 +10,6 @@
|
|||
|
||||
#include "wx/statusbr.h"
|
||||
|
||||
class QLabel;
|
||||
class QStatusBar;
|
||||
|
||||
class WXDLLIMPEXP_CORE wxStatusBar : public wxStatusBarBase
|
||||
|
|
@ -25,6 +24,7 @@ public:
|
|||
long style = wxSTB_DEFAULT_STYLE,
|
||||
const wxString& name = wxASCII_STR(wxStatusBarNameStr));
|
||||
|
||||
virtual void SetStatusWidths(int n, const int widths_field[]) override;
|
||||
virtual bool GetFieldRect(int i, wxRect& rect) const override;
|
||||
virtual void SetMinHeight(int height) override;
|
||||
virtual int GetBorderX() const override;
|
||||
|
|
@ -40,7 +40,7 @@ private:
|
|||
void UpdateFields();
|
||||
|
||||
QStatusBar *m_qtStatusBar = nullptr;
|
||||
wxVector<QLabel*> m_qtPanes;
|
||||
std::vector<QWidget*> m_qtPanes;
|
||||
|
||||
wxDECLARE_DYNAMIC_CLASS(wxStatusBar);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -94,7 +94,6 @@ public:
|
|||
#if wxUSE_TIMER
|
||||
void OnTimer(wxTimerEvent& WXUNUSED(event)) { UpdateClock(); }
|
||||
#endif
|
||||
void OnSize(wxSizeEvent& event);
|
||||
void OnToggleClock(wxCommandEvent& event);
|
||||
void OnIdle(wxIdleEvent& event);
|
||||
|
||||
|
|
@ -270,7 +269,6 @@ wxBEGIN_EVENT_TABLE(MyFrame, wxFrame)
|
|||
wxEND_EVENT_TABLE()
|
||||
|
||||
wxBEGIN_EVENT_TABLE(MyStatusBar, wxStatusBar)
|
||||
EVT_SIZE(MyStatusBar::OnSize)
|
||||
#if wxUSE_CHECKBOX
|
||||
EVT_CHECKBOX(StatusBar_Checkbox, MyStatusBar::OnToggleClock)
|
||||
#endif
|
||||
|
|
@ -939,6 +937,7 @@ MyStatusBar::MyStatusBar(wxWindow *parent, long style)
|
|||
#endif
|
||||
|
||||
m_statbmp = new wxStaticBitmap(this, wxID_ANY, wxIcon(green_xpm));
|
||||
AddFieldControl(Field_Bitmap, m_statbmp);
|
||||
|
||||
#if wxUSE_TIMER
|
||||
m_timer.Start(1000);
|
||||
|
|
@ -964,18 +963,6 @@ MyStatusBar::~MyStatusBar()
|
|||
#endif
|
||||
}
|
||||
|
||||
void MyStatusBar::OnSize(wxSizeEvent& event)
|
||||
{
|
||||
wxRect rect;
|
||||
GetFieldRect(Field_Bitmap, rect);
|
||||
wxSize size = m_statbmp->GetSize();
|
||||
|
||||
m_statbmp->Move(rect.x + (rect.width - size.x) / 2,
|
||||
rect.y + (rect.height - size.y) / 2);
|
||||
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
void MyStatusBar::OnToggleClock(wxCommandEvent& WXUNUSED(event))
|
||||
{
|
||||
DoToggle();
|
||||
|
|
|
|||
|
|
@ -50,17 +50,56 @@ bool wxStatusBar::Create(wxWindow *parent, wxWindowID WXUNUSED(winid),
|
|||
|
||||
SetFieldsCount(1);
|
||||
|
||||
// Notice that child controls, if any, will be added using addWidget() in
|
||||
// UpdateFields() function. So Unbind the base class handler which is not
|
||||
// needed here. And more importantely, it won't work properly either.
|
||||
Unbind(wxEVT_SIZE, &wxStatusBar::OnSize, static_cast<wxStatusBarBase*>(this));
|
||||
|
||||
Bind(wxEVT_SIZE, [this](wxSizeEvent& event)
|
||||
{
|
||||
const int n = this->GetFieldsCount();
|
||||
for ( int i = 0; i < n; ++i )
|
||||
{
|
||||
// Update ellipsized status texts.
|
||||
this->DoUpdateStatusText(i);
|
||||
}
|
||||
|
||||
event.Skip();
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void wxStatusBar::SetStatusWidths(int number, const int widths[])
|
||||
{
|
||||
if ( number != (int)m_panes.GetCount() )
|
||||
return;
|
||||
|
||||
if ( !m_qtPanes.empty() )
|
||||
{
|
||||
int i = 0;
|
||||
for ( auto pane : m_qtPanes )
|
||||
{
|
||||
m_qtStatusBar->removeWidget(pane);
|
||||
|
||||
// Do not delete user-added controls.
|
||||
if ( !m_panes[i++].GetFieldControl() )
|
||||
{
|
||||
delete pane;
|
||||
}
|
||||
}
|
||||
|
||||
m_qtPanes.clear();
|
||||
}
|
||||
|
||||
wxStatusBarBase::SetStatusWidths(number, widths);
|
||||
}
|
||||
|
||||
bool wxStatusBar::GetFieldRect(int i, wxRect& rect) const
|
||||
{
|
||||
wxCHECK_MSG( (i >= 0) && ((size_t)i < m_panes.GetCount()), false,
|
||||
"invalid statusbar field index" );
|
||||
|
||||
if ( m_qtPanes.size() != m_panes.GetCount() )
|
||||
const_cast<wxStatusBar*>(this)->UpdateFields();
|
||||
|
||||
rect = wxQtConvertRect(m_qtPanes[i]->geometry());
|
||||
return true;
|
||||
}
|
||||
|
|
@ -82,42 +121,85 @@ int wxStatusBar::GetBorderY() const
|
|||
|
||||
void wxStatusBar::DoUpdateStatusText(int number)
|
||||
{
|
||||
if ( m_qtPanes.size() != m_panes.GetCount() )
|
||||
UpdateFields();
|
||||
UpdateFields();
|
||||
|
||||
m_qtPanes[number]->setText( wxQtConvertString( m_panes[number].GetText() ) );
|
||||
const auto pane = dynamic_cast<QLabel*>(m_qtPanes[number]);
|
||||
|
||||
if ( !pane )
|
||||
{
|
||||
// do nothing if this pane is a field control.
|
||||
return;
|
||||
}
|
||||
|
||||
QString text = wxQtConvertString( m_panes[number].GetText() );
|
||||
|
||||
// do we need to ellipsize this string?
|
||||
Qt::TextElideMode ellmode = Qt::ElideNone;
|
||||
if ( HasFlag(wxSTB_ELLIPSIZE_START) ) ellmode = Qt::ElideLeft;
|
||||
else if ( HasFlag(wxSTB_ELLIPSIZE_MIDDLE) ) ellmode = Qt::ElideMiddle;
|
||||
else if ( HasFlag(wxSTB_ELLIPSIZE_END) ) ellmode = Qt::ElideRight;
|
||||
|
||||
if ( ellmode != Qt::ElideNone )
|
||||
{
|
||||
QFontMetrics metrics(pane->font());
|
||||
QString elidedText = metrics.elidedText(text, ellmode, pane->width());
|
||||
|
||||
if ( HasFlag(wxSTB_SHOW_TIPS) )
|
||||
{
|
||||
elidedText != text ? pane->setToolTip(text) : pane->setToolTip(QString());
|
||||
}
|
||||
|
||||
text = elidedText;
|
||||
}
|
||||
|
||||
pane->setText(text);
|
||||
}
|
||||
|
||||
void wxStatusBar::UpdateFields()
|
||||
{
|
||||
// is it a good idea to recreate all the panes every update?
|
||||
if ( !m_qtPanes.empty() )
|
||||
return;
|
||||
|
||||
for ( wxVector<QLabel*>::const_iterator it = m_qtPanes.begin();
|
||||
it != m_qtPanes.end(); ++it )
|
||||
{
|
||||
//Remove all panes
|
||||
delete *it;
|
||||
}
|
||||
m_qtPanes.clear();
|
||||
|
||||
for (size_t i = 0; i < m_panes.GetCount(); i++)
|
||||
for ( size_t i = 0; i < m_panes.GetCount(); ++i )
|
||||
{
|
||||
//Set sizes
|
||||
int width = m_panes[i].GetWidth();
|
||||
const int width = m_bSameWidthForAllPanes ? -1 : m_panes[i].GetWidth();
|
||||
|
||||
QLabel *pane = new QLabel( m_qtStatusBar );
|
||||
m_qtPanes.push_back(pane);
|
||||
QWidget* pane;
|
||||
wxWindow* win = m_panes[i].GetFieldControl();
|
||||
|
||||
if ( width >= 0 )
|
||||
if ( win )
|
||||
{
|
||||
//Fixed width field
|
||||
pane->setMinimumSize( QSize(width, 0) );
|
||||
m_qtStatusBar->addWidget( pane );
|
||||
pane = win->GetHandle();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_qtStatusBar->addWidget( pane, -width );
|
||||
pane = new QLabel;
|
||||
if ( width >= 0 )
|
||||
pane->setMinimumWidth(width);
|
||||
|
||||
int style;
|
||||
switch( m_panes[i].GetStyle() )
|
||||
{
|
||||
case wxSB_RAISED:
|
||||
style = QFrame::Panel | QFrame::Raised;
|
||||
break;
|
||||
case wxSB_SUNKEN:
|
||||
style = QFrame::Panel | QFrame::Sunken;
|
||||
break;
|
||||
case wxSB_NORMAL:
|
||||
case wxSB_FLAT:
|
||||
default:
|
||||
style = QFrame::Plain | QFrame::NoFrame;
|
||||
break;
|
||||
}
|
||||
|
||||
static_cast<QLabel*>(pane)->setFrameStyle(style);
|
||||
}
|
||||
|
||||
m_qtPanes.push_back(pane);
|
||||
|
||||
m_qtStatusBar->addWidget(pane, width < 0 ? -width : 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue