diff --git a/include/wx/control.h b/include/wx/control.h index 5fe512055b..7d839ac9f5 100644 --- a/include/wx/control.h +++ b/include/wx/control.h @@ -41,6 +41,11 @@ public: const wxValidator& validator = wxDefaultValidator, const wxString& name = wxControlNameStr); + // set the background image + virtual void SetBackground(const wxBitmap& bitmap, + int alignment = wxALIGN_CENTRE, + wxStretch stretch = wxSTRETCH_NOT); + // simulates the event of given type (i.e. wxButton::Command() is just as // if the button was clicked) virtual void Command(wxCommandEvent &event); diff --git a/include/wx/defs.h b/include/wx/defs.h index 7cc01a240a..b09eeb241f 100644 --- a/include/wx/defs.h +++ b/include/wx/defs.h @@ -817,7 +817,8 @@ enum wxStretch wxSHRINK = 0x1000, wxGROW = 0x2000, wxEXPAND = wxGROW, - wxSHAPED = 0x4000 + wxSHAPED = 0x4000, + wxTILE = 0x8000 }; // border flags: the values are chosen for backwards compatibility diff --git a/include/wx/gtk/scrolbar.h b/include/wx/gtk/scrolbar.h index 612c37afae..ddc02ebe9e 100644 --- a/include/wx/gtk/scrolbar.h +++ b/include/wx/gtk/scrolbar.h @@ -4,7 +4,7 @@ // Author: Robert Roebling // Id: $Id$ // Copyright: (c) 1998 Robert Roebling -// Licence: wxWindows licence +// Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// @@ -17,31 +17,20 @@ #include "wx/defs.h" -#if wxUSE_SCROLLBAR - -#include "wx/object.h" -#include "wx/control.h" - //----------------------------------------------------------------------------- // classes //----------------------------------------------------------------------------- class wxScrollBar; -//----------------------------------------------------------------------------- -// global data -//----------------------------------------------------------------------------- - -extern const char *wxScrollBarNameStr; - //----------------------------------------------------------------------------- // wxScrollBar //----------------------------------------------------------------------------- -class wxScrollBar: public wxControl +class wxScrollBar: public wxScrollBarBase { public: - wxScrollBar() + wxScrollBar() { m_adjust = (GtkAdjustment *) NULL; m_oldPos = 0.0; } inline wxScrollBar( wxWindow *parent, wxWindowID id, const wxPoint& pos = wxDefaultPosition, @@ -69,7 +58,7 @@ public: // Backward compatibility // ---------------------- - + int GetValue(void) const; void SetValue( int viewStart ); void GetValues( int *viewStart, int *viewLength, int *objectLength, int *pageLength) const; @@ -81,18 +70,16 @@ public: // implementation // -------------- - + bool IsOwnGtkWindow( GdkWindow *window ); void ApplyWidgetStyle(); - + GtkAdjustment *m_adjust; float m_oldPos; - + private: DECLARE_DYNAMIC_CLASS(wxScrollBar) }; -#endif - #endif // __GTKSCROLLBARH__ diff --git a/include/wx/gtk1/scrolbar.h b/include/wx/gtk1/scrolbar.h index 612c37afae..ddc02ebe9e 100644 --- a/include/wx/gtk1/scrolbar.h +++ b/include/wx/gtk1/scrolbar.h @@ -4,7 +4,7 @@ // Author: Robert Roebling // Id: $Id$ // Copyright: (c) 1998 Robert Roebling -// Licence: wxWindows licence +// Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// @@ -17,31 +17,20 @@ #include "wx/defs.h" -#if wxUSE_SCROLLBAR - -#include "wx/object.h" -#include "wx/control.h" - //----------------------------------------------------------------------------- // classes //----------------------------------------------------------------------------- class wxScrollBar; -//----------------------------------------------------------------------------- -// global data -//----------------------------------------------------------------------------- - -extern const char *wxScrollBarNameStr; - //----------------------------------------------------------------------------- // wxScrollBar //----------------------------------------------------------------------------- -class wxScrollBar: public wxControl +class wxScrollBar: public wxScrollBarBase { public: - wxScrollBar() + wxScrollBar() { m_adjust = (GtkAdjustment *) NULL; m_oldPos = 0.0; } inline wxScrollBar( wxWindow *parent, wxWindowID id, const wxPoint& pos = wxDefaultPosition, @@ -69,7 +58,7 @@ public: // Backward compatibility // ---------------------- - + int GetValue(void) const; void SetValue( int viewStart ); void GetValues( int *viewStart, int *viewLength, int *objectLength, int *pageLength) const; @@ -81,18 +70,16 @@ public: // implementation // -------------- - + bool IsOwnGtkWindow( GdkWindow *window ); void ApplyWidgetStyle(); - + GtkAdjustment *m_adjust; float m_oldPos; - + private: DECLARE_DYNAMIC_CLASS(wxScrollBar) }; -#endif - #endif // __GTKSCROLLBARH__ diff --git a/include/wx/msw/scrolbar.h b/include/wx/msw/scrolbar.h index ace2c1704c..bf601b2883 100644 --- a/include/wx/msw/scrolbar.h +++ b/include/wx/msw/scrolbar.h @@ -16,14 +16,8 @@ #pragma interface "scrolbar.h" #endif -#if wxUSE_SCROLLBAR - -#include "wx/control.h" - -WXDLLEXPORT_DATA(extern const wxChar*) wxScrollBarNameStr; - // Scrollbar item -class WXDLLEXPORT wxScrollBar: public wxControl +class WXDLLEXPORT wxScrollBar: public wxScrollBarBase { DECLARE_DYNAMIC_CLASS(wxScrollBar) @@ -89,7 +83,5 @@ protected: DECLARE_EVENT_TABLE() }; -#endif // wxUSE_SCROLLBAR - #endif // _WX_SCROLBAR_H_ diff --git a/include/wx/scrolbar.h b/include/wx/scrolbar.h index 301291e7b2..4630c70054 100644 --- a/include/wx/scrolbar.h +++ b/include/wx/scrolbar.h @@ -1,21 +1,60 @@ #ifndef _WX_SCROLBAR_H_BASE_ #define _WX_SCROLBAR_H_BASE_ +#if wxUSE_SCROLLBAR + +#include "wx/control.h" + +WXDLLEXPORT_DATA(extern const wxChar*) wxScrollBarNameStr; + +// ---------------------------------------------------------------------------- +// wxScrollBar: a scroll bar control +// ---------------------------------------------------------------------------- + +class WXDLLEXPORT wxScrollBarBase : public wxControl +{ +public: + // scrollbar construction + bool Create(wxWindow *parent, + wxWindowID id, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = wxSB_HORIZONTAL, + const wxValidator& validator = wxDefaultValidator, + const wxString& name = wxScrollBarNameStr); + + // accessors + virtual int GetThumbPosition() const = 0; + virtual int GetThumbSize() const = 0; + virtual int GetPageSize() const = 0; + virtual int GetRange() const = 0; + + // operations + virtual void SetThumbPosition(int viewStart) = 0; + virtual void SetScrollbar(int position, int thumbSize, + int range, int pageSize, + bool refresh = TRUE) = 0; +}; + #if defined(__WXMSW__) -#include "wx/msw/scrolbar.h" + #include "wx/univ/scrolbar.h" +#elif defined(__WXMSW__) + #include "wx/msw/scrolbar.h" #elif defined(__WXMOTIF__) -#include "wx/motif/scrolbar.h" + #include "wx/motif/scrolbar.h" #elif defined(__WXGTK__) -#include "wx/gtk/scrolbar.h" + #include "wx/gtk/scrolbar.h" #elif defined(__WXQT__) -#include "wx/qt/scrolbar.h" + #include "wx/qt/scrolbar.h" #elif defined(__WXMAC__) -#include "wx/mac/scrolbar.h" + #include "wx/mac/scrolbar.h" #elif defined(__WXPM__) -#include "wx/os2/scrolbar.h" + #include "wx/os2/scrolbar.h" #elif defined(__WXSTUBS__) -#include "wx/stubs/scrolbar.h" + #include "wx/stubs/scrolbar.h" #endif +#endif // wxUSE_SCROLLBAR + #endif // _WX_SCROLBAR_H_BASE_ diff --git a/include/wx/univ/button.h b/include/wx/univ/button.h index b51db4b7fd..4fb27e5f3a 100644 --- a/include/wx/univ/button.h +++ b/include/wx/univ/button.h @@ -31,6 +31,9 @@ class WXDLLEXPORT wxInputHandler; // wxButton: a push button // ---------------------------------------------------------------------------- +// class name +#define wxCONTROL_BUTTON _T("button") + class WXDLLEXPORT wxButton : public wxButtonBase { public: @@ -88,6 +91,5 @@ private: DECLARE_DYNAMIC_CLASS(wxButton) }; -#endif - // _WX_BUTTON_H_ +#endif // _WX_UNIV_BUTTON_H_ diff --git a/include/wx/univ/colschem.h b/include/wx/univ/colschem.h index 2608889e97..793c4dc30d 100644 --- a/include/wx/univ/colschem.h +++ b/include/wx/univ/colschem.h @@ -28,23 +28,30 @@ public: // the standard colours enum StdColour { - // these colours are used for drawing the shadows of 3D objects, use - // only FACE in the renderers which don't use 3D shading - DARK_SHADOW, - FACE, - HIGHLIGHT, - LIGHT, - SHADOW, - - // the default colours for the controls + // the background and text colour for the control + CONTROL, CONTROL_TEXT, + + // the background and text colour for the highlighted item HIGHLIGHT, HIGHLIGHT_TEXT, + // these colours are used for drawing the shadows of 3D objects, use + // only NORMAL in the renderers which don't use 3D shading + SHADOW_DARK, + SHADOW_HIGHLIGHT, + SHADOW_IN, + SHADOW_OUT, + MAX }; - virtual wxColour Get(StdColour col) = 0; + // get the colour for the control in the state (combination of + // wxCONTROL_XXX values) + virtual wxColour Get(StdColour col, int flags = 0) const = 0; + + // virtual dtor for any base class + virtual ~wxColourScheme(); }; // some people just can't spell it correctly :-) diff --git a/include/wx/univ/control.h b/include/wx/univ/control.h index 31f1e2eeb0..e4f8760106 100644 --- a/include/wx/univ/control.h +++ b/include/wx/univ/control.h @@ -19,6 +19,22 @@ class WXDLLEXPORT wxControlRenderer; class WXDLLEXPORT wxInputHandler; +// ---------------------------------------------------------------------------- +// constants +// ---------------------------------------------------------------------------- + +// control state flags used in wxRenderer and wxColourScheme +enum +{ + wxCONTROL_DISABLED = 0x00000001, // control is disabled + wxCONTROL_FOCUSED = 0x00000002, // currently has keyboard focus + wxCONTROL_PRESSED = 0x00000004, // (button) is pressed + wxCONTROL_ISDEFAULT = 0x00000008, // only applies to the buttons + wxCONTROL_CURRENT = 0x00000010, // mouse is currently over the control + + wxCONTROL_FLAGS_MASK = 0x0000001f +}; + // ---------------------------------------------------------------------------- // wxControlAction: the action is currently just a string which identifies it, // later it might become an atom (i.e. an opaque handler to string). As one @@ -59,6 +75,9 @@ public: // wxControl: the base class for all GUI controls // ---------------------------------------------------------------------------- +// class name +#define wxCONTROL_DEFAULT _T("") + class WXDLLEXPORT wxControl : public wxControlBase { public: @@ -88,12 +107,23 @@ public: virtual void SetLabel(const wxString &label); virtual wxString GetLabel() const; + // set/query the bg image + virtual void SetBackground(const wxBitmap& bitmap, + int alignment = wxALIGN_CENTRE, + wxStretch stretch = wxSTRETCH_NOT); + + const wxBitmap& GetBackgroundBitmap(int *alignment = NULL, + wxStretch *stretch = NULL) const; + // get the state information virtual bool IsFocused() const; virtual bool IsCurrent() const; virtual bool IsPressed() const; virtual bool IsDefault() const; + // return all state flags at once (combination of wxCONTROL_XXX values) + int GetStateFlags() const; + // operations void SetCurrent(bool doit = TRUE); @@ -113,6 +143,9 @@ protected: // action creates the default one which doesn't do anything virtual wxInputHandler *CreateInputHandler() const; + // draw the control background, return TRUE if done + virtual bool DoDrawBackground(wxControlRenderer *renderer); + // draw the controls contents virtual void DoDraw(wxControlRenderer *renderer); @@ -128,6 +161,7 @@ protected: void OnKeyUp(wxKeyEvent& event); void OnFocus(wxFocusEvent& event); void OnPaint(wxPaintEvent& event); + void OnErase(wxEraseEvent& event); private: // common part of all ctors @@ -139,10 +173,15 @@ private: // input processor wxInputHandler *m_handler; - // label with accel into + // label and accel info wxString m_label; int m_indexAccel; + // background bitmap info + wxBitmap m_bitmapBg; + int m_alignBgBitmap; + wxStretch m_stretchBgBitmap; + // state bool m_isCurrent; diff --git a/include/wx/univ/inphand.h b/include/wx/univ/inphand.h index c3ef5e68f2..d9801aa99a 100644 --- a/include/wx/univ/inphand.h +++ b/include/wx/univ/inphand.h @@ -37,11 +37,4 @@ public: virtual ~wxInputHandler(); }; -// ---------------------------------------------------------------------------- -// the control names which can be passed to wxTheme::GetInputHandler() -// ---------------------------------------------------------------------------- - -#define wxCONTROL_DEFAULT _T("control") -#define wxCONTROL_BUTTON _T("button") - #endif // _WX_UNIV_INPHAND_H_ diff --git a/include/wx/univ/renderer.h b/include/wx/univ/renderer.h index 7037afef63..cb0f1e0659 100644 --- a/include/wx/univ/renderer.h +++ b/include/wx/univ/renderer.h @@ -29,22 +29,6 @@ class WXDLLEXPORT wxWindow; #include "wx/string.h" #include "wx/gdicmn.h" -// ---------------------------------------------------------------------------- -// constants -// ---------------------------------------------------------------------------- - -// control state flags used in wxRenderer -enum -{ - wxRENDER_ENABLED = 0x00000001, - wxRENDER_FOCUSED = 0x00000002, // control currently has keyboard focus - wxRENDER_PRESSED = 0x00000004, - wxRENDER_DEFAULT = 0x00000008, // only applies to the buttons - wxRENDER_CURRENT = 0x00000010, // mouse is currently over the control - - wxRENDER_FLAGS_MASK = 0x0000001f -}; - // ---------------------------------------------------------------------------- // wxRenderer: abstract renderers interface // ---------------------------------------------------------------------------- @@ -63,7 +47,7 @@ public: virtual void DrawLabel(wxDC& dc, const wxString& label, const wxRect& rect, - int flags = wxRENDER_ENABLED, + int flags = 0, int alignment = wxALIGN_LEFT | wxALIGN_TOP, int indexAccel = -1) = 0; @@ -72,23 +56,38 @@ public: virtual void DrawBorder(wxDC& dc, wxBorder border, const wxRect& rect, - int flags = wxRENDER_ENABLED, + int flags = 0, 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, + int flags = 0, 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 flags = 0, int alignment = wxALIGN_LEFT, int indexAccel = -1) = 0; + // draw an arrow in the given direction + virtual void DrawArrow(wxDC& dc, + wxDirection dir, + const wxRect& rect, + int flags = 0) = 0; + + // draw a scrollbar: thumb positions are in percent of the full scrollbar + // length + virtual void DrawScrollbar(wxDC& dc, + wxOrientation orient, + int thumbPosStart, + int thumbPosEnd, + const wxRect& rect, + int flags = 0) = 0; + // TODO: having this is ugly but I don't see how to solve GetBestSize() // problem without something like this @@ -122,28 +121,41 @@ public: virtual void DrawLabel(wxDC& dc, const wxString& label, const wxRect& rect, - int flags = wxRENDER_ENABLED, + int flags = 0, 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, + int flags = 0, 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 flags = 0, 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, + int flags = 0, wxRect *rectIn = (wxRect *)NULL) { m_renderer->DrawButtonBorder(dc, rect, flags, rectIn); } + virtual void DrawArrow(wxDC& dc, + wxDirection dir, + const wxRect& rect, + int flags = 0) + { m_renderer->DrawArrow(dc, dir, rect, flags); } + virtual void DrawScrollbar(wxDC& dc, + wxOrientation orient, + int thumbPosStart, + int thumbPosEnd, + const wxRect& rect, + int flags = 0) + { m_renderer->DrawScrollbar(dc, orient, thumbPosStart, + thumbPosEnd, rect, flags); } virtual void AdjustSize(wxSize *size, const wxWindow *window) { m_renderer->AdjustSize(size, window); } @@ -168,6 +180,8 @@ public: void DrawBorder(); void DrawButtonBorder(); void DrawFrame(); + void DrawBackgroundBitmap(); + void DrawScrollbar(int thumbStart, int thumbEnd); // accessors wxRenderer *GetRenderer() const { return m_renderer; } @@ -177,10 +191,6 @@ public: const wxRect& GetRect() const { return m_rect; } wxRect& GetRect() { return m_rect; } -protected: - // the current window state - int GetStateFlags() const; - private: wxControl *m_ctrl; wxRenderer *m_renderer; diff --git a/include/wx/univ/scrolbar.h b/include/wx/univ/scrolbar.h new file mode 100644 index 0000000000..e8a3f6f404 --- /dev/null +++ b/include/wx/univ/scrolbar.h @@ -0,0 +1,112 @@ +/////////////////////////////////////////////////////////////////////////////// +// Name: wx/univ/scrolbar.h +// Purpose: wxScrollBar for wxUniversal +// Author: Vadim Zeitlin +// Modified by: +// Created: 20.08.00 +// RCS-ID: $Id$ +// Copyright: (c) 2000 Vadim Zeitlin +// Licence: wxWindows license +/////////////////////////////////////////////////////////////////////////////// + +#ifndef _WX_UNIV_SCROLBAR_H_ +#define _WX_UNIV_SCROLBAR_H_ + +#ifdef __GNUG__ + #pragma interface "univscrolbar.h" +#endif + +class WXDLLEXPORT wxInputHandler; + +// ---------------------------------------------------------------------------- +// the actions supported by this control +// ---------------------------------------------------------------------------- + +// scroll the bar +#define wxACTION_SCROLL_START _T("start") // to the beginning +#define wxACTION_SCROLL_END _T("end") // to the end +#define wxACTION_SCROLL_LINE_UP _T("lineup") // one line up/left +#define wxACTION_SCROLL_PAGE_UP _T("pageup") // one page up/left +#define wxACTION_SCROLL_LINE_DOWN _T("linedown") // one line down/right +#define wxACTION_SCROLL_PAGE_DOWN _T("pagedown") // one page down/right + +// the scrollbar thumb may be dragged +#define wxACTION_SCROLL_THUMB_DRAG _T("thumbdrag") +#define wxACTION_SCROLL_THUMB_MOVE _T("thumbmove") +#define wxACTION_SCROLL_THUMB_RELEASE _T("thumbrelease") + +// ---------------------------------------------------------------------------- +// wxScrollBar +// ---------------------------------------------------------------------------- + +// class name +#define wxCONTROL_SCROLLBAR _T("scrollbar") + +class WXDLLEXPORT wxScrollBar : public wxScrollBarBase +{ +public: + wxScrollBar() { Init(); } + wxScrollBar(wxWindow *parent, + wxWindowID id, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = wxSB_HORIZONTAL, + const wxValidator& validator = wxDefaultValidator, + const wxString& name = wxButtonNameStr) + { + Init(); + + Create(parent, id, pos, size, style, validator, name); + } + + bool Create(wxWindow *parent, + wxWindowID id, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = wxSB_HORIZONTAL, + const wxValidator& validator = wxDefaultValidator, + const wxString& name = wxButtonNameStr); + + virtual ~wxScrollBar(); + + // implementate base class pure virtuals + virtual int GetThumbPosition() const; + virtual int GetThumbSize() const; + virtual int GetPageSize() const; + virtual int GetRange() const; + + virtual void SetThumbPosition(int viewStart); + virtual void SetScrollbar(int position, int thumbSize, + int range, int pageSize, + bool refresh = TRUE); + + // wxScrollBar actions + +protected: + virtual wxInputHandler *CreateInputHandler() const; + virtual bool PerformAction(const wxControlAction& action, + const wxEvent& event); + virtual wxSize DoGetBestSize() const; + virtual void DoDraw(wxControlRenderer *renderer); + + // common part of all ctors + void Init(); + +private: + // total range of the scrollbar in logical units + int m_range; + + // the size of the thumb in logical units (from 0 to m_range) and its + // position (from 0 to m_range - m_thumbSize) + int m_thumbSize, + m_thumbPos; + + // the page size, i.e. the number of lines by which to scroll when page + // up/down action is performed + int m_pageSize; + + DECLARE_DYNAMIC_CLASS(wxScrollBar) +}; + +#endif // _WX_UNIV_SCROLBAR_H_ + diff --git a/include/wx/univ/setup.h b/include/wx/univ/setup.h index 68a96af833..c6029b1511 100644 --- a/include/wx/univ/setup.h +++ b/include/wx/univ/setup.h @@ -79,7 +79,7 @@ #define wxUSE_RADIOBOX 0 #define wxUSE_RADIOBTN 0 #define wxUSE_SASH 0 -#define wxUSE_SCROLLBAR 0 +#define wxUSE_SCROLLBAR 1 #define wxUSE_SLIDER 0 #define wxUSE_SPINBTN 0 #define wxUSE_SPINCTRL 0 @@ -129,7 +129,7 @@ #define wxUSE_SPLINES 0 #define wxUSE_DRAG_AND_DROP 0 #define wxUSE_XPM_IN_MSW 0 -#define wxUSE_IMAGE_LOADING_IN_MSW 0 +#define wxUSE_IMAGE_LOADING_IN_MSW 1 #define wxUSE_RESOURCE_LOADING_IN_MSW 0 #define wxUSE_WX_RESOURCES 0 #define wxUSE_POSTSCRIPT 0 diff --git a/include/wx/univ/theme.h b/include/wx/univ/theme.h index 7ea066723b..4a5840e645 100644 --- a/include/wx/univ/theme.h +++ b/include/wx/univ/theme.h @@ -54,7 +54,8 @@ public: // get the input handler for the control with this name virtual wxInputHandler *GetInputHandler(const wxString& control) = 0; - virtual wxColourScheme *GetColourScheme() = 0; + // get the colour scheme for the control with this name + virtual wxColourScheme *GetColourScheme(const wxString& control) = 0; // implementation only from now on // ------------------------------- diff --git a/samples/univ/univ.cpp b/samples/univ/univ.cpp index 3b3202c251..3c56761a7b 100644 --- a/samples/univ/univ.cpp +++ b/samples/univ/univ.cpp @@ -35,6 +35,7 @@ #include "wx/dcclient.h" #include "wx/button.h" + #include "wx/scrolbar.h" #include "wx/statbox.h" #include "wx/stattext.h" #endif @@ -117,10 +118,12 @@ bool MyUnivApp::OnInit() // ---------------------------------------------------------------------------- MyUnivFrame::MyUnivFrame(const wxString& title) - : wxFrame(NULL, -1, title, wxDefaultPosition, wxSize(600, 400)) + : wxFrame(NULL, -1, title, wxDefaultPosition, wxSize(600, 450)) { SetBackgroundColour(*wxLIGHT_GREY); + wxStaticText *text; + new wxStaticText(this, _T("Test static text"), wxPoint(10, 10)); new wxStaticText(this, _T("&Multi line\n(and very very very very long)\nstatic text"), @@ -128,7 +131,6 @@ MyUnivFrame::MyUnivFrame(const wxString& title) (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); @@ -153,6 +155,7 @@ MyUnivFrame::MyUnivFrame(const wxString& title) wxPoint(10, 150), wxSize(500, 120)); box->SetForegroundColour(*wxRED); + box->SetBackground(wxBitmap("bricks.bmp", wxBITMAP_TYPE_BMP), 0, wxTILE); x = 15; #define CREATE_STATIC_ALIGN_DEMO(align) \ @@ -172,6 +175,12 @@ MyUnivFrame::MyUnivFrame(const wxString& title) new wxButton(this, Univ_Button1, _T("&Press me"), wxPoint(10, 300)); new wxButton(this, Univ_Button2, _T("&And me"), wxPoint(100, 300)); + + wxScrollBar *sb; + sb = new wxScrollBar(this, -1, wxPoint(200, 300), wxSize(100, -1)); + sb->SetScrollbar(0, 10, 100, 10); + sb = new wxScrollBar(this, -1, wxPoint(200, 330), wxSize(-1, 50), wxSB_VERTICAL); + sb->SetScrollbar(50, 50, 100, 10); } void MyUnivFrame::OnButton(wxCommandEvent& event) diff --git a/src/common/ctrlcmn.cpp b/src/common/ctrlcmn.cpp index f9748c0df9..9e7b1861ae 100644 --- a/src/common/ctrlcmn.cpp +++ b/src/common/ctrlcmn.cpp @@ -48,7 +48,7 @@ bool wxControlBase::Create(wxWindow *parent, const wxString &name) { bool ret = wxWindow::Create(parent, id, pos, size, style, name); - + #if wxUSE_VALIDATORS if ( ret ) SetValidator(validator); @@ -114,9 +114,15 @@ void wxControlBase::InitCommandEvent(wxCommandEvent& event) const } // ---------------------------------------------------------------------------- -// border stuff +// other stuff // ---------------------------------------------------------------------------- +void wxControlBase::SetBackground(const wxBitmap& bitmap, + int alignment, + wxStretch stretch) +{ +} + wxBorder wxControlBase::GetBorder() const { wxBorder border = (wxBorder)(m_windowStyle & wxBORDER_MASK); diff --git a/src/msw/dc.cpp b/src/msw/dc.cpp index 08d453bb50..4db677187b 100644 --- a/src/msw/dc.cpp +++ b/src/msw/dc.cpp @@ -1204,7 +1204,11 @@ void wxDC::DoGetTextExtent(const wxString& string, wxCoord *x, wxCoord *y, wxFont *theFont) const { wxFont *fontToUse = theFont ? theFont : (wxFont *)&m_font; - HGDIOBJ hfontOld = ::SelectObject(GetHdc(), GetHfontOf(*fontToUse)); + HGDIOBJ hfontOld; + if ( fontToUse->Ok() ) + hfontOld = ::SelectObject(GetHdc(), GetHfontOf(*fontToUse)); + else + hfontOld = 0; SIZE sizeRect; TEXTMETRIC tm; @@ -1217,7 +1221,8 @@ void wxDC::DoGetTextExtent(const wxString& string, wxCoord *x, wxCoord *y, if (descent) *descent = tm.tmDescent; if (externalLeading) *externalLeading = tm.tmExternalLeading; - ::SelectObject(GetHdc(), hfontOld); + if ( hfontOld ) + ::SelectObject(GetHdc(), hfontOld); } void wxDC::SetMapMode(int mode) diff --git a/src/msw/window.cpp b/src/msw/window.cpp index 8e5512f4a1..0ee7511007 100644 --- a/src/msw/window.cpp +++ b/src/msw/window.cpp @@ -1886,6 +1886,16 @@ long wxWindow::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam) case WM_ACTIVATEAPP: wxTheApp->SetActive(wParam != 0, FindFocus()); break; + + case WM_NCHITTEST: + // we shouldn't allow the windows which don't want to get focus to + // get it + if ( !AcceptsFocus() ) + { + rc.result = HTTRANSPARENT; + processed = TRUE; + } + break; #endif // __WXUNIVERSAL__ case WM_ACTIVATE: diff --git a/src/univ/button.cpp b/src/univ/button.cpp index 3015bcf2b5..ce922ad67a 100644 --- a/src/univ/button.cpp +++ b/src/univ/button.cpp @@ -27,7 +27,7 @@ #pragma hdrstop #endif -#if wxUSE_STATTEXT +#if wxUSE_BUTTON #ifndef WX_PRECOMP #include "wx/dcclient.h" @@ -179,5 +179,5 @@ void wxButton::SetDefault() m_isDefault = TRUE; } -#endif // wxUSE_STATTEXT +#endif // wxUSE_BUTTON diff --git a/src/univ/control.cpp b/src/univ/control.cpp index 75ac3c96a8..737b609ac9 100644 --- a/src/univ/control.cpp +++ b/src/univ/control.cpp @@ -61,6 +61,7 @@ BEGIN_EVENT_TABLE(wxControl, wxControlBase) EVT_KILL_FOCUS(wxControl::OnFocus) EVT_PAINT(wxControl::OnPaint) + EVT_ERASE_BACKGROUND(wxControl::OnErase) END_EVENT_TABLE() // ---------------------------------------------------------------------------- @@ -121,6 +122,29 @@ void wxControl::SetCurrent(bool doit) m_isCurrent = doit; } +int wxControl::GetStateFlags() const +{ + int flags = 0; + if ( !IsEnabled() ) + flags |= wxCONTROL_DISABLED; + + // 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 ( IsCurrent() ) + flags |= wxCONTROL_CURRENT; + if ( IsFocused() ) + flags |= wxCONTROL_FOCUSED; + if ( IsPressed() ) + flags |= wxCONTROL_PRESSED; + if ( IsDefault() ) + flags |= wxCONTROL_ISDEFAULT; + } + + return flags; +} + // ---------------------------------------------------------------------------- // mnemonics handling // ---------------------------------------------------------------------------- @@ -168,10 +192,50 @@ wxString wxControl::GetLabel() const return m_label; } +// ---------------------------------------------------------------------------- +// background pixmap +// ---------------------------------------------------------------------------- + +void wxControl::SetBackground(const wxBitmap& bitmap, + int alignment, + wxStretch stretch) +{ + m_bitmapBg = bitmap; + m_alignBgBitmap = alignment; + m_stretchBgBitmap = stretch; +} + +const wxBitmap& wxControl::GetBackgroundBitmap(int *alignment, + wxStretch *stretch) const +{ + if ( m_bitmapBg.Ok() ) + { + if ( alignment ) + *alignment = m_alignBgBitmap; + if ( stretch ) + *stretch = m_stretchBgBitmap; + } + + return m_bitmapBg; +} + // ---------------------------------------------------------------------------- // painting // ---------------------------------------------------------------------------- +// the event handler executed when the window background must be painted +void wxControl::OnErase(wxEraseEvent& event) +{ + wxControlRenderer renderer(this, *event.GetDC(), + wxTheme::Get()->GetRenderer()); + + if ( !DoDrawBackground(&renderer) ) + { + // not processed + event.Skip(); + } +} + // the event handler executed when the window must be repainted void wxControl::OnPaint(wxPaintEvent& event) { @@ -183,6 +247,16 @@ void wxControl::OnPaint(wxPaintEvent& event) DoDraw(&renderer); } +bool wxControl::DoDrawBackground(wxControlRenderer *renderer) +{ + if ( !m_bitmapBg.Ok() ) + return FALSE; + + renderer->DrawBackgroundBitmap(); + + return TRUE; +} + void wxControl::DoDraw(wxControlRenderer *renderer) { renderer->DrawBorder(); diff --git a/src/univ/files.lst b/src/univ/files.lst index 6ee1692c1a..d6c1210718 100644 --- a/src/univ/files.lst +++ b/src/univ/files.lst @@ -1,5 +1,6 @@ UNIVOBJS = \ button.o \ + colschem.o \ control.o \ inphand.o \ renderer.o \ diff --git a/src/univ/renderer.cpp b/src/univ/renderer.cpp index 16bd3e2db8..d2ad1536ee 100644 --- a/src/univ/renderer.cpp +++ b/src/univ/renderer.cpp @@ -34,6 +34,8 @@ #include "wx/dc.h" #endif // WX_PRECOMP +#include "wx/image.h" + #include "wx/univ/renderer.h" // ============================================================================ @@ -63,38 +65,15 @@ wxControlRenderer::wxControlRenderer(wxControl *control, 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->IsCurrent() ) - flags |= wxRENDER_CURRENT; - 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::DrawBorder() { - int flags = GetStateFlags(); + int flags = m_ctrl->GetStateFlags(); // draw outline m_renderer->DrawBorder(m_dc, m_ctrl->GetBorder(), m_rect, flags, &m_rect); - // fill the inside + // fill the inside (TODO: query the theme for bg bitmap) m_renderer->DrawBackground(m_dc, m_ctrl->GetBackgroundColour(), m_rect, flags); } @@ -104,18 +83,10 @@ 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_rect, + m_ctrl->GetStateFlags(), m_ctrl->GetAlignment(), m_ctrl->GetAccelIndex()); } @@ -129,17 +100,90 @@ void wxControlRenderer::DrawFrame() m_renderer->DrawFrame(m_dc, m_ctrl->GetLabel(), m_rect, - GetStateFlags(), + m_ctrl->GetStateFlags(), m_ctrl->GetAlignment(), m_ctrl->GetAccelIndex()); } void wxControlRenderer::DrawButtonBorder() { - int flags = GetStateFlags(); + int flags = m_ctrl->GetStateFlags(); m_renderer->DrawButtonBorder(m_dc, m_rect, flags, &m_rect); m_renderer->DrawBackground(m_dc, m_ctrl->GetBackgroundColour(), m_rect, flags); } + +void wxControlRenderer::DrawBackgroundBitmap() +{ + // get the bitmap and the flags + int alignment; + wxStretch stretch; + wxBitmap bmp = m_ctrl->GetBackgroundBitmap(&alignment, &stretch); + if ( !bmp.Ok() ) + return; + + int width = bmp.GetWidth(), + height = bmp.GetHeight(); + + wxCoord x = 0, + y = 0; + if ( stretch & wxTILE ) + { + // tile the bitmap + for ( ; x < m_rect.width; x += width ) + { + for ( y = 0; y < m_rect.height; y += height ) + { + m_dc.DrawBitmap(bmp, x, y); + } + } + } + else if ( stretch & wxEXPAND ) + { + // stretch bitmap to fill the entire control + bmp = wxImage(bmp).Scale(m_rect.width, m_rect.height).ConvertToBitmap(); + } + else // not stretched, not tiled + { + if ( alignment & wxALIGN_RIGHT ) + { + x = m_rect.GetRight() - width; + } + else if ( alignment & wxALIGN_CENTRE ) + { + x = (m_rect.GetLeft() + m_rect.GetRight() - width) / 2; + } + else // alignment & wxALIGN_LEFT + { + x = m_rect.GetLeft(); + } + + if ( alignment & wxALIGN_BOTTOM ) + { + y = m_rect.GetBottom() - height; + } + else if ( alignment & wxALIGN_CENTRE_VERTICAL ) + { + y = (m_rect.GetTop() + m_rect.GetBottom() - height) / 2; + } + else // alignment & wxALIGN_TOP + { + y = m_rect.GetTop(); + } + } + + // do draw it + m_dc.DrawBitmap(bmp, x, y); +} + +void wxControlRenderer::DrawScrollbar(int thumbStart, int thumbEnd) +{ + m_renderer->DrawScrollbar(m_dc, + m_ctrl->GetWindowStyle() & wxVERTICAL + ? wxVERTICAL + : wxHORIZONTAL, + thumbStart, thumbEnd, m_rect, + m_ctrl->GetStateFlags()); +} diff --git a/src/univ/scrolbar.cpp b/src/univ/scrolbar.cpp new file mode 100644 index 0000000000..0105be2836 --- /dev/null +++ b/src/univ/scrolbar.cpp @@ -0,0 +1,186 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: univ/scrolbar.cpp +// Purpose: wxScrollBar implementation +// Author: Vadim Zeitlin +// Modified by: +// Created: 20.08.00 +// RCS-ID: $Id$ +// Copyright: (c) 2000 Vadim Zeitlin +// Licence: wxWindows license +///////////////////////////////////////////////////////////////////////////// + +// ============================================================================ +// declarations +// ============================================================================ + +// ---------------------------------------------------------------------------- +// headers +// ---------------------------------------------------------------------------- + +#ifdef __GNUG__ + #pragma implementation "univscrolbar.h" +#endif + +#include "wx/wxprec.h" + +#ifdef __BORLANDC__ + #pragma hdrstop +#endif + +#if wxUSE_SCROLLBAR + +#ifndef WX_PRECOMP + #include "wx/dcclient.h" + #include "wx/scrolbar.h" + #include "wx/validate.h" +#endif + +#include "wx/univ/renderer.h" +#include "wx/univ/inphand.h" +#include "wx/univ/theme.h" + +// ============================================================================ +// implementation +// ============================================================================ + +IMPLEMENT_DYNAMIC_CLASS(wxScrollBar, wxControl) + +// ---------------------------------------------------------------------------- +// creation +// ---------------------------------------------------------------------------- + +void wxScrollBar::Init() +{ + m_range = + m_thumbSize = + m_thumbPos = + m_pageSize = 0; +} + +bool wxScrollBar::Create(wxWindow *parent, + wxWindowID id, + const wxPoint &pos, + const wxSize &size, + long style, + const wxValidator& validator, + const wxString &name) +{ + if ( !wxControl::Create(parent, id, pos, size, style, wxDefaultValidator, name) ) + return FALSE; + + 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; +} + +wxScrollBar::~wxScrollBar() +{ +} + +// ---------------------------------------------------------------------------- +// scrollbar API +// ---------------------------------------------------------------------------- + +int wxScrollBar::GetThumbPosition() const +{ + return m_thumbPos; +} + +int wxScrollBar::GetThumbSize() const +{ + return m_thumbSize; +} + +int wxScrollBar::GetPageSize() const +{ + return m_pageSize; +} + +int wxScrollBar::GetRange() const +{ + return m_range; +} + +void wxScrollBar::SetThumbPosition(int pos) +{ + wxCHECK_RET( pos >= 0 && pos <= m_range, _T("thumb position out of range") ); + + if ( pos >= m_range - m_thumbSize ) + { + pos = m_range - m_thumbSize; + } + + m_thumbPos = pos; +} + +void wxScrollBar::SetScrollbar(int position, int thumbSize, + int range, int pageSize, + bool refresh) +{ + // set all parameters + m_range = range; + m_thumbSize = thumbSize; + SetThumbPosition(position); + m_pageSize = pageSize; + + if ( refresh ) + { + // and update the window + Refresh(); + } +} + +// ---------------------------------------------------------------------------- +// size management +// ---------------------------------------------------------------------------- + +wxSize wxScrollBar::DoGetBestSize() const +{ + wxSize sz(140, 140); + wxTheme::Get()->GetRenderer()->AdjustSize(&sz, this); + return sz; +} + +// ---------------------------------------------------------------------------- +// drawing +// ---------------------------------------------------------------------------- + +void wxScrollBar::DoDraw(wxControlRenderer *renderer) +{ + int thumbStart, thumbEnd; + if ( m_range ) + { + thumbStart = (100*m_thumbPos) / m_range; + thumbEnd = (100*(m_thumbPos + m_thumbSize)) / m_range; + } + else // no range + { + thumbStart = + thumbEnd = 0; + } + + renderer->DrawScrollbar(thumbStart, thumbEnd); +} + +// ---------------------------------------------------------------------------- +// input processing +// ---------------------------------------------------------------------------- + +wxInputHandler *wxScrollBar::CreateInputHandler() const +{ + return wxTheme::Get()->GetInputHandler(wxCONTROL_SCROLLBAR); +} + +bool wxScrollBar::PerformAction(const wxControlAction& action, + const wxEvent& event) +{ + return wxControl::PerformAction(action, event); +} + +#endif // wxUSE_SCROLLBAR + diff --git a/src/univ/themes/gtk.cpp b/src/univ/themes/gtk.cpp index 4915dc50df..2b4d9502b1 100644 --- a/src/univ/themes/gtk.cpp +++ b/src/univ/themes/gtk.cpp @@ -52,23 +52,23 @@ public: virtual void DrawLabel(wxDC& dc, const wxString& label, const wxRect& rect, - int flags = wxRENDER_ENABLED, + int flags = 0, int alignment = wxALIGN_LEFT | wxALIGN_TOP, int indexAccel = -1); virtual void DrawBorder(wxDC& dc, wxBorder border, const wxRect& rect, - int flags = wxRENDER_ENABLED, + int flags = 0, wxRect *rectIn = (wxRect *)NULL); virtual void DrawFrame(wxDC& dc, const wxString& label, const wxRect& rect, - int flags = wxRENDER_ENABLED, + int flags = 0, int alignment = wxALIGN_LEFT, int indexAccel = -1); virtual void DrawButtonBorder(wxDC& dc, const wxRect& rect, - int flags = wxRENDER_ENABLED, + int flags = 0, wxRect *rectIn = (wxRect *)NULL); virtual void AdjustSize(wxSize *size, const wxWindow *window); @@ -456,7 +456,7 @@ void wxGTKRenderer::DrawButtonBorder(wxDC& dc, { wxRect rect = rectTotal; - if ( flags & wxRENDER_PRESSED ) + if ( flags & wxCONTROL_PRESSED ) { // button pressed: draw a black border around it and an inward shade DrawRect(dc, &rect, m_penBlack); @@ -467,12 +467,12 @@ void wxGTKRenderer::DrawButtonBorder(wxDC& dc, { // button not pressed - if ( flags & wxRENDER_DEFAULT ) + if ( flags & wxCONTROL_ISDEFAULT ) { // TODO } - if ( flags & wxRENDER_FOCUSED ) + if ( flags & wxCONTROL_FOCUSED ) { // button is currently default: add an extra border around it DrawRect(dc, &rect, m_penBlack); @@ -481,7 +481,7 @@ void wxGTKRenderer::DrawButtonBorder(wxDC& dc, // now draw a normal button DrawShadedRect(dc, &rect, m_penHighlight, m_penBlack); DrawAntiShadedRect(dc, &rect, - flags & wxRENDER_CURRENT ? m_penHighlight + flags & wxCONTROL_CURRENT ? m_penHighlight : m_penLightGrey, m_penDarkGrey); } @@ -554,7 +554,7 @@ void wxGTKRenderer::DrawLabel(wxDC& dc, int alignment, int indexAccel) { - if ( !(flags & wxRENDER_ENABLED) ) + if ( flags & wxCONTROL_DISABLED ) { // make the text grey and draw a shade for it dc.SetTextForeground(0xe0e0e0); @@ -579,11 +579,11 @@ void wxGTKRenderer::DrawBackground(wxDC& dc, { // what colour should we use? wxColour colBg; - if ( flags & wxRENDER_PRESSED ) + if ( flags & wxCONTROL_PRESSED ) { colBg = wxColour(0x7f7f7f); } - else if ( flags & wxRENDER_CURRENT ) + else if ( flags & wxCONTROL_CURRENT ) { colBg = wxColour(0xe0e0e0); } diff --git a/src/univ/themes/win32.cpp b/src/univ/themes/win32.cpp index 4fd605ff7f..690251bd52 100644 --- a/src/univ/themes/win32.cpp +++ b/src/univ/themes/win32.cpp @@ -26,13 +26,16 @@ #ifndef WX_PRECOMP #include "wx/intl.h" - #include "wx/button.h" #include "wx/dc.h" #include "wx/window.h" + + #include "wx/button.h" + #include "wx/scrolbar.h" #endif // WX_PRECOMP #include "wx/univ/renderer.h" #include "wx/univ/inphand.h" +#include "wx/univ/colschem.h" #include "wx/univ/theme.h" // ---------------------------------------------------------------------------- @@ -42,34 +45,62 @@ class wxWin32Renderer : public wxRenderer { public: - wxWin32Renderer(); + // constants + enum wxArrowDirection + { + Arrow_Left, + Arrow_Right, + Arrow_Up, + Arrow_Down, + Arrow_Max + }; + + enum wxArrowStyle + { + Arrow_Normal, + Arrow_Disabled, + Arrow_StateMax + }; + + // ctor + wxWin32Renderer(const wxColourScheme *scheme); // implement the base class pure virtuals virtual void DrawBackground(wxDC& dc, const wxColour& col, const wxRect& rect, - int flags); + int flags = 0); virtual void DrawLabel(wxDC& dc, const wxString& label, const wxRect& rect, - int flags = wxRENDER_ENABLED, + int flags = 0, int alignment = wxALIGN_LEFT | wxALIGN_TOP, int indexAccel = -1); virtual void DrawBorder(wxDC& dc, wxBorder border, const wxRect& rect, - int flags = wxRENDER_ENABLED, + int flags = 0, wxRect *rectIn = (wxRect *)NULL); virtual void DrawFrame(wxDC& dc, const wxString& label, const wxRect& rect, - int flags = wxRENDER_ENABLED, + int flags = 0, int alignment = wxALIGN_LEFT, int indexAccel = -1); virtual void DrawButtonBorder(wxDC& dc, const wxRect& rect, - int flags = wxRENDER_ENABLED, + int flags = 0, wxRect *rectIn = (wxRect *)NULL); + virtual void DrawArrow(wxDC& dc, + wxDirection dir, + const wxRect& rect, + int flags = 0); + virtual void DrawScrollbar(wxDC& dc, + wxOrientation orient, + int thumbPosStart, + int thumbPosEnd, + const wxRect& rect, + int flags = 0); virtual void AdjustSize(wxSize *size, const wxWindow *window); @@ -91,12 +122,34 @@ protected: // draw the normal 3D border void DrawRaisedBorder(wxDC& dc, wxRect *rect); + // draw the border used for scrollbar arrows + void DrawArrowBorder(wxDC& dc, wxRect *rect); + + // public DrawArrow()s helper + void DrawArrow(wxDC& dc, const wxRect& rect, + wxArrowDirection arrowDir, wxArrowStyle arrowStyle); + + // DrawArrowButton is used by DrawScrollbar and DrawComboButton + void DrawArrowButton(wxDC& dc, const wxRect& rect, + wxArrowDirection arrowDir, + wxArrowStyle arrowStyle); + private: + // the sizing parameters (TODO make them changeable) + wxSize m_sizeScrollbarArrow; + + // GDI objects we use for drawing + wxColour m_colDarkGrey, + m_colBg, + m_colHighlight; + wxPen m_penBlack, m_penDarkGrey, m_penLightGrey, - m_penWhite, m_penHighlight; + + // first row is for the normal state, second - for the disabled + wxBitmap m_bmpArrows[Arrow_StateMax][Arrow_Max]; }; // ---------------------------------------------------------------------------- @@ -130,7 +183,7 @@ private: class wxWin32ColourScheme : public wxColourScheme { public: - virtual wxColour Get(StdColour col); + virtual wxColour Get(StdColour col, int flags = 0) const; }; // ---------------------------------------------------------------------------- @@ -147,7 +200,7 @@ public: virtual wxRenderer *GetRenderer() { return m_renderer; } virtual wxInputHandler *GetInputHandler(const wxString& control); - virtual wxColourScheme *GetColourScheme() { return m_scheme; } + virtual wxColourScheme *GetColourScheme(const wxString& control); private: wxWin32Renderer *m_renderer; @@ -174,13 +227,16 @@ WX_IMPLEMENT_THEME(wxWin32Theme, win32, wxTRANSLATE("Win32 theme")); wxWin32Theme::wxWin32Theme() { - m_renderer = new wxWin32Renderer; m_scheme = new wxWin32ColourScheme; + m_renderer = new wxWin32Renderer(m_scheme); } wxWin32Theme::~wxWin32Theme() { WX_CLEAR_ARRAY(m_handlers); + + delete m_renderer; + delete m_scheme; } wxInputHandler *wxWin32Theme::GetInputHandler(const wxString& control) @@ -194,6 +250,8 @@ wxInputHandler *wxWin32Theme::GetInputHandler(const wxString& control) if ( control == wxCONTROL_BUTTON ) handler = new wxWin32ButtonInputHandler; + else if ( control == wxCONTROL_SCROLLBAR ) + handler = new wxWin32InputHandler; // TODO else { wxASSERT_MSG( control == wxCONTROL_DEFAULT, @@ -212,27 +270,36 @@ wxInputHandler *wxWin32Theme::GetInputHandler(const wxString& control) return handler; } +wxColourScheme *wxWin32Theme::GetColourScheme(const wxString& control) +{ + // Win32 has only one colour scheme for all controls + return m_scheme; +} + // ============================================================================ // wxWin32ColourScheme // ============================================================================ -wxColour wxWin32ColourScheme::Get(wxWin32ColourScheme::StdColour col) +wxColour wxWin32ColourScheme::Get(wxWin32ColourScheme::StdColour col, + int flags) const { switch ( col ) { - case DARK_SHADOW: return wxColour(0x7f7f7f); - case FACE: return wxColour(0xc0c0c0); - case HIGHLIGHT: return wxColour(0xe0e0e0); - case LIGHT: return wxColour(0xffffff); - case SHADOW: return wxColour(0xc0c0c0); - case CONTROL_TEXT: return wxColour(0x000000); - case HIGHLIGHT: return wxColour(0x0000ff); - case HIGHLIGHT_TEXT:return wxColour(0x00ffff); + case CONTROL: return wxColour(0xc0c0c0); + case CONTROL_TEXT: return *wxBLACK; + + case HIGHLIGHT: return wxColour(0x800000); + case HIGHLIGHT_TEXT: return wxColour(0xffffff); + + case SHADOW_DARK: return *wxBLACK; + case SHADOW_HIGHLIGHT: return wxColour(0xe0e0e0); + case SHADOW_IN: return wxColour(0xc0c0c0); + case SHADOW_OUT: return wxColour(0x7f7f7f); case MAX: default: wxFAIL_MSG(_T("invalid standard colour")); - return wxColour(0x000000); + return *wxBLACK; } } @@ -244,13 +311,161 @@ wxColour wxWin32ColourScheme::Get(wxWin32ColourScheme::StdColour col) // 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) +wxWin32Renderer::wxWin32Renderer(const wxColourScheme *scheme) { + // init data + m_sizeScrollbarArrow = wxSize(16, 16); + + // init colours and pens + m_penBlack = wxPen(scheme->Get(wxColourScheme::SHADOW_DARK), 0, wxSOLID); + + m_colDarkGrey = scheme->Get(wxColourScheme::SHADOW_OUT); + m_penDarkGrey = wxPen(m_colDarkGrey, 0, wxSOLID); + + m_colBg = scheme->Get(wxColourScheme::SHADOW_IN); + m_penLightGrey = wxPen(m_colBg, 0, wxSOLID); + + m_colHighlight = scheme->Get(wxColourScheme::SHADOW_HIGHLIGHT); + m_penHighlight = wxPen(m_colHighlight, 0, wxSOLID); + + // init the arrow bitmaps + static const size_t ARROW_WIDTH = 7; + static const size_t ARROW_LENGTH = 4; + + wxMask *mask; + wxMemoryDC dcNormal, dcDisabled; + for ( size_t n = 0; n < Arrow_Max; n++ ) + { + bool isVertical = n > Arrow_Right; + int w, h; + if ( isVertical ) + { + w = ARROW_WIDTH; + h = ARROW_LENGTH; + } + else + { + h = ARROW_WIDTH; + w = ARROW_LENGTH; + } + + // disabled arrow is larger because of the shadow + m_bmpArrows[Arrow_Normal][n].Create(w, h); + m_bmpArrows[Arrow_Disabled][n].Create(w + 1, h + 1); + + dcNormal.SelectObject(m_bmpArrows[Arrow_Normal][n]); + dcDisabled.SelectObject(m_bmpArrows[Arrow_Disabled][n]); + + dcNormal.SetBackground(*wxWHITE_BRUSH); + dcDisabled.SetBackground(*wxWHITE_BRUSH); + dcNormal.Clear(); + dcDisabled.Clear(); + + dcNormal.SetPen(m_penBlack); + dcDisabled.SetPen(m_penDarkGrey); + + // calculate the position of the point of the arrow + wxCoord x1, y1; + if ( isVertical ) + { + x1 = (ARROW_WIDTH - 1)/2; + y1 = n == Arrow_Up ? 0 : ARROW_LENGTH - 1; + } + else // horizontal + { + x1 = n == Arrow_Left ? 0 : ARROW_LENGTH - 1; + y1 = (ARROW_WIDTH - 1)/2; + } + + wxCoord x2 = x1, + y2 = y1; + + if ( isVertical ) + x2++; + else + y2++; + + for ( size_t i = 0; i < ARROW_LENGTH; i++ ) + { + dcNormal.DrawLine(x1, y1, x2, y2); + dcDisabled.DrawLine(x1, y1, x2, y2); + + if ( isVertical ) + { + x1--; + x2++; + + if ( n == Arrow_Up ) + { + y1++; + y2++; + } + else // down arrow + { + y1--; + y2--; + } + } + else // left or right arrow + { + y1--; + y2++; + + if ( n == Arrow_Left ) + { + x1++; + x2++; + } + else + { + x1--; + x2--; + } + } + } + + // draw the shadow for the disabled one + dcDisabled.SetPen(m_penHighlight); + switch ( n ) + { + case Arrow_Left: + y1 += 2; + dcDisabled.DrawLine(x1, y1, x2, y2); + break; + + case Arrow_Right: + x1 = ARROW_LENGTH - 1; + y1 = (ARROW_WIDTH - 1)/2 + 1; + x2 = 0; + y2 = ARROW_WIDTH; + dcDisabled.DrawLine(x1, y1, x2, y2); + dcDisabled.DrawLine(++x1, y1, x2, ++y2); + break; + + case Arrow_Up: + x1 += 2; + dcDisabled.DrawLine(x1, y1, x2, y2); + break; + + case Arrow_Down: + x1 = ARROW_WIDTH - 1; + y1 = 1; + x2 = (ARROW_WIDTH - 1)/2; + y2 = ARROW_LENGTH; + dcDisabled.DrawLine(x1, y1, x2, y2); + dcDisabled.DrawLine(++x1, y1, x2, ++y2); + break; + + } + + dcNormal.SelectObject(wxNullBitmap); + dcDisabled.SelectObject(wxNullBitmap); + + mask = new wxMask(m_bmpArrows[Arrow_Normal][n], *wxWHITE); + m_bmpArrows[Arrow_Normal][n].SetMask(mask); + mask = new wxMask(m_bmpArrows[Arrow_Disabled][n], *wxWHITE); + m_bmpArrows[Arrow_Disabled][n].SetMask(mask); + } } // ---------------------------------------------------------------------------- @@ -374,6 +589,12 @@ void wxWin32Renderer::DrawRaisedBorder(wxDC& dc, wxRect *rect) DrawShadedRect(dc, rect, m_penLightGrey, m_penDarkGrey); } +void wxWin32Renderer::DrawArrowBorder(wxDC& dc, wxRect *rect) +{ + DrawShadedRect(dc, rect, m_penLightGrey, m_penBlack); + DrawShadedRect(dc, rect, m_penHighlight, m_penDarkGrey); +} + void wxWin32Renderer::DrawBorder(wxDC& dc, wxBorder border, const wxRect& rectTotal, @@ -398,8 +619,7 @@ void wxWin32Renderer::DrawBorder(wxDC& dc, break; case wxBORDER_DOUBLE: - DrawShadedRect(dc, &rect, m_penLightGrey, m_penBlack); - DrawShadedRect(dc, &rect, m_penHighlight, m_penDarkGrey); + DrawArrowBorder(dc, &rect); DrawRect(dc, &rect, m_penLightGrey); break; @@ -431,7 +651,7 @@ void wxWin32Renderer::DrawButtonBorder(wxDC& dc, { wxRect rect = rectTotal; - if ( flags & wxRENDER_PRESSED ) + if ( flags & wxCONTROL_PRESSED ) { // button pressed: draw a double border around it DrawRect(dc, &rect, m_penBlack); @@ -441,7 +661,7 @@ void wxWin32Renderer::DrawButtonBorder(wxDC& dc, { // button not pressed - if ( flags & (wxRENDER_FOCUSED | wxRENDER_DEFAULT) ) + if ( flags & (wxCONTROL_FOCUSED | wxCONTROL_ISDEFAULT) ) { // button either default or focused (or both): add an extra border around it DrawRect(dc, &rect, m_penBlack); @@ -520,26 +740,34 @@ void wxWin32Renderer::DrawLabel(wxDC& dc, int alignment, int indexAccel) { - if ( !(flags & wxRENDER_ENABLED) ) + // shift the label if a button is pressed + wxRect rectLabel = rect; + if ( flags & wxCONTROL_PRESSED ) + { + rectLabel.x++; + rectLabel.y++; + } + + if ( flags & wxCONTROL_DISABLED ) { // make the text grey and draw a shade for it - dc.SetTextForeground(0xe0e0e0); - wxRect rectShadow = rect; + dc.SetTextForeground(m_colHighlight); + wxRect rectShadow = rectLabel; rectShadow.x++; rectShadow.y++; dc.DrawLabel(label, rectShadow, alignment, indexAccel); - dc.SetTextForeground(0x7f7f7f); + dc.SetTextForeground(m_colDarkGrey); } - wxRect rectText = rect; - if ( flags & wxRENDER_FOCUSED ) + wxRect rectText = rectLabel; + if ( flags & wxCONTROL_FOCUSED ) { rectText.Inflate(-2); } dc.DrawLabel(label, rectText, alignment, indexAccel); - if ( flags & wxRENDER_FOCUSED ) + if ( flags & wxCONTROL_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 @@ -589,13 +817,149 @@ void wxWin32Renderer::DrawBackground(wxDC& dc, dc.DrawRectangle(rect); } +// ---------------------------------------------------------------------------- +// scrollbar +// ---------------------------------------------------------------------------- + +void wxWin32Renderer::DrawArrow(wxDC& dc, + wxDirection dir, + const wxRect& rect, + int flags) +{ + // get the bitmap for this arrow + wxArrowDirection arrowDir; + switch ( dir ) + { + case wxLEFT: arrowDir = Arrow_Left; break; + case wxRIGHT: arrowDir = Arrow_Right; break; + case wxUP: arrowDir = Arrow_Up; break; + case wxDOWN: arrowDir = Arrow_Down; break; + + default: + wxFAIL_MSG(_T("unknown arrow direction")); + return; + } + + wxArrowStyle arrowStyle = flags & wxCONTROL_DISABLED ? Arrow_Disabled + : Arrow_Normal; + DrawArrow(dc, rect, arrowDir, arrowStyle); +} + +void wxWin32Renderer::DrawArrow(wxDC& dc, + const wxRect& rect, + wxArrowDirection arrowDir, + wxArrowStyle arrowStyle) +{ + const wxBitmap& bmp = m_bmpArrows[arrowStyle][arrowDir]; + + // under Windows the arrows always have the same size so just centre it in + // the provided rectangle + wxCoord x = rect.x + (rect.width - bmp.GetWidth()) / 2, + y = rect.y + (rect.height - bmp.GetHeight()) / 2; + + // Windows does it like this... + if ( arrowDir == Arrow_Left ) + x--; + + // draw it + dc.DrawBitmap(bmp, x, y, TRUE /* use mask */); +} + +void wxWin32Renderer::DrawArrowButton(wxDC& dc, + const wxRect& rectAll, + wxArrowDirection arrowDir, + wxArrowStyle arrowStyle) +{ + wxRect rect = rectAll; + DrawArrowBorder(dc, &rect); + DrawArrow(dc, rect, arrowDir, arrowStyle); +} + +void wxWin32Renderer::DrawScrollbar(wxDC& dc, + wxOrientation orient, + int thumbPosStart, + int thumbPosEnd, + const wxRect& rect, + int flags) +{ + wxArrowStyle arrowStyle = flags & wxCONTROL_DISABLED ? Arrow_Disabled + : Arrow_Normal; + + // first, draw the arrows at the ends + wxRect rectArrow[2]; + wxArrowDirection arrowDir[2]; + + rectArrow[0] = + rectArrow[1] = rect; + if ( orient == wxVERTICAL ) + { + rectArrow[0].height = + rectArrow[1].height = m_sizeScrollbarArrow.y; + rectArrow[1].y = rect.GetBottom() - rectArrow[1].height; + + arrowDir[0] = Arrow_Up; + arrowDir[1] = Arrow_Down; + } + else // horizontal + { + rectArrow[0].width = + rectArrow[1].width = m_sizeScrollbarArrow.x; + rectArrow[1].x = rect.GetRight() - rectArrow[1].width; + + arrowDir[0] = Arrow_Left; + arrowDir[1] = Arrow_Right; + } + + for ( size_t nArrow = 0; nArrow < 2; nArrow++ ) + { + DrawArrowButton(dc, rectArrow[nArrow], arrowDir[nArrow], arrowStyle); + } + + // next draw the scrollbar area + wxRect rectBar = rect; + if ( orient == wxVERTICAL ) + rectBar.Inflate(0, -m_sizeScrollbarArrow.y); + else + rectBar.Inflate(-m_sizeScrollbarArrow.x, 0); + + DrawBackground(dc, m_colHighlight, rectBar); + + // and, finally, the thumb, if any + if ( thumbPosStart < thumbPosEnd ) + { + wxRect rectThumb = rectBar; + if ( orient == wxVERTICAL ) + { + rectThumb.y += (rectBar.height*thumbPosStart)/100; + rectThumb.height = (rectBar.height*(thumbPosEnd - thumbPosStart))/100; + } + else // horizontal + { + rectThumb.x += (rectBar.width*thumbPosStart)/100; + rectThumb.width = (rectBar.width*(thumbPosEnd - thumbPosStart))/100; + } + + DrawArrowBorder(dc, &rectThumb); + DrawBackground(dc, m_colBg, rectThumb); + } +} + // ---------------------------------------------------------------------------- // size adjustments // ---------------------------------------------------------------------------- void wxWin32Renderer::AdjustSize(wxSize *size, const wxWindow *window) { - if ( wxDynamicCast(window, wxButton) ) + if ( wxDynamicCast(window, wxScrollBar) ) + { + // we only set the width of vert scrollbars and height of the + // horizontal ones + if ( window->GetWindowStyle() & wxSB_HORIZONTAL ) + size->y = m_sizeScrollbarArrow.y; + else + size->x = m_sizeScrollbarArrow.x; + } + else if ( wxDynamicCast(window, wxButton) ) { // TODO size->x += 3*window->GetCharWidth();