From 4d3c4c2f9428cb75f7ec4536ff9c5274044d96d9 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Tue, 15 Aug 2000 20:42:47 +0000 Subject: [PATCH] 1. wxStaticText, wxStaticBox, wxButton drawing implemented 2. "pseudo dynamic" wxTheme creation 3. hack to solve GetBestSize() problem 4. more methods in wxDC:: GetMultiLineTextExtent(), DrawLabel() git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/branches/wxUNIVERSAL@8107 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- include/wx/app.h | 3 + include/wx/button.h | 53 ++++- include/wx/control.h | 11 + include/wx/dc.h | 16 ++ include/wx/defs.h | 39 +++- include/wx/gtk/statbox.h | 61 +++--- include/wx/gtk1/statbox.h | 61 +++--- include/wx/msw/app.h | 19 +- include/wx/msw/button.h | 41 ++-- include/wx/msw/statbox.h | 15 +- include/wx/msw/stattext.h | 26 +-- include/wx/statbox.h | 23 +- include/wx/univ/button.h | 73 +++++++ include/wx/univ/control.h | 29 ++- include/wx/univ/renderer.h | 150 ++++++++++++- include/wx/univ/setup.h | 6 +- include/wx/univ/statbox.h | 57 +++++ include/wx/univ/stattext.h | 10 +- include/wx/univ/theme.h | 51 ++++- include/wx/window.h | 17 -- include/wx/wx.h | 2 + samples/univ/univ.cpp | 56 ++++- src/common/ctrlcmn.cpp | 20 ++ src/common/dcbase.cpp | 202 +++++++++++++++++- src/common/wincmn.cpp | 5 - src/gtk/statbox.cpp | 10 +- src/gtk1/statbox.cpp | 10 +- src/msw/app.cpp | 1 + src/msw/dc.cpp | 9 +- src/msw/window.cpp | 52 +++-- src/univ/button.cpp | 126 +++++++++++ src/univ/control.cpp | 74 ++++++- src/univ/renderer.cpp | 138 ++++++++++++ src/univ/statbox.cpp | 74 +++++++ src/univ/stattext.cpp | 90 ++------ src/univ/theme.cpp | 91 ++++---- src/univ/themes/win32.cpp | 420 ++++++++++++++++++++++++++++++------- src/univ/winuniv.cpp | 10 +- 38 files changed, 1752 insertions(+), 399 deletions(-) create mode 100644 include/wx/univ/button.h create mode 100644 include/wx/univ/statbox.h create mode 100644 src/univ/button.cpp create mode 100644 src/univ/renderer.cpp create mode 100644 src/univ/statbox.cpp diff --git a/include/wx/app.h b/include/wx/app.h index 3fe38bf7f4..7eb05d1339 100644 --- a/include/wx/app.h +++ b/include/wx/app.h @@ -163,6 +163,9 @@ public: // top level window functions // -------------------------- + // return TRUE if the active window belongs to our app + virtual bool IsActive() const = 0; + // set the "main" top level window void SetTopWindow(wxWindow *win) { m_topWindow = win; } diff --git a/include/wx/button.h b/include/wx/button.h index 4a67b06532..cc7232fc7c 100644 --- a/include/wx/button.h +++ b/include/wx/button.h @@ -1,22 +1,59 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: wx/button.h +// Purpose: wxButtonBase class +// Author: Vadim Zetlin +// Modified by: +// Created: 15.08.00 +// RCS-ID: $Id$ +// Copyright: (c) Vadim Zetlin +// Licence: wxWindows licence +///////////////////////////////////////////////////////////////////////////// + #ifndef _WX_BUTTON_H_BASE_ #define _WX_BUTTON_H_BASE_ #if wxUSE_BUTTON -#if defined(__WXMSW__) -#include "wx/msw/button.h" +#include "wx/control.h" + +class WXDLLEXPORT wxBitmap; + +WXDLLEXPORT_DATA(extern const wxChar*) wxButtonNameStr; + +// ---------------------------------------------------------------------------- +// wxButton: a push button +// ---------------------------------------------------------------------------- + +class WXDLLEXPORT wxButtonBase : public wxControl +{ +public: + // show the image in the button in addition to the label + virtual void SetImageLabel(const wxBitmap& bitmap) { } + + // this wxButton method is called when the button becomes the default one + // on its panel + virtual void SetDefault() { } + + // returns the default button size for this platform + static wxSize GetDefaultSize(); +}; + +#if defined(__WXUNIVERSAL__) + #include "wx/univ/button.h" +#elif defined(__WXMSW__) + #include "wx/msw/button.h" #elif defined(__WXMOTIF__) -#include "wx/motif/button.h" + #include "wx/motif/button.h" #elif defined(__WXGTK__) -#include "wx/gtk/button.h" + #include "wx/gtk/button.h" #elif defined(__WXQT__) -#include "wx/qt/button.h" + #include "wx/qt/button.h" #elif defined(__WXMAC__) -#include "wx/mac/button.h" + #include "wx/mac/button.h" #elif defined(__WXPM__) -#include "wx/os2/button.h" + #include "wx/os2/button.h" #elif defined(__WXSTUBS__) -#include "wx/stubs/button.h" + #include "wx/stubs/button.h" #endif #endif // wxUSE_BUTTON diff --git a/include/wx/control.h b/include/wx/control.h index df4bd1698b..5fe512055b 100644 --- a/include/wx/control.h +++ b/include/wx/control.h @@ -45,6 +45,13 @@ public: // if the button was clicked) virtual void Command(wxCommandEvent &event); + // get the control alignment (left/right/centre, top/bottom/centre) + int GetAlignment() const { return m_windowStyle & wxALIGN_MASK; } + + // get the control border style: uses the current style and falls back to + // the default style for this class otherwise + wxBorder GetBorder() const; + protected: // creates the control (calls wxWindowBase::CreateBase inside) and adds it // to the list of parents children @@ -61,6 +68,10 @@ protected: // initialize the common fields of wxCommandEvent void InitCommandEvent(wxCommandEvent& event) const; + + // override this to change the default (i.e. used when no style is + // specified) border for the control + virtual wxBorder GetDefaultBorder() const; }; // ---------------------------------------------------------------------------- diff --git a/include/wx/dc.h b/include/wx/dc.h index 4b0b0d8ff0..dd3f71e69d 100644 --- a/include/wx/dc.h +++ b/include/wx/dc.h @@ -256,6 +256,14 @@ public: void DrawRotatedText(const wxString& text, const wxPoint& pt, double angle) { DoDrawRotatedText(text, pt.x, pt.y, angle); } + // this verson puts text into the given rectangle and aligns is as + // specified by alignment parameter; it also will emphasize the character + // with the given index if it is != -1 and return the boundign rectangle + virtual void DrawLabel(const wxString& text, const wxRect& rect, + int alignment = wxALIGN_LEFT | wxALIGN_TOP, + int indexAccel = -1, + wxRect *rectBounding = NULL); + bool Blit(wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord height, wxDC *source, wxCoord xsrc, wxCoord ysrc, int rop = wxCOPY, bool useMask = FALSE) @@ -332,6 +340,7 @@ public: virtual wxCoord GetCharHeight() const = 0; virtual wxCoord GetCharWidth() const = 0; + // only works for single line strings void GetTextExtent(const wxString& string, wxCoord *x, wxCoord *y, wxCoord *descent = NULL, @@ -339,6 +348,13 @@ public: wxFont *theFont = NULL) const { DoGetTextExtent(string, x, y, descent, externalLeading, theFont); } + // works for single as well as multi-line strings + virtual void GetMultiLineTextExtent(const wxString& text, + wxCoord *width, + wxCoord *height, + wxCoord *heightLine = NULL, + wxFont *font = NULL); + // size and resolution // ------------------- diff --git a/include/wx/defs.h b/include/wx/defs.h index cf69eb5312..7cc01a240a 100644 --- a/include/wx/defs.h +++ b/include/wx/defs.h @@ -805,7 +805,10 @@ enum wxAlignment wxALIGN_CENTRE_VERTICAL = wxALIGN_CENTER_VERTICAL, wxALIGN_CENTER = (wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL), - wxALIGN_CENTRE = wxALIGN_CENTER + wxALIGN_CENTRE = wxALIGN_CENTER, + + // a mask to extract alignment from the combination of flags + wxALIGN_MASK = 0x0f00 }; enum wxStretch @@ -817,6 +820,24 @@ enum wxStretch wxSHAPED = 0x4000 }; +// border flags: the values are chosen for backwards compatibility +enum wxBorder +{ + // this is different from wxBORDER_NONE as by default the controls do have + // border + wxBORDER_DEFAULT = 0, + + wxBORDER_NONE = 0x00200000, + wxBORDER_STATIC = 0x01000000, + wxBORDER_SIMPLE = 0x02000000, + wxBORDER_RAISED = 0x04000000, + wxBORDER_SUNKEN = 0x08000000, + wxBORDER_DOUBLE = 0x10000000, + + // a mask to extract border style from the combination of flags + wxBORDER_MASK = 0x1f200000 +}; + // ---------------------------------------------------------------------------- // Window style flags // ---------------------------------------------------------------------------- @@ -841,15 +862,15 @@ enum wxStretch #define wxHSCROLL 0x40000000 #define wxCAPTION 0x20000000 -// New styles -#define wxDOUBLE_BORDER 0x10000000 -#define wxSUNKEN_BORDER 0x08000000 -#define wxRAISED_BORDER 0x04000000 -#define wxBORDER 0x02000000 -#define wxSIMPLE_BORDER wxBORDER -#define wxSTATIC_BORDER 0x01000000 +// New styles (border styles are now in their own enum) +#define wxDOUBLE_BORDER wxBORDER_DOUBLE +#define wxSUNKEN_BORDER wxBORDER_SUNKEN +#define wxRAISED_BORDER wxBORDER_RAISED +#define wxBORDER wxBORDER_SIMPLE +#define wxSIMPLE_BORDER wxBORDER_SIMPLE +#define wxSTATIC_BORDER wxBORDER_STATIC #define wxTRANSPARENT_WINDOW 0x00100000 -#define wxNO_BORDER 0x00200000 +#define wxNO_BORDER wxBORDER_NONE // Override CTL3D etc. control colour processing to allow own background // colour. diff --git a/include/wx/gtk/statbox.h b/include/wx/gtk/statbox.h index 7978dd9bc8..abda2db802 100644 --- a/include/wx/gtk/statbox.h +++ b/include/wx/gtk/statbox.h @@ -1,10 +1,10 @@ ///////////////////////////////////////////////////////////////////////////// -// Name: stabox.h +// Name: wx/gtk/stabox.h // Purpose: // Author: Robert Roebling // Id: $Id$ // Copyright: (c) 1998 Robert Roebling -// Licence: wxWindows licence +// Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// @@ -15,50 +15,37 @@ #pragma interface #endif -#include "wx/defs.h" - -#if wxUSE_STATBOX - -#include "wx/object.h" -#include "wx/list.h" -#include "wx/control.h" - -//----------------------------------------------------------------------------- -// classes -//----------------------------------------------------------------------------- - -class wxStaticBox; - -//----------------------------------------------------------------------------- -// global data -//----------------------------------------------------------------------------- - -extern const char *wxStaticBoxNameStr; - //----------------------------------------------------------------------------- // wxStaticBox //----------------------------------------------------------------------------- -class wxStaticBox: public wxControl +class wxStaticBox : public wxStaticBoxBase { - DECLARE_DYNAMIC_CLASS(wxStaticBox) +public: + wxStaticBox(); + wxStaticBox( wxWindow *parent, + wxWindowID id, + const wxString &label, + const wxPoint &pos = wxDefaultPosition, + const wxSize &size = wxDefaultSize, + long style = 0, + const wxString &name = wxStaticBoxNameStr ); + bool Create( wxWindow *parent, + wxWindowID id, + const wxString &label, + const wxPoint &pos = wxDefaultPosition, + const wxSize &size = wxDefaultSize, + long style = 0, + const wxString &name = wxStaticBoxNameStr ); - public: + virtual void SetLabel( const wxString &label ); - wxStaticBox(void); - wxStaticBox( wxWindow *parent, wxWindowID id, const wxString &label, - const wxPoint &pos = wxDefaultPosition, const wxSize &size = wxDefaultSize, - long style = 0, const wxString &name = wxStaticBoxNameStr ); - bool Create( wxWindow *parent, wxWindowID id, const wxString &label, - const wxPoint &pos = wxDefaultPosition, const wxSize &size = wxDefaultSize, - long style = 0, const wxString &name = wxStaticBoxNameStr ); - void SetLabel( const wxString &label ); + // implementation - // implementation - void ApplyWidgetStyle(); + +private: + DECLARE_DYNAMIC_CLASS(wxStaticBox) }; -#endif - #endif // __GTKSTATICBOXH__ diff --git a/include/wx/gtk1/statbox.h b/include/wx/gtk1/statbox.h index 7978dd9bc8..abda2db802 100644 --- a/include/wx/gtk1/statbox.h +++ b/include/wx/gtk1/statbox.h @@ -1,10 +1,10 @@ ///////////////////////////////////////////////////////////////////////////// -// Name: stabox.h +// Name: wx/gtk/stabox.h // Purpose: // Author: Robert Roebling // Id: $Id$ // Copyright: (c) 1998 Robert Roebling -// Licence: wxWindows licence +// Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// @@ -15,50 +15,37 @@ #pragma interface #endif -#include "wx/defs.h" - -#if wxUSE_STATBOX - -#include "wx/object.h" -#include "wx/list.h" -#include "wx/control.h" - -//----------------------------------------------------------------------------- -// classes -//----------------------------------------------------------------------------- - -class wxStaticBox; - -//----------------------------------------------------------------------------- -// global data -//----------------------------------------------------------------------------- - -extern const char *wxStaticBoxNameStr; - //----------------------------------------------------------------------------- // wxStaticBox //----------------------------------------------------------------------------- -class wxStaticBox: public wxControl +class wxStaticBox : public wxStaticBoxBase { - DECLARE_DYNAMIC_CLASS(wxStaticBox) +public: + wxStaticBox(); + wxStaticBox( wxWindow *parent, + wxWindowID id, + const wxString &label, + const wxPoint &pos = wxDefaultPosition, + const wxSize &size = wxDefaultSize, + long style = 0, + const wxString &name = wxStaticBoxNameStr ); + bool Create( wxWindow *parent, + wxWindowID id, + const wxString &label, + const wxPoint &pos = wxDefaultPosition, + const wxSize &size = wxDefaultSize, + long style = 0, + const wxString &name = wxStaticBoxNameStr ); - public: + virtual void SetLabel( const wxString &label ); - wxStaticBox(void); - wxStaticBox( wxWindow *parent, wxWindowID id, const wxString &label, - const wxPoint &pos = wxDefaultPosition, const wxSize &size = wxDefaultSize, - long style = 0, const wxString &name = wxStaticBoxNameStr ); - bool Create( wxWindow *parent, wxWindowID id, const wxString &label, - const wxPoint &pos = wxDefaultPosition, const wxSize &size = wxDefaultSize, - long style = 0, const wxString &name = wxStaticBoxNameStr ); - void SetLabel( const wxString &label ); + // implementation - // implementation - void ApplyWidgetStyle(); + +private: + DECLARE_DYNAMIC_CLASS(wxStaticBox) }; -#endif - #endif // __GTKSTATICBOXH__ diff --git a/include/wx/msw/app.h b/include/wx/msw/app.h index f56a67871f..657d274945 100644 --- a/include/wx/msw/app.h +++ b/include/wx/msw/app.h @@ -36,12 +36,13 @@ public: virtual ~wxApp(); // override base class (pure) virtuals - virtual bool OnInitGui() { return TRUE; } virtual int MainLoop(); virtual void ExitMainLoop(); virtual bool Initialized(); - virtual bool Pending() ; - virtual void Dispatch() ; + virtual bool Pending(); + virtual void Dispatch(); + + virtual bool IsActive() const { return m_isActive; } virtual wxIcon GetStdIcon(int which) const; @@ -64,10 +65,14 @@ public: void SetAuto3D(bool flag) { m_auto3D = flag; } bool GetAuto3D() const { return m_auto3D; } + // for private use only + void SetActive(bool isActive) { m_isActive = isActive; } + protected: - bool m_showOnInit; - int m_printMode; // wxPRINT_WINDOWS, wxPRINT_POSTSCRIPT - bool m_auto3D ; // Always use 3D controls, except where overriden + bool m_showOnInit; + int m_printMode; // wxPRINT_WINDOWS, wxPRINT_POSTSCRIPT + bool m_auto3D ; // Always use 3D controls, except where overriden + bool m_isActive; /* Windows-specific wxApp definitions */ @@ -99,7 +104,7 @@ public: int m_nCmdShow; protected: - bool m_keepGoing ; + bool m_keepGoing; DECLARE_EVENT_TABLE() }; diff --git a/include/wx/msw/button.h b/include/wx/msw/button.h index 0b0476844e..52a68b5ab3 100644 --- a/include/wx/msw/button.h +++ b/include/wx/msw/button.h @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////////////////// -// Name: button.h +// Name: wx/msw/button.h // Purpose: wxButton class // Author: Julian Smart // Modified by: @@ -16,41 +16,39 @@ #pragma interface "button.h" #endif -#include "wx/control.h" - -WXDLLEXPORT_DATA(extern const wxChar*) wxButtonNameStr; - // ---------------------------------------------------------------------------- // Pushbutton // ---------------------------------------------------------------------------- -class WXDLLEXPORT wxButton : public wxControl +class WXDLLEXPORT wxButton : public wxButtonBase { -DECLARE_DYNAMIC_CLASS(wxButton) - public: wxButton() { } - wxButton(wxWindow *parent, wxWindowID id, const wxString& label, - const wxPoint& pos = wxDefaultPosition, - const wxSize& size = wxDefaultSize, long style = 0, - const wxValidator& validator = wxDefaultValidator, - const wxString& name = wxButtonNameStr) + wxButton(wxWindow *parent, + wxWindowID id, + const wxString& label, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = 0, + const wxValidator& validator = wxDefaultValidator, + const wxString& name = wxButtonNameStr) { Create(parent, id, label, pos, size, style, validator, name); } - bool Create(wxWindow *parent, wxWindowID id, const wxString& label, - const wxPoint& pos = wxDefaultPosition, - const wxSize& size = wxDefaultSize, long style = 0, - const wxValidator& validator = wxDefaultValidator, - const wxString& name = wxButtonNameStr); + bool Create(wxWindow *parent, + wxWindowID id, + const wxString& label, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = 0, + const wxValidator& validator = wxDefaultValidator, + const wxString& name = wxButtonNameStr); virtual ~wxButton(); virtual void SetDefault(); - static wxSize GetDefaultSize(); - // implementation from now on virtual void Command(wxCommandEvent& event); virtual long MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam); @@ -72,6 +70,9 @@ protected: bool SendClickEvent(); virtual wxSize DoGetBestSize() const; + +private: + DECLARE_DYNAMIC_CLASS(wxButton) }; #endif diff --git a/include/wx/msw/statbox.h b/include/wx/msw/statbox.h index 24dfe5ec91..2e18c72266 100644 --- a/include/wx/msw/statbox.h +++ b/include/wx/msw/statbox.h @@ -16,17 +16,9 @@ #pragma interface "statbox.h" #endif -#if wxUSE_STATBOX - -#include "wx/control.h" - -WXDLLEXPORT_DATA(extern const wxChar*) wxStaticBoxNameStr; - // Group box -class WXDLLEXPORT wxStaticBox : public wxControl +class WXDLLEXPORT wxStaticBox : public wxStaticBoxBase { -DECLARE_DYNAMIC_CLASS(wxStaticBox) - public: wxStaticBox() { } @@ -57,9 +49,10 @@ public: protected: virtual wxSize DoGetBestSize() const; -}; -#endif // wxUSE_STATBOX +private: + DECLARE_DYNAMIC_CLASS(wxStaticBox) +}; #endif // _WX_STATBOX_H_ diff --git a/include/wx/msw/stattext.h b/include/wx/msw/stattext.h index fd0f63d801..4f7ca61e4b 100644 --- a/include/wx/msw/stattext.h +++ b/include/wx/msw/stattext.h @@ -27,22 +27,24 @@ DECLARE_DYNAMIC_CLASS(wxStaticText) public: wxStaticText() { } - wxStaticText(wxWindow *parent, wxWindowID id, - const wxString& label, - const wxPoint& pos = wxDefaultPosition, - const wxSize& size = wxDefaultSize, - long style = 0, - const wxString& name = wxStaticTextNameStr) + wxStaticText(wxWindow *parent, + wxWindowID id, + const wxString& label, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = 0, + const wxString& name = wxStaticTextNameStr) { Create(parent, id, label, pos, size, style, name); } - bool Create(wxWindow *parent, wxWindowID id, - const wxString& label, - const wxPoint& pos = wxDefaultPosition, - const wxSize& size = wxDefaultSize, - long style = 0, - const wxString& name = wxStaticTextNameStr); + bool Create(wxWindow *parent, + wxWindowID id, + const wxString& label, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = 0, + const wxString& name = wxStaticTextNameStr); // accessors void SetLabel(const wxString& label); diff --git a/include/wx/statbox.h b/include/wx/statbox.h index e67a1698e3..3edf096c1e 100644 --- a/include/wx/statbox.h +++ b/include/wx/statbox.h @@ -1,7 +1,26 @@ #ifndef _WX_STATBOX_H_BASE_ #define _WX_STATBOX_H_BASE_ -#if defined(__WXMSW__) +#if wxUSE_STATBOX + +#include "wx/control.h" + +WXDLLEXPORT_DATA(extern const wxChar*) wxStaticBoxNameStr; + +// ---------------------------------------------------------------------------- +// wxStaticBox: a grouping box with a label +// ---------------------------------------------------------------------------- + +class WXDLLEXPORT wxStaticBoxBase : public wxControl +{ +public: + // overriden base class virtuals + virtual bool AcceptsFocus() const { return FALSE; } +}; + +#if defined(__WXUNIVERSAL__) +#include "wx/univ/statbox.h" +#elif defined(__WXMSW__) #include "wx/msw/statbox.h" #elif defined(__WXMOTIF__) #include "wx/motif/statbox.h" @@ -17,5 +36,7 @@ #include "wx/stubs/statbox.h" #endif +#endif // wxUSE_STATBOX + #endif // _WX_STATBOX_H_BASE_ diff --git a/include/wx/univ/button.h b/include/wx/univ/button.h new file mode 100644 index 0000000000..d2a008199d --- /dev/null +++ b/include/wx/univ/button.h @@ -0,0 +1,73 @@ +/////////////////////////////////////////////////////////////////////////////// +// Name: wx/univ/button.h +// Purpose: wxButton for wxUniversal +// Author: Vadim Zeitlin +// Modified by: +// Created: 15.08.00 +// RCS-ID: $Id$ +// Copyright: (c) 2000 Vadim Zeitlin +// Licence: wxWindows license +/////////////////////////////////////////////////////////////////////////////// + +#ifndef _WX_UNIV_BUTTON_H_ +#define _WX_UNIV_BUTTON_H_ + +#ifdef __GNUG__ + #pragma interface "univbutton.h" +#endif + +// ---------------------------------------------------------------------------- +// Pushbutton +// ---------------------------------------------------------------------------- + +class WXDLLEXPORT wxButton : public wxButtonBase +{ +public: + wxButton() { Init(); } + wxButton(wxWindow *parent, + wxWindowID id, + const wxString& label, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = 0, + const wxValidator& validator = wxDefaultValidator, + const wxString& name = wxButtonNameStr) + { + Init(); + + Create(parent, id, label, pos, size, style, validator, name); + } + + bool Create(wxWindow *parent, + wxWindowID id, + const wxString& label, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = 0, + const wxValidator& validator = wxDefaultValidator, + const wxString& name = wxButtonNameStr); + + virtual ~wxButton(); + + virtual void SetDefault(); + + virtual bool IsPressed() const { return m_isPressed; } + virtual bool IsDefault() const { return m_isDefault; } + +protected: + virtual wxSize DoGetBestSize() const; + virtual void DoDraw(wxControlRenderer *renderer); + + // common part of all ctors + void Init(); + + bool m_isPressed, + m_isDefault; + +private: + DECLARE_DYNAMIC_CLASS(wxButton) +}; + +#endif + // _WX_BUTTON_H_ + diff --git a/include/wx/univ/control.h b/include/wx/univ/control.h index c1b5b347be..dff129d1f3 100644 --- a/include/wx/univ/control.h +++ b/include/wx/univ/control.h @@ -16,6 +16,8 @@ #pragma interface "control.h" #endif +class WXDLLEXPORT wxControlRenderer; + class WXDLLEXPORT wxControl : public wxControlBase { public: @@ -35,12 +37,35 @@ public: virtual void SetLabel(const wxString &label); virtual wxString GetLabel() const; + // get the state information + virtual bool IsFocused() const; + virtual bool IsPressed() const; + virtual bool IsDefault() const; + + // implementation only from now on + + // return the index of the accel char in the label or -1 if none + int GetAccelIndex() const { return m_indexAccel; } + + // return the accel char itself or 0 if none + wxChar GetAccelChar() const + { + return m_indexAccel == -1 ? _T('\0') : m_label[m_indexAccel]; + } + protected: - wxString m_label; - wxChar m_chAccel; + // draw the controls contents + virtual void DoDraw(wxControlRenderer *renderer); + + // event handlers + void OnPaint(wxPaintEvent& event); private: + wxString m_label; + int m_indexAccel; + DECLARE_DYNAMIC_CLASS(wxControl) + DECLARE_EVENT_TABLE() }; #endif // _WX_UNIV_CONTROL_H_ diff --git a/include/wx/univ/renderer.h b/include/wx/univ/renderer.h index e844130255..5f99331d32 100644 --- a/include/wx/univ/renderer.h +++ b/include/wx/univ/renderer.h @@ -13,23 +13,163 @@ wxRenderer class is used to draw all wxWindows controls. This is an ABC and the look of the application is determined by the concrete derivation of wxRenderer used in the program. - */ +#ifdef __GNUG__ + #pragma implementation "renderer.h" +#endif + #ifndef _WX_UNIX_RENDERER_H_ #define _WX_UNIX_RENDERER_H_ class WXDLLEXPORT wxDC; class WXDLLEXPORT wxWindow; +// ---------------------------------------------------------------------------- +// constants +// ---------------------------------------------------------------------------- + +// control state flags used in wxRenderer +enum +{ + wxRENDER_ENABLED = 0x00000001, + wxRENDER_FOCUSED = 0x00000002, + wxRENDER_PRESSED = 0x00000004, + wxRENDER_DEFAULT = 0x00000008, // button... + + wxRENDER_FLAGS_MASK = 0x0000000f +}; + +// ---------------------------------------------------------------------------- +// wxRenderer: abstract renderers interface +// ---------------------------------------------------------------------------- + class WXDLLEXPORT wxRenderer { public: - // draw the label - virtual void DrawLabel(wxDC& dc, wxWindow *window) = 0; + // draw the label inside the given rectangle with the specified alignment + // and optionally emphasize the character with the given index + virtual void DrawLabel(wxDC& dc, + const wxString& label, + const wxRect& rect, + int flags = wxRENDER_ENABLED, + int alignment = wxALIGN_LEFT | wxALIGN_TOP, + int indexAccel = -1) = 0; - // draw the border and adjust the DC - virtual void DrawBorder(wxDC& dc, wxWindow *window) = 0; + // draw the border and optionally return the rectangle containing the + // region inside the border + virtual void DrawBorder(wxDC& dc, + wxBorder border, + const wxRect& rect, + int flags = wxRENDER_ENABLED, + wxRect *rectIn = (wxRect *)NULL) = 0; + + // draw push button border and return the rectangle left for the label + virtual void DrawButtonBorder(wxDC& dc, + const wxRect& rect, + int flags = wxRENDER_ENABLED, + wxRect *rectIn = (wxRect *)NULL) = 0; + + // draw a frame with the label (horizontal alignment can be specified) + virtual void DrawFrame(wxDC& dc, + const wxString& label, + const wxRect& rect, + int flags = wxRENDER_ENABLED, + int alignment = wxALIGN_LEFT, + int indexAccel = -1) = 0; + + // TODO: having this is ugly but I don't see how to solve GetBestSize() + // problem without something like this + + // adjust the size of the control of the given class: for most controls, + // this just takes into account the border, but for some (buttons, for + // example) it is more complicated - the result being, in any case, that + // the control looks "nice" if it uses the adjusted rectangle + virtual void AdjustSize(wxSize *size, const wxWindow *window) = 0; +}; + +// ---------------------------------------------------------------------------- +// wxDelegateRenderer: it is impossible to inherit from any of standard +// renderers as their declarations are in private code, but you can use this +// class to override only some of the Draw() functions - all the other ones +// will be left to the original renderer +// ---------------------------------------------------------------------------- + +class WXDLLEXPORT wxDelegateRenderer : public wxRenderer +{ +public: + wxDelegateRenderer(wxRenderer *renderer) : m_renderer(renderer) { } + + virtual void DrawLabel(wxDC& dc, + const wxString& label, + const wxRect& rect, + int flags = wxRENDER_ENABLED, + int align = wxALIGN_LEFT | wxALIGN_TOP, + int indexAccel = -1) + { m_renderer->DrawLabel(dc, label, rect, flags, align, indexAccel); } + virtual void DrawBorder(wxDC& dc, + wxBorder border, + const wxRect& rect, + int flags = wxRENDER_ENABLED, + wxRect *rectIn = (wxRect *)NULL) + { m_renderer->DrawBorder(dc, border, rect, flags, rectIn); } + virtual void DrawFrame(wxDC& dc, + const wxString& label, + const wxRect& rect, + int flags = wxRENDER_ENABLED, + int align = wxALIGN_LEFT, + int indexAccel = -1) + { m_renderer->DrawFrame(dc, label, rect, flags, align, indexAccel); } + virtual void DrawButtonBorder(wxDC& dc, + const wxRect& rect, + int flags = wxRENDER_ENABLED, + wxRect *rectIn = (wxRect *)NULL) + { m_renderer->DrawButtonBorder(dc, rect, flags, rectIn); } + + virtual void AdjustSize(wxSize *size, const wxWindow *window) + { m_renderer->AdjustSize(size, window); } + +protected: + wxRenderer *m_renderer; +}; + +// ---------------------------------------------------------------------------- +// wxControlRenderer: wraps the wxRenderer functions in a form easy to use from +// OnPaint() +// ---------------------------------------------------------------------------- + +class WXDLLEXPORT wxControlRenderer +{ +public: + // create a renderer for this dc with this "fundamental" renderer + wxControlRenderer(wxControl *control, wxDC& dc, wxRenderer *renderer); + + // operations + void DrawLabel(); + void DrawBorder(); + void DrawButtonBorder(); + void DrawFrame(); + + // accessors + wxRenderer *GetRenderer() const { return m_renderer; } + + wxDC& GetDC() { return m_dc; } + + const wxRect& GetRect() const { return m_rect; } + wxRect& GetRect() { return m_rect; } + +protected: + // the current window state + int GetStateFlags() const; + + // paint the control background + void PaintBackground(); + +private: + wxControl *m_ctrl; + wxRenderer *m_renderer; + wxDC& m_dc; + wxRect m_rect; }; #endif // _WX_UNIX_RENDERER_H_ diff --git a/include/wx/univ/setup.h b/include/wx/univ/setup.h index 86c0748cd7..68a96af833 100644 --- a/include/wx/univ/setup.h +++ b/include/wx/univ/setup.h @@ -65,7 +65,8 @@ #define wxUSE_FONTMAP 0 #define wxUSE_MIMETYPE 0 -#define wxUSE_BUTTON 0 +#define wxUSE_CONTROLS 1 +#define wxUSE_BUTTON 1 #define wxUSE_BMPBUTTON 0 #define wxUSE_CARET 0 #define wxUSE_CHECKBOX 0 @@ -82,8 +83,9 @@ #define wxUSE_SLIDER 0 #define wxUSE_SPINBTN 0 #define wxUSE_SPINCTRL 0 +#define wxUSE_STATBOX 1 #define wxUSE_STATLINE 0 -#define wxUSE_STATTEXT 0 +#define wxUSE_STATTEXT 1 #define wxUSE_STATLBMP 0 #define wxUSE_STATUSBAR 0 #define wxUSE_TOOLTIPS 0 diff --git a/include/wx/univ/statbox.h b/include/wx/univ/statbox.h new file mode 100644 index 0000000000..7a8f530f61 --- /dev/null +++ b/include/wx/univ/statbox.h @@ -0,0 +1,57 @@ +/////////////////////////////////////////////////////////////////////////////// +// Name: wx/univ/statbox.h +// Purpose: wxStaticBox declaration +// Author: Vadim Zeitlin +// Modified by: +// Created: 15.08.00 +// RCS-ID: $Id$ +// Copyright: (c) 2000 Vadim Zeitlin +// Licence: wxWindows license +/////////////////////////////////////////////////////////////////////////////// + +#ifndef _WX_UNIV_STATBOX_H_ +#define _WX_UNIV_STATBOX_H_ + +#ifdef __GNUG__ + #pragma interface "univstatbox.h" +#endif + +class WXDLLEXPORT wxStaticBox : public wxStaticBoxBase +{ +public: + wxStaticBox() { } + + wxStaticBox(wxWindow *parent, + const wxString& label, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize) + { + Create(parent, -1, label, pos, size); + } + + wxStaticBox(wxWindow *parent, wxWindowID id, + const wxString& label, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = 0, + const wxString& name = wxStaticBoxNameStr) + { + Create(parent, id, label, pos, size, style, name); + } + + bool Create(wxWindow *parent, + wxWindowID id, + const wxString& label, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = 0, + const wxString& name = wxStaticBoxNameStr); + +protected: + virtual void DoDraw(wxControlRenderer *renderer); + +private: + DECLARE_DYNAMIC_CLASS(wxStaticBox) +}; + +#endif // _WX_UNIV_STATBOX_H_ diff --git a/include/wx/univ/stattext.h b/include/wx/univ/stattext.h index b992c0524a..c7dca9d350 100644 --- a/include/wx/univ/stattext.h +++ b/include/wx/univ/stattext.h @@ -13,10 +13,10 @@ #define _WX_UNIV_STATTEXT_H_ #ifdef __GNUG__ - #pragma interface "stattext.h" + #pragma interface "univstattext.h" #endif -class WXDLLEXPORT wxStaticText : wxStaticTextBase +class WXDLLEXPORT wxStaticText : public wxStaticTextBase { public: // usual ctor @@ -49,12 +49,16 @@ public: long style = 0, const wxString &name = wxStaticTextNameStr); + // implementation only from now on + + virtual void SetLabel(const wxString& label); + protected: // calculate the optimal size for the label virtual wxSize DoGetBestSize() const; // draw the control - virtual void DoDraw(wxDC& dc, wxRenderer *renderer); + virtual void DoDraw(wxControlRenderer *renderer); }; #endif // _WX_UNIV_STATTEXT_H_ diff --git a/include/wx/univ/theme.h b/include/wx/univ/theme.h index 34dff5a975..9adcc47d24 100644 --- a/include/wx/univ/theme.h +++ b/include/wx/univ/theme.h @@ -23,31 +23,78 @@ // ---------------------------------------------------------------------------- class WXDLLEXPORT wxRenderer; -class WXDLLEXPORT wxInputHandler; -class WXDLLEXPORT wxColourScheme; +class WXDLLEXPORT wxInputHandler { }; +class WXDLLEXPORT wxColourScheme { }; class WXDLLEXPORT wxTheme { public: + // static methods + // -------------- + // create the default theme static bool CreateDefault(); + // create the theme by name (will return NULL if not found) + static wxTheme *Create(const wxString& name); + // change the current scheme static wxTheme *Set(wxTheme *theme); // get the current theme (never NULL) static wxTheme *Get() { return ms_theme; } + // the theme methods + // ----------------- virtual wxRenderer *GetRenderer() = 0; virtual wxInputHandler *GetInputHandler() = 0; virtual wxColourScheme *GetColourScheme() = 0; + // implementation only from now on + // ------------------------------- + virtual ~wxTheme(); + // dynamic creation helpers + typedef wxTheme *(*Constructor)(); + + struct wxThemeInfo + { + // theme name and (user readable) description + wxString name, desc; + + // the function to create a theme object + Constructor ctor; + + // next node in the linked list or NULL + wxThemeInfo *next; + + // constructor for the struct itself + wxThemeInfo(Constructor ctor, const wxChar *name, const wxChar *desc); + }; + private: + // the list of descriptions of all known themes + static wxThemeInfo *ms_allThemes; + // the current theme static wxTheme *ms_theme; + + friend wxThemeInfo; }; +// ---------------------------------------------------------------------------- +// macros +// ---------------------------------------------------------------------------- + +// to declare a new theme, this macro must be used in the class declaration +#define WX_DECLARE_THEME() static wxThemeInfo ms_info + +// and this one must be inserted in the source file +#define WX_IMPLEMENT_THEME(classname, themename, themedesc) \ + wxTheme *wxCtorFor##themename() { return new classname; } \ + wxTheme::wxThemeInfo classname::ms_info(wxCtorFor##themename, \ + #themename, themedesc) + #endif // _WX_UNIX_THEME_H_ diff --git a/include/wx/window.h b/include/wx/window.h index 04312191df..f4fc98faed 100644 --- a/include/wx/window.h +++ b/include/wx/window.h @@ -48,9 +48,6 @@ class WXDLLEXPORT wxDC; class WXDLLEXPORT wxDropTarget; class WXDLLEXPORT wxItemResource; class WXDLLEXPORT wxLayoutConstraints; -#ifdef __WXUNIVERSAL__ - class WXDLLEXPORT wxRenderer; -#endif // __WXUNIVERSAL__ class WXDLLEXPORT wxResourceTable; class WXDLLEXPORT wxSizer; class WXDLLEXPORT wxToolTip; @@ -855,20 +852,6 @@ protected: ClientData_Void // client data is untyped and we don't own it } m_clientDataType; -#ifdef __WXUNIVERSAL__ - // draw the controls contents: the base class version draws the border as - // required (depending on the window style flags and enabled state) and - // adjusts the DC so that subsequent drawing is clipped to the area inside - // the border - virtual void DoDraw(wxDC& dc, wxRenderer *renderer); - - // draw the border corresponding to the window style - virtual void DoDrawBorder(wxDC& dc, wxRenderer *renderer); - - // event handlers - void OnPaint(wxPaintEvent& event); -#endif // __WXUNIVERSAL__ - private: // contains the last id generated by NewControlId static int ms_lastControlId; diff --git a/include/wx/wx.h b/include/wx/wx.h index 719a25e964..d287d275d7 100644 --- a/include/wx/wx.h +++ b/include/wx/wx.h @@ -47,6 +47,8 @@ #include "wx/msgdlg.h" #include "wx/cmndata.h" +#include "wx/control.h" +#include "wx/ctrlsub.h" #include "wx/bmpbuttn.h" #include "wx/checkbox.h" #include "wx/choice.h" diff --git a/samples/univ/univ.cpp b/samples/univ/univ.cpp index 1ac3c7ff60..d103d00759 100644 --- a/samples/univ/univ.cpp +++ b/samples/univ/univ.cpp @@ -34,6 +34,8 @@ #include "wx/frame.h" #include "wx/dcclient.h" + #include "wx/button.h" + #include "wx/statbox.h" #include "wx/stattext.h" #endif @@ -97,10 +99,60 @@ bool MyUnivApp::OnInit() // ---------------------------------------------------------------------------- MyUnivFrame::MyUnivFrame(const wxString& title) - : wxFrame(NULL, -1, title, wxDefaultPosition, wxSize(300, 150)) + : wxFrame(NULL, -1, title, wxDefaultPosition, wxSize(600, 400)) { + SetBackgroundColour(*wxLIGHT_GREY); + new wxStaticText(this, _T("Test static text"), wxPoint(10, 10)); - new wxStaticText(this, _T("Ctrl-click to exit."), wxPoint(40, 10)); + new wxStaticText(this, + _T("&Multi line\n(and very very very very long)\nstatic text"), + wxPoint(210, 10)); + + (new wxStaticText(this, _T("&Disabled text"), wxPoint(10, 30)))->Disable(); + + wxStaticText *text; + text = new wxStaticText(this, _T("Demo of &border styles:"), wxPoint(10, 60)); + text->SetFont(*wxITALIC_FONT); + text->SetBackgroundColour(*wxWHITE); + text->SetForegroundColour(*wxBLUE); + + wxCoord x = 10; + #define CREATE_STATIC_BORDER_DEMO(border) \ + (new wxStaticText(this, -1, _T(#border), \ + wxPoint(x, 100), wxSize(70, -1), wx##border##_BORDER)); \ + x += 80 + + CREATE_STATIC_BORDER_DEMO(NO); + CREATE_STATIC_BORDER_DEMO(SIMPLE); + CREATE_STATIC_BORDER_DEMO(SUNKEN); + CREATE_STATIC_BORDER_DEMO(RAISED); + CREATE_STATIC_BORDER_DEMO(STATIC); + CREATE_STATIC_BORDER_DEMO(DOUBLE); + + #undef CREATE_STATIC_BORDER_DEMO + + wxStaticBox *box = new wxStaticBox(this, _T("&Alignments demo:"), + wxPoint(10, 150), + wxSize(500, 120)); + box->SetForegroundColour(*wxRED); + + x = 15; + #define CREATE_STATIC_ALIGN_DEMO(align) \ + (new wxStaticText(this, -1, _T(#align), \ + wxPoint(x, 175), wxSize(70, 70), \ + wxSIMPLE_BORDER | wxALIGN_##align)); \ + x += 80 + + CREATE_STATIC_ALIGN_DEMO(LEFT); + CREATE_STATIC_ALIGN_DEMO(RIGHT); + CREATE_STATIC_ALIGN_DEMO(CENTRE); + CREATE_STATIC_ALIGN_DEMO(TOP); + CREATE_STATIC_ALIGN_DEMO(BOTTOM); + CREATE_STATIC_ALIGN_DEMO(CENTRE_VERTICAL); + + #undef CREATE_STATIC_ALIGN_DEMO + + new wxButton(this, -1, _T("&Press me"), wxPoint(10, 300)); } void MyUnivFrame::OnLeftUp(wxMouseEvent& event) diff --git a/src/common/ctrlcmn.cpp b/src/common/ctrlcmn.cpp index 313027e091..f9748c0df9 100644 --- a/src/common/ctrlcmn.cpp +++ b/src/common/ctrlcmn.cpp @@ -113,5 +113,25 @@ void wxControlBase::InitCommandEvent(wxCommandEvent& event) const } } +// ---------------------------------------------------------------------------- +// border stuff +// ---------------------------------------------------------------------------- + +wxBorder wxControlBase::GetBorder() const +{ + wxBorder border = (wxBorder)(m_windowStyle & wxBORDER_MASK); + if ( border == wxBORDER_DEFAULT ) + { + border = GetDefaultBorder(); + } + + return border; +} + +wxBorder wxControlBase::GetDefaultBorder() const +{ + return wxBORDER_NONE; +} + #endif // wxUSE_CONTROLS diff --git a/src/common/dcbase.cpp b/src/common/dcbase.cpp index e625e91d07..5e7c4e91b5 100644 --- a/src/common/dcbase.cpp +++ b/src/common/dcbase.cpp @@ -1,7 +1,7 @@ ///////////////////////////////////////////////////////////////////////////// -// Name: dc.cpp -// Purpose: wxDC Class -// Author: Brian Macy +// Name: common/dcbase.cpp +// Purpose: generic methods of the wxDC Class +// Author: Vadim Zeitlin // Modified by: // Created: 05/25/99 // RCS-ID: $Id$ @@ -9,10 +9,18 @@ // Licence: wxWindows license ///////////////////////////////////////////////////////////////////////////// +// ============================================================================ +// declarations +// ============================================================================ + #ifdef __GNUG__ -#pragma implementation "dcbase.h" + #pragma implementation "dcbase.h" #endif +// ---------------------------------------------------------------------------- +// headers +// ---------------------------------------------------------------------------- + // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" @@ -30,6 +38,14 @@ #include "wx/dc.h" +// ============================================================================ +// implementation +// ============================================================================ + +// ---------------------------------------------------------------------------- +// special symbols +// ---------------------------------------------------------------------------- + void wxDCBase::DoDrawCheckMark(wxCoord x1, wxCoord y1, wxCoord width, wxCoord height) { @@ -51,6 +67,10 @@ void wxDCBase::DoDrawCheckMark(wxCoord x1, wxCoord y1, CalcBoundingBox(x2, y2); } +// ---------------------------------------------------------------------------- +// line/polygons +// ---------------------------------------------------------------------------- + void wxDCBase::DrawLines(const wxList *list, wxCoord xoffset, wxCoord yoffset) { int n = list->Number(); @@ -90,6 +110,9 @@ void wxDCBase::DrawPolygon(const wxList *list, delete [] points; } +// ---------------------------------------------------------------------------- +// splines +// ---------------------------------------------------------------------------- #if wxUSE_SPLINES @@ -131,3 +154,174 @@ void wxDCBase::DrawSpline(int n, wxPoint points[]) } #endif // wxUSE_SPLINES + +// ---------------------------------------------------------------------------- +// enhanced text drawing +// ---------------------------------------------------------------------------- + +void wxDCBase::GetMultiLineTextExtent(const wxString& text, + wxCoord *x, + wxCoord *y, + wxCoord *h, + wxFont *font) +{ + int widthTextMax = 0, widthLine, + heightTextTotal = 0, heightLineDefault = 0, heightLine = 0; + + wxString curLine; + for ( const wxChar *pc = text; ; pc++ ) + { + if ( *pc == _T('\n') || *pc == _T('\0') ) + { + if ( curLine.empty() ) + { + // we can't use GetTextExtent - it will return 0 for both width + // and height and an empty line should count in height + // calculation + + // assume that this line has the same height as the previous + // one + if ( !heightLineDefault ) + heightLineDefault = heightLine; + + if ( !heightLineDefault ) + { + // but we don't know it yet - choose something reasonable + GetTextExtent(_T("W"), NULL, &heightLineDefault, + NULL, NULL, font); + } + + heightTextTotal += heightLineDefault; + } + else + { + GetTextExtent(curLine, &widthLine, &heightLine, + NULL, NULL, font); + if ( widthLine > widthTextMax ) + widthTextMax = widthLine; + heightTextTotal += heightLine; + } + + if ( *pc == _T('\n') ) + { + curLine.clear(); + } + else + { + // the end of string + break; + } + } + else + { + curLine += *pc; + } + } + + if ( x ) + *x = widthTextMax; + if ( y ) + *y = heightTextTotal; + if ( h ) + *h = heightLine; +} + +void wxDCBase::DrawLabel(const wxString& text, + const wxRect& rect, + int alignment, + int indexAccel, + wxRect *rectBounding) +{ + // find the text position + wxCoord width, height, heightLine; + GetMultiLineTextExtent(text, &width, &height, &heightLine); + + wxCoord x, y; + if ( alignment & wxALIGN_RIGHT ) + { + x = rect.GetRight() - width; + } + else if ( alignment & wxALIGN_CENTRE ) + { + x = (rect.GetLeft() + rect.GetRight() - width) / 2; + } + else // alignment & wxALIGN_LEFT + { + x = rect.GetLeft(); + } + + if ( alignment & wxALIGN_BOTTOM ) + { + y = rect.GetBottom() - height; + } + else if ( alignment & wxALIGN_CENTRE_VERTICAL ) + { + y = (rect.GetTop() + rect.GetBottom() - height) / 2; + } + else // alignment & wxALIGN_TOP + { + y = rect.GetTop(); + } + + // we will darw the underscore under the accel char later + wxCoord startUnderscore = 0, + endUnderscore = 0, + yUnderscore = 0; + + // split the string into lines and draw each of them separately + wxString curLine; + for ( const wxChar *pc = text; ; pc++ ) + { + if ( *pc == _T('\n') || *pc == _T('\0') ) + { + if ( !curLine.empty() ) + { + DrawText(curLine, x, y); + } + + if ( *pc == _T('\0') ) + break; + + y += heightLine; + + curLine.clear(); + } + else // not end of line + { + if ( pc - text == indexAccel ) + { + // remeber to draw underscore here + GetTextExtent(curLine, &startUnderscore, NULL); + curLine += *pc; + GetTextExtent(curLine, &endUnderscore, NULL); + + yUnderscore = y + heightLine; + } + else + { + curLine += *pc; + } + } + } + + // draw the underscore if found + if ( startUnderscore != endUnderscore ) + { + // it should be of the same colour as text + SetPen(wxPen(GetTextForeground(), 0, wxSOLID)); + + yUnderscore--; + + DrawLine(x + startUnderscore, yUnderscore, + x + endUnderscore, yUnderscore); + } + + // return bounding rect if requested + if ( rectBounding ) + { + *rectBounding = wxRect(x, y, width, height); + } + + CalcBoundingBox(x, y); + CalcBoundingBox(x + width, y + height); +} diff --git a/src/common/wincmn.cpp b/src/common/wincmn.cpp index 51b6b12d1b..05a5a12d64 100644 --- a/src/common/wincmn.cpp +++ b/src/common/wincmn.cpp @@ -78,11 +78,6 @@ BEGIN_EVENT_TABLE(wxWindowBase, wxEvtHandler) EVT_SYS_COLOUR_CHANGED(wxWindowBase::OnSysColourChanged) EVT_INIT_DIALOG(wxWindowBase::OnInitDialog) EVT_MIDDLE_DOWN(wxWindowBase::OnMiddleClick) - -#ifdef __WXUNIVERSAL__ - EVT_PAINT(wxWindowBase::OnPaint) -#endif // __WXUNIVERSAL__ - END_EVENT_TABLE() // ============================================================================ diff --git a/src/gtk/statbox.cpp b/src/gtk/statbox.cpp index 7afc40103d..5758ed13ee 100644 --- a/src/gtk/statbox.cpp +++ b/src/gtk/statbox.cpp @@ -45,22 +45,22 @@ bool wxStaticBox::Create( wxWindow *parent, wxWindowID id, const wxString &label !CreateBase( parent, id, pos, size, style, wxDefaultValidator, name )) { wxFAIL_MSG( wxT("wxStaticBox creation failed") ); - return FALSE; + return FALSE; } m_isStaticBox = TRUE; - + if (label.IsEmpty()) m_widget = gtk_frame_new( (char*) NULL ); else m_widget = gtk_frame_new( m_label.mbc_str() ); m_parent->DoAddChild( this ); - + PostCreation(); SetLabel(label); - + SetFont( parent->GetFont() ); SetBackgroundColour( parent->GetBackgroundColour() ); @@ -84,4 +84,4 @@ void wxStaticBox::ApplyWidgetStyle() gtk_widget_set_style( m_widget, m_widgetStyle ); } -#endif +#endif // wxUSE_STATBOX diff --git a/src/gtk1/statbox.cpp b/src/gtk1/statbox.cpp index 7afc40103d..5758ed13ee 100644 --- a/src/gtk1/statbox.cpp +++ b/src/gtk1/statbox.cpp @@ -45,22 +45,22 @@ bool wxStaticBox::Create( wxWindow *parent, wxWindowID id, const wxString &label !CreateBase( parent, id, pos, size, style, wxDefaultValidator, name )) { wxFAIL_MSG( wxT("wxStaticBox creation failed") ); - return FALSE; + return FALSE; } m_isStaticBox = TRUE; - + if (label.IsEmpty()) m_widget = gtk_frame_new( (char*) NULL ); else m_widget = gtk_frame_new( m_label.mbc_str() ); m_parent->DoAddChild( this ); - + PostCreation(); SetLabel(label); - + SetFont( parent->GetFont() ); SetBackgroundColour( parent->GetBackgroundColour() ); @@ -84,4 +84,4 @@ void wxStaticBox::ApplyWidgetStyle() gtk_widget_set_style( m_widget, m_widgetStyle ); } -#endif +#endif // wxUSE_STATBOX diff --git a/src/msw/app.cpp b/src/msw/app.cpp index d994f7b343..cd32781e0b 100644 --- a/src/msw/app.cpp +++ b/src/msw/app.cpp @@ -837,6 +837,7 @@ wxApp::wxApp() m_printMode = wxPRINT_WINDOWS; m_exitOnFrameDelete = TRUE; m_auto3D = TRUE; + m_isActive = FALSE; } wxApp::~wxApp() diff --git a/src/msw/dc.cpp b/src/msw/dc.cpp index b9d10eac95..08d453bb50 100644 --- a/src/msw/dc.cpp +++ b/src/msw/dc.cpp @@ -1203,20 +1203,21 @@ void wxDC::DoGetTextExtent(const wxString& string, wxCoord *x, wxCoord *y, wxCoord *descent, wxCoord *externalLeading, wxFont *theFont) const { - wxFont *fontToUse = (wxFont*) theFont; - if (!fontToUse) - fontToUse = (wxFont*) &m_font; + wxFont *fontToUse = theFont ? theFont : (wxFont *)&m_font; + HGDIOBJ hfontOld = ::SelectObject(GetHdc(), GetHfontOf(*fontToUse)); SIZE sizeRect; TEXTMETRIC tm; - GetTextExtentPoint(GetHdc(), WXSTRINGCAST string, wxStrlen(WXSTRINGCAST string), &sizeRect); + GetTextExtentPoint(GetHdc(), string, string.length(), &sizeRect); GetTextMetrics(GetHdc(), &tm); if (x) *x = XDEV2LOGREL(sizeRect.cx); if (y) *y = YDEV2LOGREL(sizeRect.cy); if (descent) *descent = tm.tmDescent; if (externalLeading) *externalLeading = tm.tmExternalLeading; + + ::SelectObject(GetHdc(), hfontOld); } void wxDC::SetMapMode(int mode) diff --git a/src/msw/window.cpp b/src/msw/window.cpp index 50f3d5e42e..a646f0990d 100644 --- a/src/msw/window.cpp +++ b/src/msw/window.cpp @@ -169,9 +169,12 @@ wxWindow *wxWindow::FindItem(long id) const wxControl *item = wxDynamicCast(this, wxControl); if ( item ) { - // i it we or one of our "internal" children? - if ( item->GetId() == id || - (item->GetSubcontrols().Index(id) != wxNOT_FOUND) ) + // is it we or one of our "internal" children? + if ( item->GetId() == id +#ifndef __WXUNIVERSAL__ + || (item->GetSubcontrols().Index(id) != wxNOT_FOUND) +#endif // __WXUNIVERSAL__ + ) { return item; } @@ -313,7 +316,13 @@ bool wxWindow::Create(wxWindow *parent, wxWindowID id, parent->AddChild(this); - DWORD msflags = 0; + // all windows are created visible + DWORD msflags = WS_CHILD | WS_VISIBLE; + +#ifdef __WXUNIVERSAL__ + // no 3d effects, we draw them ourselves + WXDWORD exStyle = 0; +#else // !wxUniversal if ( style & wxBORDER ) msflags |= WS_BORDER; /* Not appropriate for non-frame/dialog windows, and @@ -321,8 +330,6 @@ bool wxWindow::Create(wxWindow *parent, wxWindowID id, if ( style & wxTHICK_FRAME ) msflags |= WS_THICKFRAME; */ - //msflags |= WS_CHILD /* | WS_CLIPSIBLINGS */ | WS_VISIBLE; - msflags |= WS_CHILD | WS_VISIBLE; if ( style & wxCLIP_CHILDREN ) msflags |= WS_CLIPCHILDREN; @@ -344,13 +351,12 @@ bool wxWindow::Create(wxWindow *parent, wxWindowID id, m_lDlgCode = DLGC_WANTARROWS | DLGC_WANTCHARS | DLGC_WANTTAB | DLGC_WANTMESSAGE; } +#endif // wxUniversal/!wxUniversal - MSWCreate(m_windowId, parent, wxCanvasClassName, this, NULL, - pos.x, pos.y, - WidthDefault(size.x), HeightDefault(size.y), - msflags, NULL, exStyle); - - return TRUE; + return MSWCreate(m_windowId, parent, wxCanvasClassName, this, NULL, + pos.x, pos.y, + WidthDefault(size.x), HeightDefault(size.y), + msflags, NULL, exStyle); } // --------------------------------------------------------------------------- @@ -1876,6 +1882,24 @@ long wxWindow::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam) processed = HandleSize(LOWORD(lParam), HIWORD(lParam), wParam); break; +#ifdef __WXUNIVERSAL__ + case WM_ACTIVATEAPP: + { + // refresh the focused window + static wxWindow *s_lastFocus = NULL; + wxTheApp->SetActive(wParam != 0); + if ( !wParam ) + { + // we're being de activated + s_lastFocus = FindFocus(); + } + + if ( s_lastFocus ) + s_lastFocus->Refresh(); + } + break; +#endif // __WXUNIVERSAL__ + case WM_ACTIVATE: { WXWORD state, minimized; @@ -2986,11 +3010,15 @@ bool wxWindow::HandlePaint() // Can be called from an application's OnPaint handler void wxWindow::OnPaint(wxPaintEvent& event) { +#ifdef __WXUNIVERSAL__ + event.Skip(); +#else HDC hDC = (HDC) wxPaintDC::FindDCInCache((wxWindow*) event.GetEventObject()); if (hDC != 0) { MSWDefWindowProc(WM_PAINT, (WPARAM) hDC, 0); } +#endif } bool wxWindow::HandleEraseBkgnd(WXHDC hdc) diff --git a/src/univ/button.cpp b/src/univ/button.cpp new file mode 100644 index 0000000000..1b9db532eb --- /dev/null +++ b/src/univ/button.cpp @@ -0,0 +1,126 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: univ/button.cpp +// Purpose: wxButton +// Author: Vadim Zeitlin +// Modified by: +// Created: 14.08.00 +// RCS-ID: $Id$ +// Copyright: (c) 2000 Vadim Zeitlin +// Licence: wxWindows license +///////////////////////////////////////////////////////////////////////////// + +// ============================================================================ +// declarations +// ============================================================================ + +// ---------------------------------------------------------------------------- +// headers +// ---------------------------------------------------------------------------- + +#ifdef __GNUG__ + #pragma implementation "univbutton.h" +#endif + +#include "wx/wxprec.h" + +#ifdef __BORLANDC__ + #pragma hdrstop +#endif + +#if wxUSE_STATTEXT + +#ifndef WX_PRECOMP + #include "wx/dc.h" + #include "wx/button.h" + #include "wx/validate.h" +#endif + +#include "wx/univ/renderer.h" +#include "wx/univ/theme.h" + +// ============================================================================ +// implementation +// ============================================================================ + +IMPLEMENT_DYNAMIC_CLASS(wxButton, wxControl) + +// ---------------------------------------------------------------------------- +// creation +// ---------------------------------------------------------------------------- + +void wxButton::Init() +{ + m_isPressed = + m_isDefault = FALSE; +} + +bool wxButton::Create(wxWindow *parent, + wxWindowID id, + const wxString &label, + const wxPoint &pos, + const wxSize &size, + long style, + const wxValidator& validator, + const wxString &name) +{ + // center label by default + if ( !(style & wxALIGN_MASK) ) + { + style |= wxALIGN_CENTRE | wxALIGN_CENTRE_VERTICAL; + } + + if ( !wxControl::Create(parent, id, pos, size, style, wxDefaultValidator, name) ) + return FALSE; + + SetLabel(label); + + if ( size.x == -1 || size.y == -1 ) + { + wxSize sizeBest = DoGetBestSize(); + SetSize(size.x == -1 ? sizeBest.x : size.x, + size.y == -1 ? sizeBest.y : size.y); + } + + return TRUE; +} + +wxButton::~wxButton() +{ +} + +// ---------------------------------------------------------------------------- +// size management +// ---------------------------------------------------------------------------- + +wxSize wxButton::DoGetBestSize() const +{ + wxClientDC dc(wxConstCast(this, wxButton)); + wxCoord width, height; + dc.GetMultiLineTextExtent(GetLabel(), &width, &height); + + wxSize sz(width, height); + wxTheme::Get()->GetRenderer()->AdjustSize(&sz, this); + return sz; +} + +// ---------------------------------------------------------------------------- +// drawing +// ---------------------------------------------------------------------------- + +void wxButton::DoDraw(wxControlRenderer *renderer) +{ + renderer->DrawButtonBorder(); + renderer->DrawLabel(); +} + +// ---------------------------------------------------------------------------- +// +// ---------------------------------------------------------------------------- + +void wxButton::SetDefault() +{ + m_isDefault = TRUE; +} + +#endif // wxUSE_STATTEXT + diff --git a/src/univ/control.cpp b/src/univ/control.cpp index 7df9b6fbc0..2a020b6a10 100644 --- a/src/univ/control.cpp +++ b/src/univ/control.cpp @@ -33,41 +33,87 @@ #include "wx/control.h" #endif +#include "wx/univ/renderer.h" +#include "wx/univ/theme.h" + // ============================================================================ // implementation // ============================================================================ IMPLEMENT_DYNAMIC_CLASS(wxControl, wxWindow) +BEGIN_EVENT_TABLE(wxControl, wxControlBase) + EVT_PAINT(wxControl::OnPaint) +END_EVENT_TABLE() + // ---------------------------------------------------------------------------- // creation // ---------------------------------------------------------------------------- wxControl::wxControl() { + m_indexAccel = -1; +} + +// ---------------------------------------------------------------------------- +// state flags +// ---------------------------------------------------------------------------- + +bool wxControl::IsFocused() const +{ + wxControl *self = wxConstCast(this, wxControl); + return self->FindFocus() == self; +} + +bool wxControl::IsPressed() const +{ + return FALSE; +} + +bool wxControl::IsDefault() const +{ + return FALSE; } // ---------------------------------------------------------------------------- // mnemonics handling // ---------------------------------------------------------------------------- -void wxControl::SetLabel( const wxString &label ) +void wxControl::SetLabel(const wxString& label) { // the character following MNEMONIC_PREFIX is the accelerator for this // control unless it is MNEMONIC_PREFIX too - this allows to insert // literal MNEMONIC_PREFIX chars into the label static const wxChar MNEMONIC_PREFIX = _T('&'); - m_label.Empty(); + wxString labelOld = m_label; + m_indexAccel = -1; + m_label.clear(); for ( const wxChar *pc = label; *pc != wxT('\0'); pc++ ) { if ( *pc == MNEMONIC_PREFIX ) { pc++; // skip it if ( *pc != MNEMONIC_PREFIX ) - m_chAccel = *pc; + { + if ( m_indexAccel == -1 ) + { + // remember it (-1 is for MNEMONIC_PREFIX itself + m_indexAccel = pc - label.c_str() - 1; + } + else + { + wxFAIL_MSG(_T("duplicate accel char in control label")); + } + } } - m_label << *pc; + + m_label += *pc; + } + + if ( m_label != labelOld ) + { + Refresh(); } } @@ -76,4 +122,24 @@ wxString wxControl::GetLabel() const return m_label; } +// ---------------------------------------------------------------------------- +// painting +// ---------------------------------------------------------------------------- + +// the event handler executed when the window must be repainted +void wxControl::OnPaint(wxPaintEvent& event) +{ + // get the DC to use and create renderer on it + wxPaintDC dc(this); + wxControlRenderer renderer(this, dc, wxTheme::Get()->GetRenderer()); + + // do draw the control! + DoDraw(&renderer); +} + +void wxControl::DoDraw(wxControlRenderer *renderer) +{ + renderer->DrawBorder(); +} + #endif // wxUSE_CONTROLS diff --git a/src/univ/renderer.cpp b/src/univ/renderer.cpp new file mode 100644 index 0000000000..b7ce110d10 --- /dev/null +++ b/src/univ/renderer.cpp @@ -0,0 +1,138 @@ +/////////////////////////////////////////////////////////////////////////////// +// Name: univ/renderer.cpp +// Purpose: wxControlRenderer implementation +// Author: Vadim Zeitlin +// Modified by: +// Created: 15.08.00 +// RCS-ID: $Id$ +// Copyright: (c) 2000 Vadim Zeitlin +// Licence: wxWindows license +/////////////////////////////////////////////////////////////////////////////// + +// =========================================================================== +// declarations +// =========================================================================== + +// --------------------------------------------------------------------------- +// headers +// --------------------------------------------------------------------------- + +#ifdef __GNUG__ + #pragma implementation "renderer.h" +#endif + +// For compilers that support precompilation, includes "wx.h". +#include "wx/wxprec.h" + +#ifdef __BORLANDC__ + #pragma hdrstop +#endif + +#ifndef WX_PRECOMP +#endif // WX_PRECOMP + +#include "wx/univ/renderer.h" + +// ============================================================================ +// implementation +// ============================================================================ + +// ---------------------------------------------------------------------------- +// wxControlRenderer +// ---------------------------------------------------------------------------- + +wxControlRenderer::wxControlRenderer(wxControl *control, + wxDC& dc, + wxRenderer *renderer) + : m_dc(dc) +{ + m_ctrl = control; + m_renderer = renderer; + + wxSize size = m_ctrl->GetSize(); + m_rect.x = + m_rect.y = 0; + m_rect.width = size.x; + m_rect.height = size.y; +} + +int wxControlRenderer::GetStateFlags() const +{ + int flags = 0; + if ( m_ctrl->IsEnabled() ) + flags |= wxRENDER_ENABLED; + + // the following states are only possible if our application is active - if + // it is not, even our default/focused controls shouldn't appear as such + if ( wxTheApp->IsActive() ) + { + if ( m_ctrl->IsFocused() ) + flags |= wxRENDER_FOCUSED; + if ( m_ctrl->IsPressed() ) + flags |= wxRENDER_PRESSED; + if ( m_ctrl->IsDefault() ) + flags |= wxRENDER_DEFAULT; + } + + return flags; +} + +void wxControlRenderer::PaintBackground() +{ + wxBrush brush(m_ctrl->GetBackgroundColour(), wxSOLID); + m_dc.SetBrush(brush); + m_dc.SetPen(*wxTRANSPARENT_PEN); + m_dc.DrawRectangle(m_rect); +} + +void wxControlRenderer::DrawBorder() +{ + // draw outline + m_renderer->DrawBorder(m_dc, m_ctrl->GetBorder(), + m_rect, GetStateFlags(), &m_rect); + + // fill the inside + PaintBackground(); +} + +void wxControlRenderer::DrawLabel() +{ + m_dc.SetFont(m_ctrl->GetFont()); + m_dc.SetTextForeground(m_ctrl->GetForegroundColour()); + + // shift the label if a button is pressed + wxRect rectLabel = m_rect; + if ( GetStateFlags() & wxRENDER_PRESSED ) + { + rectLabel.x++; + rectLabel.y++; + } + + m_renderer->DrawLabel(m_dc, + m_ctrl->GetLabel(), + rectLabel, + GetStateFlags(), + m_ctrl->GetAlignment(), + m_ctrl->GetAccelIndex()); +} + +void wxControlRenderer::DrawFrame() +{ + m_dc.SetFont(m_ctrl->GetFont()); + m_dc.SetTextForeground(m_ctrl->GetForegroundColour()); + m_dc.SetTextBackground(m_ctrl->GetBackgroundColour()); + + m_renderer->DrawFrame(m_dc, + m_ctrl->GetLabel(), + m_rect, + GetStateFlags(), + m_ctrl->GetAlignment(), + m_ctrl->GetAccelIndex()); +} + +void wxControlRenderer::DrawButtonBorder() +{ + m_renderer->DrawButtonBorder(m_dc, m_rect, GetStateFlags(), &m_rect); + + PaintBackground(); +} diff --git a/src/univ/statbox.cpp b/src/univ/statbox.cpp new file mode 100644 index 0000000000..542d929a62 --- /dev/null +++ b/src/univ/statbox.cpp @@ -0,0 +1,74 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: univ/statbox.cpp +// Purpose: wxStaticBox implementation +// Author: Vadim Zeitlin +// Modified by: +// Created: 15.08.00 +// RCS-ID: $Id$ +// Copyright: (c) 2000 Vadim Zeitlin +// Licence: wxWindows license +///////////////////////////////////////////////////////////////////////////// + +// ============================================================================ +// declarations +// ============================================================================ + +// ---------------------------------------------------------------------------- +// headers +// ---------------------------------------------------------------------------- + +#ifdef __GNUG__ + #pragma implementation "univstatbox.h" +#endif + +#include "wx/wxprec.h" + +#ifdef __BORLANDC__ + #pragma hdrstop +#endif + +#if wxUSE_STATTEXT + +#ifndef WX_PRECOMP + #include "wx/dc.h" + #include "wx/statbox.h" + #include "wx/validate.h" +#endif + +#include "wx/univ/renderer.h" + +// ============================================================================ +// implementation +// ============================================================================ + +IMPLEMENT_DYNAMIC_CLASS(wxStaticBox, wxControl) + +// ---------------------------------------------------------------------------- +// wxStaticBox +// ---------------------------------------------------------------------------- + +bool wxStaticBox::Create(wxWindow *parent, + wxWindowID id, + const wxString &label, + const wxPoint &pos, + const wxSize &size, + long style, + const wxString &name) +{ + if ( !wxControl::Create(parent, id, pos, size, style, wxDefaultValidator, name) ) + return FALSE; + + SetLabel(label); + + return TRUE; +} + +void wxStaticBox::DoDraw(wxControlRenderer *renderer) +{ + // we never have a border, so don't call the base class version whcih draws + // it + renderer->DrawFrame(); +} + +#endif // wxUSE_STATTEXT + diff --git a/src/univ/stattext.cpp b/src/univ/stattext.cpp index 5293eaa4e1..003c654e15 100644 --- a/src/univ/stattext.cpp +++ b/src/univ/stattext.cpp @@ -18,7 +18,7 @@ // ---------------------------------------------------------------------------- #ifdef __GNUG__ - #pragma implementation "stattext.h" + #pragma implementation "univstattext.h" #endif #include "wx/wxprec.h" @@ -35,6 +35,9 @@ #include "wx/validate.h" #endif +#include "wx/univ/renderer.h" +#include "wx/univ/theme.h" + // ============================================================================ // implementation // ============================================================================ @@ -47,7 +50,7 @@ bool wxStaticText::Create(wxWindow *parent, wxWindowID id, const wxString &label, const wxPoint &pos, - const wxSize &size, + const wxSize &size, long style, const wxString &name) { @@ -70,86 +73,31 @@ bool wxStaticText::Create(wxWindow *parent, // size management // ---------------------------------------------------------------------------- +void wxStaticText::SetLabel(const wxString& label) +{ + wxControl::SetLabel(label); +} + wxSize wxStaticText::DoGetBestSize() const { - wxString text = GetLabel(); + wxClientDC dc(wxConstCast(this, wxStaticText)); + wxCoord width, height; + dc.GetMultiLineTextExtent(GetLabel(), &width, &height); - int widthTextMax = 0, widthLine, - heightTextTotal = 0, heightLineDefault = 0, heightLine = 0; - - wxString curLine; - for ( const wxChar *pc = text; ; pc++ ) { - if ( *pc == _T('\n') || *pc == _T('\0') ) { - if ( !curLine ) { - // we can't use GetTextExtent - it will return 0 for both width - // and height and an empty line should count in height - // calculation - if ( !heightLineDefault ) - heightLineDefault = heightLine; - if ( !heightLineDefault ) - GetTextExtent(_T("W"), NULL, &heightLineDefault); - - heightTextTotal += heightLineDefault; - } - else { - GetTextExtent(curLine, &widthLine, &heightLine); - if ( widthLine > widthTextMax ) - widthTextMax = widthLine; - heightTextTotal += heightLine; - } - - if ( *pc == _T('\n') ) { - curLine.Empty(); - } - else { - // the end of string - break; - } - } - else { - curLine += *pc; - } - } - - return wxSize(widthTextMax, heightTextTotal); + wxSize sz(width, height); + wxTheme::Get()->GetRenderer()->AdjustSize(&sz, this); + return sz; } // ---------------------------------------------------------------------------- // drawing // ---------------------------------------------------------------------------- -void wxStaticText::DoDraw(wxDC& dc, wxRenderer *renderer) +void wxStaticText::DoDraw(wxControlRenderer *renderer) { - // get the position of the label start - const wxString text = GetLabel(); + wxControl::DoDraw(renderer); - wxCoord heightLine; - dc.GetTextExtent(text[0u], NULL, &heightLine); - - wxCoord x = 0, - y = heightLine; - - // split the string into lines and draw each of them separately - wxString curLine; - for ( const wxChar *pc = text; ; pc++ ) - { - if ( *pc == _T('\n') || *pc == _T('\0') ) - { - if ( !curLine.empty() ) - { - dc.DrawText(curLine, x, y); - } - - if ( *pc == _T('\0') ) - break; - - y += heightLine; - } - else - { - curLine += *pc; - } - } + renderer->DrawLabel(); } #endif // wxUSE_STATTEXT diff --git a/src/univ/theme.cpp b/src/univ/theme.cpp index 6a03e17186..5ef926ff66 100644 --- a/src/univ/theme.cpp +++ b/src/univ/theme.cpp @@ -29,55 +29,74 @@ #endif #ifndef WX_PRECOMP - #include "wx/univ/renderer.h" - #include "wx/univ/theme.h" #endif // WX_PRECOMP -// ---------------------------------------------------------------------------- -// dummy theme class -// ---------------------------------------------------------------------------- - -class wxDummyRenderer : public wxRenderer -{ -public: - virtual void DrawLabel(wxDC& dc, wxWindow *window) { } - virtual void DrawBorder(wxDC& dc, wxWindow *window) { } -}; - -class wxDummyTheme : public wxTheme -{ -public: - wxDummyTheme() - { - m_renderer = new wxDummyRenderer; - } - - virtual ~wxDummyTheme() - { - delete m_renderer; - } - - virtual wxRenderer *GetRenderer() { return m_renderer; } - virtual wxInputHandler *GetInputHandler() { return NULL; } - virtual wxColourScheme *GetColourScheme() { return NULL; } - -private: - wxDummyRenderer *m_renderer; -}; +#include "wx/univ/renderer.h" +#include "wx/univ/theme.h" // ============================================================================ // implementation // ============================================================================ +wxTheme::wxThemeInfo *wxTheme::ms_allThemes = (wxTheme::wxThemeInfo *)NULL; +wxTheme *wxTheme::ms_theme = (wxTheme *)NULL; + // ---------------------------------------------------------------------------- -// creation of the default theme (called by wxApp::OnInitGui) +// "dynamic" theme creation // ---------------------------------------------------------------------------- -wxTheme *wxTheme::ms_theme = (wxTheme *)NULL; +wxTheme::wxThemeInfo::wxThemeInfo(wxTheme::Constructor c, + const wxChar *n, + const wxChar *d) + : ctor(c), name(n), desc(d) +{ + // insert us (in the head of) the linked list + next = ms_allThemes; + ms_allThemes = this; +} + +/* static */ wxTheme *wxTheme::Create(const wxString& name) +{ + // find the theme in the list by name + wxThemeInfo *info = ms_allThemes; + while ( info ) + { + if ( name == info->name ) + { + return info->ctor(); + } + + info = info->next; + } + + return (wxTheme *)NULL; +} + +// ---------------------------------------------------------------------------- +// the default theme (called by wxApp::OnInitGui) +// ---------------------------------------------------------------------------- /* static */ bool wxTheme::CreateDefault() { - ms_theme = new wxDummyTheme; + wxCHECK_MSG( !ms_theme, TRUE, _T("we already have a theme") ); + +#if defined(__WXMSW__) + ms_theme = Create(_T("win32")); +#endif + + // fallback to the first one in the list + if ( !ms_theme && ms_allThemes ) + { + ms_theme = ms_allThemes->ctor(); + } + + // abort if still nothing + if ( !ms_theme ) + { + wxLogError(_("Failed to initialize GUI: no built-in themes found.")); + + return FALSE; + } return TRUE; } diff --git a/src/univ/themes/win32.cpp b/src/univ/themes/win32.cpp index fe3e1a67a2..3e45374dc4 100644 --- a/src/univ/themes/win32.cpp +++ b/src/univ/themes/win32.cpp @@ -25,8 +25,14 @@ #endif #ifndef WX_PRECOMP + #include "wx/intl.h" + #include "wx/dc.h" + #include "wx/window.h" #endif // WX_PRECOMP +#include "wx/univ/renderer.h" +#include "wx/univ/theme.h" + // ---------------------------------------------------------------------------- // private classes // ---------------------------------------------------------------------------- @@ -34,27 +40,65 @@ class wxWin32Renderer : public wxRenderer { public: + wxWin32Renderer(); + // implement the base class pure virtuals - virtual void DrawLabel(wxDC& dc, wxWindow *window); - virtual void DrawBorder(wxDC& dc, wxWindow *window); + virtual void DrawLabel(wxDC& dc, + const wxString& label, + const wxRect& rect, + int flags = wxRENDER_ENABLED, + int alignment = wxALIGN_LEFT | wxALIGN_TOP, + int indexAccel = -1); + virtual void DrawBorder(wxDC& dc, + wxBorder border, + const wxRect& rect, + int flags = wxRENDER_ENABLED, + wxRect *rectIn = (wxRect *)NULL); + virtual void DrawFrame(wxDC& dc, + const wxString& label, + const wxRect& rect, + int flags = wxRENDER_ENABLED, + int alignment = wxALIGN_LEFT, + int indexAccel = -1); + virtual void DrawButtonBorder(wxDC& dc, + const wxRect& rect, + int flags = wxRENDER_ENABLED, + wxRect *rectIn = (wxRect *)NULL); + + virtual void AdjustSize(wxSize *size, const wxWindow *window); protected: // DrawBorder() helpers: all of them shift and clip the DC after drawing // the border // just draw a rectangle with the given pen - void DrawRect(wxDC& dc, wxCoord x, wxCoord y, const wxPen& pen); + void DrawRect(wxDC& dc, wxRect *rect, const wxPen& pen); // draw the lower left part of rectangle - void DrawHalfRect(wxDC& dc, wxCoord x, wxCoord y, const wxPen& pen); + void DrawHalfRect(wxDC& dc, wxRect *rect, const wxPen& pen); // draw the rectange using the first brush for the left and top sides and // the second one for the bottom and right ones - void DrawShadedRect(wxDC& dc, wxCoord x, wxCoord y, + void DrawShadedRect(wxDC& dc, wxRect *rect, const wxPen& pen1, const wxPen& pen2); // draw the normal 3D border - void DrawRaisedBorder(wxDC& dc, wxCoord x, wxCoord y); + void DrawRaisedBorder(wxDC& dc, wxRect *rect); + +private: + wxPen m_penBlack, + m_penDarkGrey, + m_penLightGrey, + m_penWhite, + m_penHighlight; +}; + +class wxWin32InputHandler : public wxInputHandler +{ +}; + +class wxWin32ColourScheme : public wxColourScheme +{ }; class wxWin32Theme : public wxTheme @@ -70,12 +114,16 @@ private: wxWin32Renderer *m_renderer; wxWin32InputHandler *m_handler; wxWin32ColourScheme *m_scheme; + + WX_DECLARE_THEME(); }; // ============================================================================ // implementation // ============================================================================ +WX_IMPLEMENT_THEME(wxWin32Theme, win32, wxTRANSLATE("Win32 theme")); + // ---------------------------------------------------------------------------- // wxWin32Theme // ---------------------------------------------------------------------------- @@ -83,47 +131,57 @@ private: wxWin32Theme::wxWin32Theme() { m_renderer = new wxWin32Renderer; + m_handler = NULL; + m_scheme = NULL; } // ---------------------------------------------------------------------------- // wxWin32Renderer // ---------------------------------------------------------------------------- +// ---------------------------------------------------------------------------- // construction +// ---------------------------------------------------------------------------- + wxWin32Renderer::wxWin32Renderer() + : m_penBlack(*wxBLACK_PEN), + m_penDarkGrey(wxColour(0x7f7f7f), 0, wxSOLID), + m_penLightGrey(wxColour(0xc0c0c0), 0, wxSOLID), + m_penWhite(*wxWHITE_PEN), + m_penHighlight(wxColour(0xe0e0e0), 0, wxSOLID) { - m_penBlack = new wxPen("BLACK"); - m_penDarkGrey = new wxPen("GREY"); - m_penLightGrey = new wxPen("LIGHT GREY"); - m_penWhite = new wxPen("WHITE"); } -/* - The normal (== raised) border in Win32 looks like this: +// ---------------------------------------------------------------------------- +// border stuff +// ---------------------------------------------------------------------------- - WWWWWWWWWWWWWWWWWWWWWWB - W GB - W GB W = white (HILIGHT) - W GB H = light grey (LIGHT) - W GB G = dark grey (SHADOW) - W GB B = black (DKSHADOW) - W GB - W GB - WGGGGGGGGGGGGGGGGGGGGGB +/* + The raised border in Win32 looks like this: + + IIIIIIIIIIIIIIIIIIIIIIB + I GB + I GB I = white (HILIGHT) + I GB H = light grey (LIGHT) + I GB G = dark grey (SHADOI) + I GB B = black (DKSHADOI) + I GB I = hIghlight (COLOR_3DHILIGHT) + I GB + IGGGGGGGGGGGGGGGGGGGGGB BBBBBBBBBBBBBBBBBBBBBBB The sunken border looks like this: - GGGGGGGGGGGGGGGGGGGGGGW - GBBBBBBBBBBBBBBBBBBBBHW - GB HW - GB HW - GB HW - GB HW - GB HW - GB HW - GHHHHHHHHHHHHHHHHHHHHHW - WWWWWWWWWWWWWWWWWWWWWWW + GGGGGGGGGGGGGGGGGGGGGGI + GBBBBBBBBBBBBBBBBBBBBHI + GB HI + GB HI + GB HI + GB HI + GB HI + GB HI + GHHHHHHHHHHHHHHHHHHHHHI + IIIIIIIIIIIIIIIIIIIIIII The static border (used for the controls which don't get focus) is like this: @@ -165,81 +223,297 @@ wxWin32Renderer::wxWin32Renderer() BBBBBBBBBBBBBBBBBBBBBBB */ -void wxWin32Renderer::DrawRect(wxDC& dc, wxCorod x, wxCoord y, const wxPen& pen) +void wxWin32Renderer::DrawRect(wxDC& dc, wxRect *rect, const wxPen& pen) { // draw dc.SetPen(pen); - dc.DrawRectangle(0, 0, x, y); + dc.SetBrush(*wxTRANSPARENT_BRUSH); + dc.DrawRectangle(*rect); - // adjust - dc.SetLogicalOrigin(1, 1); - dc.SetClippingRegion(0, 0, x - 1, y - 1); + // adjust the rect + rect->Inflate(-1); } -void wxWin32Renderer::DrawHalfRect(wxDC& dc, wxCorod x, wxCoord y, - const wxPen& pen) +void wxWin32Renderer::DrawHalfRect(wxDC& dc, wxRect *rect, const wxPen& pen) { // draw the bottom and right sides dc.SetPen(pen); - dc.DrawLine(1, y, x, y); - dc.DrawLine(x, 0, x, y - 1); + dc.DrawLine(rect->GetLeft(), rect->GetBottom(), + rect->GetRight() + 1, rect->GetBottom()); + dc.DrawLine(rect->GetRight(), rect->GetTop(), + rect->GetRight(), rect->GetBottom()); - // clip the DC - dc.SetClippingRegion(0, 0, x - 1, y - 1); + // adjust the rect + rect->width--; + rect->height--; } -void wxWin32Renderer::DrawShadedRect(wxDC& dc, wxCorod x, wxCoord y, +void wxWin32Renderer::DrawShadedRect(wxDC& dc, wxRect *rect, const wxPen& pen1, const wxPen& pen2) { // draw the rectangle dc.SetPen(pen1); - dc.DrawLine(0, 0, 0, y - 1); - dc.DrawLine(1, 0, x - 1, 0); + dc.DrawLine(rect->GetLeft(), rect->GetTop(), + rect->GetLeft(), rect->GetBottom()); + dc.DrawLine(rect->GetLeft() + 1, rect->GetTop(), + rect->GetRight(), rect->GetTop()); dc.SetPen(pen2); - dc.DrawLine(x, 0, x, y); - dc.DrawLine(0, y, x - 1, y); + dc.DrawLine(rect->GetRight(), rect->GetTop(), + rect->GetRight(), rect->GetBottom()); + dc.DrawLine(rect->GetLeft(), rect->GetBottom(), + rect->GetRight() + 1, rect->GetBottom()); - // shift the DC and clip it - dc.SetLogicalOrigin(1, 1); - dc.SetClippingRegion(0, 0, x - 1, y - 1); + // adjust the rect + rect->Inflate(-1); } -void wxWin32Renderer::DrawRaisedBorder(wxDC& dc, wxCoord x, wxCoord y) +void wxWin32Renderer::DrawRaisedBorder(wxDC& dc, wxRect *rect) { - DrawShadedRect(dc, x--, y--, m_penWhite, m_penBlack); - DrawHalfRect(dc, x, y, m_penDarkGrey); + DrawShadedRect(dc, rect, m_penHighlight, m_penBlack); + DrawShadedRect(dc, rect, m_penLightGrey, m_penDarkGrey); } -void wxWin32Renderer::DrawBorder(wxDC& dc, wxWindow *window) +void wxWin32Renderer::DrawBorder(wxDC& dc, + wxBorder border, + const wxRect& rectTotal, + int WXUNUSED(flags), + wxRect *rectIn) { - wxCoord x, y; - window->GetClientSize(&x, &y); - long style = window->GetWindowStyle(); - if ( style & wxSUNKEN_BORDER ) + wxRect rect = rectTotal; + + switch ( border ) { - DrawShadedRect(dc, x--, y--, m_penDarkGrey, m_penWhite); - DrawShadedRect(dc, x, y, m_penBlack, m_penLightGrey); + case wxBORDER_SUNKEN: + DrawShadedRect(dc, &rect, m_penDarkGrey, m_penHighlight); + DrawShadedRect(dc, &rect, m_penBlack, m_penLightGrey); + break; + + case wxBORDER_STATIC: + DrawShadedRect(dc, &rect, m_penDarkGrey, m_penHighlight); + break; + + case wxBORDER_RAISED: + DrawRaisedBorder(dc, &rect); + break; + + case wxBORDER_DOUBLE: + DrawShadedRect(dc, &rect, m_penLightGrey, m_penBlack); + DrawShadedRect(dc, &rect, m_penHighlight, m_penDarkGrey); + DrawRect(dc, &rect, m_penLightGrey); + break; + + case wxBORDER_SIMPLE: + DrawRect(dc, &rect, m_penBlack); + break; + + default: + wxFAIL_MSG(_T("unknwon border type")); + // fall through + + case wxBORDER_DEFAULT: + case wxBORDER_NONE: + break; } - else if ( style & wxSTATIC_BORDER ) + + if ( rectIn ) + *rectIn = rect; +} + +// ---------------------------------------------------------------------------- +// button border +// ---------------------------------------------------------------------------- + +void wxWin32Renderer::DrawButtonBorder(wxDC& dc, + const wxRect& rectTotal, + int flags, + wxRect *rectIn) +{ + wxRect rect = rectTotal; + + if ( flags & wxRENDER_PRESSED ) { - DrawShadedRect(dc, x, y, m_penDarkGrey, m_penWhite); + // button pressed: draw a double border around it + DrawRect(dc, &rect, m_penBlack); + DrawRect(dc, &rect, m_penDarkGrey); } - else if ( style & wxRAISED_BORDER ) + else { - DrawRaisedBorder(dc, x, y); + // button not pressed + + if ( flags & (wxRENDER_FOCUSED | wxRENDER_DEFAULT) ) + { + // button either default or focused (or both): add an extra border around it + DrawRect(dc, &rect, m_penBlack); + } + + // now draw a normal button + DrawShadedRect(dc, &rect, m_penHighlight, m_penBlack); + DrawHalfRect(dc, &rect, m_penDarkGrey); } - else if ( style & wxDOUBLE_BORDER ) + + if ( rectIn ) { - DrawShadedRect(dc, x--, y--, m_penLightGrey, m_penBlack); - DrawShadedRect(dc, x--, y--, m_penWhite, m_penDarkGrey); - DrawRect(dc, x, y, m_penLightGrey); - } - else if ( style & wxSIMPLE_BORDER ) - { - DrawRect(dc, x, y, m_penBlack); + *rectIn = rect; } } -void wxWin32Renderer::DrawLabel(wxDC& dc, wxWindow *window) +// ---------------------------------------------------------------------------- +// frame +// ---------------------------------------------------------------------------- + +void wxWin32Renderer::DrawFrame(wxDC& dc, + const wxString& label, + const wxRect& rect, + int flags, + int alignment, + int indexAccel) { + wxCoord height = 0; // of the label + wxRect rectFrame = rect; + if ( !label.empty() ) + { + // the text should touch the top border of the rect, so the frame + // itself should be lower + dc.GetTextExtent(label, NULL, &height); + rectFrame.y += height / 2; + rectFrame.height -= height / 2; + } + + // draw the frame + DrawShadedRect(dc, &rectFrame, m_penDarkGrey, m_penHighlight); + DrawShadedRect(dc, &rectFrame, m_penHighlight, m_penDarkGrey); + + // and overwrite it with label (if any) + if ( !label.empty() ) + { + // TODO: the +5 and space insertion should be customizable + + wxRect rectText; + rectText.x = rectFrame.x + 5; + rectText.y = rect.y; + rectText.width = rectFrame.width - 7; // +2 border width + rectText.height = height; + + wxString label2; + label2 << _T(' ') << label << _T(' '); + if ( indexAccel != -1 ) + { + // adjust it as we prepended a space + indexAccel++; + } + + dc.SetBackgroundMode(wxSOLID); + DrawLabel(dc, label2, rectText, flags, alignment, indexAccel); + dc.SetBackgroundMode(wxTRANSPARENT); + } +} + +// ---------------------------------------------------------------------------- +// label +// ---------------------------------------------------------------------------- + +void wxWin32Renderer::DrawLabel(wxDC& dc, + const wxString& label, + const wxRect& rect, + int flags, + int alignment, + int indexAccel) +{ + if ( !(flags & wxRENDER_ENABLED) ) + { + // make the text grey and draw a shade for it + dc.SetTextForeground(0xe0e0e0); + wxRect rectShadow = rect; + rectShadow.x++; + rectShadow.y++; + dc.DrawLabel(label, rectShadow, alignment, indexAccel); + dc.SetTextForeground(0x7f7f7f); + } + + wxRect rectText = rect; + if ( flags & wxRENDER_FOCUSED ) + { + rectText.Inflate(-2); + } + + dc.DrawLabel(label, rectText, alignment, indexAccel); + + if ( flags & wxRENDER_FOCUSED ) + { + // VZ: this doesn't work under Windows, the dotted pen has dots of 3 + // pixels each while we really need dots here... PS_ALTERNATE might + // work, but it is for NT 5 only +#if 0 + DrawRect(dc, &rectText, wxPen(*wxBLACK, 0, wxDOT)); +#else + // draw the pixels manually + dc.SetPen(wxPen(*wxBLACK, 0, wxSOLID)); + + // Windows quirk: appears to draw them like this, from right to left + // (and I don't have Hebrew windows to see what happens there) + for ( wxCoord x = rectText.GetRight(); x >= rectText.GetLeft(); x -= 2 ) + { + dc.DrawPoint(x, rectText.GetTop()); + dc.DrawPoint(x, rectText.GetBottom()); + } + + wxCoord shift = rectText.width % 2 ? 0 : 1; + for ( wxCoord y = rectText.GetTop() + 2; y <= rectText.GetBottom(); y+= 2 ) + { + dc.DrawPoint(rectText.GetLeft(), y - shift); + dc.DrawPoint(rectText.GetRight(), y); + } + + if ( shift ) + { + dc.DrawPoint(rectText.GetLeft(), rectText.GetBottom() - 1); + } +#endif // 0/1 + } +} + +// ---------------------------------------------------------------------------- +// size adjustments +// ---------------------------------------------------------------------------- + +void wxWin32Renderer::AdjustSize(wxSize *size, const wxWindow *window) +{ + if ( wxDynamicCast(window, wxButton) ) + { + // TODO + size->x += 3*window->GetCharWidth(); + size->y = (11*(window->GetCharHeight() + 8))/10; + } + else + { + // take into account the border width + wxBorder border = (wxBorder)(window->GetWindowStyle() & wxBORDER_MASK); + switch ( border ) + { + case wxBORDER_SUNKEN: + case wxBORDER_RAISED: + size->x += 2; + size->y += 2; + break; + + case wxBORDER_SIMPLE: + case wxBORDER_STATIC: + size->x++; + size->y++; + break; + + case wxBORDER_DOUBLE: + size->x += 3; + size->y += 3; + break; + + default: + wxFAIL_MSG(_T("unknwon border type")); + // fall through + + case wxBORDER_DEFAULT: + case wxBORDER_NONE: + break; + } + } } diff --git a/src/univ/winuniv.cpp b/src/univ/winuniv.cpp index a458c69f2d..ed4ab74d3a 100644 --- a/src/univ/winuniv.cpp +++ b/src/univ/winuniv.cpp @@ -33,11 +33,11 @@ #include "wx/dc.h" #include "wx/dcclient.h" #include "wx/event.h" - - #include "wx/univ/renderer.h" - #include "wx/univ/theme.h" #endif // WX_PRECOMP +#include "wx/univ/renderer.h" +#include "wx/univ/theme.h" + // ---------------------------------------------------------------------------- // macros // ---------------------------------------------------------------------------- @@ -57,7 +57,7 @@ void wxWindowBase::OnPaint(wxPaintEvent& event) { // get the renderer and the DC to use - wxRenderer *renderer = wxTheme::Get()->GetRenderer(); + wxWindowRenderer renderer = wxTheme::Get()->GetRenderer(); wxPaintDC dc(self); // draw the border @@ -70,7 +70,7 @@ void wxWindowBase::OnPaint(wxPaintEvent& event) // draw the border void wxWindowBase::DoDrawBorder(wxDC& dc, wxRenderer *renderer) { - if ( !(m_windowStyle & wxNO_BORDER) ) + if ( !IsTopLevel() && !(m_windowStyle & wxNO_BORDER) ) { renderer->DrawBorder(dc, self); }