wxWidgets/samples/statbar/statbar.cpp
Vadim Zeitlin bced985eb0 Add a test of precisely sized status bar fields.
Modify the status bar sample to use two fields of just the right size for
their contents to confirm that this doesn't work correctly under at least MSW
currently (see #10696).

Notice that we need two fields because the behaviour/problem is different for
the last field and all the other ones.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@61991 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
2009-09-21 13:00:23 +00:00

1022 lines
30 KiB
C++

/////////////////////////////////////////////////////////////////////////////
// Name: statbar.cpp
// Purpose: wxStatusBar sample
// Author: Vadim Zeitlin
// Created: 04.02.00
// RCS-ID: $Id$
// Copyright: (c) Vadim Zeitlin
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
// ============================================================================
// declarations
// ============================================================================
// ----------------------------------------------------------------------------
// headers
// ----------------------------------------------------------------------------
// For compilers that support precompilation, includes "wx/wx.h".
#include "wx/wxprec.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#if !wxUSE_STATUSBAR
#error "You need to set wxUSE_STATUSBAR to 1 to compile this sample"
#endif // wxUSE_STATUSBAR
// for all others, include the necessary headers
#ifndef WX_PRECOMP
#include "wx/app.h"
#include "wx/dcclient.h"
#include "wx/log.h"
#include "wx/frame.h"
#include "wx/statusbr.h"
#include "wx/timer.h"
#include "wx/checkbox.h"
#include "wx/statbmp.h"
#include "wx/menu.h"
#include "wx/msgdlg.h"
#include "wx/textdlg.h"
#include "wx/sizer.h"
#include "wx/stattext.h"
#include "wx/bmpbuttn.h"
#include "wx/dcmemory.h"
#endif
#include "wx/datetime.h"
#include "wx/numdlg.h"
#include "wx/fontdlg.h"
#ifndef __WXMSW__
#include "../sample.xpm"
#endif
//#define USE_MDI_PARENT_FRAME 1
#ifdef USE_MDI_PARENT_FRAME
#include "wx/mdi.h"
#endif // USE_MDI_PARENT_FRAME
static const char *SAMPLE_DIALOGS_TITLE = "wxWidgets statbar sample";
// ----------------------------------------------------------------------------
// resources
// ----------------------------------------------------------------------------
#include "green.xpm"
#include "red.xpm"
// ----------------------------------------------------------------------------
// private classes
// ----------------------------------------------------------------------------
// Define a new application type, each program should derive a class from wxApp
class MyApp : public wxApp
{
public:
// override base class virtuals
// ----------------------------
// this one is called on application startup and is a good place for the app
// initialization (doing it here and not in the ctor allows to have an error
// return: if OnInit() returns false, the application terminates)
virtual bool OnInit();
};
// A custom status bar which contains controls, icons &c
class MyStatusBar : public wxStatusBar
{
public:
MyStatusBar(wxWindow *parent, long style = wxSTB_DEFAULT_STYLE);
virtual ~MyStatusBar();
void UpdateClock();
// event handlers
#if wxUSE_TIMER
void OnTimer(wxTimerEvent& WXUNUSED(event)) { UpdateClock(); }
#endif
void OnSize(wxSizeEvent& event);
void OnToggleClock(wxCommandEvent& event);
void OnIdle(wxIdleEvent& event);
private:
// toggle the state of the status bar controls
void DoToggle();
enum
{
Field_Text,
Field_Checkbox,
Field_Bitmap,
Field_NumLockIndicator,
Field_Clock,
Field_CapsLockIndicator,
Field_Max
};
#if wxUSE_TIMER
wxTimer m_timer;
#endif
#if wxUSE_CHECKBOX
wxCheckBox *m_checkbox;
#endif
wxStaticBitmap *m_statbmp;
DECLARE_EVENT_TABLE()
};
// Define a new frame type: this is going to be our main frame
#ifdef USE_MDI_PARENT_FRAME
class MyFrame : public wxMDIParentFrame
#else
class MyFrame : public wxFrame
#endif
{
public:
// ctor(s)
MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size);
// event handlers (these functions should _not_ be virtual)
void OnQuit(wxCommandEvent& event);
void OnAbout(wxCommandEvent& event);
void OnSetStatusField(wxCommandEvent& event);
void OnSetStatusText(wxCommandEvent& event);
void OnPushStatusText(wxCommandEvent& event);
void OnPopStatusText(wxCommandEvent& event);
void OnResetFieldsWidth(wxCommandEvent& event);
void OnShowFieldsRect(wxCommandEvent& event);
void OnSetStatusFields(wxCommandEvent& event);
void OnSetStatusFont(wxCommandEvent& event);
void OnRecreateStatusBar(wxCommandEvent& event);
void OnSetPaneStyle(wxCommandEvent& event);
void OnSetStyle(wxCommandEvent& event);
private:
enum StatusBarKind
{
StatBar_Default,
StatBar_Custom,
StatBar_Max
} m_statbarKind;
void OnUpdateForDefaultStatusbar(wxUpdateUIEvent& event);
void OnUpdateStatusBarToggle(wxUpdateUIEvent& event);
void OnUpdateSetPaneStyle(wxUpdateUIEvent& event);
void OnUpdateSetStyle(wxUpdateUIEvent& event);
void OnStatusBarToggle(wxCommandEvent& event);
void DoCreateStatusBar(StatusBarKind kind, long style);
void ApplyPaneStyle();
int m_statbarPaneStyle;
// the index of the field used by some commands
int m_field;
// any class wishing to process wxWidgets events must use this macro
DECLARE_EVENT_TABLE()
};
// Our about dialog ith its status bar
class MyAboutDialog : public wxDialog
{
public:
MyAboutDialog(wxWindow *parent);
};
// ----------------------------------------------------------------------------
// constants
// ----------------------------------------------------------------------------
// IDs for the controls and the menu commands
enum
{
// menu items
StatusBar_Quit = wxID_EXIT,
StatusBar_About = wxID_ABOUT,
StatusBar_SetFields = wxID_HIGHEST+1,
StatusBar_SetField,
StatusBar_SetText,
StatusBar_PushText,
StatusBar_PopText,
StatusBar_SetFont,
StatusBar_ResetFieldsWidth,
StatusBar_ShowFieldsRect,
StatusBar_Recreate,
StatusBar_Toggle,
StatusBar_Checkbox,
StatusBar_SetPaneStyle,
StatusBar_SetPaneStyleNormal,
StatusBar_SetPaneStyleFlat,
StatusBar_SetPaneStyleRaised,
StatusBar_SetStyleSizeGrip,
StatusBar_SetStyleEllipsizeStart,
StatusBar_SetStyleEllipsizeMiddle,
StatusBar_SetStyleEllipsizeEnd,
StatusBar_SetStyleShowTips
};
static const int BITMAP_SIZE_X = 32;
static const int BITMAP_SIZE_Y = 15;
// ----------------------------------------------------------------------------
// event tables and other macros for wxWidgets
// ----------------------------------------------------------------------------
// the event tables connect the wxWidgets events with the functions (event
// handlers) which process them. It can be also done at run-time, but for the
// simple menu events like this the static method is much simpler.
#ifdef USE_MDI_PARENT_FRAME
BEGIN_EVENT_TABLE(MyFrame, wxMDIParentFrame)
#else
BEGIN_EVENT_TABLE(MyFrame, wxFrame)
#endif
EVT_MENU(StatusBar_Quit, MyFrame::OnQuit)
EVT_MENU(StatusBar_SetFields, MyFrame::OnSetStatusFields)
EVT_MENU(StatusBar_SetField, MyFrame::OnSetStatusField)
EVT_MENU(StatusBar_SetText, MyFrame::OnSetStatusText)
EVT_MENU(StatusBar_PushText, MyFrame::OnPushStatusText)
EVT_MENU(StatusBar_PopText, MyFrame::OnPopStatusText)
EVT_MENU(StatusBar_SetFont, MyFrame::OnSetStatusFont)
EVT_MENU(StatusBar_ResetFieldsWidth, MyFrame::OnResetFieldsWidth)
EVT_MENU(StatusBar_ShowFieldsRect, MyFrame::OnShowFieldsRect)
EVT_MENU(StatusBar_Recreate, MyFrame::OnRecreateStatusBar)
EVT_MENU(StatusBar_About, MyFrame::OnAbout)
EVT_MENU(StatusBar_Toggle, MyFrame::OnStatusBarToggle)
EVT_MENU(StatusBar_SetPaneStyleNormal, MyFrame::OnSetPaneStyle)
EVT_MENU(StatusBar_SetPaneStyleFlat, MyFrame::OnSetPaneStyle)
EVT_MENU(StatusBar_SetPaneStyleRaised, MyFrame::OnSetPaneStyle)
EVT_MENU(StatusBar_SetStyleSizeGrip, MyFrame::OnSetStyle)
EVT_MENU(StatusBar_SetStyleEllipsizeStart, MyFrame::OnSetStyle)
EVT_MENU(StatusBar_SetStyleEllipsizeMiddle, MyFrame::OnSetStyle)
EVT_MENU(StatusBar_SetStyleEllipsizeEnd, MyFrame::OnSetStyle)
EVT_MENU(StatusBar_SetStyleShowTips, MyFrame::OnSetStyle)
EVT_UPDATE_UI_RANGE(StatusBar_SetFields, StatusBar_ResetFieldsWidth,
MyFrame::OnUpdateForDefaultStatusbar)
EVT_UPDATE_UI(StatusBar_Toggle, MyFrame::OnUpdateStatusBarToggle)
EVT_UPDATE_UI_RANGE(StatusBar_SetPaneStyleNormal,
StatusBar_SetPaneStyleRaised,
MyFrame::OnUpdateSetPaneStyle)
EVT_UPDATE_UI_RANGE(StatusBar_SetStyleSizeGrip, StatusBar_SetStyleShowTips,
MyFrame::OnUpdateSetStyle)
END_EVENT_TABLE()
BEGIN_EVENT_TABLE(MyStatusBar, wxStatusBar)
EVT_SIZE(MyStatusBar::OnSize)
#if wxUSE_CHECKBOX
EVT_CHECKBOX(StatusBar_Checkbox, MyStatusBar::OnToggleClock)
#endif
#if wxUSE_TIMER
EVT_TIMER(wxID_ANY, MyStatusBar::OnTimer)
#endif
EVT_IDLE(MyStatusBar::OnIdle)
END_EVENT_TABLE()
// Create a new application object: this macro will allow wxWidgets to create
// the application object during program execution (it's better than using a
// static object for many reasons) and also declares the accessor function
// wxGetApp() which will return the reference of the right type (i.e. MyApp and
// not wxApp)
IMPLEMENT_APP(MyApp)
// ============================================================================
// implementation
// ============================================================================
// ----------------------------------------------------------------------------
// the application class
// ----------------------------------------------------------------------------
// `Main program' equivalent: the program execution "starts" here
bool MyApp::OnInit()
{
if ( !wxApp::OnInit() )
return false;
// create the main application window
MyFrame *frame = new MyFrame(wxT("wxStatusBar sample"),
wxPoint(50, 50), wxSize(450, 340));
// and show it (the frames, unlike simple controls, are not shown when
// created initially)
frame->Show(true);
// success: wxApp::OnRun() will be called which will enter the main message
// loop and the application will run. If we returned 'false' here, the
// application would exit immediately.
return true;
}
// ----------------------------------------------------------------------------
// main frame
// ----------------------------------------------------------------------------
// frame constructor
MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size)
#ifdef USE_MDI_PARENT_FRAME
: wxMDIParentFrame(NULL, wxID_ANY, title, pos, size)
#else
: wxFrame(NULL, wxID_ANY, title, pos, size)
#endif
{
SetIcon(wxICON(sample));
m_statbarPaneStyle = wxSB_NORMAL;
m_field = 1;
// create a menu bar
wxMenu *menuFile = new wxMenu;
menuFile->Append(StatusBar_Quit, wxT("E&xit\tAlt-X"),
wxT("Quit this program"));
wxMenu *statbarMenu = new wxMenu;
wxMenu *statbarStyleMenu = new wxMenu;
statbarStyleMenu->Append(StatusBar_SetStyleSizeGrip, wxT("wxSTB_SIZE_GRIP"),
wxT("Toggles the wxSTB_SIZE_GRIP style"), true);
statbarStyleMenu->Append(StatusBar_SetStyleShowTips, wxT("wxSTB_SHOW_TIPS"),
wxT("Toggles the wxSTB_SHOW_TIPS style"), true);
statbarStyleMenu->AppendSeparator();
statbarStyleMenu->AppendCheckItem(StatusBar_SetStyleEllipsizeStart,
wxT("wxSTB_ELLIPSIZE_START"),
wxT("Toggle wxSTB_ELLIPSIZE_START style"));
statbarStyleMenu->AppendCheckItem(StatusBar_SetStyleEllipsizeMiddle,
wxT("wxSTB_ELLIPSIZE_MIDDLE"),
wxT("Toggle wxSTB_ELLIPSIZE_MIDDLE style"));
statbarStyleMenu->AppendCheckItem(StatusBar_SetStyleEllipsizeEnd,
wxT("wxSTB_ELLIPSIZE_END"),
wxT("Toggle wxSTB_ELLIPSIZE_END style"));
statbarMenu->Append(StatusBar_SetPaneStyle, wxT("Status bar style"),
statbarStyleMenu);
statbarMenu->AppendSeparator();
statbarMenu->Append(StatusBar_SetField, "Set active field &number\tCtrl-N",
"Set the number of field used by the next commands.");
statbarMenu->Append(StatusBar_SetText, wxT("Set field &text\tCtrl-T"),
wxT("Set the text of the selected field."));
statbarMenu->Append(StatusBar_PushText, "P&ush field text\tCtrl-P",
"Push a message on top the selected field.");
statbarMenu->Append(StatusBar_PopText, "&Pop field text\tShift-Ctrl-P",
"Restore the previous contents of the selected field.");
statbarMenu->AppendSeparator();
statbarMenu->Append(StatusBar_SetFields, wxT("&Set field count\tCtrl-C"),
wxT("Set the number of status bar fields"));
statbarMenu->Append(StatusBar_SetFont, wxT("&Set field font\tCtrl-F"),
wxT("Set the font to use for status bar fields"));
wxMenu *statbarPaneStyleMenu = new wxMenu;
statbarPaneStyleMenu->AppendCheckItem
(
StatusBar_SetPaneStyleNormal,
wxT("&Normal"),
wxT("Sets the style of the first field to normal (sunken) look")
);
statbarPaneStyleMenu->AppendCheckItem
(
StatusBar_SetPaneStyleFlat,
wxT("&Flat"),
wxT("Sets the style of the first field to flat look")
);
statbarPaneStyleMenu->AppendCheckItem
(
StatusBar_SetPaneStyleRaised,
wxT("&Raised"),
wxT("Sets the style of the first field to raised look")
);
statbarMenu->Append(StatusBar_SetPaneStyle, wxT("Field style"),
statbarPaneStyleMenu);
statbarMenu->Append(StatusBar_ResetFieldsWidth, wxT("Reset field widths"),
wxT("Sets all fields to the same width"));
statbarMenu->Append(StatusBar_ShowFieldsRect,
wxT("Sho&w field rectangles\tCtrl-W"),
wxT("Visually show field rectangles"));
statbarMenu->AppendSeparator();
statbarMenu->AppendCheckItem(StatusBar_Toggle, wxT("&Toggle Status Bar"),
wxT("Toggle the status bar display"));
statbarMenu->Append(StatusBar_Recreate, wxT("&Recreate\tCtrl-R"),
wxT("Toggle status bar format"));
wxMenu *helpMenu = new wxMenu;
helpMenu->Append(StatusBar_About, wxT("&About...\tCtrl-A"),
wxT("Show about dialog"));
// now append the freshly created menu to the menu bar...
wxMenuBar *menuBar = new wxMenuBar();
menuBar->Append(menuFile, wxT("&File"));
menuBar->Append(statbarMenu, wxT("&Status bar"));
menuBar->Append(helpMenu, wxT("&Help"));
// ... and attach this menu bar to the frame
SetMenuBar(menuBar);
// create default status bar to start with
DoCreateStatusBar(StatBar_Default, wxSTB_DEFAULT_STYLE);
SetStatusText(wxT("Welcome to wxWidgets!"));
}
void MyFrame::DoCreateStatusBar(MyFrame::StatusBarKind kind, long style)
{
wxStatusBar *statbarOld = GetStatusBar();
if ( statbarOld )
{
SetStatusBar(NULL);
delete statbarOld;
}
wxStatusBar *statbarNew = NULL;
switch ( kind )
{
case StatBar_Default:
statbarNew = new wxStatusBar(this, wxID_ANY, style, "wxStatusBar");
statbarNew->SetFieldsCount(2);
break;
case StatBar_Custom:
statbarNew = new MyStatusBar(this, style);
break;
default:
wxFAIL_MSG(wxT("unknown status bar kind"));
}
SetStatusBar(statbarNew);
ApplyPaneStyle();
PositionStatusBar();
m_statbarKind = kind;
}
// ----------------------------------------------------------------------------
// main frame - event handlers
// ----------------------------------------------------------------------------
void MyFrame::OnUpdateForDefaultStatusbar(wxUpdateUIEvent& event)
{
// only allow this feature for the default status bar
wxStatusBar *sb = GetStatusBar();
if (!sb)
return;
event.Enable(sb->GetName() == "wxStatusBar");
}
void MyFrame::OnSetStatusField(wxCommandEvent& WXUNUSED(event))
{
wxStatusBar *sb = GetStatusBar();
if (!sb)
return;
long rc = wxGetNumberFromUser
(
"Configure the field index to be used by the set, push "
"and pop text commands in the menu.\n"
"\n"
"0 corresponds to the first field, 1 to the second one "
"and so on.",
"Field &index:",
SAMPLE_DIALOGS_TITLE,
m_field,
0,
sb->GetFieldsCount() - 1,
NULL
);
if ( rc == -1 )
return;
m_field = rc;
wxLogStatus("Status bar text will be set for field #%d", m_field);
}
void MyFrame::OnSetStatusText(wxCommandEvent& WXUNUSED(event))
{
wxStatusBar *sb = GetStatusBar();
if (!sb)
return;
wxString txt = wxGetTextFromUser
(
wxString::Format
(
"Enter the text from for the field #%d",
m_field
),
SAMPLE_DIALOGS_TITLE,
sb->GetStatusText(m_field),
this
);
if ( txt.empty() )
return;
sb->SetStatusText(txt, m_field);
}
// the current depth of the stack used by Push/PopStatusText()
static int gs_depth = 0;
void MyFrame::OnPushStatusText(wxCommandEvent& WXUNUSED(event))
{
wxStatusBar *sb = GetStatusBar();
if (!sb)
return;
static int s_countPush = 0;
sb->PushStatusText(wxString::Format
(
"Pushed message #%d (depth = %d)",
++s_countPush, ++gs_depth
), m_field);
}
void MyFrame::OnPopStatusText(wxCommandEvent& WXUNUSED(event))
{
wxStatusBar *sb = GetStatusBar();
if (!sb)
return;
if ( !gs_depth )
{
wxLogStatus("No message to pop.");
return;
}
gs_depth--;
sb->PopStatusText(m_field);
}
void MyFrame::OnSetStatusFont(wxCommandEvent& WXUNUSED(event))
{
wxStatusBar *sb = GetStatusBar();
if (!sb)
return;
wxFont
fnt = wxGetFontFromUser(this, sb->GetFont(), "Choose status bar font");
if (fnt.IsOk())
{
sb->SetFont(fnt);
sb->SetSize(sb->GetBestSize());
}
}
void MyFrame::OnSetStatusFields(wxCommandEvent& WXUNUSED(event))
{
wxStatusBar *sb = GetStatusBar();
if (!sb)
return;
long nFields = wxGetNumberFromUser
(
wxT("Select the number of fields in the status bar"),
wxT("Fields:"),
SAMPLE_DIALOGS_TITLE,
sb->GetFieldsCount(),
1, 5,
this
);
// we don't check if the number changed at all on purpose: calling
// SetFieldsCount() with the same number of fields should be ok
if ( nFields != -1 )
{
static const int widthsFor2Fields[] = { 200, -1 };
static const int widthsFor3Fields[] = { -1, -2, -1 };
static const int widthsFor4Fields[] = { 100, -1, 100, -2, 100 };
static const int *widthsAll[] =
{
NULL, // 1 field: default
widthsFor2Fields, // 2 fields: 1 fixed, 1 var
widthsFor3Fields, // 3 fields: 3 var
widthsFor4Fields, // 4 fields: 3 fixed, 2 vars
NULL // 5 fields: default (all have same width)
};
const int * const widths = widthsAll[nFields - 1];
sb->SetFieldsCount(nFields, widths);
wxString s;
for ( long n = 0; n < nFields; n++ )
{
if ( widths )
{
if ( widths[n] > 0 )
s.Printf(wxT("fixed (%d)"), widths[n]);
else
s.Printf(wxT("variable (*%d)"), -widths[n]);
}
else
{
s = wxT("default");
}
SetStatusText(s, n);
}
if ( m_field >= nFields )
m_field = nFields - 1;
}
else
{
wxLogStatus(this, wxT("Cancelled"));
}
}
void MyFrame::OnResetFieldsWidth(wxCommandEvent& WXUNUSED(event))
{
wxStatusBar *pStat = GetStatusBar();
if ( !pStat )
return;
const int n = pStat->GetFieldsCount();
pStat->SetStatusWidths(n, NULL);
for ( int i = 0; i < n; i++ )
pStat->SetStatusText("same size", i);
}
void MyFrame::OnShowFieldsRect(wxCommandEvent& WXUNUSED(event))
{
wxStatusBar *pStat = GetStatusBar();
if ( !pStat )
return;
wxClientDC dc(pStat);
dc.SetPen(*wxRED_PEN);
dc.SetBrush(*wxTRANSPARENT_BRUSH);
const int n = pStat->GetFieldsCount();
for ( int i = 0; i < n; i++ )
{
wxRect r;
if ( pStat->GetFieldRect(i, r) )
dc.DrawRectangle(r);
}
}
void MyFrame::OnUpdateStatusBarToggle(wxUpdateUIEvent& event)
{
event.Check(GetStatusBar() != NULL);
}
void MyFrame::OnStatusBarToggle(wxCommandEvent& WXUNUSED(event))
{
wxStatusBar *statbarOld = GetStatusBar();
if ( statbarOld )
{
SetStatusBar(NULL);
delete statbarOld;
}
else
{
DoCreateStatusBar(m_statbarKind, wxSTB_DEFAULT_STYLE);
}
}
void MyFrame::OnRecreateStatusBar(wxCommandEvent& WXUNUSED(event))
{
DoCreateStatusBar(m_statbarKind == StatBar_Custom ? StatBar_Default
: StatBar_Custom,
wxSTB_DEFAULT_STYLE);
}
void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
{
// true is to force the frame to close
Close(true);
}
void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
{
MyAboutDialog dlg(this);
dlg.ShowModal();
}
void MyFrame::OnUpdateSetPaneStyle(wxUpdateUIEvent& event)
{
switch (event.GetId())
{
case StatusBar_SetPaneStyleNormal:
event.Check(m_statbarPaneStyle == wxSB_NORMAL);
break;
case StatusBar_SetPaneStyleFlat:
event.Check(m_statbarPaneStyle == wxSB_FLAT);
break;
case StatusBar_SetPaneStyleRaised:
event.Check(m_statbarPaneStyle == wxSB_RAISED);
break;
}
}
void MyFrame::OnSetPaneStyle(wxCommandEvent& event)
{
switch (event.GetId())
{
case StatusBar_SetPaneStyleNormal:
m_statbarPaneStyle = wxSB_NORMAL;
break;
case StatusBar_SetPaneStyleFlat:
m_statbarPaneStyle = wxSB_FLAT;
break;
case StatusBar_SetPaneStyleRaised:
m_statbarPaneStyle = wxSB_RAISED;
break;
}
ApplyPaneStyle();
}
void MyFrame::ApplyPaneStyle()
{
wxStatusBar *sb = GetStatusBar();
if (!sb)
return;
int fields = sb->GetFieldsCount();
int *styles = new int[fields];
for (int i = 1; i < fields; i++)
styles[i] = wxSB_NORMAL;
styles[0] = m_statbarPaneStyle;
sb->SetStatusStyles(fields, styles);
delete [] styles;
}
void MyFrame::OnUpdateSetStyle(wxUpdateUIEvent& event)
{
long currentStyle = wxSTB_DEFAULT_STYLE;
if (GetStatusBar())
currentStyle = GetStatusBar()->GetWindowStyle();
switch (event.GetId())
{
case StatusBar_SetStyleSizeGrip:
event.Check((currentStyle & wxSTB_SIZEGRIP) != 0);
break;
case StatusBar_SetStyleShowTips:
event.Check((currentStyle & wxSTB_SHOW_TIPS) != 0);
break;
case StatusBar_SetStyleEllipsizeStart:
event.Check((currentStyle & wxSTB_ELLIPSIZE_START) != 0);
break;
case StatusBar_SetStyleEllipsizeMiddle:
event.Check((currentStyle & wxSTB_ELLIPSIZE_MIDDLE) != 0);
break;
case StatusBar_SetStyleEllipsizeEnd:
event.Check((currentStyle & wxSTB_ELLIPSIZE_END) != 0);
break;
}
}
void MyFrame::OnSetStyle(wxCommandEvent& event)
{
long oldStyle = wxSTB_DEFAULT_STYLE;
if (GetStatusBar())
oldStyle = GetStatusBar()->GetWindowStyle();
#define STB_ELLIPSIZE_MASK \
(wxSTB_ELLIPSIZE_START|wxSTB_ELLIPSIZE_MIDDLE|wxSTB_ELLIPSIZE_END)
long newStyle = oldStyle;
long newStyleBit = 0;
switch (event.GetId())
{
case StatusBar_SetStyleSizeGrip:
newStyleBit = wxSTB_SIZEGRIP;
break;
case StatusBar_SetStyleShowTips:
newStyleBit = wxSTB_SHOW_TIPS;
break;
case StatusBar_SetStyleEllipsizeStart:
newStyleBit = wxSTB_ELLIPSIZE_START;
newStyle &= ~STB_ELLIPSIZE_MASK;
break;
case StatusBar_SetStyleEllipsizeMiddle:
newStyleBit = wxSTB_ELLIPSIZE_MIDDLE;
newStyle &= ~STB_ELLIPSIZE_MASK;
break;
case StatusBar_SetStyleEllipsizeEnd:
newStyleBit = wxSTB_ELLIPSIZE_END;
newStyle &= ~STB_ELLIPSIZE_MASK;
break;
}
newStyle = event.IsChecked() ? (newStyle | newStyleBit) :
(newStyle & ~newStyleBit);
if (newStyle != oldStyle)
{
DoCreateStatusBar(m_statbarKind, newStyle);
SetStatusText("Status bar recreated with a new style");
}
}
// ----------------------------------------------------------------------------
// MyAboutDialog
// ----------------------------------------------------------------------------
MyAboutDialog::MyAboutDialog(wxWindow *parent)
: wxDialog(parent, wxID_ANY, wxString(wxT("About statbar")),
wxDefaultPosition, wxDefaultSize,
wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
{
wxStaticText *text = new wxStaticText(this, wxID_ANY,
wxT("wxStatusBar sample\n")
wxT("(c) 2000 Vadim Zeitlin"));
wxButton *btn = new wxButton(this, wxID_OK, wxT("&Close"));
// create the top status bar without the size grip (default style),
// otherwise it looks weird
wxStatusBar *statbarTop = new wxStatusBar(this, wxID_ANY, 0);
statbarTop->SetFieldsCount(3);
statbarTop->SetStatusText(wxT("This is a top status bar"), 0);
statbarTop->SetStatusText(wxT("in a dialog"), 1);
statbarTop->SetStatusText(wxT("Great, isn't it?"), 2);
wxStatusBar *statbarBottom = new wxStatusBar(this, wxID_ANY);
statbarBottom->SetFieldsCount(2);
statbarBottom->SetStatusText(wxT("This is a bottom status bar"), 0);
statbarBottom->SetStatusText(wxT("in a dialog"), 1);
wxBoxSizer *sizerTop = new wxBoxSizer(wxVERTICAL);
sizerTop->Add(statbarTop, 0, wxGROW);
sizerTop->Add(-1, 10, 1, wxGROW);
sizerTop->Add(text, 0, wxCENTRE | wxRIGHT | wxLEFT, 20);
sizerTop->Add(-1, 10, 1, wxGROW);
sizerTop->Add(btn, 0, wxCENTRE | wxRIGHT | wxLEFT, 20);
sizerTop->Add(-1, 10, 1, wxGROW);
sizerTop->Add(statbarBottom, 0, wxGROW);
SetSizerAndFit(sizerTop);
}
// ----------------------------------------------------------------------------
// MyStatusBar
// ----------------------------------------------------------------------------
#ifdef __VISUALC__
// 'this' : used in base member initializer list -- so what??
#pragma warning(disable: 4355)
#endif
static const char *numlockIndicators[] = { "OFF", "NUM" };
static const char *capslockIndicators[] = { "", "CAPS" };
MyStatusBar::MyStatusBar(wxWindow *parent, long style)
: wxStatusBar(parent, wxID_ANY, style, "MyStatusBar")
#if wxUSE_TIMER
, m_timer(this)
#endif
#if wxUSE_CHECKBOX
, m_checkbox(NULL)
#endif
{
// compute the size needed for num lock indicator pane
wxClientDC dc(this);
wxSize sizeNumLock = dc.GetTextExtent(numlockIndicators[0]);
sizeNumLock.IncTo(dc.GetTextExtent(numlockIndicators[1]));
int widths[Field_Max];
widths[Field_Text] = -1; // growable
widths[Field_Checkbox] = 150;
widths[Field_Bitmap] = BITMAP_SIZE_X;
widths[Field_NumLockIndicator] = sizeNumLock.x;
widths[Field_Clock] = 100;
widths[Field_CapsLockIndicator] = dc.GetTextExtent(capslockIndicators[1]).x;
SetFieldsCount(Field_Max);
SetStatusWidths(Field_Max, widths);
#if wxUSE_CHECKBOX
m_checkbox = new wxCheckBox(this, StatusBar_Checkbox, wxT("&Toggle clock"));
m_checkbox->SetValue(true);
#endif
m_statbmp = new wxStaticBitmap(this, wxID_ANY, wxIcon(green_xpm));
#if wxUSE_TIMER
m_timer.Start(1000);
#endif
SetMinHeight(wxMax(m_statbmp->GetBestSize().GetHeight(),
m_checkbox->GetBestSize().GetHeight()));
UpdateClock();
}
#ifdef __VISUALC__
#pragma warning(default: 4355)
#endif
MyStatusBar::~MyStatusBar()
{
#if wxUSE_TIMER
if ( m_timer.IsRunning() )
{
m_timer.Stop();
}
#endif
}
void MyStatusBar::OnSize(wxSizeEvent& event)
{
#if wxUSE_CHECKBOX
if ( !m_checkbox )
return;
#endif
// TEMPORARY HACK: TODO find a more general solution
#ifdef wxStatusBarGeneric
wxStatusBar::OnSize(event);
#endif
wxRect rect;
if (!GetFieldRect(Field_Checkbox, rect))
{
event.Skip();
return;
}
#if wxUSE_CHECKBOX
wxRect rectCheck = rect;
rectCheck.Deflate(2);
m_checkbox->SetSize(rectCheck);
#endif
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();
}
void MyStatusBar::OnIdle(wxIdleEvent& event)
{
SetStatusText(numlockIndicators[wxGetKeyState(WXK_NUMLOCK)],
Field_NumLockIndicator);
SetStatusText(capslockIndicators[wxGetKeyState(WXK_CAPITAL)],
Field_CapsLockIndicator);
event.Skip();
}
void MyStatusBar::DoToggle()
{
#if wxUSE_CHECKBOX
if ( m_checkbox->GetValue() )
{
#if wxUSE_TIMER
m_timer.Start(1000);
#endif
m_statbmp->SetIcon(wxIcon(green_xpm));
UpdateClock();
}
else // don't show clock
{
#if wxUSE_TIMER
m_timer.Stop();
#endif
m_statbmp->SetIcon(wxIcon(red_xpm));
SetStatusText(wxEmptyString, Field_Clock);
}
#endif // wxUSE_CHECKBOX
}
void MyStatusBar::UpdateClock()
{
SetStatusText(wxDateTime::Now().FormatTime(), Field_Clock);
}