diff --git a/include/wx/frame.h b/include/wx/frame.h index da6fa02d1b..c97bcf8e34 100644 --- a/include/wx/frame.h +++ b/include/wx/frame.h @@ -27,7 +27,7 @@ WXDLLEXPORT_DATA(extern const wxChar*) wxFrameNameStr; WXDLLEXPORT_DATA(extern const wxChar*) wxStatusLineNameStr; WXDLLEXPORT_DATA(extern const wxChar*) wxToolBarNameStr; -WXDLLEXPORT_DATA(extern wxWindow*) wxWndHook; +WXDLLEXPORT_DATA(extern wxWindowMSW*) wxWndHook; class WXDLLEXPORT wxMenuBar; class WXDLLEXPORT wxStatusBar; diff --git a/include/wx/generic/scrolwin.h b/include/wx/generic/scrolwin.h index aa4d19a3c5..31c5367a10 100644 --- a/include/wx/generic/scrolwin.h +++ b/include/wx/generic/scrolwin.h @@ -28,25 +28,31 @@ WXDLLEXPORT_DATA(extern const wxChar*) wxPanelNameStr; // default scrolled window style #define wxScrolledWindowStyle (wxHSCROLL | wxVSCROLL) +// avoid triggering this stupid VC++ warning +#ifdef __VISUALC__ + #pragma warning(disable:4355) // 'this' used in base member initializer list +#endif + // ---------------------------------------------------------------------------- // wxScrolledWindow // ---------------------------------------------------------------------------- -class WXDLLEXPORT wxScrolledWindow : public wxPanel +class WXDLLEXPORT wxScrolledWindow : public wxPanel, public wxScrollHelper { public: - wxScrolledWindow(); + wxScrolledWindow() : wxScrollHelper(this) { } wxScrolledWindow(wxWindow *parent, wxWindowID id = -1, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxScrolledWindowStyle, const wxString& name = wxPanelNameStr) + : wxScrollHelper(this) { Create(parent, id, pos, size, style, name); } - ~wxScrolledWindow(); + virtual ~wxScrolledWindow(); bool Create(wxWindow *parent, wxWindowID id, @@ -55,98 +61,15 @@ public: long style = wxScrolledWindowStyle, const wxString& name = wxPanelNameStr); - // Normally the wxScrolledWindow will scroll itself, but in - // some rare occasions you might want it to scroll another - // window (e.g. a child of it in order to scroll only a portion - // the area between the scrollbars (spreadsheet: only cell area - // will move). - virtual void SetTargetWindow( wxWindow *target ); - virtual wxWindow *GetTargetWindow(); - - // Number of pixels per user unit (0 or -1 for no scrollbar) - // Length of virtual canvas in user units - // Length of page in user units - virtual void SetScrollbars(int pixelsPerUnitX, int pixelsPerUnitY, - int noUnitsX, int noUnitsY, - int xPos = 0, int yPos = 0, - bool noRefresh = FALSE ); - - // Physically scroll the window - virtual void Scroll(int x_pos, int y_pos); - -#if WXWIN_COMPATIBILITY - virtual void GetScrollUnitsPerPage(int *x_page, int *y_page) const; - virtual void CalcUnscrolledPosition(int x, int y, float *xx, float *yy) const; -#endif - - int GetScrollPageSize(int orient) const; - void SetScrollPageSize(int orient, int pageSize); - - virtual void GetScrollPixelsPerUnit(int *x_unit, int *y_unit) const; - - // Enable/disable Windows scrolling in either direction. - // If TRUE, wxWindows scrolls the canvas and only a bit of - // the canvas is invalidated; no Clear() is necessary. - // If FALSE, the whole canvas is invalidated and a Clear() is - // necessary. Disable for when the scroll increment is used - // to actually scroll a non-constant distance - virtual void EnableScrolling(bool x_scrolling, bool y_scrolling); - - // Get the view start - virtual void GetViewStart(int *x, int *y) const; - // Compatibility - void ViewStart(int *x, int *y) const - { GetViewStart( x, y ); } - - // Actual size in pixels when scrolling is taken into account - virtual void GetVirtualSize(int *x, int *y) const; - - // Set the scale factor, used in PrepareDC - void SetScale(double xs, double ys) { m_scaleX = xs; m_scaleY = ys; } - double GetScaleX() const { return m_scaleX; } - double GetScaleY() const { return m_scaleY; } - - virtual void CalcScrolledPosition(int x, int y, int *xx, int *yy) const; - virtual void CalcUnscrolledPosition(int x, int y, int *xx, int *yy) const; - - // Adjust the scrollbars - virtual void AdjustScrollbars(void); - - // Override this function to draw the graphic (or just process EVT_PAINT) - virtual void OnDraw(wxDC& WXUNUSED(dc)) {}; - - // Override this function if you don't want to have wxScrolledWindow - // automatically change the origin according to the scroll position. - virtual void PrepareDC(wxDC& dc); - - // implementation from now on - void OnScroll(wxScrollWinEvent& event); - void OnSize(wxSizeEvent& event); - void OnPaint(wxPaintEvent& event); - void OnChar(wxKeyEvent& event); - - // Calculate scroll increment - virtual int CalcScrollInc(wxScrollWinEvent& event); - -protected: - wxWindow *m_targetWindow; - int m_xScrollPixelsPerLine; - int m_yScrollPixelsPerLine; - bool m_xScrollingEnabled; - bool m_yScrollingEnabled; - int m_xScrollPosition; - int m_yScrollPosition; - int m_xScrollLines; - int m_yScrollLines; - int m_xScrollLinesPerPage; - int m_yScrollLinesPerPage; - double m_scaleX; - double m_scaleY; + virtual void PrepareDC(wxDC& dc) { DoPrepareDC(dc); } private: - DECLARE_EVENT_TABLE() DECLARE_ABSTRACT_CLASS(wxScrolledWindow) }; +#ifdef __VISUALC__ + #pragma warning(default:4355) +#endif + #endif // _WX_GENERIC_SCROLLWIN_H_ diff --git a/include/wx/listbox.h b/include/wx/listbox.h index 92c7bf7c08..52b846b93f 100644 --- a/include/wx/listbox.h +++ b/include/wx/listbox.h @@ -78,6 +78,16 @@ public: void SetFirstItem(int n) { DoSetFirstItem(n); } void SetFirstItem(const wxString& s); + // return TRUE if the listbox allows multiple selection + bool HasMultipleSelection() const + { + return (m_windowStyle & wxLB_MULTIPLE) || + (m_windowStyle & wxLB_EXTENDED); + } + + // return TRUE if this listbox is sorted + bool IsSorted() const { return (m_windowStyle & wxLB_SORT) != 0; } + // emulate selecting or deselecting the item event.GetInt() (depending on // event.GetExtraLong()) void Command(wxCommandEvent& event); @@ -103,7 +113,9 @@ protected: // include the platform-specific class declaration // ---------------------------------------------------------------------------- -#if defined(__WXMSW__) +#if defined(__WXUNIVERSAL__) + #include "wx/univ/listbox.h" +#elif defined(__WXMSW__) #include "wx/msw/listbox.h" #elif defined(__WXMOTIF__) #include "wx/motif/listbox.h" diff --git a/include/wx/msw/listbox.h b/include/wx/msw/listbox.h index 38c95ca792..a6e9766278 100644 --- a/include/wx/msw/listbox.h +++ b/include/wx/msw/listbox.h @@ -115,9 +115,6 @@ public: virtual void SetupColours(); protected: - // do we have multiple selections? - bool HasMultipleSelection() const; - // free memory (common part of Clear() and dtor) void Free(); diff --git a/include/wx/msw/window.h b/include/wx/msw/window.h index 53d44496b4..e51bc7dd46 100644 --- a/include/wx/msw/window.h +++ b/include/wx/msw/window.h @@ -1,8 +1,9 @@ ///////////////////////////////////////////////////////////////////////////// -// Name: window.h +// Name: wx/msw/window.h // Purpose: wxWindow class // Author: Julian Smart -// Modified by: +// Modified by: Vadim Zeitlin on 13.05.99: complete refont of message handling, +// elimination of Default(), ... // Created: 01/02/97 // RCS-ID: $Id$ // Copyright: (c) Julian Smart and Markus Holzem @@ -20,8 +21,6 @@ #pragma interface "window.h" #endif -// #include "wx/msw/winundef.h" - // VZ: apparently some version of Windows send extra mouse move messages after // a mouse click. My tests under NT 4.0 and 95 didn't show it so I'm // tempted to think that it was just an effect of a poor mouse and so the @@ -29,12 +28,6 @@ // to reenable it #define wxUSE_MOUSEEVENT_HACK 0 -// --------------------------------------------------------------------------- -// forward declarations -// --------------------------------------------------------------------------- - -class WXDLLEXPORT wxButton; - // --------------------------------------------------------------------------- // constants // --------------------------------------------------------------------------- @@ -50,23 +43,23 @@ enum // wxWindow declaration for MSW // --------------------------------------------------------------------------- -class WXDLLEXPORT wxWindow : public wxWindowBase +class WXDLLEXPORT wxWindowMSW : public wxWindowBase { public: - wxWindow() { Init(); } + wxWindowMSW() { Init(); } - wxWindow(wxWindow *parent, - wxWindowID id, - const wxPoint& pos = wxDefaultPosition, - const wxSize& size = wxDefaultSize, - long style = 0, - const wxString& name = wxPanelNameStr) + wxWindowMSW(wxWindow *parent, + wxWindowID id, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = 0, + const wxString& name = wxPanelNameStr) { Init(); Create(parent, id, pos, size, style, name); } - virtual ~wxWindow(); + virtual ~wxWindowMSW(); bool Create(wxWindow *parent, wxWindowID id, @@ -87,7 +80,7 @@ public: virtual void SetFocus(); - virtual bool Reparent( wxWindow *newParent ); + virtual bool Reparent(wxWindowBase *newParent); virtual void WarpPointer(int x, int y); virtual void CaptureMouse(); @@ -437,8 +430,8 @@ private: // the helper functions used by HandleChar/KeyXXX methods wxKeyEvent CreateKeyEvent(wxEventType evType, int id, WXLPARAM lp) const; - DECLARE_DYNAMIC_CLASS(wxWindow); - DECLARE_NO_COPY_CLASS(wxWindow); + DECLARE_DYNAMIC_CLASS(wxWindowMSW); + DECLARE_NO_COPY_CLASS(wxWindowMSW); DECLARE_EVENT_TABLE() }; diff --git a/include/wx/scrolwin.h b/include/wx/scrolwin.h index 44298184bb..0da445f5f4 100644 --- a/include/wx/scrolwin.h +++ b/include/wx/scrolwin.h @@ -1,6 +1,115 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: include/wx/scrolwin.h +// Purpose: wxScrolledWindow, wxScrolledControl and wxScrollHelper +// Author: Vadim Zeitlin +// Modified by: +// Created: 30.08.00 +// RCS-ID: $Id$ +// Copyright: (c) 2000 Vadim Zeitlin +// Licence: wxWindows licence +///////////////////////////////////////////////////////////////////////////// + #ifndef _WX_SCROLWIN_H_BASE_ #define _WX_SCROLWIN_H_BASE_ +// ---------------------------------------------------------------------------- +// wxScrollHelper: this class implements the scrolling logic which is used by +// wxScrolledWindow and wxScrolledControl. It is a mix-in: just derive from it +// to implement scrolling in your class. +// ---------------------------------------------------------------------------- + +class WXDLLEXPORT wxScrollHelper +{ +public: + // ctor and dtor + wxScrollHelper(wxWindow *winToScroll = (wxWindow *)NULL); + void SetWindow(wxWindow *winToScroll); + virtual ~wxScrollHelper(); + + // configure the scrolling + virtual void SetScrollbars(int pixelsPerUnitX, int pixelsPerUnitY, + int noUnitsX, int noUnitsY, + int xPos = 0, int yPos = 0, + bool noRefresh = FALSE ); + + // scroll to the given (in logical coords) position + virtual void Scroll(int x, int y); + + // get/set the page size for this orientation (wxVERTICAL/wxHORIZONTAL) + int GetScrollPageSize(int orient) const; + void SetScrollPageSize(int orient, int pageSize); + + // get the size of one logical unit in physical ones + virtual void GetScrollPixelsPerUnit(int *pixelsPerUnitX, + int *pixelsPerUnitY) const; + + // Enable/disable Windows scrolling in either direction. If TRUE, wxWindows + // scrolls the canvas and only a bit of the canvas is invalidated; no + // Clear() is necessary. If FALSE, the whole canvas is invalidated and a + // Clear() is necessary. Disable for when the scroll increment is used to + // actually scroll a non-constant distance + virtual void EnableScrolling(bool x_scrolling, bool y_scrolling); + + // Get the view start + virtual void GetViewStart(int *x, int *y) const; + + // Actual size in pixels when scrolling is taken into account + virtual void GetVirtualSize(int *x, int *y) const; + + // Set the scale factor, used in PrepareDC + void SetScale(double xs, double ys) { m_scaleX = xs; m_scaleY = ys; } + double GetScaleX() const { return m_scaleX; } + double GetScaleY() const { return m_scaleY; } + + // translate between scrolled and unscrolled coordinates + virtual void CalcScrolledPosition(int x, int y, int *xx, int *yy) const; + virtual void CalcUnscrolledPosition(int x, int y, int *xx, int *yy) const; + + // Adjust the scrollbars + virtual void AdjustScrollbars(void); + + // Calculate scroll increment + virtual int CalcScrollInc(wxScrollWinEvent& event); + + // Normally the wxScrolledWindow will scroll itself, but in some rare + // occasions you might want it to scroll another window (e.g. a child of it + // in order to scroll only a portion the area between the scrollbars + // (spreadsheet: only cell area will move). + virtual void SetTargetWindow( wxWindow *target ); + virtual wxWindow *GetTargetWindow() const; + + // Override this function to draw the graphic (or just process EVT_PAINT) + virtual void OnDraw(wxDC& WXUNUSED(dc)) { } + + // change the DC origin according to the scroll position. + void DoPrepareDC(wxDC& dc); + + // the methods to be called from the window event handlers + void HandleOnScroll(wxScrollWinEvent& event); + void HandleOnSize(wxSizeEvent& event); + void HandleOnPaint(wxPaintEvent& event); + void HandleOnChar(wxKeyEvent& event); + +protected: + wxWindow *m_win, + *m_targetWindow; + + int m_xScrollPixelsPerLine; + int m_yScrollPixelsPerLine; + int m_xScrollPosition; + int m_yScrollPosition; + int m_xScrollLines; + int m_yScrollLines; + int m_xScrollLinesPerPage; + int m_yScrollLinesPerPage; + + bool m_xScrollingEnabled; + bool m_yScrollingEnabled; + + double m_scaleX; + double m_scaleY; +}; + #include "wx/generic/scrolwin.h" #endif diff --git a/include/wx/string.h b/include/wx/string.h index fe9787845f..0b696e5a32 100644 --- a/include/wx/string.h +++ b/include/wx/string.h @@ -1008,6 +1008,7 @@ public: void Remove(const wxChar *sz); // remove item by index void Remove(size_t nIndex); + void RemoveAt(size_t nIndex) { Remove(nIndex); } // sorting // sort array elements in alphabetical order (or reversed alphabetical diff --git a/include/wx/univ/button.h b/include/wx/univ/button.h index c2849199cf..b22305bcf5 100644 --- a/include/wx/univ/button.h +++ b/include/wx/univ/button.h @@ -106,8 +106,9 @@ public: protected: virtual bool PerformAction(const wxControlAction& action, - const wxEvent& event); - virtual wxSize DoGetBestSize() const; + long numArg = 0, + const wxString& strArg = wxEmptyString); + virtual wxSize DoGetBestClientSize() const; virtual void DoDraw(wxControlRenderer *renderer); // common part of all ctors diff --git a/include/wx/univ/control.h b/include/wx/univ/control.h index ec9478f404..9caee6e0d4 100644 --- a/include/wx/univ/control.h +++ b/include/wx/univ/control.h @@ -22,32 +22,10 @@ class WXDLLEXPORT wxRenderer; // ---------------------------------------------------------------------------- // 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 -// input event may result in several control actions (e.g. a macro expansion -// in the text control) we define an array of actions as well. +// later it might become an atom (i.e. an opaque handler to string). // ---------------------------------------------------------------------------- typedef wxString wxControlAction; -class WXDLLEXPORT wxControlActions : public wxArrayString -{ -public: - wxControlActions() { } - wxControlActions(const wxControlAction& action) - { wxArrayString::Add(action); } - wxControlActions(const wxChar *action) - { wxArrayString::Add(action); } - - wxControlActions& Add(const wxControlActions& other) - { - size_t count = other.GetCount(); - for ( size_t n = 0; n < count; n++ ) - { - wxArrayString::Add(other[n]); - } - - return *this; - } -}; // the list of actions which apply to all controls (other actions are defined // in the controls headers) @@ -87,7 +65,7 @@ public: virtual void SetLabel(const wxString &label); virtual wxString GetLabel() const; - // implementation only from now on + // wxUniversal-specific methods // return the index of the accel char in the label or -1 if none int GetAccelIndex() const { return m_indexAccel; } @@ -98,13 +76,24 @@ public: return m_indexAccel == -1 ? _T('\0') : m_label[m_indexAccel]; } - // perform the action which resulted from the translation of the event - // (the exact event type depends on the action), return TRUE if the - // control must be updated + // perform a control-dependent action: an action may have an optional + // numeric and another (also optional) string argument whose interpretation + // depends on the action + // + // NB: we might use ellipsis in PerformAction() declaration but this + // wouldn't be more efficient than always passing 2 unused parameters + // but would be more difficult. Another solution would be to have + // several overloaded versions but this will expose the problem of + // virtual function hiding we don't have here. virtual bool PerformAction(const wxControlAction& action, - const wxEvent& event); + long numArg = 0l, + const wxString& strArg = wxEmptyString); protected: + // by default static controls don't have the border and all the others do + // have it + virtual wxBorder GetDefaultBorder() const; + // create the event translator object for this control: the base class // action creates the default one which doesn't do anything virtual wxInputHandler *CreateInputHandler() const; @@ -119,9 +108,6 @@ private: // common part of all ctors void Init(); - // common part of OnMouse/OnKeyDown/Up - void PerformActions(const wxControlActions& actions, const wxEvent& event); - // input processor wxInputHandler *m_handler; diff --git a/include/wx/univ/inphand.h b/include/wx/univ/inphand.h index 5534674dff..da1ba41a37 100644 --- a/include/wx/univ/inphand.h +++ b/include/wx/univ/inphand.h @@ -17,7 +17,9 @@ #pragma interface "inphand.h" #endif -#include "wx/control.h" // for wxControlAction(s) +#include "wx/control.h" // for wxControlAction(s) + +#include "wx/univ/renderer.h" // for wxHitTest class WXDLLEXPORT wxRenderer; class WXDLLEXPORT wxScrollBar; @@ -30,31 +32,27 @@ class WXDLLEXPORT wxInputHandler { public: // map a keyboard event to one or more actions (pressed == TRUE if the key - // was pressed, FALSE if released) - virtual wxControlActions Map(wxControl *control, - const wxKeyEvent& event, - bool pressed) = 0; + // was pressed, FALSE if released), returns TRUE if something was done + virtual bool HandleKey(wxControl *control, + const wxKeyEvent& event, + bool pressed) = 0; // map a mouse (click) event to one or more actions - virtual wxControlActions Map(wxControl *control, - const wxMouseEvent& event) = 0; + virtual bool HandleMouse(wxControl *control, + const wxMouseEvent& event) = 0; - // do something with mouse move/enter/leave: unlike the Map() functions, - // this doesn't translate the event into an action but, normally, uses the - // renderer directly to change the controls appearance as needed - // - // this is faster than using Map() which is important for mouse move - // events as they occur often and in a quick succession - // - // return TRUE to refresh the control, FALSE otherwise - virtual bool OnMouseMove(wxControl *control, const wxMouseEvent& event); + // handle mouse movement (or enter/leave) event: it is separated from + // HandleMouse() for convenience as many controls don't care about mouse + // movements at all + virtual bool HandleMouseMove(wxControl *control, + const wxMouseEvent& event); // do something with focus set/kill event: this is different from - // OnMouseMove() as the mouse maybe over the control without it having + // HandleMouseMove() as the mouse maybe over the control without it having // focus // // return TRUE to refresh the control, FALSE otherwise - virtual bool OnFocus(wxControl *control, const wxFocusEvent& event); + virtual bool HandleFocus(wxControl *control, const wxFocusEvent& event); // virtual dtor for any base class virtual ~wxInputHandler(); @@ -76,17 +74,17 @@ class WXDLLEXPORT wxStdInputHandler : public wxInputHandler public: wxStdInputHandler(wxInputHandler *handler) : m_handler(handler) { } - virtual wxControlActions Map(wxControl *control, - const wxKeyEvent& event, - bool pressed) - { return m_handler->Map(control, event, pressed); } - virtual wxControlActions Map(wxControl *control, - const wxMouseEvent& event) - { return m_handler->Map(control, event); } - virtual bool OnMouseMove(wxControl *control, const wxMouseEvent& event) - { return m_handler->OnMouseMove(control, event); } - virtual bool OnFocus(wxControl *control, const wxFocusEvent& event) - { return m_handler->OnFocus(control, event); } + virtual bool HandleKey(wxControl *control, + const wxKeyEvent& event, + bool pressed) + { return m_handler->HandleKey(control, event, pressed); } + virtual bool HandleMouse(wxControl *control, + const wxMouseEvent& event) + { return m_handler->HandleMouse(control, event); } + virtual bool HandleMouseMove(wxControl *control, const wxMouseEvent& event) + { return m_handler->HandleMouseMove(control, event); } + virtual bool HandleFocus(wxControl *control, const wxFocusEvent& event) + { return m_handler->HandleFocus(control, event); } private: wxInputHandler *m_handler; @@ -102,13 +100,13 @@ class WXDLLEXPORT wxStdButtonInputHandler : public wxStdInputHandler public: wxStdButtonInputHandler(wxInputHandler *inphand); - virtual wxControlActions Map(wxControl *control, - const wxKeyEvent& event, - bool pressed); - virtual wxControlActions Map(wxControl *control, - const wxMouseEvent& event); - virtual bool OnMouseMove(wxControl *control, const wxMouseEvent& event); - virtual bool OnFocus(wxControl *control, const wxFocusEvent& event); + virtual bool HandleKey(wxControl *control, + const wxKeyEvent& event, + bool pressed); + virtual bool HandleMouse(wxControl *control, + const wxMouseEvent& event); + virtual bool HandleMouseMove(wxControl *control, const wxMouseEvent& event); + virtual bool HandleFocus(wxControl *control, const wxFocusEvent& event); private: // the window (button) which has capture or NULL and the flag telling if @@ -130,12 +128,12 @@ public: wxStdScrollBarInputHandler(wxRenderer *renderer, wxInputHandler *inphand); - virtual wxControlActions Map(wxControl *control, - const wxKeyEvent& event, - bool pressed); - virtual wxControlActions Map(wxControl *control, - const wxMouseEvent& event); - virtual bool OnMouseMove(wxControl *control, const wxMouseEvent& event); + virtual bool HandleKey(wxControl *control, + const wxKeyEvent& event, + bool pressed); + virtual bool HandleMouse(wxControl *control, + const wxMouseEvent& event); + virtual bool HandleMouseMove(wxControl *control, const wxMouseEvent& event); virtual ~wxStdScrollBarInputHandler(); @@ -143,8 +141,7 @@ public: // // return TRUE to continue scrolling, FALSE to stop the timer virtual bool OnScrollTimer(wxScrollBar *scrollbar, - const wxControlAction& action, - const wxMouseEvent& event); + const wxControlAction& action); protected: // the methods which must be overridden in the derived class @@ -169,6 +166,13 @@ protected: // stop scrolling because we reached the end point void StopScrolling(wxScrollBar *scrollbar); + // get the mouse coordinates in the scrollbar direction from the event + wxCoord GetMouseCoord(const wxScrollBar *scrollbar, + const wxMouseEvent& event) const; + + // generate a "thumb move" action for this mouse event + void HandleThumbMove(wxScrollBar *scrollbar, const wxMouseEvent& event); + // the window (scrollbar) which has capture or NULL and the flag telling if // the mouse is inside the element which captured it or not wxWindow *m_winCapture; @@ -184,9 +188,32 @@ protected: // the renderer (we use it only for hit testing) wxRenderer *m_renderer; + // the offset of the top/left of the scrollbar relative to the mouse to + // keep during the thumb drag + int m_ofsMouse; + // the timer for generating scroll events when the mouse stays pressed on // a scrollbar class wxTimer *m_timerScroll; }; +// ---------------------------------------------------------------------------- +// wxStdListboxInputHandler: handles mouse and kbd in a single or multi +// selection listbox +// ---------------------------------------------------------------------------- + +class WXDLLEXPORT wxStdListboxInputHandler : public wxStdInputHandler +{ +public: + wxStdListboxInputHandler(wxInputHandler *inphand); + + virtual bool HandleKey(wxControl *control, + const wxKeyEvent& event, + bool pressed); + virtual bool HandleMouse(wxControl *control, + const wxMouseEvent& event); + virtual bool HandleMouseMove(wxControl *control, + const wxMouseEvent& event); +}; + #endif // _WX_UNIV_INPHAND_H_ diff --git a/include/wx/univ/listbox.h b/include/wx/univ/listbox.h new file mode 100644 index 0000000000..1bf6758f4f --- /dev/null +++ b/include/wx/univ/listbox.h @@ -0,0 +1,191 @@ +/////////////////////////////////////////////////////////////////////////////// +// Name: wx/univ/listbox.h +// Purpose: the universal listbox +// Author: Vadim Zeitlin +// Modified by: +// Created: 30.08.00 +// RCS-ID: $Id$ +// Copyright: (c) 2000 Vadim Zeitlin +// Licence: wxWindows licence +/////////////////////////////////////////////////////////////////////////////// + +#ifndef _WX_UNIV_LISTBOX_H_ +#define _WX_UNIV_LISTBOX_H_ + +#ifdef __GNUG__ + #pragma implementation "univlistbox.h" +#endif + +#include "wx/scrolwin.h" // for wxScrollHelper + +// ---------------------------------------------------------------------------- +// the actions supported by this control +// ---------------------------------------------------------------------------- + +// change the current item +#define wxACTION_LISTBOX_SETFOCUS _T("setfocus") // select the item +#define wxACTION_LISTBOX_MOVEDOWN _T("down") // select item below +#define wxACTION_LISTBOX_MOVEUP _T("up") // select item above +#define wxACTION_LISTBOX_PAGEDOWN _T("pagedown") // go page down +#define wxACTION_LISTBOX_PAGEUP _T("pageup") // go page up +#define wxACTION_LISTBOX_START _T("start") // go to first item +#define wxACTION_LISTBOX_END _T("end") // go to last item + +// do something with the current item +#define wxACTION_LISTBOX_ACTIVATE _T("activate") // activate (choose) +#define wxACTION_LISTBOX_TOGGLE _T("toggle") // togglee selected state +#define wxACTION_LISTBOX_SELECT _T("select") // select/focus +#define wxACTION_LISTBOX_UNSELECT _T("unselect") // unselect/unfocus + +// ---------------------------------------------------------------------------- +// wxListBox: a list of selectable items +// ---------------------------------------------------------------------------- + +class wxListBox : public wxListBoxBase, public wxScrollHelper +{ +public: + // ctors and such + wxListBox() { Init(); } + wxListBox(wxWindow *parent, + wxWindowID id, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + int n = 0, const wxString choices[] = (const wxString *) NULL, + long style = 0, + const wxValidator& validator = wxDefaultValidator, + const wxString& name = wxListBoxNameStr ) + { + Init(); + + Create(parent, id, pos, size, n, choices, style, validator, name); + } + + virtual ~wxListBox(); + + bool Create(wxWindow *parent, + wxWindowID id, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + int n = 0, const wxString choices[] = (const wxString *) NULL, + long style = 0, + const wxValidator& validator = wxDefaultValidator, + const wxString& name = wxListBoxNameStr); + + // implement the listbox interface defined by wxListBoxBase + virtual void Clear(); + virtual void Delete(int n); + + virtual int GetCount() const + { return (int)m_strings.GetCount(); } + virtual wxString GetString(int n) const + { return m_strings[n]; } + virtual void SetString(int n, const wxString& s) + { m_strings[n] = s; RefreshItem(n); } + virtual int FindString(const wxString& s) const + { return m_strings.Index(s); } + + virtual bool IsSelected(int n) const + { return m_selections.Index(n) != wxNOT_FOUND; } + virtual void SetSelection(int n, bool select = TRUE); + virtual int GetSelection() const; + virtual int GetSelections(wxArrayInt& aSelections) const; + +protected: + virtual int DoAppend(const wxString& item); + virtual void DoInsertItems(const wxArrayString& items, int pos); + virtual void DoSetItems(const wxArrayString& items, void **clientData); + + virtual void DoSetFirstItem(int n); + + virtual void DoSetItemClientData(int n, void* clientData); + virtual void* DoGetItemClientData(int n) const; + virtual void DoSetItemClientObject(int n, wxClientData* clientData); + virtual wxClientData* DoGetItemClientObject(int n) const; + +public: + // override some more base class methods + virtual bool SetFont(const wxFont& font); + + // the wxUniversal-specific additions + + // the current item is the same as the selected one for wxLB_SINGLE + // listboxes but for the other ones it is just the focused item which may + // be selected or not + int GetCurrentItem() const { return m_current; } + void SetCurrentItem(int n); + + // select the item which is diff items below the current one + void ChangeCurrent(int diff); + + // actions + void Activate(); + void Select(bool sel = TRUE); + + // get, calculating it if necessary, the number of items per page and the + // height of each line + int GetItemsPerPage() const; + wxCoord GetLineHeight() const; + + // override the wxControl virtual methods + virtual bool PerformAction(const wxControlAction& action, + long numArg = 0l, + const wxString& strArg = wxEmptyString); + +protected: + virtual wxSize DoGetBestClientSize() const; + virtual void DoDraw(wxControlRenderer *renderer); + + // common part of all ctors + void Init(); + + // event handlers + void OnIdle(wxIdleEvent& event); + void OnSize(wxSizeEvent& event); + + // common part of Clear() and DoSetItems(): clears everything + void DoClear(); + + // refresh the given item(s) or everything + void RefreshItems(int from, int count); + void RefreshItem(int n); + void RefreshAll(); + + // send an event of the given type + bool SendEvent(int item, wxEventType type); + + // calculate the number of items per page using our current size + void CalcItemsPerPage(); + + // the array containing all items (it is sorted if the listbox has + // wxLB_SORT style) + wxArrayString m_strings; + + // this array contains the indices of the selected items (for the single + // selection listboxes only the first element of it is used and contains + // the current selection) + wxArrayInt m_selections; + + // and this one the client data (either void or wxClientData) + wxArrayPtrVoid m_clientData; + + // the current item + int m_current; + +private: + // the range of elements which must be updated: if m_updateCount is 0 no + // update is needed, if it is -1 everything must be updated, otherwise + // m_updateCount items starting from m_updateFrom have to be redrawn + int m_updateFrom, + m_updateCount; + + // the height of one line in the listbox (all lines have the same height) + wxCoord m_lineHeight; + + // the number of items per page + size_t m_itemsPerPage; + + DECLARE_EVENT_TABLE() + DECLARE_DYNAMIC_CLASS(wxListBox) +}; + +#endif // _WX_UNIV_LISTBOX_H_ diff --git a/include/wx/univ/renderer.h b/include/wx/univ/renderer.h index c3729d1d92..948e38ad2c 100644 --- a/include/wx/univ/renderer.h +++ b/include/wx/univ/renderer.h @@ -29,11 +29,13 @@ #define _WX_UNIV_RENDERER_H_ class WXDLLEXPORT wxDC; +class WXDLLEXPORT wxListBox; class WXDLLEXPORT wxScrollBar; class WXDLLEXPORT wxWindow; #include "wx/string.h" #include "wx/gdicmn.h" +#include "wx/scrolbar.h" // for wxScrollBar::Element // ---------------------------------------------------------------------------- // constants @@ -70,6 +72,7 @@ public: // draw the controls background virtual void DrawBackground(wxDC& dc, + const wxColour& col, const wxRect& rect, int flags) = 0; @@ -120,18 +123,24 @@ public: const wxRect& rect, int flags = 0) = 0; - // draw a scrollbar: thumb positions are in percent of the full scrollbar - // length and the flags array contains the flags corresponding to each of - // wxScrollBar::Elements - virtual void DrawScrollbar(wxDC& dc, - wxOrientation orient, - int thumbPosStart, - int thumbPosEnd, - const wxRect& rect, - const int *flags = NULL) = 0; + // draw the scrollbar thumb + virtual void DrawScrollbarThumb(wxDC& dc, + 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 + // draw a (part of) scrollbar shaft + virtual void DrawScrollbarShaft(wxDC& dc, + const wxRect& rect, + int flags = 0) = 0; + + // draw an item of a wxControlWithItems + virtual void DrawItem(wxDC& dc, + const wxString& label, + const wxRect& rect, + int flags = 0) = 0; + + // geometry functions + // ------------------ // 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 @@ -142,13 +151,20 @@ public: // hit testing functions // --------------------- + // gets the bounding box for a scrollbar element for the given (by default + // - current) thumb position + virtual wxRect GetScrollbarRect(const wxScrollBar *scrollbar, + wxScrollBar::Element elem, + int thumbPos = -1) const = 0; + // returns one of wxHT_SCROLLBAR_XXX constants virtual wxHitTest HitTestScrollbar(const wxScrollBar *scrollbar, const wxPoint& pt) const = 0; // translate the scrollbar position (in logical units) into physical // coordinate (in pixels) and the other way round - virtual wxCoord ScrollbarToPixel(const wxScrollBar *scrollbar) = 0; + virtual wxCoord ScrollbarToPixel(const wxScrollBar *scrollbar, + int thumbPos = -1) = 0; virtual int PixelToScrollbar(const wxScrollBar *scrollbar, wxCoord coord) = 0; @@ -165,10 +181,15 @@ protected: // standard scrollbar hit testing: this assumes that it only has 2 arrows // and a thumb, so the themes which have more complicated scrollbars (e.g. // BeOS) can't use this method + static wxRect StandardGetScrollbarRect(const wxScrollBar *scrollbar, + wxScrollBar::Element elem, + int thumbPos, + const wxSize& sizeArrow); static wxHitTest StandardHitTestScrollbar(const wxScrollBar *scrollbar, const wxPoint& pt, const wxSize& sizeArrow); static wxCoord StandardScrollbarToPixel(const wxScrollBar *scrollbar, + int thumbPos, const wxSize& sizeArrow); static int StandardPixelToScrollbar(const wxScrollBar *scrollbar, wxCoord coord, @@ -190,9 +211,10 @@ public: wxDelegateRenderer(wxRenderer *renderer) : m_renderer(renderer) { } virtual void DrawBackground(wxDC& dc, + const wxColour& col, const wxRect& rect, int flags) - { m_renderer->DrawBackground(dc, rect, flags); } + { m_renderer->DrawBackground(dc, col, rect, flags); } virtual void DrawLabel(wxDC& dc, const wxString& label, const wxBitmap& image, @@ -232,23 +254,33 @@ public: 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, - const int *flags = NULL) - { m_renderer->DrawScrollbar(dc, orient, thumbPosStart, - thumbPosEnd, rect, flags); } + virtual void DrawScrollbarThumb(wxDC& dc, + const wxRect& rect, + int flags = 0) + { m_renderer->DrawScrollbarThumb(dc, rect, flags); } + virtual void DrawScrollbarShaft(wxDC& dc, + const wxRect& rect, + int flags = 0) + { m_renderer->DrawScrollbarShaft(dc, rect, flags); } + virtual void DrawItem(wxDC& dc, + const wxString& label, + const wxRect& rect, + int flags = 0) + { m_renderer->DrawItem(dc, label, rect, flags); } virtual void AdjustSize(wxSize *size, const wxWindow *window) { m_renderer->AdjustSize(size, window); } + virtual wxRect GetScrollbarRect(const wxScrollBar *scrollbar, + wxScrollBar::Element elem, + int thumbPos = -1) const + { return m_renderer->GetScrollbarRect(scrollbar, elem, thumbPos); } virtual wxHitTest HitTestScrollbar(const wxScrollBar *scrollbar, const wxPoint& pt) const { return m_renderer->HitTestScrollbar(scrollbar, pt); } - virtual wxCoord ScrollbarToPixel(const wxScrollBar *scrollbar) - { return m_renderer->ScrollbarToPixel(scrollbar); } + virtual wxCoord ScrollbarToPixel(const wxScrollBar *scrollbar, + int thumbPos = -1) + { return m_renderer->ScrollbarToPixel(scrollbar, thumbPos); } virtual int PixelToScrollbar(const wxScrollBar *scrollbar, wxCoord coord) { return m_renderer->PixelToScrollbar(scrollbar, coord); } @@ -271,6 +303,8 @@ public: // operations void DrawLabel(const wxBitmap& bitmap = wxNullBitmap, wxCoord marginX = 0, wxCoord marginY = 0); + void DrawItems(const wxListBox *listbox, + size_t itemFirst, size_t itemLast); void DrawBorder(); void DrawButtonBorder(); // the line must be either horizontal or vertical @@ -282,7 +316,7 @@ public: int alignment = wxALIGN_CENTRE | wxALIGN_CENTRE_VERTICAL, wxStretch stretch = wxSTRETCH_NOT); void DrawBackgroundBitmap(); - void DrawScrollbar(const wxScrollBar *scrollbar); + void DrawScrollbar(const wxScrollBar *scrollbar, int thumbPosOld); // accessors wxWindow *GetWindow() const { return m_window; } diff --git a/include/wx/univ/scrolbar.h b/include/wx/univ/scrolbar.h index 12e021b597..bca358022c 100644 --- a/include/wx/univ/scrolbar.h +++ b/include/wx/univ/scrolbar.h @@ -16,8 +16,6 @@ #pragma interface "univscrolbar.h" #endif -#include "wx/univ/renderer.h" // for wxHitTest - class WXDLLEXPORT wxInputHandler; // ---------------------------------------------------------------------------- @@ -100,16 +98,20 @@ public: void ScrollPages(int nPages); virtual bool PerformAction(const wxControlAction& action, - const wxEvent& event); + long numArg = 0, + const wxString& strArg = wxEmptyString); // wxScrollBar sub elements state (combination of wxCONTROL_XXX) - void SetState(Element which, int flags) { m_elementsState[which] = flags; } + void SetState(Element which, int flags); int GetState(Element which) const { return m_elementsState[which]; } protected: - virtual wxSize DoGetBestSize() const; + virtual wxSize DoGetBestClientSize() const; virtual void DoDraw(wxControlRenderer *renderer); + // event handler + void OnIdle(wxIdleEvent& event); + // SetThumbPosition() helper void DoSetThumb(int thumbPos); @@ -117,17 +119,15 @@ protected: void Init(); private: - // get the mouse coordinates in the scrollbar direction from a - // wxMouseEvent (the event *must* really be of this type!) - wxCoord GetMouseCoord(const wxEvent& event) const; - // 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) + // the current and previous (after last refresh - this is used for + // repainting optimisation) 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; + m_thumbPos, + m_thumbPosOld; // the page size, i.e. the number of lines by which to scroll when page // up/down action is performed @@ -136,10 +136,10 @@ private: // the state of the sub elements int m_elementsState[Element_Max]; - // the offset of the top/left of the scrollbar relative to the mouse to - // keep during the thumb drag - int m_ofsMouse; + // the dirty flag: if set, scrollbar must be updated + bool m_dirty; + DECLARE_EVENT_TABLE() DECLARE_DYNAMIC_CLASS(wxScrollBar) }; diff --git a/include/wx/univ/setup.h b/include/wx/univ/setup.h index 71ac6609f9..99c2b0ac71 100644 --- a/include/wx/univ/setup.h +++ b/include/wx/univ/setup.h @@ -74,7 +74,7 @@ #define wxUSE_CHOICE 0 #define wxUSE_COMBOBOX 0 #define wxUSE_GAUGE 0 -#define wxUSE_LISTBOX 0 +#define wxUSE_LISTBOX 1 #define wxUSE_LISTCTRL 0 #define wxUSE_RADIOBOX 0 #define wxUSE_RADIOBTN 0 diff --git a/include/wx/univ/statbmp.h b/include/wx/univ/statbmp.h index 90da398bf7..b3b045a4bc 100644 --- a/include/wx/univ/statbmp.h +++ b/include/wx/univ/statbmp.h @@ -64,7 +64,7 @@ public: wxIcon GetIcon() const; private: - virtual wxSize DoGetBestSize() const; + virtual wxSize DoGetBestClientSize() const; virtual void DoDraw(wxControlRenderer *renderer); // the bitmap which we show diff --git a/include/wx/univ/stattext.h b/include/wx/univ/stattext.h index c7dca9d350..f6ef3232cd 100644 --- a/include/wx/univ/stattext.h +++ b/include/wx/univ/stattext.h @@ -55,7 +55,7 @@ public: protected: // calculate the optimal size for the label - virtual wxSize DoGetBestSize() const; + virtual wxSize DoGetBestClientSize() const; // draw the control virtual void DoDraw(wxControlRenderer *renderer); diff --git a/include/wx/univ/window.h b/include/wx/univ/window.h index a9e30a927d..07ef1ac8b2 100644 --- a/include/wx/univ/window.h +++ b/include/wx/univ/window.h @@ -36,8 +36,14 @@ enum wxCONTROL_PRESSED = 0x00000004, // (button) is pressed wxCONTROL_ISDEFAULT = 0x00000008, // only applies to the buttons wxCONTROL_CURRENT = 0x00000010, // mouse is currently over the control + wxCONTROL_SELECTED = 0x00000020, // selected item in e.g. listbox + wxCONTROL_CHECKED = 0x00000040, // (check/radio button) is checked - wxCONTROL_FLAGS_MASK = 0x0000001f + wxCONTROL_FLAGS_MASK = 0x0000007f, + + // this is a pseudo flag not used directly by wxRenderer but rather by some + // controls internally + wxCONTROL_DIRTY = 0x80000000 }; // ---------------------------------------------------------------------------- @@ -119,7 +125,7 @@ protected: // returns the (low level) renderer to use for drawing the control by // querying the current theme - wxRenderer *GetRenderer() const; + wxRenderer *GetRenderer() const { return m_renderer; } // draw the control background, return TRUE if done virtual bool DoDrawBackground(wxControlRenderer *renderer); @@ -127,6 +133,12 @@ protected: // draw the controls contents virtual void DoDraw(wxControlRenderer *renderer); + // calculate the best size for the client area of the window: default + // implementation of DoGetBestSize() uses this method and adds the border + // width to the result + virtual wxSize DoGetBestClientSize() const; + virtual wxSize DoGetBestSize() const; + // adjust the size of the window to take into account its borders wxSize AdjustSize(const wxSize& size) const; @@ -139,6 +151,9 @@ protected: // put the scrollbars along the edges of the window void PositionScrollbars(); + // the renderer we use + wxRenderer *m_renderer; + // background bitmap info wxBitmap m_bitmapBg; int m_alignBgBitmap; diff --git a/samples/univ/univ.cpp b/samples/univ/univ.cpp index f3e3e95e0e..163499df16 100644 --- a/samples/univ/univ.cpp +++ b/samples/univ/univ.cpp @@ -36,6 +36,7 @@ #include "wx/bmpbuttn.h" #include "wx/button.h" + #include "wx/listbox.h" #include "wx/scrolbar.h" #include "wx/scrolwin.h" #include "wx/statbox.h" @@ -47,6 +48,8 @@ #include "wx/univ/theme.h" +//#define DEBUG_SCROLL + // ---------------------------------------------------------------------------- // resources // ---------------------------------------------------------------------------- @@ -184,7 +187,10 @@ bool MyUnivApp::OnInit() wxFrame *frame = new MyUnivFrame(_T("wxUniversal demo")); frame->Show(); +#ifdef DEBUG_SCROLL wxLog::AddTraceMask(_T("scroll")); +#endif + wxLog::AddTraceMask(_T("listbox")); return TRUE; } @@ -194,7 +200,7 @@ bool MyUnivApp::OnInit() // ---------------------------------------------------------------------------- MyUnivFrame::MyUnivFrame(const wxString& title) - : wxFrame(NULL, -1, title, wxDefaultPosition, wxSize(600, 600)) + : wxFrame(NULL, -1, title, wxDefaultPosition, wxSize(700, 600)) { SetBackgroundColour(wxGetApp().GetBgColour()); @@ -295,6 +301,17 @@ MyUnivFrame::MyUnivFrame(const wxString& title) ); bmpBtn->SetBitmapSelected(bmp2); bmpBtn->SetBitmapFocus(bmp3); + + static const wxString choices[] = + { + _T("This"), + _T("is one of my"), + _T("really"), + _T("wonderful"), + _T("examples."), + }; + new wxListBox(this, -1, wxPoint(550, 10), wxDefaultSize, + WXSIZEOF(choices), choices); } void MyUnivFrame::OnButton(wxCommandEvent& event) @@ -331,10 +348,14 @@ void MyUnivCanvas::OnPaint(wxPaintEvent& event) s_oddRepaint = !s_oddRepaint; wxCoord x, y; GetViewStart(&x, &y); +#ifdef DEBUG_SCROLL wxLogDebug("Repainting with %s pen (at %dx%d)", s_oddRepaint ? "red" : "green", x, y); +#endif // DEBUG_SCROLL dc.SetPen(s_oddRepaint ? *wxRED_PEN: *wxGREEN_PEN); + dc.SetTextForeground(s_oddRepaint ? *wxRED : *wxGREEN); + dc.DrawLine(0, 0, 1000, 1000); dc.DrawText(_T("This is the top of the canvas"), 10, 10); dc.DrawLabel(_T("This is the bottom of the canvas"), diff --git a/src/common/event.cpp b/src/common/event.cpp index 3ace246251..161311328d 100644 --- a/src/common/event.cpp +++ b/src/common/event.cpp @@ -397,7 +397,7 @@ void wxKeyEvent::CopyObject(wxObject& obj_d) const obj->m_x = m_x; obj->m_y = m_y; obj->m_keyCode = m_keyCode; - + obj->m_shiftDown = m_shiftDown; obj->m_controlDown = m_controlDown; obj->m_metaDown = m_metaDown; @@ -643,7 +643,7 @@ void wxEvtHandler::AddPendingEvent(wxEvent& event) wxPendingEvents->Append(this); wxLEAVE_CRIT_SECT(*wxPendingEventsLocker); - + // 3) Inform the system that new pending events are somwehere, // and that these should be processed in idle time. wxWakeUpIdle(); @@ -664,7 +664,7 @@ void wxEvtHandler::ProcessPendingEvents() delete node; // In ProcessEvent, new events might get added and - // we can safely leave the crtical section here. + // we can safely leave the crtical section here. #if defined(__VISAGECPP__) wxLEAVE_CRIT_SECT( m_eventsLocker); #else @@ -696,13 +696,14 @@ bool wxEvtHandler::ProcessEvent(wxEvent& event) { #if wxUSE_GUI // check that our flag corresponds to reality - wxASSERT( m_isWindow == IsKindOf(CLASSINFO(wxWindow)) ); + wxASSERT_MSG( m_isWindow == IsKindOf(CLASSINFO(wxWindowBase)), + _T("this should [not] be a window but it is [not]") ); #endif // wxUSE_GUI // An event handler can be enabled or disabled if ( GetEvtHandlerEnabled() ) { - + #if 0 /* What is this? When using GUI threads, a non main diff --git a/src/generic/scrolwin.cpp b/src/generic/scrolwin.cpp index 3a82c58361..aeb535791e 100644 --- a/src/generic/scrolwin.cpp +++ b/src/generic/scrolwin.cpp @@ -2,10 +2,11 @@ // Name: generic/scrolwin.cpp // Purpose: wxScrolledWindow implementation // Author: Julian Smart -// Modified by: +// Modified by: Vadim Zeitlin on 31.08.00: wxScrollHelper allows to implement +// scrolling in any class, not just wxScrolledWindow // Created: 01/02/97 // RCS-ID: $Id$ -// Copyright: (c) Julian Smart and Markus Holzem +// Copyright: (c) wxWindows team // Licence: wxWindows license ///////////////////////////////////////////////////////////////////////////// @@ -51,90 +52,119 @@ #endif // ---------------------------------------------------------------------------- -// event tables +// wxScrollHelperEvtHandler: intercept the events from the window and forward +// them to wxScrollHelper // ---------------------------------------------------------------------------- -BEGIN_EVENT_TABLE(wxScrolledWindow, wxPanel) - EVT_SCROLLWIN(wxScrolledWindow::OnScroll) - EVT_SIZE(wxScrolledWindow::OnSize) - EVT_PAINT(wxScrolledWindow::OnPaint) - EVT_CHAR(wxScrolledWindow::OnChar) -END_EVENT_TABLE() +class wxScrollHelperEvtHandler : public wxEvtHandler +{ +public: + wxScrollHelperEvtHandler(wxScrollHelper *scrollHelper) + { + m_scrollHelper = scrollHelper; + } -IMPLEMENT_DYNAMIC_CLASS(wxScrolledWindow, wxPanel) + virtual bool ProcessEvent(wxEvent& event) + { + if ( wxEvtHandler::ProcessEvent(event) ) + return TRUE; + + switch ( event.GetEventType() ) + { + case wxEVT_SCROLLWIN_TOP: + case wxEVT_SCROLLWIN_BOTTOM: + case wxEVT_SCROLLWIN_LINEUP: + case wxEVT_SCROLLWIN_LINEDOWN: + case wxEVT_SCROLLWIN_PAGEUP: + case wxEVT_SCROLLWIN_PAGEDOWN: + case wxEVT_SCROLLWIN_THUMBTRACK: + case wxEVT_SCROLLWIN_THUMBRELEASE: + m_scrollHelper->HandleOnScroll((wxScrollWinEvent&)event); + break; + + case wxEVT_PAINT: + m_scrollHelper->HandleOnPaint((wxPaintEvent&)event); + break; + + case wxEVT_SIZE: + m_scrollHelper->HandleOnSize((wxSizeEvent&)event); + break; + + case wxEVT_CHAR: + m_scrollHelper->HandleOnChar((wxKeyEvent&)event); + break; + + default: + return FALSE; + } + + return TRUE; + } + +private: + wxScrollHelper *m_scrollHelper; +}; // ============================================================================ // implementation // ============================================================================ // ---------------------------------------------------------------------------- -// wxScrolledWindow creation +// wxScrollHelper construction // ---------------------------------------------------------------------------- -wxScrolledWindow::wxScrolledWindow() +wxScrollHelper::wxScrollHelper(wxWindow *win) { - m_xScrollPixelsPerLine = 0; - m_yScrollPixelsPerLine = 0; - m_xScrollingEnabled = TRUE; - m_yScrollingEnabled = TRUE; - m_xScrollPosition = 0; - m_yScrollPosition = 0; - m_xScrollLines = 0; - m_yScrollLines = 0; - m_xScrollLinesPerPage = 0; + m_xScrollPixelsPerLine = + m_yScrollPixelsPerLine = + m_xScrollPosition = + m_yScrollPosition = + m_xScrollLines = + m_yScrollLines = + m_xScrollLinesPerPage = m_yScrollLinesPerPage = 0; - m_scaleX = 1.0; - m_scaleY = 1.0; - m_targetWindow = (wxWindow*) NULL; -} -bool wxScrolledWindow::Create(wxWindow *parent, - wxWindowID id, - const wxPoint& pos, - const wxSize& size, - long style, - const wxString& name) -{ - m_xScrollPixelsPerLine = 0; - m_yScrollPixelsPerLine = 0; - m_xScrollingEnabled = TRUE; + m_xScrollingEnabled = m_yScrollingEnabled = TRUE; - m_xScrollPosition = 0; - m_yScrollPosition = 0; - m_xScrollLines = 0; - m_yScrollLines = 0; - m_xScrollLinesPerPage = 0; - m_yScrollLinesPerPage = 0; - m_scaleX = 1.0; + + m_scaleX = m_scaleY = 1.0; - m_targetWindow = this; + m_win = + m_targetWindow = (wxWindow *)NULL; - bool ok = wxPanel::Create(parent, id, pos, size, style, name); - -#ifdef __WXMSW__ - // we need to process arrows ourselves for scrolling - m_lDlgCode |= DLGC_WANTARROWS; -#endif // __WXMSW__ - - return ok; + if ( win ) + SetWindow(win); } -wxScrolledWindow::~wxScrolledWindow() +void wxScrollHelper::SetWindow(wxWindow *win) { + wxCHECK_RET( win, _T("wxScrollHelper needs a window to scroll") ); + + m_targetWindow = m_win = win; + + // install the event handler which will intercept the events we're + // interested in + m_win->PushEventHandler(new wxScrollHelperEvtHandler(this)); +} + +wxScrollHelper::~wxScrollHelper() +{ + if ( m_targetWindow ) + m_targetWindow->PopEventHandler(TRUE /* do delete it */); } // ---------------------------------------------------------------------------- // setting scrolling parameters // ---------------------------------------------------------------------------- -/* - * pixelsPerUnitX/pixelsPerUnitY: number of pixels per unit (e.g. pixels per text line) - * noUnitsX/noUnitsY: : no. units per scrollbar - */ -void wxScrolledWindow::SetScrollbars (int pixelsPerUnitX, int pixelsPerUnitY, - int noUnitsX, int noUnitsY, - int xPos, int yPos, bool noRefresh ) +void wxScrollHelper::SetScrollbars(int pixelsPerUnitX, + int pixelsPerUnitY, + int noUnitsX, + int noUnitsY, + int xPos, + int yPos, + bool noRefresh) { int xpos, ypos; @@ -142,14 +172,12 @@ void wxScrolledWindow::SetScrollbars (int pixelsPerUnitX, int pixelsPerUnitY, bool do_refresh = ( (noUnitsX != 0 && m_xScrollLines == 0) || - (noUnitsX < m_xScrollLines && xpos > pixelsPerUnitX*noUnitsX) || + (noUnitsX < m_xScrollLines && xpos > pixelsPerUnitX*noUnitsX) || (noUnitsY != 0 && m_yScrollLines == 0) || (noUnitsY < m_yScrollLines && ypos > pixelsPerUnitY*noUnitsY) || (xPos != m_xScrollPosition) || (yPos != m_yScrollPosition) -// (pixelsPerUnitX != m_xScrollPixelsPerLine) || -// (pixelsPerUnitY != m_yScrollPixelsPerLine) ); m_xScrollPixelsPerLine = pixelsPerUnitX; @@ -165,21 +193,21 @@ void wxScrolledWindow::SetScrollbars (int pixelsPerUnitX, int pixelsPerUnitY, // be entirely generic because it relies on the wxWindowDC implementation // to duplicate X drawing calls for the backing pixmap. - if ((m_windowStyle & wxRETAINED) == wxRETAINED) + if ( m_targetWindow->GetWindowStyle() & wxRETAINED ) { - Display* dpy = XtDisplay((Widget) GetMainWidget()); + Display* dpy = XtDisplay((Widget)m_targetWindow->GetMainWidget()); int totalPixelWidth = m_xScrollLines * m_xScrollPixelsPerLine; int totalPixelHeight = m_yScrollLines * m_yScrollPixelsPerLine; - if (m_backingPixmap && - !((m_pixmapWidth == totalPixelWidth) && - (m_pixmapHeight == totalPixelHeight))) + if (m_targetWindow->m_backingPixmap && + !((m_targetWindow->m_pixmapWidth == totalPixelWidth) && + (m_targetWindow->m_pixmapHeight == totalPixelHeight))) { - XFreePixmap (dpy, (Pixmap) m_backingPixmap); - m_backingPixmap = (WXPixmap) 0; + XFreePixmap (dpy, (Pixmap) m_targetWindow->m_backingPixmap); + m_targetWindow->m_backingPixmap = (WXPixmap) 0; } - if (!m_backingPixmap && + if (!m_targetWindow->m_backingPixmap && (noUnitsX != 0) && (noUnitsY != 0)) { int depth = wxDisplayDepth(); @@ -197,16 +225,6 @@ void wxScrolledWindow::SetScrollbars (int pixelsPerUnitX, int pixelsPerUnitY, if (do_refresh && !noRefresh) m_targetWindow->Refresh(); -#ifdef __WXMSW__ - // GRG: if this turns out to be really necessary, we could - // at least move it to the above if { ... } so that it is - // only done if noRefresh = FALSE (the default). OTOH, if - // this doesn't break anything, which seems to be the - // case, we could just leave it out. - - // Necessary? - // UpdateWindow ((HWND) m_targetWindow->GetHWND()); -#endif #ifdef __WXMAC__ m_targetWindow->MacUpdateImmediately() ; #endif @@ -216,13 +234,13 @@ void wxScrolledWindow::SetScrollbars (int pixelsPerUnitX, int pixelsPerUnitY, // target window handling // ---------------------------------------------------------------------------- -void wxScrolledWindow::SetTargetWindow( wxWindow *target ) +void wxScrollHelper::SetTargetWindow( wxWindow *target ) { wxASSERT_MSG( target, wxT("target window must not be NULL") ); m_targetWindow = target; } -wxWindow *wxScrolledWindow::GetTargetWindow() +wxWindow *wxScrollHelper::GetTargetWindow() const { return m_targetWindow; } @@ -231,7 +249,7 @@ wxWindow *wxScrolledWindow::GetTargetWindow() // scrolling implementation itself // ---------------------------------------------------------------------------- -void wxScrolledWindow::OnScroll(wxScrollWinEvent& event) +void wxScrollHelper::HandleOnScroll(wxScrollWinEvent& event) { int orient = event.GetOrientation(); @@ -241,12 +259,12 @@ void wxScrolledWindow::OnScroll(wxScrollWinEvent& event) if (orient == wxHORIZONTAL) { int newPos = m_xScrollPosition + nScrollInc; - SetScrollPos(wxHORIZONTAL, newPos, FALSE ); + m_win->SetScrollPos(wxHORIZONTAL, newPos, FALSE ); } else { int newPos = m_yScrollPosition + nScrollInc; - SetScrollPos(wxVERTICAL, newPos, FALSE ); + m_win->SetScrollPos(wxVERTICAL, newPos, FALSE ); } if (orient == wxHORIZONTAL) @@ -277,7 +295,7 @@ void wxScrolledWindow::OnScroll(wxScrollWinEvent& event) #endif } -int wxScrolledWindow::CalcScrollInc(wxScrollWinEvent& event) +int wxScrollHelper::CalcScrollInc(wxScrollWinEvent& event) { int pos = event.GetPosition(); int orient = event.GetOrientation(); @@ -387,7 +405,7 @@ int wxScrolledWindow::CalcScrollInc(wxScrollWinEvent& event) } // Adjust the scrollbars - new version. -void wxScrolledWindow::AdjustScrollbars() +void wxScrollHelper::AdjustScrollbars() { int w, h; m_targetWindow->GetClientSize(&w, &h); @@ -407,14 +425,14 @@ void wxScrolledWindow::AdjustScrollbars() m_xScrollPosition = wxMin( m_xScrollLines-noPagePositions, m_xScrollPosition); m_xScrollPosition = wxMax( 0, m_xScrollPosition ); - SetScrollbar(wxHORIZONTAL, m_xScrollPosition, noPagePositions, m_xScrollLines); + m_win->SetScrollbar(wxHORIZONTAL, m_xScrollPosition, noPagePositions, m_xScrollLines); // The amount by which we scroll when paging SetScrollPageSize(wxHORIZONTAL, noPagePositions); } else { m_xScrollPosition = 0; - SetScrollbar (wxHORIZONTAL, 0, 0, 0, FALSE); + m_win->SetScrollbar (wxHORIZONTAL, 0, 0, 0, FALSE); } if (m_yScrollLines > 0) @@ -429,14 +447,14 @@ void wxScrolledWindow::AdjustScrollbars() m_yScrollPosition = wxMin( m_yScrollLines-noPagePositions, m_yScrollPosition ); m_yScrollPosition = wxMax( 0, m_yScrollPosition ); - SetScrollbar(wxVERTICAL, m_yScrollPosition, noPagePositions, m_yScrollLines); + m_win->SetScrollbar(wxVERTICAL, m_yScrollPosition, noPagePositions, m_yScrollLines); // The amount by which we scroll when paging SetScrollPageSize(wxVERTICAL, noPagePositions); } else { m_yScrollPosition = 0; - SetScrollbar (wxVERTICAL, 0, 0, 0, FALSE); + m_win->SetScrollbar (wxVERTICAL, 0, 0, 0, FALSE); } if (oldXScroll != m_xScrollPosition) @@ -456,9 +474,7 @@ void wxScrolledWindow::AdjustScrollbars() } } -// Override this function if you don't want to have wxScrolledWindow -// automatically change the origin according to the scroll position. -void wxScrolledWindow::PrepareDC(wxDC& dc) +void wxScrollHelper::DoPrepareDC(wxDC& dc) { dc.SetDeviceOrigin( -m_xScrollPosition * m_xScrollPixelsPerLine, -m_yScrollPosition * m_yScrollPixelsPerLine ); @@ -467,30 +483,14 @@ void wxScrolledWindow::PrepareDC(wxDC& dc) // for wxUniversal we need to set the clipping region to avoid overwriting // the scrollbars with the user drawing #ifdef __WXUNIVERSAL__ - wxSize size = GetClientSize(); + wxSize size = m_win->GetClientSize(); dc.SetClippingRegion(m_xScrollPosition * m_xScrollPixelsPerLine, m_yScrollPosition * m_yScrollPixelsPerLine, size.x, size.y); #endif // __WXUNIVERSAL__ } -#if WXWIN_COMPATIBILITY -void wxScrolledWindow::GetScrollUnitsPerPage (int *x_page, int *y_page) const -{ - *x_page = GetScrollPageSize(wxHORIZONTAL); - *y_page = GetScrollPageSize(wxVERTICAL); -} - -void wxScrolledWindow::CalcUnscrolledPosition(int x, int y, float *xx, float *yy) const -{ - if ( xx ) - *xx = (float)(x + m_xScrollPosition * m_xScrollPixelsPerLine); - if ( yy ) - *yy = (float)(y + m_yScrollPosition * m_yScrollPixelsPerLine); -} -#endif // WXWIN_COMPATIBILITY - -void wxScrolledWindow::GetScrollPixelsPerUnit (int *x_unit, int *y_unit) const +void wxScrollHelper::GetScrollPixelsPerUnit (int *x_unit, int *y_unit) const { if ( x_unit ) *x_unit = m_xScrollPixelsPerLine; @@ -498,7 +498,7 @@ void wxScrolledWindow::GetScrollPixelsPerUnit (int *x_unit, int *y_unit) const *y_unit = m_yScrollPixelsPerLine; } -int wxScrolledWindow::GetScrollPageSize(int orient) const +int wxScrollHelper::GetScrollPageSize(int orient) const { if ( orient == wxHORIZONTAL ) return m_xScrollLinesPerPage; @@ -506,7 +506,7 @@ int wxScrolledWindow::GetScrollPageSize(int orient) const return m_yScrollLinesPerPage; } -void wxScrolledWindow::SetScrollPageSize(int orient, int pageSize) +void wxScrollHelper::SetScrollPageSize(int orient, int pageSize) { if ( orient == wxHORIZONTAL ) m_xScrollLinesPerPage = pageSize; @@ -517,7 +517,7 @@ void wxScrolledWindow::SetScrollPageSize(int orient, int pageSize) /* * Scroll to given position (scroll position, not pixel position) */ -void wxScrolledWindow::Scroll( int x_pos, int y_pos ) +void wxScrollHelper::Scroll( int x_pos, int y_pos ) { if (!m_targetWindow) return; @@ -562,7 +562,7 @@ void wxScrolledWindow::Scroll( int x_pos, int y_pos ) // the visible portion of it or if below zero m_yScrollPosition = wxMin( m_yScrollLines-noPagePositions, m_yScrollPosition ); m_yScrollPosition = wxMax( 0, m_yScrollPosition ); - + if (old_y != m_yScrollPosition) { m_targetWindow->SetScrollPos( wxVERTICAL, m_yScrollPosition, TRUE ); m_targetWindow->ScrollWindow( 0, (old_y-m_yScrollPosition)*m_yScrollPixelsPerLine ); @@ -574,13 +574,13 @@ void wxScrolledWindow::Scroll( int x_pos, int y_pos ) #endif } -void wxScrolledWindow::EnableScrolling (bool x_scroll, bool y_scroll) +void wxScrollHelper::EnableScrolling (bool x_scroll, bool y_scroll) { m_xScrollingEnabled = x_scroll; m_yScrollingEnabled = y_scroll; } -void wxScrolledWindow::GetVirtualSize (int *x, int *y) const +void wxScrollHelper::GetVirtualSize (int *x, int *y) const { if ( x ) *x = m_xScrollPixelsPerLine * m_xScrollLines; @@ -589,7 +589,7 @@ void wxScrolledWindow::GetVirtualSize (int *x, int *y) const } // Where the current view starts from -void wxScrolledWindow::GetViewStart (int *x, int *y) const +void wxScrollHelper::GetViewStart (int *x, int *y) const { if ( x ) *x = m_xScrollPosition; @@ -597,7 +597,7 @@ void wxScrolledWindow::GetViewStart (int *x, int *y) const *y = m_yScrollPosition; } -void wxScrolledWindow::CalcScrolledPosition(int x, int y, int *xx, int *yy) const +void wxScrollHelper::CalcScrolledPosition(int x, int y, int *xx, int *yy) const { if ( xx ) *xx = x - m_xScrollPosition * m_xScrollPixelsPerLine; @@ -605,7 +605,7 @@ void wxScrolledWindow::CalcScrolledPosition(int x, int y, int *xx, int *yy) cons *yy = y - m_yScrollPosition * m_yScrollPixelsPerLine; } -void wxScrolledWindow::CalcUnscrolledPosition(int x, int y, int *xx, int *yy) const +void wxScrollHelper::CalcUnscrolledPosition(int x, int y, int *xx, int *yy) const { if ( xx ) *xx = x + m_xScrollPosition * m_xScrollPixelsPerLine; @@ -618,11 +618,11 @@ void wxScrolledWindow::CalcUnscrolledPosition(int x, int y, int *xx, int *yy) co // ---------------------------------------------------------------------------- // Default OnSize resets scrollbars, if any -void wxScrolledWindow::OnSize(wxSizeEvent& WXUNUSED(event)) +void wxScrollHelper::HandleOnSize(wxSizeEvent& WXUNUSED(event)) { #if wxUSE_CONSTRAINTS - if (GetAutoLayout()) - Layout(); + if ( m_targetWindow->GetAutoLayout() ) + m_targetWindow->Layout(); #endif AdjustScrollbars(); @@ -630,10 +630,10 @@ void wxScrolledWindow::OnSize(wxSizeEvent& WXUNUSED(event)) // This calls OnDraw, having adjusted the origin according to the current // scroll position -void wxScrolledWindow::OnPaint(wxPaintEvent& WXUNUSED(event)) +void wxScrollHelper::HandleOnPaint(wxPaintEvent& WXUNUSED(event)) { - wxPaintDC dc(this); - PrepareDC(dc); + wxPaintDC dc(m_targetWindow); + DoPrepareDC(dc); OnDraw(dc); } @@ -642,14 +642,14 @@ void wxScrolledWindow::OnPaint(wxPaintEvent& WXUNUSED(event)) // compatibility here - if we used OnKeyDown(), the programs which process // arrows themselves in their OnChar() would never get the message and like // this they always have the priority -void wxScrolledWindow::OnChar(wxKeyEvent& event) +void wxScrollHelper::HandleOnChar(wxKeyEvent& event) { int stx, sty, // view origin szx, szy, // view size (total) clix, cliy; // view size (on screen) - ViewStart(&stx, &sty); - GetClientSize(&clix, &cliy); + GetViewStart(&stx, &sty); + m_win->GetClientSize(&clix, &cliy); GetVirtualSize(&szx, &szy); if( m_xScrollPixelsPerLine ) @@ -716,3 +716,49 @@ void wxScrolledWindow::OnChar(wxKeyEvent& event) event.Skip(); } } + +// ---------------------------------------------------------------------------- +// wxScrolledWindow implementation +// ---------------------------------------------------------------------------- + +IMPLEMENT_DYNAMIC_CLASS(wxScrolledWindow, wxPanel) + +bool wxScrolledWindow::Create(wxWindow *parent, + wxWindowID id, + const wxPoint& pos, + const wxSize& size, + long style, + const wxString& name) +{ + m_targetWindow = this; + + bool ok = wxPanel::Create(parent, id, pos, size, style, name); + +#ifdef __WXMSW__ + // we need to process arrows ourselves for scrolling + m_lDlgCode |= DLGC_WANTARROWS; +#endif // __WXMSW__ + + return ok; +} + +wxScrolledWindow::~wxScrolledWindow() +{ +} + +#if WXWIN_COMPATIBILITY +void wxScrolledWindow::GetScrollUnitsPerPage (int *x_page, int *y_page) const +{ + *x_page = GetScrollPageSize(wxHORIZONTAL); + *y_page = GetScrollPageSize(wxVERTICAL); +} + +void wxScrolledWindow::CalcUnscrolledPosition(int x, int y, float *xx, float *yy) const +{ + if ( xx ) + *xx = (float)(x + m_xScrollPosition * m_xScrollPixelsPerLine); + if ( yy ) + *yy = (float)(y + m_yScrollPosition * m_yScrollPixelsPerLine); +} +#endif // WXWIN_COMPATIBILITY + diff --git a/src/msw/window.cpp b/src/msw/window.cpp index 1b1b69184e..8935b07ad4 100644 --- a/src/msw/window.cpp +++ b/src/msw/window.cpp @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////////////////// -// Name: windows.cpp +// Name: src/msw/windows.cpp // Purpose: wxWindow // Author: Julian Smart // Modified by: VZ on 13.05.99: no more Default(), MSWOnXXX() reorganisation @@ -129,29 +129,30 @@ LRESULT WXDLLEXPORT APIENTRY _EXPORT wxWndProc(HWND hWnd, UINT message, const char *wxGetMessageName(int message); #endif //__WXDEBUG__ -void wxRemoveHandleAssociation(wxWindow *win); -void wxAssociateWinWithHandle(HWND hWnd, wxWindow *win); +void wxRemoveHandleAssociation(wxWindowMSW *win); +void wxAssociateWinWithHandle(HWND hWnd, wxWindowMSW *win); wxWindow *wxFindWinFromHandle(WXHWND hWnd); // this magical function is used to translate VK_APPS key presses to right // mouse clicks -static void TranslateKbdEventToMouse(wxWindow *win, int *x, int *y, WPARAM *flags); +static void TranslateKbdEventToMouse(wxWindowMSW *win, + int *x, int *y, WPARAM *flags); // get the text metrics for the current font -static TEXTMETRIC wxGetTextMetrics(const wxWindow *win); +static TEXTMETRIC wxGetTextMetrics(const wxWindowMSW *win); // --------------------------------------------------------------------------- // event tables // --------------------------------------------------------------------------- -IMPLEMENT_DYNAMIC_CLASS(wxWindow, wxWindowBase) +IMPLEMENT_DYNAMIC_CLASS(wxWindowMSW, wxWindowBase) -BEGIN_EVENT_TABLE(wxWindow, wxWindowBase) - EVT_ERASE_BACKGROUND(wxWindow::OnEraseBackground) - EVT_SYS_COLOUR_CHANGED(wxWindow::OnSysColourChanged) - EVT_INIT_DIALOG(wxWindow::OnInitDialog) - EVT_IDLE(wxWindow::OnIdle) - EVT_SET_FOCUS(wxWindow::OnSetFocus) +BEGIN_EVENT_TABLE(wxWindowMSW, wxWindowBase) + EVT_ERASE_BACKGROUND(wxWindowMSW::OnEraseBackground) + EVT_SYS_COLOUR_CHANGED(wxWindowMSW::OnSysColourChanged) + EVT_INIT_DIALOG(wxWindowMSW::OnInitDialog) + EVT_IDLE(wxWindowMSW::OnIdle) + EVT_SET_FOCUS(wxWindowMSW::OnSetFocus) END_EVENT_TABLE() // =========================================================================== @@ -163,7 +164,7 @@ END_EVENT_TABLE() // --------------------------------------------------------------------------- // Find an item given the MS Windows id -wxWindow *wxWindow::FindItem(long id) const +wxWindow *wxWindowMSW::FindItem(long id) const { #if wxUSE_CONTROLS wxControl *item = wxDynamicCast(this, wxControl); @@ -197,7 +198,7 @@ wxWindow *wxWindow::FindItem(long id) const } // Find an item given the MS Windows handle -wxWindow *wxWindow::FindItemByHWND(WXHWND hWnd, bool controlOnly) const +wxWindow *wxWindowMSW::FindItemByHWND(WXHWND hWnd, bool controlOnly) const { wxWindowList::Node *current = GetChildren().GetFirst(); while (current) @@ -231,7 +232,7 @@ wxWindow *wxWindow::FindItemByHWND(WXHWND hWnd, bool controlOnly) const } // Default command handler -bool wxWindow::MSWCommand(WXUINT WXUNUSED(param), WXWORD WXUNUSED(id)) +bool wxWindowMSW::MSWCommand(WXUINT WXUNUSED(param), WXWORD WXUNUSED(id)) { return FALSE; } @@ -240,7 +241,7 @@ bool wxWindow::MSWCommand(WXUINT WXUNUSED(param), WXWORD WXUNUSED(id)) // constructors and such // ---------------------------------------------------------------------------- -void wxWindow::Init() +void wxWindowMSW::Init() { // generic InitBase(); @@ -277,7 +278,7 @@ void wxWindow::Init() } // Destructor -wxWindow::~wxWindow() +wxWindowMSW::~wxWindowMSW() { m_isBeingDeleted = TRUE; @@ -303,7 +304,7 @@ wxWindow::~wxWindow() } // real construction (Init() must have been called before!) -bool wxWindow::Create(wxWindow *parent, wxWindowID id, +bool wxWindowMSW::Create(wxWindow *parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, @@ -353,7 +354,8 @@ bool wxWindow::Create(wxWindow *parent, wxWindowID id, } #endif // wxUniversal/!wxUniversal - return MSWCreate(m_windowId, parent, wxCanvasClassName, this, NULL, + return MSWCreate(m_windowId, parent, wxCanvasClassName, + (wxWindow *)this, NULL, pos.x, pos.y, WidthDefault(size.x), HeightDefault(size.y), msflags, NULL, exStyle); @@ -363,7 +365,7 @@ bool wxWindow::Create(wxWindow *parent, wxWindowID id, // basic operations // --------------------------------------------------------------------------- -void wxWindow::SetFocus() +void wxWindowMSW::SetFocus() { HWND hWnd = GetHwnd(); if ( hWnd ) @@ -382,7 +384,7 @@ wxWindow *wxWindowBase::FindFocus() return NULL; } -bool wxWindow::Enable(bool enable) +bool wxWindowMSW::Enable(bool enable) { if ( !wxWindowBase::Enable(enable) ) return FALSE; @@ -408,7 +410,7 @@ bool wxWindow::Enable(bool enable) return TRUE; } -bool wxWindow::Show(bool show) +bool wxWindowMSW::Show(bool show) { if ( !wxWindowBase::Show(show) ) return FALSE; @@ -426,29 +428,29 @@ bool wxWindow::Show(bool show) } // Raise the window to the top of the Z order -void wxWindow::Raise() +void wxWindowMSW::Raise() { ::BringWindowToTop(GetHwnd()); } // Lower the window to the bottom of the Z order -void wxWindow::Lower() +void wxWindowMSW::Lower() { ::SetWindowPos(GetHwnd(), HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); } -void wxWindow::SetTitle( const wxString& title) +void wxWindowMSW::SetTitle( const wxString& title) { SetWindowText(GetHwnd(), title.c_str()); } -wxString wxWindow::GetTitle() const +wxString wxWindowMSW::GetTitle() const { return wxGetWindowText(GetHWND()); } -void wxWindow::CaptureMouse() +void wxWindowMSW::CaptureMouse() { HWND hWnd = GetHwnd(); if ( hWnd && !m_winCaptured ) @@ -458,7 +460,7 @@ void wxWindow::CaptureMouse() } } -void wxWindow::ReleaseMouse() +void wxWindowMSW::ReleaseMouse() { if ( m_winCaptured ) { @@ -467,7 +469,7 @@ void wxWindow::ReleaseMouse() } } -bool wxWindow::SetFont(const wxFont& font) +bool wxWindowMSW::SetFont(const wxFont& font) { if ( !wxWindowBase::SetFont(font) ) { @@ -487,7 +489,7 @@ bool wxWindow::SetFont(const wxFont& font) return TRUE; } -bool wxWindow::SetCursor(const wxCursor& cursor) +bool wxWindowMSW::SetCursor(const wxCursor& cursor) { if ( !wxWindowBase::SetCursor(cursor) ) { @@ -513,7 +515,7 @@ bool wxWindow::SetCursor(const wxCursor& cursor) return TRUE; } -void wxWindow::WarpPointer (int x_pos, int y_pos) +void wxWindowMSW::WarpPointer (int x_pos, int y_pos) { // Move the pointer to (x_pos,y_pos) coordinates. They are expressed in // pixel coordinates, relatives to the canvas -- So, we first need to @@ -530,7 +532,7 @@ void wxWindow::WarpPointer (int x_pos, int y_pos) } #if WXWIN_COMPATIBILITY -void wxWindow::MSWDeviceToLogical (float *x, float *y) const +void wxWindowMSW::MSWDeviceToLogical (float *x, float *y) const { } #endif // WXWIN_COMPATIBILITY @@ -540,7 +542,7 @@ void wxWindow::MSWDeviceToLogical (float *x, float *y) const // --------------------------------------------------------------------------- #if WXWIN_COMPATIBILITY -void wxWindow::SetScrollRange(int orient, int range, bool refresh) +void wxWindowMSW::SetScrollRange(int orient, int range, bool refresh) { #if defined(__WIN95__) @@ -586,7 +588,7 @@ void wxWindow::SetScrollRange(int orient, int range, bool refresh) #endif } -void wxWindow::SetScrollPage(int orient, int page, bool refresh) +void wxWindowMSW::SetScrollPage(int orient, int page, bool refresh) { #if defined(__WIN95__) SCROLLINFO info; @@ -616,7 +618,7 @@ void wxWindow::SetScrollPage(int orient, int page, bool refresh) #endif } -int wxWindow::OldGetScrollRange(int orient) const +int wxWindowMSW::OldGetScrollRange(int orient) const { int wOrient; if ( orient == wxHORIZONTAL ) @@ -648,7 +650,7 @@ int wxWindow::OldGetScrollRange(int orient) const return 0; } -int wxWindow::GetScrollPage(int orient) const +int wxWindowMSW::GetScrollPage(int orient) const { if ( orient == wxHORIZONTAL ) return m_xThumbSize; @@ -658,7 +660,7 @@ int wxWindow::GetScrollPage(int orient) const #endif // WXWIN_COMPATIBILITY -int wxWindow::GetScrollPos(int orient) const +int wxWindowMSW::GetScrollPos(int orient) const { int wOrient; if ( orient == wxHORIZONTAL ) @@ -676,7 +678,7 @@ int wxWindow::GetScrollPos(int orient) const // This now returns the whole range, not just the number // of positions that we can scroll. -int wxWindow::GetScrollRange(int orient) const +int wxWindowMSW::GetScrollRange(int orient) const { int wOrient; if ( orient == wxHORIZONTAL ) @@ -711,7 +713,7 @@ int wxWindow::GetScrollRange(int orient) const return 0; } -int wxWindow::GetScrollThumb(int orient) const +int wxWindowMSW::GetScrollThumb(int orient) const { if ( orient == wxHORIZONTAL ) return m_xThumbSize; @@ -719,7 +721,7 @@ int wxWindow::GetScrollThumb(int orient) const return m_yThumbSize; } -void wxWindow::SetScrollPos(int orient, int pos, bool refresh) +void wxWindowMSW::SetScrollPos(int orient, int pos, bool refresh) { #if defined(__WIN95__) SCROLLINFO info; @@ -754,7 +756,7 @@ void wxWindow::SetScrollPos(int orient, int pos, bool refresh) } // New function that will replace some of the above. -void wxWindow::SetScrollbar(int orient, int pos, int thumbVisible, +void wxWindowMSW::SetScrollbar(int orient, int pos, int thumbVisible, int range, bool refresh) { #if defined(__WIN95__) @@ -810,7 +812,7 @@ void wxWindow::SetScrollbar(int orient, int pos, int thumbVisible, } } -void wxWindow::ScrollWindow(int dx, int dy, const wxRect *rect) +void wxWindowMSW::ScrollWindow(int dx, int dy, const wxRect *rect) { RECT rect2; if ( rect ) @@ -831,7 +833,7 @@ void wxWindow::ScrollWindow(int dx, int dy, const wxRect *rect) // subclassing // --------------------------------------------------------------------------- -void wxWindow::SubclassWin(WXHWND hWnd) +void wxWindowMSW::SubclassWin(WXHWND hWnd) { wxASSERT_MSG( !m_oldWndProc, wxT("subclassing window twice?") ); @@ -844,7 +846,7 @@ void wxWindow::SubclassWin(WXHWND hWnd) SetWindowLong(hwnd, GWL_WNDPROC, (LONG) wxWndProc); } -void wxWindow::UnsubclassWin() +void wxWindowMSW::UnsubclassWin() { wxRemoveHandleAssociation(this); @@ -866,7 +868,7 @@ void wxWindow::UnsubclassWin() } // Make a Windows extended style from the given wxWindows window style -WXDWORD wxWindow::MakeExtendedStyle(long style, bool eliminateBorders) +WXDWORD wxWindowMSW::MakeExtendedStyle(long style, bool eliminateBorders) { WXDWORD exStyle = 0; if ( style & wxTRANSPARENT_WINDOW ) @@ -891,7 +893,7 @@ WXDWORD wxWindow::MakeExtendedStyle(long style, bool eliminateBorders) // Determines whether native 3D effects or CTL3D should be used, // applying a default border style if required, and returning an extended // style to pass to CreateWindowEx. -WXDWORD wxWindow::Determine3DEffects(WXDWORD defaultBorderStyle, +WXDWORD wxWindowMSW::Determine3DEffects(WXDWORD defaultBorderStyle, bool *want3D) const { // If matches certain criteria, then assume no 3D effects @@ -955,7 +957,7 @@ WXDWORD wxWindow::Determine3DEffects(WXDWORD defaultBorderStyle, // If nothing defined for this, try the parent. // E.g. we may be a button loaded from a resource, with no callback function // defined. -void wxWindow::OnCommand(wxWindow& win, wxCommandEvent& event) +void wxWindowMSW::OnCommand(wxWindow& win, wxCommandEvent& event) { if ( GetEventHandler()->ProcessEvent(event) ) return; @@ -965,7 +967,7 @@ void wxWindow::OnCommand(wxWindow& win, wxCommandEvent& event) #endif // WXWIN_COMPATIBILITY_2 #if WXWIN_COMPATIBILITY -wxObject* wxWindow::GetChild(int number) const +wxObject* wxWindowMSW::GetChild(int number) const { // Return a pointer to the Nth object in the Panel wxNode *node = GetChildren().First(); @@ -983,13 +985,13 @@ wxObject* wxWindow::GetChild(int number) const #endif // WXWIN_COMPATIBILITY // Setup background and foreground colours correctly -void wxWindow::SetupColours() +void wxWindowMSW::SetupColours() { if ( GetParent() ) SetBackgroundColour(GetParent()->GetBackgroundColour()); } -void wxWindow::OnIdle(wxIdleEvent& event) +void wxWindowMSW::OnIdle(wxIdleEvent& event) { // Check if we need to send a LEAVE event if ( m_mouseInWindow ) @@ -1027,7 +1029,7 @@ void wxWindow::OnIdle(wxIdleEvent& event) } // Set this window to be the child of 'parent'. -bool wxWindow::Reparent(wxWindow *parent) +bool wxWindowMSW::Reparent(wxWindowBase *parent) { if ( !wxWindowBase::Reparent(parent) ) return FALSE; @@ -1040,15 +1042,15 @@ bool wxWindow::Reparent(wxWindow *parent) return TRUE; } -void wxWindow::Clear() +void wxWindowMSW::Clear() { - wxClientDC dc(this); + wxClientDC dc((wxWindow *)this); wxBrush brush(GetBackgroundColour(), wxSOLID); dc.SetBackground(brush); dc.Clear(); } -void wxWindow::Refresh(bool eraseBack, const wxRect *rect) +void wxWindowMSW::Refresh(bool eraseBack, const wxRect *rect) { HWND hWnd = GetHwnd(); if ( hWnd ) @@ -1074,7 +1076,7 @@ void wxWindow::Refresh(bool eraseBack, const wxRect *rect) #if wxUSE_DRAG_AND_DROP -void wxWindow::SetDropTarget(wxDropTarget *pDropTarget) +void wxWindowMSW::SetDropTarget(wxDropTarget *pDropTarget) { if ( m_dropTarget != 0 ) { m_dropTarget->Revoke(m_hWnd); @@ -1090,7 +1092,7 @@ void wxWindow::SetDropTarget(wxDropTarget *pDropTarget) // old style file-manager drag&drop support: we retain the old-style // DragAcceptFiles in parallel with SetDropTarget. -void wxWindow::DragAcceptFiles(bool accept) +void wxWindowMSW::DragAcceptFiles(bool accept) { HWND hWnd = GetHwnd(); if ( hWnd ) @@ -1103,7 +1105,7 @@ void wxWindow::DragAcceptFiles(bool accept) #if wxUSE_TOOLTIPS -void wxWindow::DoSetToolTip(wxToolTip *tooltip) +void wxWindowMSW::DoSetToolTip(wxToolTip *tooltip) { wxWindowBase::DoSetToolTip(tooltip); @@ -1118,7 +1120,7 @@ void wxWindow::DoSetToolTip(wxToolTip *tooltip) // --------------------------------------------------------------------------- // Get total size -void wxWindow::DoGetSize(int *x, int *y) const +void wxWindowMSW::DoGetSize(int *x, int *y) const { HWND hWnd = GetHwnd(); RECT rect; @@ -1136,7 +1138,7 @@ void wxWindow::DoGetSize(int *x, int *y) const *y = rect.bottom - rect.top; } -void wxWindow::DoGetPosition(int *x, int *y) const +void wxWindowMSW::DoGetPosition(int *x, int *y) const { HWND hWnd = GetHwnd(); @@ -1176,7 +1178,7 @@ void wxWindow::DoGetPosition(int *x, int *y) const *y = point.y; } -void wxWindow::DoScreenToClient(int *x, int *y) const +void wxWindowMSW::DoScreenToClient(int *x, int *y) const { POINT pt; if ( x ) @@ -1193,7 +1195,7 @@ void wxWindow::DoScreenToClient(int *x, int *y) const *y = pt.y; } -void wxWindow::DoClientToScreen(int *x, int *y) const +void wxWindowMSW::DoClientToScreen(int *x, int *y) const { POINT pt; if ( x ) @@ -1211,7 +1213,7 @@ void wxWindow::DoClientToScreen(int *x, int *y) const } // Get size *available for subwindows* i.e. excluding menu bar etc. -void wxWindow::DoGetClientSize(int *x, int *y) const +void wxWindowMSW::DoGetClientSize(int *x, int *y) const { HWND hWnd = GetHwnd(); RECT rect; @@ -1222,7 +1224,7 @@ void wxWindow::DoGetClientSize(int *x, int *y) const *y = rect.bottom; } -void wxWindow::DoMoveWindow(int x, int y, int width, int height) +void wxWindowMSW::DoMoveWindow(int x, int y, int width, int height) { if ( !::MoveWindow(GetHwnd(), x, y, width, height, TRUE) ) { @@ -1238,7 +1240,7 @@ void wxWindow::DoMoveWindow(int x, int y, int width, int height) // If sizeFlags contains wxSIZE_AUTO_WIDTH/HEIGHT flags (default), we calculate // the width/height to best suit our contents, otherwise we reuse the current // width/height -void wxWindow::DoSetSize(int x, int y, int width, int height, int sizeFlags) +void wxWindowMSW::DoSetSize(int x, int y, int width, int height, int sizeFlags) { // get the current size and position... int currentX, currentY; @@ -1297,7 +1299,7 @@ void wxWindow::DoSetSize(int x, int y, int width, int height, int sizeFlags) DoMoveWindow(x, y, width, height); } -void wxWindow::DoSetClientSize(int width, int height) +void wxWindowMSW::DoSetClientSize(int width, int height) { wxWindow *parent = GetParent(); HWND hWnd = GetHwnd(); @@ -1337,14 +1339,14 @@ void wxWindow::DoSetClientSize(int width, int height) // For implementation purposes - sometimes decorations make the client area // smaller -wxPoint wxWindow::GetClientAreaOrigin() const +wxPoint wxWindowMSW::GetClientAreaOrigin() const { return wxPoint(0, 0); } // Makes an adjustment to the window position (for example, a frame that has // a toolbar that it manages itself). -void wxWindow::AdjustForParentClientOrigin(int& x, int& y, int sizeFlags) +void wxWindowMSW::AdjustForParentClientOrigin(int& x, int& y, int sizeFlags) { // don't do it for the dialogs/frames - they float independently of their // parent @@ -1363,12 +1365,12 @@ void wxWindow::AdjustForParentClientOrigin(int& x, int& y, int sizeFlags) // text metrics // --------------------------------------------------------------------------- -int wxWindow::GetCharHeight() const +int wxWindowMSW::GetCharHeight() const { return wxGetTextMetrics(this).tmHeight; } -int wxWindow::GetCharWidth() const +int wxWindowMSW::GetCharWidth() const { // +1 is needed because Windows apparently adds it when calculating the // dialog units size in pixels @@ -1379,7 +1381,7 @@ int wxWindow::GetCharWidth() const #endif } -void wxWindow::GetTextExtent(const wxString& string, +void wxWindowMSW::GetTextExtent(const wxString& string, int *x, int *y, int *descent, int *externalLeading, const wxFont *theFont) const @@ -1425,36 +1427,36 @@ void wxWindow::GetTextExtent(const wxString& string, // Caret manipulation // --------------------------------------------------------------------------- -void wxWindow::CreateCaret(int w, int h) +void wxWindowMSW::CreateCaret(int w, int h) { SetCaret(new wxCaret(this, w, h)); } -void wxWindow::CreateCaret(const wxBitmap *WXUNUSED(bitmap)) +void wxWindowMSW::CreateCaret(const wxBitmap *WXUNUSED(bitmap)) { wxFAIL_MSG("not implemented"); } -void wxWindow::ShowCaret(bool show) +void wxWindowMSW::ShowCaret(bool show) { wxCHECK_RET( m_caret, "no caret to show" ); m_caret->Show(show); } -void wxWindow::DestroyCaret() +void wxWindowMSW::DestroyCaret() { SetCaret(NULL); } -void wxWindow::SetCaretPos(int x, int y) +void wxWindowMSW::SetCaretPos(int x, int y) { wxCHECK_RET( m_caret, "no caret to move" ); m_caret->Move(x, y); } -void wxWindow::GetCaretPos(int *x, int *y) const +void wxWindowMSW::GetCaretPos(int *x, int *y) const { wxCHECK_RET( m_caret, "no caret to get position of" ); @@ -1468,7 +1470,7 @@ void wxWindow::GetCaretPos(int *x, int *y) const #if wxUSE_MENUS -bool wxWindow::DoPopupMenu(wxMenu *menu, int x, int y) +bool wxWindowMSW::DoPopupMenu(wxMenu *menu, int x, int y) { menu->SetInvokingWindow(this); menu->UpdateUI(); @@ -1495,7 +1497,7 @@ bool wxWindow::DoPopupMenu(wxMenu *menu, int x, int y) // pre/post message processing // =========================================================================== -long wxWindow::MSWDefWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam) +long wxWindowMSW::MSWDefWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam) { if ( m_oldWndProc ) return ::CallWindowProc(CASTWNDPROC m_oldWndProc, GetHwnd(), (UINT) nMsg, (WPARAM) wParam, (LPARAM) lParam); @@ -1503,7 +1505,7 @@ long wxWindow::MSWDefWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam) return ::DefWindowProc(GetHwnd(), nMsg, wParam, lParam); } -bool wxWindow::MSWProcessMessage(WXMSG* pMsg) +bool wxWindowMSW::MSWProcessMessage(WXMSG* pMsg) { if ( m_hWnd != 0 && (GetWindowStyleFlag() & wxTAB_TRAVERSAL) ) { @@ -1684,7 +1686,7 @@ bool wxWindow::MSWProcessMessage(WXMSG* pMsg) return FALSE; } -bool wxWindow::MSWTranslateMessage(WXMSG* pMsg) +bool wxWindowMSW::MSWTranslateMessage(WXMSG* pMsg) { #if wxUSE_ACCEL return m_acceleratorTable.Translate(this, pMsg); @@ -1699,7 +1701,7 @@ bool wxWindow::MSWTranslateMessage(WXMSG* pMsg) #ifdef __WIN32__ -void wxWindow::UnpackCommand(WXWPARAM wParam, WXLPARAM lParam, +void wxWindowMSW::UnpackCommand(WXWPARAM wParam, WXLPARAM lParam, WORD *id, WXHWND *hwnd, WORD *cmd) { *id = LOWORD(wParam); @@ -1707,7 +1709,7 @@ void wxWindow::UnpackCommand(WXWPARAM wParam, WXLPARAM lParam, *cmd = HIWORD(wParam); } -void wxWindow::UnpackActivate(WXWPARAM wParam, WXLPARAM lParam, +void wxWindowMSW::UnpackActivate(WXWPARAM wParam, WXLPARAM lParam, WXWORD *state, WXWORD *minimized, WXHWND *hwnd) { *state = LOWORD(wParam); @@ -1715,7 +1717,7 @@ void wxWindow::UnpackActivate(WXWPARAM wParam, WXLPARAM lParam, *hwnd = (WXHWND)lParam; } -void wxWindow::UnpackScroll(WXWPARAM wParam, WXLPARAM lParam, +void wxWindowMSW::UnpackScroll(WXWPARAM wParam, WXLPARAM lParam, WXWORD *code, WXWORD *pos, WXHWND *hwnd) { *code = LOWORD(wParam); @@ -1723,7 +1725,7 @@ void wxWindow::UnpackScroll(WXWPARAM wParam, WXLPARAM lParam, *hwnd = (WXHWND)lParam; } -void wxWindow::UnpackCtlColor(WXWPARAM wParam, WXLPARAM lParam, +void wxWindowMSW::UnpackCtlColor(WXWPARAM wParam, WXLPARAM lParam, WXWORD *nCtlColor, WXHDC *hdc, WXHWND *hwnd) { *nCtlColor = CTLCOLOR_BTN; @@ -1731,7 +1733,7 @@ void wxWindow::UnpackCtlColor(WXWPARAM wParam, WXLPARAM lParam, *hdc = (WXHDC)wParam; } -void wxWindow::UnpackMenuSelect(WXWPARAM wParam, WXLPARAM lParam, +void wxWindowMSW::UnpackMenuSelect(WXWPARAM wParam, WXLPARAM lParam, WXWORD *item, WXWORD *flags, WXHMENU *hmenu) { *item = (WXWORD)wParam; @@ -1741,7 +1743,7 @@ void wxWindow::UnpackMenuSelect(WXWPARAM wParam, WXLPARAM lParam, #else // Win16 -void wxWindow::UnpackCommand(WXWPARAM wParam, WXLPARAM lParam, +void wxWindowMSW::UnpackCommand(WXWPARAM wParam, WXLPARAM lParam, WXWORD *id, WXHWND *hwnd, WXWORD *cmd) { *id = (WXWORD)wParam; @@ -1749,7 +1751,7 @@ void wxWindow::UnpackCommand(WXWPARAM wParam, WXLPARAM lParam, *cmd = HIWORD(lParam); } -void wxWindow::UnpackActivate(WXWPARAM wParam, WXLPARAM lParam, +void wxWindowMSW::UnpackActivate(WXWPARAM wParam, WXLPARAM lParam, WXWORD *state, WXWORD *minimized, WXHWND *hwnd) { *state = (WXWORD)wParam; @@ -1757,7 +1759,7 @@ void wxWindow::UnpackActivate(WXWPARAM wParam, WXLPARAM lParam, *hwnd = (WXHWND)HIWORD(lParam); } -void wxWindow::UnpackScroll(WXWPARAM wParam, WXLPARAM lParam, +void wxWindowMSW::UnpackScroll(WXWPARAM wParam, WXLPARAM lParam, WXWORD *code, WXWORD *pos, WXHWND *hwnd) { *code = (WXWORD)wParam; @@ -1765,7 +1767,7 @@ void wxWindow::UnpackScroll(WXWPARAM wParam, WXLPARAM lParam, *hwnd = (WXHWND)HIWORD(lParam); } -void wxWindow::UnpackCtlColor(WXWPARAM wParam, WXLPARAM lParam, +void wxWindowMSW::UnpackCtlColor(WXWPARAM wParam, WXLPARAM lParam, WXWORD *nCtlColor, WXHDC *hdc, WXHWND *hwnd) { *hwnd = (WXHWND)LOWORD(lParam); @@ -1773,7 +1775,7 @@ void wxWindow::UnpackCtlColor(WXWPARAM wParam, WXLPARAM lParam, *hdc = (WXHDC)wParam; } -void wxWindow::UnpackMenuSelect(WXWPARAM wParam, WXLPARAM lParam, +void wxWindowMSW::UnpackMenuSelect(WXWPARAM wParam, WXLPARAM lParam, WXWORD *item, WXWORD *flags, WXHMENU *hmenu) { *item = (WXWORD)wParam; @@ -1789,7 +1791,7 @@ void wxWindow::UnpackMenuSelect(WXWPARAM wParam, WXLPARAM lParam, // Hook for new window just as it's being created, when the window isn't yet // associated with the handle -wxWindow *wxWndHook = NULL; +wxWindowMSW *wxWndHook = NULL; // Main window proc LRESULT WXDLLEXPORT APIENTRY _EXPORT wxWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) @@ -1800,7 +1802,7 @@ LRESULT WXDLLEXPORT APIENTRY _EXPORT wxWndProc(HWND hWnd, UINT message, WPARAM w wxGetMessageName(message), wParam, lParam); #endif // __WXDEBUG__ - wxWindow *wnd = wxFindWinFromHandle((WXHWND) hWnd); + wxWindowMSW *wnd = wxFindWinFromHandle((WXHWND) hWnd); // when we get the first message for the HWND we just created, we associate // it with wxWindow stored in wxWndHook @@ -1839,7 +1841,7 @@ LRESULT WXDLLEXPORT APIENTRY _EXPORT wxWndProc(HWND hWnd, UINT message, WPARAM w return rc; } -long wxWindow::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam) +long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam) { // did we process the message? bool processed = FALSE; @@ -2260,7 +2262,7 @@ wxWindow *wxFindWinFromHandle(WXHWND hWnd) static int gs_AssociationCount = 0; #endif -void wxAssociateWinWithHandle(HWND hWnd, wxWindow *win) +void wxAssociateWinWithHandle(HWND hWnd, wxWindowMSW *win) { // adding NULL hWnd is (first) surely a result of an error and // (secondly) breaks menu command processing @@ -2285,7 +2287,7 @@ void wxAssociateWinWithHandle(HWND hWnd, wxWindow *win) } } -void wxRemoveHandleAssociation(wxWindow *win) +void wxRemoveHandleAssociation(wxWindowMSW *win) { #if 0 // def __WXDEBUG__ if (wxWinHandleList->Member(win)) @@ -2299,11 +2301,11 @@ void wxRemoveHandleAssociation(wxWindow *win) // Default destroyer - override if you destroy it in some other way // (e.g. with MDI child windows) -void wxWindow::MSWDestroyWindow() +void wxWindowMSW::MSWDestroyWindow() { } -void wxWindow::MSWDetachWindowMenu() +void wxWindowMSW::MSWDetachWindowMenu() { if ( m_hMenu ) { @@ -2332,7 +2334,7 @@ void wxWindow::MSWDetachWindowMenu() } } -bool wxWindow::MSWCreate(int id, +bool wxWindowMSW::MSWCreate(int id, wxWindow *parent, const wxChar *wclass, wxWindow *wx_win, @@ -2479,7 +2481,7 @@ bool wxWindow::MSWCreate(int id, #ifdef __WIN95__ // FIXME: VZ: I'm not sure at all that the order of processing is correct -bool wxWindow::HandleNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result) +bool wxWindowMSW::HandleNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result) { LPNMHDR hdr = (LPNMHDR)lParam; HWND hWnd = hdr->hwndFrom; @@ -2508,7 +2510,7 @@ bool wxWindow::HandleNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result) return MSWOnNotify(idCtrl, lParam, result); } -bool wxWindow::MSWOnNotify(int WXUNUSED(idCtrl), +bool wxWindowMSW::MSWOnNotify(int WXUNUSED(idCtrl), WXLPARAM lParam, WXLPARAM* WXUNUSED(result)) { @@ -2532,7 +2534,7 @@ bool wxWindow::MSWOnNotify(int WXUNUSED(idCtrl), // end session messages // --------------------------------------------------------------------------- -bool wxWindow::HandleQueryEndSession(long logOff, bool *mayEnd) +bool wxWindowMSW::HandleQueryEndSession(long logOff, bool *mayEnd) { wxCloseEvent event(wxEVT_QUERY_END_SESSION, -1); event.SetEventObject(wxTheApp); @@ -2551,7 +2553,7 @@ bool wxWindow::HandleQueryEndSession(long logOff, bool *mayEnd) return rc; } -bool wxWindow::HandleEndSession(bool endSession, long logOff) +bool wxWindowMSW::HandleEndSession(bool endSession, long logOff) { // do nothing if the session isn't ending if ( !endSession ) @@ -2572,10 +2574,10 @@ bool wxWindow::HandleEndSession(bool endSession, long logOff) // window creation/destruction // --------------------------------------------------------------------------- -bool wxWindow::HandleCreate(WXLPCREATESTRUCT cs, bool *mayCreate) +bool wxWindowMSW::HandleCreate(WXLPCREATESTRUCT cs, bool *mayCreate) { // TODO: should generate this event from WM_NCCREATE - wxWindowCreateEvent event(this); + wxWindowCreateEvent event((wxWindow *)this); (void)GetEventHandler()->ProcessEvent(event); *mayCreate = TRUE; @@ -2583,9 +2585,9 @@ bool wxWindow::HandleCreate(WXLPCREATESTRUCT cs, bool *mayCreate) return TRUE; } -bool wxWindow::HandleDestroy() +bool wxWindowMSW::HandleDestroy() { - wxWindowDestroyEvent event(this); + wxWindowDestroyEvent event((wxWindow *)this); (void)GetEventHandler()->ProcessEvent(event); // delete our drop target if we've got one @@ -2607,7 +2609,7 @@ bool wxWindow::HandleDestroy() // activation/focus // --------------------------------------------------------------------------- -void wxWindow::OnSetFocus(wxFocusEvent& event) +void wxWindowMSW::OnSetFocus(wxFocusEvent& event) { // panel wants to track the window which was the last to have focus in it, // so we want to set ourselves as the window which last had focus @@ -2615,7 +2617,7 @@ void wxWindow::OnSetFocus(wxFocusEvent& event) // notice that it's also important to do it upwards the tree becaus // otherwise when the top level panel gets focus, it won't set it back to // us, but to some other sibling - wxWindow *win = this; + wxWindow *win = (wxWindow *)this; while ( win ) { wxWindow *parent = win->GetParent(); @@ -2634,7 +2636,7 @@ void wxWindow::OnSetFocus(wxFocusEvent& event) event.Skip(); } -bool wxWindow::HandleActivate(int state, +bool wxWindowMSW::HandleActivate(int state, bool WXUNUSED(minimized), WXHWND WXUNUSED(activate)) { @@ -2646,7 +2648,7 @@ bool wxWindow::HandleActivate(int state, return GetEventHandler()->ProcessEvent(event); } -bool wxWindow::HandleSetFocus(WXHWND WXUNUSED(hwnd)) +bool wxWindowMSW::HandleSetFocus(WXHWND WXUNUSED(hwnd)) { #if wxUSE_CARET // Deal with caret @@ -2662,7 +2664,7 @@ bool wxWindow::HandleSetFocus(WXHWND WXUNUSED(hwnd)) return GetEventHandler()->ProcessEvent(event); } -bool wxWindow::HandleKillFocus(WXHWND WXUNUSED(hwnd)) +bool wxWindowMSW::HandleKillFocus(WXHWND WXUNUSED(hwnd)) { #if wxUSE_CARET // Deal with caret @@ -2682,7 +2684,7 @@ bool wxWindow::HandleKillFocus(WXHWND WXUNUSED(hwnd)) // miscellaneous // --------------------------------------------------------------------------- -bool wxWindow::HandleShow(bool show, int status) +bool wxWindowMSW::HandleShow(bool show, int status) { wxShowEvent event(GetId(), show); event.m_eventObject = this; @@ -2690,7 +2692,7 @@ bool wxWindow::HandleShow(bool show, int status) return GetEventHandler()->ProcessEvent(event); } -bool wxWindow::HandleInitDialog(WXHWND WXUNUSED(hWndFocus)) +bool wxWindowMSW::HandleInitDialog(WXHWND WXUNUSED(hWndFocus)) { wxInitDialogEvent event(GetId()); event.m_eventObject = this; @@ -2698,7 +2700,7 @@ bool wxWindow::HandleInitDialog(WXHWND WXUNUSED(hWndFocus)) return GetEventHandler()->ProcessEvent(event); } -bool wxWindow::HandleDropFiles(WXWPARAM wParam) +bool wxWindowMSW::HandleDropFiles(WXWPARAM wParam) { HDROP hFilesInfo = (HDROP) wParam; POINT dropPoint; @@ -2733,7 +2735,7 @@ bool wxWindow::HandleDropFiles(WXWPARAM wParam) return rc; } -bool wxWindow::HandleSetCursor(WXHWND hWnd, +bool wxWindowMSW::HandleSetCursor(WXHWND hWnd, short nHitTest, int WXUNUSED(mouseMsg)) { @@ -2822,7 +2824,7 @@ bool wxWindow::HandleSetCursor(WXHWND hWnd, // owner drawn stuff // --------------------------------------------------------------------------- -bool wxWindow::MSWOnDrawItem(int id, WXDRAWITEMSTRUCT *itemStruct) +bool wxWindowMSW::MSWOnDrawItem(int id, WXDRAWITEMSTRUCT *itemStruct) { #if wxUSE_OWNER_DRAWN @@ -2864,7 +2866,7 @@ bool wxWindow::MSWOnDrawItem(int id, WXDRAWITEMSTRUCT *itemStruct) return FALSE; } -bool wxWindow::MSWOnMeasureItem(int id, WXMEASUREITEMSTRUCT *itemStruct) +bool wxWindowMSW::MSWOnMeasureItem(int id, WXMEASUREITEMSTRUCT *itemStruct) { #if wxUSE_OWNER_DRAWN // is it a menu item? @@ -2892,7 +2894,7 @@ bool wxWindow::MSWOnMeasureItem(int id, WXMEASUREITEMSTRUCT *itemStruct) // colours and palettes // --------------------------------------------------------------------------- -bool wxWindow::HandleSysColorChange() +bool wxWindowMSW::HandleSysColorChange() { wxSysColourChangedEvent event; event.SetEventObject(this); @@ -2900,7 +2902,7 @@ bool wxWindow::HandleSysColorChange() return GetEventHandler()->ProcessEvent(event); } -bool wxWindow::HandleCtlColor(WXHBRUSH *brush, +bool wxWindowMSW::HandleCtlColor(WXHBRUSH *brush, WXHDC pDC, WXHWND pWnd, WXUINT nCtlColor, @@ -2930,7 +2932,7 @@ bool wxWindow::HandleCtlColor(WXHBRUSH *brush, } // Define for each class of dialog and control -WXHBRUSH wxWindow::OnCtlColor(WXHDC hDC, +WXHBRUSH wxWindowMSW::OnCtlColor(WXHDC hDC, WXHWND hWnd, WXUINT nCtlColor, WXUINT message, @@ -2940,7 +2942,7 @@ WXHBRUSH wxWindow::OnCtlColor(WXHDC hDC, return (WXHBRUSH)0; } -bool wxWindow::HandlePaletteChanged(WXHWND hWndPalChange) +bool wxWindowMSW::HandlePaletteChanged(WXHWND hWndPalChange) { wxPaletteChangedEvent event(GetId()); event.SetEventObject(this); @@ -2949,7 +2951,7 @@ bool wxWindow::HandlePaletteChanged(WXHWND hWndPalChange) return GetEventHandler()->ProcessEvent(event); } -bool wxWindow::HandleQueryNewPalette() +bool wxWindowMSW::HandleQueryNewPalette() { wxQueryNewPaletteEvent event(GetId()); event.SetEventObject(this); @@ -2958,7 +2960,7 @@ bool wxWindow::HandleQueryNewPalette() } // Responds to colour changes: passes event on to children. -void wxWindow::OnSysColourChanged(wxSysColourChangedEvent& event) +void wxWindowMSW::OnSysColourChanged(wxSysColourChangedEvent& event) { wxNode *node = GetChildren().First(); while ( node ) @@ -2980,7 +2982,7 @@ void wxWindow::OnSysColourChanged(wxSysColourChangedEvent& event) // painting // --------------------------------------------------------------------------- -bool wxWindow::HandlePaint() +bool wxWindowMSW::HandlePaint() { #ifdef __WIN32__ HRGN hRegion = ::CreateRectRgn(0, 0, 0, 0); // Dummy call to get a handle @@ -3006,7 +3008,7 @@ bool wxWindow::HandlePaint() } // Can be called from an application's OnPaint handler -void wxWindow::OnPaint(wxPaintEvent& event) +void wxWindowMSW::OnPaint(wxPaintEvent& event) { #ifdef __WXUNIVERSAL__ event.Skip(); @@ -3019,7 +3021,7 @@ void wxWindow::OnPaint(wxPaintEvent& event) #endif } -bool wxWindow::HandleEraseBkgnd(WXHDC hdc) +bool wxWindowMSW::HandleEraseBkgnd(WXHDC hdc) { // Prevents flicker when dragging if ( ::IsIconic(GetHwnd()) ) @@ -3028,7 +3030,7 @@ bool wxWindow::HandleEraseBkgnd(WXHDC hdc) wxDC dc; dc.SetHDC(hdc); - dc.SetWindow(this); + dc.SetWindow((wxWindow *)this); dc.BeginDrawing(); wxEraseEvent event(m_windowId, &dc); @@ -3042,7 +3044,7 @@ bool wxWindow::HandleEraseBkgnd(WXHDC hdc) return rc; } -void wxWindow::OnEraseBackground(wxEraseEvent& event) +void wxWindowMSW::OnEraseBackground(wxEraseEvent& event) { RECT rect; ::GetClientRect(GetHwnd(), &rect); @@ -3067,7 +3069,7 @@ void wxWindow::OnEraseBackground(wxEraseEvent& event) // moving and resizing // --------------------------------------------------------------------------- -bool wxWindow::HandleMinimize() +bool wxWindowMSW::HandleMinimize() { wxIconizeEvent event(m_windowId); event.SetEventObject(this); @@ -3075,7 +3077,7 @@ bool wxWindow::HandleMinimize() return GetEventHandler()->ProcessEvent(event); } -bool wxWindow::HandleMaximize() +bool wxWindowMSW::HandleMaximize() { wxMaximizeEvent event(m_windowId); event.SetEventObject(this); @@ -3083,7 +3085,7 @@ bool wxWindow::HandleMaximize() return GetEventHandler()->ProcessEvent(event); } -bool wxWindow::HandleMove(int x, int y) +bool wxWindowMSW::HandleMove(int x, int y) { wxMoveEvent event(wxPoint(x, y), m_windowId); event.SetEventObject(this); @@ -3091,7 +3093,7 @@ bool wxWindow::HandleMove(int x, int y) return GetEventHandler()->ProcessEvent(event); } -bool wxWindow::HandleSize(int w, int h, WXUINT WXUNUSED(flag)) +bool wxWindowMSW::HandleSize(int w, int h, WXUINT WXUNUSED(flag)) { wxSizeEvent event(wxSize(w, h), m_windowId); event.SetEventObject(this); @@ -3099,7 +3101,7 @@ bool wxWindow::HandleSize(int w, int h, WXUINT WXUNUSED(flag)) return GetEventHandler()->ProcessEvent(event); } -bool wxWindow::HandleGetMinMaxInfo(void *mmInfo) +bool wxWindowMSW::HandleGetMinMaxInfo(void *mmInfo) { MINMAXINFO *info = (MINMAXINFO *)mmInfo; @@ -3133,7 +3135,7 @@ bool wxWindow::HandleGetMinMaxInfo(void *mmInfo) } // generate an artificial resize event -void wxWindow::SendSizeEvent() +void wxWindowMSW::SendSizeEvent() { RECT r; #ifdef __WIN16__ @@ -3153,7 +3155,7 @@ void wxWindow::SendSizeEvent() // command messages // --------------------------------------------------------------------------- -bool wxWindow::HandleCommand(WXWORD id, WXWORD cmd, WXHWND control) +bool wxWindowMSW::HandleCommand(WXWORD id, WXWORD cmd, WXHWND control) { #if wxUSE_MENUS if ( wxCurrentPopupMenu ) @@ -3204,7 +3206,7 @@ bool wxWindow::HandleCommand(WXWORD id, WXWORD cmd, WXHWND control) return FALSE; } -bool wxWindow::HandleSysCommand(WXWPARAM wParam, WXLPARAM lParam) +bool wxWindowMSW::HandleSysCommand(WXWPARAM wParam, WXLPARAM lParam) { // 4 bits are reserved switch ( wParam & 0xFFFFFFF0 ) @@ -3223,7 +3225,7 @@ bool wxWindow::HandleSysCommand(WXWPARAM wParam, WXLPARAM lParam) // mouse events // --------------------------------------------------------------------------- -void wxWindow::InitMouseEvent(wxMouseEvent& event, int x, int y, WXUINT flags) +void wxWindowMSW::InitMouseEvent(wxMouseEvent& event, int x, int y, WXUINT flags) { event.m_x = x; event.m_y = y; @@ -3243,7 +3245,7 @@ void wxWindow::InitMouseEvent(wxMouseEvent& event, int x, int y, WXUINT flags) } -bool wxWindow::HandleMouseEvent(WXUINT msg, int x, int y, WXUINT flags) +bool wxWindowMSW::HandleMouseEvent(WXUINT msg, int x, int y, WXUINT flags) { // the mouse events take consecutive IDs from WM_MOUSEFIRST to // WM_MOUSELAST, so it's enough to substract WM_MOUSEMOVE == WM_MOUSEFIRST @@ -3269,7 +3271,7 @@ bool wxWindow::HandleMouseEvent(WXUINT msg, int x, int y, WXUINT flags) return GetEventHandler()->ProcessEvent(event); } -bool wxWindow::HandleMouseMove(int x, int y, WXUINT flags) +bool wxWindowMSW::HandleMouseMove(int x, int y, WXUINT flags) { if ( !m_mouseInWindow ) { @@ -3315,7 +3317,7 @@ bool wxWindow::HandleMouseMove(int x, int y, WXUINT flags) // create the key event of the given type for the given key - used by // HandleChar and HandleKeyDown/Up -wxKeyEvent wxWindow::CreateKeyEvent(wxEventType evType, +wxKeyEvent wxWindowMSW::CreateKeyEvent(wxEventType evType, int id, WXLPARAM lParam) const { @@ -3345,7 +3347,7 @@ wxKeyEvent wxWindow::CreateKeyEvent(wxEventType evType, // isASCII is TRUE only when we're called from WM_CHAR handler and not from // WM_KEYDOWN one -bool wxWindow::HandleChar(WXWORD wParam, WXLPARAM lParam, bool isASCII) +bool wxWindowMSW::HandleChar(WXWORD wParam, WXLPARAM lParam, bool isASCII) { bool ctrlDown = FALSE; @@ -3398,7 +3400,7 @@ bool wxWindow::HandleChar(WXWORD wParam, WXLPARAM lParam, bool isASCII) return FALSE; } -bool wxWindow::HandleKeyDown(WXWORD wParam, WXLPARAM lParam) +bool wxWindowMSW::HandleKeyDown(WXWORD wParam, WXLPARAM lParam) { int id = wxCharCodeMSWToWX(wParam); @@ -3420,7 +3422,7 @@ bool wxWindow::HandleKeyDown(WXWORD wParam, WXLPARAM lParam) return FALSE; } -bool wxWindow::HandleKeyUp(WXWORD wParam, WXLPARAM lParam) +bool wxWindowMSW::HandleKeyUp(WXWORD wParam, WXLPARAM lParam) { int id = wxCharCodeMSWToWX(wParam); @@ -3444,7 +3446,7 @@ bool wxWindow::HandleKeyUp(WXWORD wParam, WXLPARAM lParam) // joystick // --------------------------------------------------------------------------- -bool wxWindow::HandleJoystickEvent(WXUINT msg, int x, int y, WXUINT flags) +bool wxWindowMSW::HandleJoystickEvent(WXUINT msg, int x, int y, WXUINT flags) { int change = 0; if ( flags & JOY_BUTTON1CHG ) @@ -3528,7 +3530,7 @@ bool wxWindow::HandleJoystickEvent(WXUINT msg, int x, int y, WXUINT flags) // scrolling // --------------------------------------------------------------------------- -bool wxWindow::MSWOnScroll(int orientation, WXWORD wParam, +bool wxWindowMSW::MSWOnScroll(int orientation, WXWORD wParam, WXWORD pos, WXHWND control) { if ( control ) @@ -4348,7 +4350,8 @@ const char *wxGetMessageName(int message) } #endif //__WXDEBUG__ -static void TranslateKbdEventToMouse(wxWindow *win, int *x, int *y, WPARAM *flags) +static void TranslateKbdEventToMouse(wxWindowMSW *win, + int *x, int *y, WPARAM *flags) { // construct the key mask WPARAM& fwKeys = *flags; @@ -4367,7 +4370,7 @@ static void TranslateKbdEventToMouse(wxWindow *win, int *x, int *y, WPARAM *flag win->ScreenToClient(x, y); } -static TEXTMETRIC wxGetTextMetrics(const wxWindow *win) +static TEXTMETRIC wxGetTextMetrics(const wxWindowMSW *win) { // prepare the DC TEXTMETRIC tm; diff --git a/src/univ/button.cpp b/src/univ/button.cpp index eff9ab78b4..960aee4641 100644 --- a/src/univ/button.cpp +++ b/src/univ/button.cpp @@ -6,7 +6,7 @@ // Created: 14.08.00 // RCS-ID: $Id$ // Copyright: (c) 2000 Vadim Zeitlin -// Licence: wxWindows license +// Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// // ============================================================================ @@ -97,7 +97,7 @@ wxButton::~wxButton() // size management // ---------------------------------------------------------------------------- -wxSize wxButton::DoGetBestSize() const +wxSize wxButton::DoGetBestClientSize() const { wxClientDC dc(wxConstCast(this, wxButton)); wxCoord width, height; @@ -113,7 +113,7 @@ wxSize wxButton::DoGetBestSize() const width += m_bitmap.GetWidth() + 2*m_marginBmpX; } - return AdjustSize(wxSize(width, height)); + return wxSize(width, height); } // ---------------------------------------------------------------------------- @@ -132,12 +132,22 @@ void wxButton::DoDraw(wxControlRenderer *renderer) void wxButton::Press() { - m_isPressed = TRUE; + if ( !m_isPressed ) + { + m_isPressed = TRUE; + + Refresh(); + } } void wxButton::Release() { - m_isPressed = FALSE; + if ( m_isPressed ) + { + m_isPressed = FALSE; + + Refresh(); + } } void wxButton::Toggle() @@ -162,10 +172,9 @@ void wxButton::Click() } bool wxButton::PerformAction(const wxControlAction& action, - const wxEvent& event) + long numArg, + const wxString& strArg) { - bool wasPressed = IsPressed(); - if ( action == wxACTION_BUTTON_TOGGLE ) Toggle(); else if ( action == wxACTION_BUTTON_CLICK ) @@ -175,9 +184,9 @@ bool wxButton::PerformAction(const wxControlAction& action, else if ( action == wxACTION_BUTTON_RELEASE ) Release(); else - return wxControl::PerformAction(action, event); + return wxControl::PerformAction(action, numArg, strArg); - return wasPressed != IsPressed(); + return TRUE; } // ---------------------------------------------------------------------------- @@ -202,5 +211,121 @@ void wxButton::SetDefault() m_isDefault = TRUE; } +// ============================================================================ +// wxStdButtonInputHandler +// ============================================================================ + +wxStdButtonInputHandler::wxStdButtonInputHandler(wxInputHandler *handler) + : wxStdInputHandler(handler) +{ + m_winCapture = NULL; +} + +bool wxStdButtonInputHandler::HandleKey(wxControl *control, + const wxKeyEvent& event, + bool pressed) +{ + int keycode = event.GetKeyCode(); + if ( keycode == WXK_SPACE || keycode == WXK_RETURN ) + { + control->PerformAction(wxACTION_BUTTON_TOGGLE); + + return TRUE; + } + + return wxStdInputHandler::HandleKey(control, event, pressed); +} + +bool wxStdButtonInputHandler::HandleMouse(wxControl *control, + const wxMouseEvent& event) +{ + // the button has 2 states: pressed and normal with the following + // transitions between them: + // + // normal -> left down -> capture mouse and go to pressed state + // pressed -> left up inside -> generate click -> go to normal + // outside ------------------> + // + // the other mouse buttons are ignored + if ( event.Button(1) ) + { + if ( event.ButtonDown(1) ) + { + m_winCapture = control; + m_winCapture->CaptureMouse(); + m_winHasMouse = TRUE; + + control->PerformAction(wxACTION_BUTTON_PRESS); + + return TRUE; + } + else // up + { + if ( m_winCapture ) + { + m_winCapture->ReleaseMouse(); + m_winCapture = NULL; + } + + if ( m_winHasMouse ) + { + // this will generate a click event + control->PerformAction(wxACTION_BUTTON_TOGGLE); + + return TRUE; + } + //else: the mouse was released outside the window, this doesn't + // count as a click + } + } + + return wxStdInputHandler::HandleMouse(control, event); +} + +bool wxStdButtonInputHandler::HandleMouseMove(wxControl *control, + const wxMouseEvent& event) +{ + // we only have to do something when the mouse leaves/enters the pressed + // button and don't care about the other ones + if ( event.GetEventObject() == m_winCapture ) + { + // leaving the button should remove its pressed state + if ( event.Leaving() ) + { + // remember that the mouse is now outside + m_winHasMouse = FALSE; + + // we do have a pressed button, so release it + control->PerformAction(wxACTION_BUTTON_RELEASE); + + return TRUE; + } + // and entering it back should make it pressed again if it had been + // pressed + else if ( event.Entering() ) + { + // the mouse is (back) inside the button + m_winHasMouse = TRUE; + + // we did have a pressed button which we released when leaving the + // window, press it again + control->PerformAction(wxACTION_BUTTON_PRESS); + + return TRUE; + } + } + + return wxStdInputHandler::HandleMouseMove(control, event); +} + +bool wxStdButtonInputHandler::HandleFocus(wxControl *control, + const wxFocusEvent& event) +{ + // buttons change appearance when they get/lose focus + control->Refresh(); + + return TRUE; +} + #endif // wxUSE_BUTTON diff --git a/src/univ/control.cpp b/src/univ/control.cpp index 5af83215f8..a5e0432ef4 100644 --- a/src/univ/control.cpp +++ b/src/univ/control.cpp @@ -62,6 +62,8 @@ END_EVENT_TABLE() void wxControl::Init() { m_indexAccel = -1; + + m_handler = (wxInputHandler *)NULL; } bool wxControl::Create(wxWindow *parent, @@ -75,10 +77,11 @@ bool wxControl::Create(wxWindow *parent, if ( !wxControlBase::Create(parent, id, pos, size, style, validator, name) ) return FALSE; - SetBackgroundColour(parent->GetBackgroundColour()); - + m_renderer = wxTheme::Get()->GetRenderer(); m_handler = CreateInputHandler(); + SetBackgroundColour(parent->GetBackgroundColour()); + return TRUE; } @@ -135,8 +138,8 @@ wxString wxControl::GetLabel() const void wxControl::OnFocus(wxFocusEvent& event) { - if ( m_handler->OnFocus(this, event) ) - Refresh(); + if ( !m_handler || !m_handler->HandleFocus(this, event) ) + event.Skip(); } // ---------------------------------------------------------------------------- @@ -150,56 +153,53 @@ wxInputHandler *wxControl::CreateInputHandler() const void wxControl::OnKeyDown(wxKeyEvent& event) { - PerformActions(m_handler->Map(this, event, TRUE), event); + if ( !m_handler || !m_handler->HandleKey(this, event, TRUE) ) + event.Skip(); } void wxControl::OnKeyUp(wxKeyEvent& event) { - PerformActions(m_handler->Map(this, event, FALSE), event); + if ( !m_handler || !m_handler->HandleKey(this, event, FALSE) ) + event.Skip(); } void wxControl::OnMouse(wxMouseEvent& event) { - if ( event.Moving() || event.Entering() || event.Leaving() ) + if ( m_handler ) { - // don't process it at all for static controls which are not supposed - // to react to the mouse in any way at all - if ( AcceptsFocus() && m_handler->OnMouseMove(this, event) ) - Refresh(); - } - else // a click action - { - PerformActions(m_handler->Map(this, event), event); + if ( event.Moving() || event.Entering() || event.Leaving() ) + { + if ( m_handler->HandleMouseMove(this, event) ) + return; + } + else // a click action + { + if ( m_handler->HandleMouse(this, event) ) + return; + } } + + event.Skip(); } // ---------------------------------------------------------------------------- // the actions // ---------------------------------------------------------------------------- -void wxControl::PerformActions(const wxControlActions& actions, - const wxEvent& event) -{ - bool needsRefresh = FALSE; - size_t count = actions.GetCount(); - for ( size_t n = 0; n < count; n++ ) - { - const wxControlAction& action = actions[n]; - if ( !action ) - continue; - - if ( PerformAction(action, event) ) - needsRefresh = TRUE; - } - - if ( needsRefresh ) - Refresh(); -} - bool wxControl::PerformAction(const wxControlAction& action, - const wxEvent& event) + long numArg, + const wxString& strArg) { return FALSE; } +// ---------------------------------------------------------------------------- +// border +// ---------------------------------------------------------------------------- + +wxBorder wxControl::GetDefaultBorder() const +{ + return AcceptsFocus() ? wxBORDER_SUNKEN : wxBORDER_NONE; +} + #endif // wxUSE_CONTROLS diff --git a/src/univ/inphand.cpp b/src/univ/inphand.cpp index a582fb8c48..36305663f6 100644 --- a/src/univ/inphand.cpp +++ b/src/univ/inphand.cpp @@ -29,77 +29,25 @@ #endif #ifndef WX_PRECOMP - #include "wx/timer.h" - - #include "wx/button.h" - #include "wx/scrolbar.h" - #include "wx/univ/renderer.h" #endif // WX_PRECOMP #include "wx/univ/inphand.h" -// ---------------------------------------------------------------------------- -// wxScrollBarTimer: this class is used to repeatedly scroll the scrollbar -// when the mouse is help pressed on the arrow or on the bar. It generates the -// given scroll action command periodically. -// ---------------------------------------------------------------------------- - -class wxScrollBarTimer : public wxTimer -{ -public: - wxScrollBarTimer(wxStdScrollBarInputHandler *handler, - const wxControlAction& action, - const wxMouseEvent& event, - wxScrollBar *control); - - virtual void Notify(); - -private: - wxStdScrollBarInputHandler *m_handler; - wxControlAction m_action; - wxMouseEvent m_event; - wxScrollBar *m_control; -}; - // ============================================================================ // implementation // ============================================================================ -// ---------------------------------------------------------------------------- -// wxScrollBarTimer -// ---------------------------------------------------------------------------- - -wxScrollBarTimer::wxScrollBarTimer(wxStdScrollBarInputHandler *handler, - const wxControlAction& action, - const wxMouseEvent& event, - wxScrollBar *control) - : m_event(event) -{ - m_handler = handler; - m_action = action; - m_control = control; -} - -void wxScrollBarTimer::Notify() -{ - if ( m_handler->OnScrollTimer(m_control, m_action, m_event) ) - { - // keep scrolling - m_control->Refresh(); - } -} - // ---------------------------------------------------------------------------- // wxInputHandler // ---------------------------------------------------------------------------- -bool wxInputHandler::OnMouseMove(wxControl * WXUNUSED(control), - const wxMouseEvent& WXUNUSED(event)) +bool wxInputHandler::HandleMouseMove(wxControl * WXUNUSED(control), + const wxMouseEvent& WXUNUSED(event)) { return FALSE; } -bool wxInputHandler::OnFocus(wxControl *control, const wxFocusEvent& event) +bool wxInputHandler::HandleFocus(wxControl *control, const wxFocusEvent& event) { return FALSE; } @@ -108,396 +56,3 @@ wxInputHandler::~wxInputHandler() { } -// ---------------------------------------------------------------------------- -// wxStdButtonInputHandler -// ---------------------------------------------------------------------------- - -wxStdButtonInputHandler::wxStdButtonInputHandler(wxInputHandler *handler) - : wxStdInputHandler(handler) -{ - m_winCapture = NULL; -} - -wxControlActions wxStdButtonInputHandler::Map(wxControl *control, - const wxKeyEvent& event, - bool pressed) -{ - int keycode = event.GetKeyCode(); - if ( keycode == WXK_SPACE || keycode == WXK_RETURN ) - { - return wxACTION_BUTTON_TOGGLE; - } - - return wxStdInputHandler::Map(control, event, pressed); -} - -wxControlActions wxStdButtonInputHandler::Map(wxControl *control, - const wxMouseEvent& event) -{ - // the button has 2 states: pressed and normal with the following - // transitions between them: - // - // normal -> left down -> capture mouse and go to pressed state - // pressed -> left up inside -> generate click -> go to normal - // outside ------------------> - // - // the other mouse buttons are ignored - if ( event.Button(1) ) - { - if ( event.ButtonDown(1) ) - { - m_winCapture = control; - m_winCapture->CaptureMouse(); - m_winHasMouse = TRUE; - - return wxACTION_BUTTON_PRESS; - } - else // up - { - if ( m_winCapture ) - { - m_winCapture->ReleaseMouse(); - m_winCapture = NULL; - } - - if ( m_winHasMouse ) - { - // this will generate a click event - return wxACTION_BUTTON_TOGGLE; - } - //else: the mouse was released outside the window, this doesn't - // count as a click - } - } - - return wxStdInputHandler::Map(control, event); -} - -bool wxStdButtonInputHandler::OnMouseMove(wxControl *control, - const wxMouseEvent& event) -{ - // we only have to do soemthing when the mouse leaves/enters the pressed - // button and don't care about the other ones - if ( event.GetEventObject() == m_winCapture ) - { - // leaving the button should remove its pressed state - if ( event.Leaving() ) - { - // remember that the mouse is now outside - m_winHasMouse = FALSE; - - // we do have a pressed button, so release it - if ( control->PerformAction(wxACTION_BUTTON_RELEASE, event) ) - { - // the button state changed, refresh needed - return TRUE; - } - } - // and entering it back should make it pressed again if it had been - // pressed - else if ( event.Entering() ) - { - // the mouse is (back) inside the button - m_winHasMouse = TRUE; - - // we did have a pressed button which we released when leaving the - // window, press it again - if ( control->PerformAction(wxACTION_BUTTON_PRESS, event) ) - { - return TRUE; - } - } - } - - return wxStdInputHandler::OnMouseMove(control, event); -} - -bool wxStdButtonInputHandler::OnFocus(wxControl *control, - const wxFocusEvent& event) -{ - // buttons chaneg appearance when they get/lose focus - return TRUE; -} - -// ---------------------------------------------------------------------------- -// wxStdScrollBarInputHandler -// ---------------------------------------------------------------------------- - -wxStdScrollBarInputHandler::wxStdScrollBarInputHandler(wxRenderer *renderer, - wxInputHandler *handler) - : wxStdInputHandler(handler) -{ - m_renderer = renderer; - m_winCapture = NULL; - m_htLast = wxHT_NOWHERE; - m_timerScroll = NULL; -} - -wxStdScrollBarInputHandler::~wxStdScrollBarInputHandler() -{ - // normally, it's NULL by now but just in case the user somehow managed to - // keep the mouse captured until now... - delete m_timerScroll; -} - -void wxStdScrollBarInputHandler::SetElementState(wxScrollBar *control, - int flag, - bool doIt) -{ - if ( m_htLast > wxHT_SCROLLBAR_FIRST && m_htLast < wxHT_SCROLLBAR_LAST ) - { - wxScrollBar::Element - elem = (wxScrollBar::Element)(m_htLast - wxHT_SCROLLBAR_FIRST - 1); - - int flags = control->GetState(elem); - if ( doIt ) - flags |= flag; - else - flags &= ~flag; - control->SetState(elem, flags); - } -} - -bool wxStdScrollBarInputHandler::OnScrollTimer(wxScrollBar *scrollbar, - const wxControlAction& action, - const wxMouseEvent& event) -{ - if ( scrollbar->PerformAction(action, event) ) - return TRUE; - - // we scrolled till the end - m_timerScroll->Stop(); - - return FALSE; -} - -void wxStdScrollBarInputHandler::StopScrolling(wxScrollBar *control) -{ - // return everything to the normal state - if ( m_winCapture ) - { - m_winCapture->ReleaseMouse(); - m_winCapture = NULL; - } - - m_btnCapture = -1; - - if ( m_timerScroll ) - { - delete m_timerScroll; - m_timerScroll = NULL; - } - - // unpress the arrow and highlight the current element - Press(control, FALSE); -} - -wxControlActions wxStdScrollBarInputHandler::Map(wxControl *control, - const wxKeyEvent& event, - bool pressed) -{ - // we only react to the key presses here - if ( pressed ) - { - switch ( event.GetKeyCode() ) - { - case WXK_DOWN: - case WXK_RIGHT: return wxACTION_SCROLL_LINE_DOWN; - case WXK_UP: - case WXK_LEFT: return wxACTION_SCROLL_LINE_UP; - case WXK_HOME: return wxACTION_SCROLL_START; - case WXK_END: return wxACTION_SCROLL_END; - case WXK_PRIOR: return wxACTION_SCROLL_PAGE_UP; - case WXK_NEXT: return wxACTION_SCROLL_PAGE_DOWN; - } - } - - return wxStdInputHandler::Map(control, event, pressed); -} - -wxControlActions wxStdScrollBarInputHandler::Map(wxControl *control, - const wxMouseEvent& event) -{ - // is this a click event from an acceptable button? - int btn = -1; - if ( event.IsButton() ) - { - for ( int i = 1; i <= 3; i++ ) - { - if ( event.Button(i) ) - { - btn = i; - break; - } - } - - wxASSERT_MSG( btn != -1, _T("unknown mouse button") ); - } - - if ( (btn != -1) && IsAllowedButton(btn) ) - { - // determine which part of the window mouse is in - wxScrollBar *scrollbar = wxStaticCast(control, wxScrollBar); - wxHitTest ht = m_renderer->HitTestScrollbar - ( - scrollbar, - event.GetPosition() - ); - - // when the mouse is pressed on any scrollbar element, we capture it - // and hold capture until the same mouse button is released - if ( event.ButtonDown() || event.ButtonDClick() ) - { - if ( !m_winCapture ) - { - m_btnCapture = btn; - m_winCapture = control; - m_winCapture->CaptureMouse(); - - // generate the command - bool hasAction = TRUE; - wxControlAction action; - switch ( ht ) - { - case wxHT_SCROLLBAR_ARROW_LINE_1: - action = wxACTION_SCROLL_LINE_UP; - break; - - case wxHT_SCROLLBAR_ARROW_LINE_2: - action = wxACTION_SCROLL_LINE_DOWN; - break; - - case wxHT_SCROLLBAR_BAR_1: - action = wxACTION_SCROLL_PAGE_UP; - m_ptStartScrolling = event.GetPosition(); - break; - - case wxHT_SCROLLBAR_BAR_2: - action = wxACTION_SCROLL_PAGE_DOWN; - m_ptStartScrolling = event.GetPosition(); - break; - - case wxHT_SCROLLBAR_THUMB: - control->PerformAction(wxACTION_SCROLL_THUMB_DRAG, event); - // fall through: there is no immediate action - - default: - hasAction = FALSE; - } - - // remove highlighting - Highlight(scrollbar, FALSE); - m_htLast = ht; - - // and press the arrow or highlight thumb now instead - if ( m_htLast == wxHT_SCROLLBAR_THUMB ) - Highlight(scrollbar, TRUE); - else - Press(scrollbar, TRUE); - - // start dragging - if ( hasAction ) - { - m_timerScroll = new wxScrollBarTimer(this, - action, - event, - scrollbar); - // start scrolling immediately - m_timerScroll->Notify(); - - // and continue it later - m_timerScroll->Start(50); // FIXME hardcoded delay - } - else // no (immediate) action - { - // highlighting still might have changed - control->Refresh(); - } - - } - //else: mouse already captured, nothing to do - } - // release mouse if the *same* button went up - else if ( btn == m_btnCapture ) - { - if ( m_winCapture ) - { - StopScrolling(scrollbar); - - // if we were dragging the thumb, send the last event - if ( m_htLast == wxHT_SCROLLBAR_THUMB ) - { - scrollbar->PerformAction(wxACTION_SCROLL_THUMB_RELEASE, event); - } - - m_htLast = ht; - Highlight(scrollbar, TRUE); - - control->Refresh(); - } - else - { - // this is not supposed to happen as the button can't go up - // without going down previously and then we'd have - // m_winCapture by now - wxFAIL_MSG( _T("logic error in mouse capturing code") ); - } - } - } - - return wxStdInputHandler::Map(control, event); -} - -bool wxStdScrollBarInputHandler::OnMouseMove(wxControl *control, - const wxMouseEvent& event) -{ - if ( m_winCapture ) - { - if ( (m_htLast == wxHT_SCROLLBAR_THUMB) && event.Moving() ) - { - // drag the thumb so that it follows the mouse - if ( control->PerformAction(wxACTION_SCROLL_THUMB_MOVE, event) ) - return TRUE; - } - - // no other changes are possible while the mouse is captured - return FALSE; - } - - wxScrollBar *scrollbar = wxStaticCast(control, wxScrollBar); - - if ( event.Moving() ) - { - wxHitTest ht = m_renderer->HitTestScrollbar - ( - scrollbar, - event.GetPosition() - ); - if ( ht == m_htLast ) - { - // nothing changed - return FALSE; - } - -#ifdef DEBUG_MOUSE - wxLogDebug("Scrollbar::OnMouseMove: ht = %d", ht); -#endif // DEBUG_MOUSE - - Highlight(scrollbar, FALSE); - m_htLast = ht; - Highlight(scrollbar, TRUE); - } - else if ( event.Leaving() ) - { - Highlight(scrollbar, FALSE); - m_htLast = wxHT_NOWHERE; - } - else - { - // don't refresh - return FALSE; - } - - // highlighting changed - return TRUE; -} diff --git a/src/univ/listbox.cpp b/src/univ/listbox.cpp new file mode 100644 index 0000000000..8c11446894 --- /dev/null +++ b/src/univ/listbox.cpp @@ -0,0 +1,675 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: univ/listbox.cpp +// Purpose: wxListBox implementation +// Author: Vadim Zeitlin +// Modified by: +// Created: 30.08.00 +// RCS-ID: $Id$ +// Copyright: (c) 2000 Vadim Zeitlin +// Licence: wxWindows licence +///////////////////////////////////////////////////////////////////////////// + +// ============================================================================ +// declarations +// ============================================================================ + +// ---------------------------------------------------------------------------- +// headers +// ---------------------------------------------------------------------------- + +#ifdef __GNUG__ + #pragma implementation "univlistbox.h" +#endif + +#include "wx/wxprec.h" + +#ifdef __BORLANDC__ + #pragma hdrstop +#endif + +#if wxUSE_LISTBOX + +#ifndef WX_PRECOMP + #include "wx/dcclient.h" + #include "wx/listbox.h" + #include "wx/validate.h" +#endif + +#include "wx/univ/renderer.h" +#include "wx/univ/inphand.h" +#include "wx/univ/theme.h" + +// ============================================================================ +// implementation of wxListBox +// ============================================================================ + +IMPLEMENT_DYNAMIC_CLASS(wxListBox, wxControl) + +BEGIN_EVENT_TABLE(wxListBox, wxListBoxBase) + EVT_SIZE(wxListBox::OnSize) + + EVT_IDLE(wxListBox::OnIdle) +END_EVENT_TABLE() + +// ---------------------------------------------------------------------------- +// construction +// ---------------------------------------------------------------------------- + +void wxListBox::Init() +{ + // will be calculated later when needed + m_lineHeight = 0; + m_itemsPerPage = 0; + + // no items hence no current item + m_current = -1; + + // no need to update anything initially + m_updateCount = 0; +} + +bool wxListBox::Create(wxWindow *parent, + wxWindowID id, + const wxPoint &pos, + const wxSize &size, + int n, + const wxString choices[], + long style, + const wxValidator& validator, + const wxString &name) +{ + if ( !wxControl::Create(parent, id, pos, size, style, wxDefaultValidator, name) ) + return FALSE; + + SetBackgroundColour(*wxWHITE); + + if ( style & wxLB_SORT ) + m_strings = wxArrayString(TRUE /* auto sort */); + + Set(n, choices); + + SetBestSize(size); + + return TRUE; +} + +wxListBox::~wxListBox() +{ +} + +// ---------------------------------------------------------------------------- +// adding/inserting strings +// ---------------------------------------------------------------------------- + +int wxListBox::DoAppend(const wxString& item) +{ + size_t index = m_strings.Add(item); + m_clientData.Insert(NULL, index); + + RefreshItem(m_strings.GetCount() - 1); + + return index; +} + +void wxListBox::DoInsertItems(const wxArrayString& items, int pos) +{ + // the position of the item being added to a sorted listbox can't be + // specified + wxCHECK_RET( !IsSorted(), _T("can't insert items into sorted listbox") ); + + size_t count = items.GetCount(); + for ( size_t n = 0; n < count; n++ ) + { + m_strings.Insert(items[n], pos + n); + m_clientData.Insert(NULL, pos + n); + } + + RefreshItems(pos, count); +} + +void wxListBox::DoSetItems(const wxArrayString& items, void **clientData) +{ + DoClear(); + + size_t count = items.GetCount(); + m_strings.Alloc(count); + m_clientData.Alloc(count); + for ( size_t n = 0; n < count; n++ ) + { + size_t index = m_strings.Add(items[n]); + + if ( clientData ) + m_clientData.Insert(clientData[n], index); + } + + RefreshAll(); +} + +// ---------------------------------------------------------------------------- +// removing strings +// ---------------------------------------------------------------------------- + +void wxListBox::DoClear() +{ + m_strings.Clear(); + + if ( HasClientObjectData() ) + { + size_t count = m_clientData.GetCount(); + for ( size_t n = 0; n < count; n++ ) + { + delete m_clientData[n]; + } + } + + m_clientData.Clear(); +} + +void wxListBox::Clear() +{ + DoClear(); + + RefreshAll(); +} + +void wxListBox::Delete(int n) +{ + wxCHECK_RET( n < GetCount(), _T("invalid index in wxListBox::Delete") ); + + m_strings.RemoveAt(n); + + if ( HasClientObjectData() ) + { + delete m_clientData[n]; + } + + m_clientData.RemoveAt(n); + + RefreshItems(n, GetCount() - n); +} + +// ---------------------------------------------------------------------------- +// client data handling +// ---------------------------------------------------------------------------- + +void wxListBox::DoSetItemClientData(int n, void* clientData) +{ + m_clientData[n] = clientData; +} + +void *wxListBox::DoGetItemClientData(int n) const +{ + return m_clientData[n]; +} + +void wxListBox::DoSetItemClientObject(int n, wxClientData* clientData) +{ + m_clientData[n] = clientData; +} + +wxClientData* wxListBox::DoGetItemClientObject(int n) const +{ + return (wxClientData *)m_clientData[n]; +} + +// ---------------------------------------------------------------------------- +// selection +// ---------------------------------------------------------------------------- + +void wxListBox::SetSelection(int n, bool select) +{ + if ( select ) + { + if ( m_selections.Index(n) == wxNOT_FOUND ) + { + m_selections.Add(n); + + RefreshItem(n); + } + //else: already selected + } + else // unselect + { + int index = m_selections.Index(n); + if ( index != wxNOT_FOUND ) + { + m_selections.RemoveAt(index); + + RefreshItem(n); + } + //else: not selected + } +} + +int wxListBox::GetSelection() const +{ + wxCHECK_MSG( !HasMultipleSelection(), -1, + _T("use wxListBox::GetSelections for ths listbox") ); + + return m_selections.IsEmpty() ? -1 : m_selections[0]; +} + +int wxListBox::GetSelections(wxArrayInt& selections) const +{ + selections = m_selections; + + return m_selections.GetCount(); +} + +// ---------------------------------------------------------------------------- +// refresh logic: we use delayed refreshing which allows to avoid multiple +// refreshes (and hence flicker) in case when several listbox items are +// added/deleted/changed subsequently +// ---------------------------------------------------------------------------- + +void wxListBox::RefreshItems(int from, int count) +{ + switch ( m_updateCount ) + { + case 0: + m_updateFrom = from; + m_updateCount = count; + break; + + case -1: + // we refresh everything anyhow + break; + + default: + // add these items to the others which we have to refresh + if ( m_updateFrom < from ) + { + count += from - m_updateFrom; + if ( m_updateCount < count ) + m_updateCount = count; + } + else // m_updateFrom >= from + { + m_updateCount = wxMax(m_updateCount, + from + count - m_updateFrom); + m_updateFrom = from; + } + } +} + +void wxListBox::RefreshItem(int n) +{ + switch ( m_updateCount ) + { + case 0: + // refresh this item only + m_updateFrom = n; + m_updateCount = 1; + break; + + case -1: + // we refresh everything anyhow + break; + + default: + // add this item to the others which we have to refresh + if ( m_updateFrom < n ) + { + if ( m_updateCount < n - m_updateFrom ) + m_updateFrom = n - m_updateFrom; + } + else // n <= m_updateFrom + { + m_updateCount += m_updateFrom - n; + m_updateFrom = n; + } + } +} + +void wxListBox::RefreshAll() +{ + m_updateCount = -1; +} + +void wxListBox::OnIdle(wxIdleEvent& event) +{ + if ( m_updateCount ) + { + // only refresh the items which must be refreshed + if ( m_updateCount == -1 ) + { + // refresh all + wxLogTrace(_T("listbox"), _T("Refreshing all")); + + Refresh(); + } + else + { + wxLogTrace(_T("listbox"), _T("Refreshing items %d..%d"), + m_updateFrom, m_updateFrom + m_updateCount); + + wxRect rect; + rect.x = 0; + rect.y = m_updateFrom*GetLineHeight(); + rect.width = 32767; // larger than our size + rect.height = m_updateCount*GetLineHeight(); + Refresh(TRUE, &rect); + } + + m_updateCount = 0; + } +} + +// ---------------------------------------------------------------------------- +// drawing +// ---------------------------------------------------------------------------- + +void wxListBox::DoDraw(wxControlRenderer *renderer) +{ + // draw the border first + wxControl::DoDraw(renderer); + + // adjust the DC to account for scrolling + wxDC& dc = renderer->GetDC(); + PrepareDC(dc); + + // get the items which must be redrawn +#if 0 + int y; + GetViewStart(NULL, &y); +#endif + wxCoord lineHeight = GetLineHeight(); + wxRect rectUpdate = GetUpdateRegion().GetBox(); + size_t itemFirst = rectUpdate.GetTop() / lineHeight, + itemLast = (rectUpdate.GetBottom() + lineHeight - 1) / lineHeight, + itemMax = m_strings.GetCount(); + + if ( itemFirst >= itemMax ) + return; + + if ( itemLast > itemMax ) + itemLast = itemMax; + + // do draw them + wxLogTrace(_T("listbox"), _T("Repainting items %d..%d"), + itemFirst, itemLast); + renderer->DrawItems(this, itemFirst, itemLast); +} + +// ---------------------------------------------------------------------------- +// size calculations +// ---------------------------------------------------------------------------- + +bool wxListBox::SetFont(const wxFont& font) +{ + if ( !wxControl::SetFont(font) ) + return FALSE; + + CalcItemsPerPage(); + + RefreshAll(); + + return TRUE; +} + +void wxListBox::CalcItemsPerPage() +{ + m_lineHeight = wxClientDC(this).GetCharHeight(); + m_itemsPerPage = GetClientSize().y / m_lineHeight; +} + +int wxListBox::GetItemsPerPage() const +{ + if ( !m_itemsPerPage ) + { + wxConstCast(this, wxListBox)->CalcItemsPerPage(); + } + + return m_itemsPerPage; +} + +wxCoord wxListBox::GetLineHeight() const +{ + if ( !m_lineHeight ) + { + wxConstCast(this, wxListBox)->CalcItemsPerPage(); + } + + return m_lineHeight; +} + +void wxListBox::OnSize(wxSizeEvent& event) +{ + // recalculate the number of items per page + CalcItemsPerPage(); + + event.Skip(); +} + +void wxListBox::DoSetFirstItem(int n) +{ + wxFAIL_MSG( _T("TODO") ); +} + +wxSize wxListBox::DoGetBestClientSize() const +{ + wxClientDC dc(wxConstCast(this, wxListBox)); + + wxCoord width = 0, + height = 0; + + size_t count = m_strings.GetCount(); + for ( size_t n = 0; n < count; n++ ) + { + wxCoord w,h; + dc.GetTextExtent(m_strings[n], &w, &h); + + if ( w > width ) + width = w; + if ( h > height ) + height = h; + } + + // if the listbox is empty, still give it some non zero (even if + // arbitrary) size - otherwise, leave small margin around the strings + if ( !width ) + width = 100; + else + width += 3*dc.GetCharWidth(); + + if ( !height ) + height = dc.GetCharHeight(); + + // we need the height of the entire listbox, not just of one line + height *= wxMax(count, 7); + + return wxSize(width, height); +} + +// ---------------------------------------------------------------------------- +// listbox actions +// ---------------------------------------------------------------------------- + +bool wxListBox::SendEvent(int item, wxEventType type) +{ + wxCommandEvent event(type, m_windowId); + event.SetEventObject(this); + + int n; + if ( m_selections.GetCount() > 0 ) + { + n = m_selections[0]; + if ( HasClientObjectData() ) + event.SetClientObject(GetClientObject(n)); + else if ( HasClientUntypedData() ) + event.SetClientData(GetClientData(n)); + + event.SetString(GetString(n)); + } + else // no selection + { + n = -1; + } + + event.m_commandInt = n; + + return GetEventHandler()->ProcessEvent(event); +} + +void wxListBox::SetCurrentItem(int n) +{ + if ( m_current != -1 ) + RefreshItem(n); + + m_current = n; + + if ( m_current != -1 ) + RefreshItem(n); +} + +void wxListBox::ChangeCurrent(int diff) +{ + int current = m_current == -1 ? 0 : m_current; + + current += diff; + + int last = GetCount() - 1; + if ( current < 0 ) + current = 0; + else if ( current > last ) + current = last; + + SetCurrentItem(current); +} + +void wxListBox::Select(bool sel) +{ + if ( sel && !HasMultipleSelection() ) + { + // deselect the old item first + int selOld = GetSelection(); + if ( selOld != -1 ) + { + SetSelection(selOld, FALSE); + } + } + + if ( m_current != -1 ) + { + // [de]select the new one + SetSelection(m_current, sel); + + if ( sel ) + { + SendEvent(m_current, wxEVT_COMMAND_LISTBOX_SELECTED); + } + } +} + +void wxListBox::Activate() +{ + if ( m_current != -1 ) + { + Select(); + + SendEvent(m_current, wxEVT_COMMAND_LISTBOX_DOUBLECLICKED); + } +} + +bool wxListBox::PerformAction(const wxControlAction& action, + long numArg, + const wxString& strArg) +{ + if ( action == wxACTION_LISTBOX_SETFOCUS ) + SetCurrentItem(numArg); + else if ( action == wxACTION_LISTBOX_ACTIVATE ) + Activate(); + else if ( action == wxACTION_LISTBOX_TOGGLE ) + Select(!IsSelected(m_current)); + else if ( action == wxACTION_LISTBOX_SELECT ) + Select(TRUE); + else if ( action == wxACTION_LISTBOX_UNSELECT ) + Select(FALSE); + else if ( action == wxACTION_LISTBOX_MOVEDOWN ) + ChangeCurrent(1); + else if ( action == wxACTION_LISTBOX_MOVEUP ) + ChangeCurrent(-1); + else if ( action == wxACTION_LISTBOX_PAGEDOWN ) + ChangeCurrent(GetItemsPerPage()); + else if ( action == wxACTION_LISTBOX_PAGEUP ) + ChangeCurrent(-GetItemsPerPage()); + else if ( action == wxACTION_LISTBOX_START ) + SetCurrentItem(0); + else if ( action == wxACTION_LISTBOX_END ) + SetCurrentItem(GetCount() - 1); + else + return wxControl::PerformAction(action, numArg, strArg); + + return TRUE; +} + +// ============================================================================ +// implementation of wxStdListboxInputHandler +// ============================================================================ + +wxStdListboxInputHandler::wxStdListboxInputHandler(wxInputHandler *handler) + : wxStdInputHandler(handler) +{ +} + +bool wxStdListboxInputHandler::HandleKey(wxControl *control, + const wxKeyEvent& event, + bool pressed) +{ + // we're only interested in the key presses + if ( pressed ) + { + wxControlAction action; + switch ( event.GetKeyCode() ) + { + // movement + case WXK_UP: action = wxACTION_LISTBOX_MOVEUP; break; + case WXK_DOWN: action = wxACTION_LISTBOX_MOVEDOWN; break; + case WXK_PRIOR: action = wxACTION_LISTBOX_PAGEUP; break; + case WXK_NEXT: action = wxACTION_LISTBOX_PAGEDOWN; break; + case WXK_HOME: action = wxACTION_LISTBOX_START; break; + case WXK_END: action = wxACTION_LISTBOX_END; break; + + // selection + case WXK_SPACE: action = wxACTION_LISTBOX_TOGGLE; break; + case WXK_RETURN:action = wxACTION_LISTBOX_ACTIVATE; break; + } + + if ( !!action ) + { + control->PerformAction(action); + + return TRUE; + } + } + + return wxStdInputHandler::HandleKey(control, event, pressed); +} + +bool wxStdListboxInputHandler::HandleMouse(wxControl *control, + const wxMouseEvent& event) +{ + if ( event.LeftDown() ) + { + wxListBox *lbox = wxStaticCast(control, wxListBox); + int item = event.GetPosition().y / lbox->GetLineHeight(); + if ( item < lbox->GetCount() ) + { + lbox->PerformAction(wxACTION_LISTBOX_SETFOCUS, item); + lbox->PerformAction(wxACTION_LISTBOX_TOGGLE); + + return TRUE; + } + //else: click outside the item area, ignore + } + + return wxStdInputHandler::HandleMouse(control, event); +} + +bool wxStdListboxInputHandler::HandleMouseMove(wxControl *control, + const wxMouseEvent& event) +{ + return wxStdInputHandler::HandleMouseMove(control, event); +} + +#endif // wxUSE_LISTBOX diff --git a/src/univ/renderer.cpp b/src/univ/renderer.cpp index bdc9973298..7ba570abf0 100644 --- a/src/univ/renderer.cpp +++ b/src/univ/renderer.cpp @@ -70,6 +70,106 @@ void wxRenderer::StandardDrawFrame(wxDC& dc, // wxRenderer: scrollbar geometry // ---------------------------------------------------------------------------- +/* static */ +wxRect wxRenderer::StandardGetScrollbarRect(const wxScrollBar *scrollbar, + wxScrollBar::Element elem, + int thumbPos, + const wxSize& sizeArrow) +{ + if ( thumbPos == -1 ) + { + thumbPos = scrollbar->GetThumbPosition(); + } + + wxSize sizeTotal = scrollbar->GetClientSize(); + wxCoord *start, *width, length, arrow; + wxRect rect; + if ( scrollbar->IsVertical() ) + { + rect.x = 0; + rect.width = sizeTotal.x; + length = sizeTotal.y; + start = &rect.y; + width = &rect.height; + arrow = sizeArrow.y; + } + else // horizontal + { + rect.y = 0; + rect.height = sizeTotal.y; + length = sizeTotal.x; + start = &rect.x; + width = &rect.width; + arrow = sizeArrow.x; + } + + switch ( elem ) + { + case wxScrollBar::Element_Arrow_Line_1: + *start = 0; + *width = arrow; + break; + + case wxScrollBar::Element_Arrow_Line_2: + *start = length - arrow; + *width = arrow; + break; + + case wxScrollBar::Element_Arrow_Page_1: + case wxScrollBar::Element_Arrow_Page_2: + // we don't have them at all + break; + + case wxScrollBar::Element_Thumb: + case wxScrollBar::Element_Bar_1: + case wxScrollBar::Element_Bar_2: + // we need to calculate the thumb position - do it + { + length -= 2*arrow; + wxCoord thumbStart, thumbEnd; + int range = scrollbar->GetRange(); + if ( !range ) + { + thumbStart = + thumbEnd = 0; + } + else + { + int thumbSize = scrollbar->GetThumbSize(); + + thumbStart = (length*thumbPos) / range; + thumbEnd = (length*(thumbPos + thumbSize)) / range; + } + + if ( elem == wxScrollBar::Element_Thumb ) + { + *start = thumbStart; + *width = thumbEnd - thumbStart; + } + else if ( elem == wxScrollBar::Element_Bar_1 ) + { + *start = 0; + *width = thumbStart; + } + else // elem == wxScrollBar::Element_Bar_2 + { + *start = thumbEnd; + *width = length - thumbEnd; + } + + // everything is relative to the start of the shaft so far + *start += arrow; + } + break; + + case wxScrollBar::Element_Max: + default: + wxFAIL_MSG( _T("unknown scrollbar element") ); + } + + return rect; +} + /* static */ wxCoord wxRenderer::StandardScrollBarSize(const wxScrollBar *scrollbar, const wxSize& sizeArrowSB) @@ -91,6 +191,7 @@ wxCoord wxRenderer::StandardScrollBarSize(const wxScrollBar *scrollbar, /* static */ wxCoord wxRenderer::StandardScrollbarToPixel(const wxScrollBar *scrollbar, + int thumbPos, const wxSize& sizeArrow) { int range = scrollbar->GetRange(); @@ -100,8 +201,13 @@ wxCoord wxRenderer::StandardScrollbarToPixel(const wxScrollBar *scrollbar, return 0; } - return ( scrollbar->GetThumbPosition() * - StandardScrollBarSize(scrollbar, sizeArrow) ) / range + if ( thumbPos == -1 ) + { + // by default use the current thumb position + thumbPos = scrollbar->GetThumbPosition(); + } + + return ( thumbPos*StandardScrollBarSize(scrollbar, sizeArrow) ) / range + (scrollbar->IsVertical() ? sizeArrow.y : sizeArrow.x); } @@ -219,8 +325,13 @@ void wxControlRenderer::DrawBorder() m_renderer->DrawBorder(m_dc, m_window->GetBorder(), m_rect, flags, &m_rect); - // fill the inside (TODO: query the theme for bg bitmap) - m_renderer->DrawBackground(m_dc, m_rect, flags); + // fill the inside unless we have the background bitmap as we don't want to + // overwrite it + if ( !m_window->GetBackgroundBitmap().Ok() ) + { + m_renderer->DrawBackground(m_dc, m_window->GetBackgroundColour(), + m_rect, flags); + } } void wxControlRenderer::DrawLabel(const wxBitmap& bitmap, @@ -272,7 +383,8 @@ void wxControlRenderer::DrawButtonBorder() m_renderer->DrawButtonBorder(m_dc, m_rect, flags, &m_rect); - m_renderer->DrawBackground(m_dc, m_rect, flags); + m_renderer->DrawBackground(m_dc, m_window->GetBackgroundColour(), + m_rect, flags); } void wxControlRenderer::DrawBitmap(const wxBitmap& bitmap) @@ -357,36 +469,85 @@ void wxControlRenderer::DrawBitmap(const wxBitmap& bitmap, m_dc.DrawBitmap(bmp, x, y, TRUE /* use mask */); } -void wxControlRenderer::DrawScrollbar(const wxScrollBar *scrollbar) +void wxControlRenderer::DrawScrollbar(const wxScrollBar *scrollbar, + int thumbPosOld) { - int thumbStart, thumbEnd; - int range = scrollbar->GetRange(); - if ( range ) - { - int thumbPos = scrollbar->GetThumbPosition(), - thumbSize = scrollbar->GetThumbSize(); + // we will only redraw the parts which must be redrawn and not everything + wxRegion rgnUpdate = scrollbar->GetUpdateRegion(); - thumbStart = (100*thumbPos) / range; - thumbEnd = (100*(thumbPos + thumbSize)) / range; - } - else // no range + // arrows + static const wxDirection arrowDirs[2][2] = { - thumbStart = - thumbEnd = 0; + { wxLEFT, wxRIGHT }, + { wxUP, wxDOWN } + }; + + for ( int nArrow = 0; nArrow < 2; nArrow++ ) + { + wxScrollBar::Element elem = + (wxScrollBar::Element)(wxScrollBar::Element_Arrow_Line_1 + nArrow); + + wxRect rectArrow = m_renderer->GetScrollbarRect(scrollbar, elem); + if ( rgnUpdate.Contains(rectArrow) ) + { + m_renderer->DrawArrow(m_dc, + arrowDirs[scrollbar->IsVertical()][nArrow], + rectArrow, + scrollbar->GetState(elem)); + } } - int flags[wxScrollBar::Element_Max]; - for ( size_t n = 0; n < WXSIZEOF(flags); n++ ) + // TODO: support for page arrows + + // the shaft + for ( int nBar = 0; nBar < 2; nBar++ ) { - flags[n] = scrollbar->GetState((wxScrollBar::Element)n); + wxScrollBar::Element elem = + (wxScrollBar::Element)(wxScrollBar::Element_Bar_1 + nBar); + + wxRect rectBar = m_renderer->GetScrollbarRect(scrollbar, elem); + + if ( rgnUpdate.Contains(rectBar) ) + { +#if 0 + // we try to avoid redrawing the entire shaft (which might be quite + // long) if possible by only redrawing the area between the old and + // current positions of the thumb + if ( thumbPosOld != -1 ) + { + wxRect rectBarOld = m_renderer->GetScrollbarRect(scrollbar, + elem, + thumbPosOld); + if ( scrollbar->IsVertical() ) + { + if ( nBar ) + rectBar.SetBottom(rectBar.GetTop()); + else + rectBar.SetTop(rectBarOld.GetBottom()); + } + else // horizontal + { + if ( nBar ) + rectBar.SetRight(rectBar.GetLeft()); + else + rectBar.SetLeft(rectBarOld.GetRight()); + } + } +#endif // 0 + + m_renderer->DrawScrollbarShaft(m_dc, rectBar, + scrollbar->GetState(elem)); + } } - m_renderer->DrawScrollbar(m_dc, - m_window->GetWindowStyle() & wxVERTICAL - ? wxVERTICAL - : wxHORIZONTAL, - thumbStart, thumbEnd, m_rect, - flags); + // and the thumb + wxScrollBar::Element elem = wxScrollBar::Element_Thumb; + wxRect rectThumb = m_renderer->GetScrollbarRect(scrollbar, elem); + if ( rgnUpdate.Contains(rectThumb) ) + { + m_renderer->DrawScrollbarThumb(m_dc, rectThumb, + scrollbar->GetState(elem)); + } } void wxControlRenderer::DrawLine(wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2) @@ -399,3 +560,24 @@ void wxControlRenderer::DrawLine(wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2) else // horizontal m_renderer->DrawHorizontalLine(m_dc, y1, x1, x2); } + +void wxControlRenderer::DrawItems(const wxListBox *lbox, + size_t itemFirst, size_t itemLast) +{ + wxCoord lineHeight = lbox->GetLineHeight(); + wxRect rect = m_rect; + rect.y += itemFirst*lineHeight; + rect.height = lineHeight; + for ( size_t n = itemFirst; n < itemLast; n++ ) + { + int flags = 0; + if ( (int)n == lbox->GetCurrentItem() ) + flags |= wxCONTROL_FOCUSED; + if ( lbox->IsSelected(n) ) + flags |= wxCONTROL_SELECTED; + + m_renderer->DrawItem(m_dc, lbox->GetString(n), rect, flags); + + rect.y += lineHeight; + } +} diff --git a/src/univ/scrolbar.cpp b/src/univ/scrolbar.cpp index 11102a8014..bf213d6d2a 100644 --- a/src/univ/scrolbar.cpp +++ b/src/univ/scrolbar.cpp @@ -30,6 +30,8 @@ #if wxUSE_SCROLLBAR #ifndef WX_PRECOMP + #include "wx/timer.h" + #include "wx/dcclient.h" #include "wx/scrolbar.h" #include "wx/validate.h" @@ -39,12 +41,37 @@ #include "wx/univ/inphand.h" #include "wx/univ/theme.h" +// ---------------------------------------------------------------------------- +// wxScrollBarTimer: this class is used to repeatedly scroll the scrollbar +// when the mouse is help pressed on the arrow or on the bar. It generates the +// given scroll action command periodically. +// ---------------------------------------------------------------------------- + +class wxScrollBarTimer : public wxTimer +{ +public: + wxScrollBarTimer(wxStdScrollBarInputHandler *handler, + const wxControlAction& action, + wxScrollBar *control); + + virtual void Notify(); + +private: + wxStdScrollBarInputHandler *m_handler; + wxControlAction m_action; + wxScrollBar *m_control; +}; + // ============================================================================ // implementation // ============================================================================ IMPLEMENT_DYNAMIC_CLASS(wxScrollBar, wxControl) +BEGIN_EVENT_TABLE(wxScrollBar, wxScrollBarBase) + EVT_IDLE(wxScrollBar::OnIdle) +END_EVENT_TABLE() + // ---------------------------------------------------------------------------- // creation // ---------------------------------------------------------------------------- @@ -56,10 +83,14 @@ void wxScrollBar::Init() m_thumbPos = m_pageSize = 0; + m_thumbPosOld = -1; + for ( size_t n = 0; n < WXSIZEOF(m_elementsState); n++ ) { m_elementsState[n] = 0; } + + m_dirty = FALSE; } bool wxScrollBar::Create(wxWindow *parent, @@ -102,7 +133,20 @@ void wxScrollBar::DoSetThumb(int pos) pos = m_range - m_thumbSize; } + if ( m_thumbPosOld == -1 ) + { + // remember the old thumb position + m_thumbPosOld = m_thumbPos; + } + m_thumbPos = pos; + + // we have to refresh the part of the bar which was under the thumb and the + // thumb itself + m_elementsState[Element_Thumb] |= wxCONTROL_DIRTY; + m_elementsState[m_thumbPos > m_thumbPosOld + ? Element_Bar_1 : Element_Bar_2] |= wxCONTROL_DIRTY; + m_dirty = TRUE; } int wxScrollBar::GetThumbPosition() const @@ -130,8 +174,6 @@ void wxScrollBar::SetThumbPosition(int pos) wxCHECK_RET( pos >= 0 && pos <= m_range, _T("thumb position out of range") ); DoSetThumb(pos); - - Refresh(); } void wxScrollBar::SetScrollbar(int position, int thumbSize, @@ -155,34 +197,67 @@ void wxScrollBar::SetScrollbar(int position, int thumbSize, // size management // ---------------------------------------------------------------------------- -wxSize wxScrollBar::DoGetBestSize() const +wxSize wxScrollBar::DoGetBestClientSize() const { // completely arbitrary - return AdjustSize(wxSize(140, 140)); + return wxSize(140, 140); } // ---------------------------------------------------------------------------- // drawing // ---------------------------------------------------------------------------- +void wxScrollBar::OnIdle(wxIdleEvent& event) +{ + if ( m_dirty ) + { + for ( size_t n = 0; n < WXSIZEOF(m_elementsState); n++ ) + { + if ( m_elementsState[n] & wxCONTROL_DIRTY ) + { + wxRect rect = GetRenderer()->GetScrollbarRect(this, (Element)n); + + if ( rect.width && rect.height ) + { + // don't refresh the background when refreshing the shaft + Refresh(TRUE, //(n != Element_Bar_1) && (n != Element_Bar_2) + &rect); + } + + m_elementsState[n] &= ~wxCONTROL_DIRTY; + } + } + + m_dirty = FALSE; + } +} + void wxScrollBar::DoDraw(wxControlRenderer *renderer) { - renderer->DrawScrollbar(this); + renderer->DrawScrollbar(this, m_thumbPosOld); + + // clear all dirty flags + m_dirty = FALSE; + m_thumbPosOld = -1; } // ---------------------------------------------------------------------------- // input processing // ---------------------------------------------------------------------------- -wxCoord wxScrollBar::GetMouseCoord(const wxEvent& eventOrig) const +void wxScrollBar::SetState(Element which, int flags) { - const wxMouseEvent& event = (const wxMouseEvent&)eventOrig; - wxPoint pt = event.GetPosition(); - return GetWindowStyle() & wxVERTICAL ? pt.y : pt.x; + if ( (m_elementsState[which] & ~wxCONTROL_DIRTY) != flags ) + { + m_elementsState[which] = flags | wxCONTROL_DIRTY; + + m_dirty = TRUE; + } } bool wxScrollBar::PerformAction(const wxControlAction& action, - const wxEvent& event) + long numArg, + const wxString& strArg) { int thumbOld = m_thumbPos; @@ -193,10 +268,7 @@ bool wxScrollBar::PerformAction(const wxControlAction& action, // test for thumb move first as these events happen in quick succession if ( action == wxACTION_SCROLL_THUMB_MOVE ) { - // make the thumb follow the mouse by keeping the same offset between - // the mouse position and the top/left of the thumb - int thumbPos = GetMouseCoord(event) - m_ofsMouse; - DoSetThumb(GetRenderer()->PixelToScrollbar(this, thumbPos)); + DoSetThumb(numArg); scrollType = wxEVT_SCROLLWIN_THUMBTRACK; } @@ -232,8 +304,10 @@ bool wxScrollBar::PerformAction(const wxControlAction& action, } else if ( action == wxACTION_SCROLL_THUMB_DRAG ) { - m_ofsMouse = GetMouseCoord(event) - - GetRenderer()->ScrollbarToPixel(this); + // we won't use it but this line suppresses the compiler + // warning about "variable may be used without having been + // initialized" + scrollType = wxEVT_NULL; } else if ( action == wxACTION_SCROLL_THUMB_RELEASE ) { @@ -242,7 +316,7 @@ bool wxScrollBar::PerformAction(const wxControlAction& action, scrollType = wxEVT_SCROLLWIN_THUMBRELEASE; } else - return wxControl::PerformAction(action, event); + return wxControl::PerformAction(action, numArg, strArg); // has scrollbar position changed? bool changed = m_thumbPos != thumbOld; @@ -254,8 +328,7 @@ bool wxScrollBar::PerformAction(const wxControlAction& action, GetParent()->GetEventHandler()->ProcessEvent(event); } - // refresh if something changed - return changed; + return TRUE; } void wxScrollBar::ScrollToStart() @@ -278,5 +351,333 @@ void wxScrollBar::ScrollPages(int nPages) DoSetThumb(m_thumbPos + nPages*m_pageSize); } +// ============================================================================ +// scroll bar input handler +// ============================================================================ + +// ---------------------------------------------------------------------------- +// wxScrollBarTimer +// ---------------------------------------------------------------------------- + +wxScrollBarTimer::wxScrollBarTimer(wxStdScrollBarInputHandler *handler, + const wxControlAction& action, + wxScrollBar *control) +{ + m_handler = handler; + m_action = action; + m_control = control; +} + +void wxScrollBarTimer::Notify() +{ + m_handler->OnScrollTimer(m_control, m_action); +} + +// ---------------------------------------------------------------------------- +// wxStdScrollBarInputHandler +// ---------------------------------------------------------------------------- + +wxStdScrollBarInputHandler::wxStdScrollBarInputHandler(wxRenderer *renderer, + wxInputHandler *handler) + : wxStdInputHandler(handler) +{ + m_renderer = renderer; + m_winCapture = NULL; + m_htLast = wxHT_NOWHERE; + m_timerScroll = NULL; +} + +wxStdScrollBarInputHandler::~wxStdScrollBarInputHandler() +{ + // normally, it's NULL by now but just in case the user somehow managed to + // keep the mouse captured until now... + delete m_timerScroll; +} + +void wxStdScrollBarInputHandler::SetElementState(wxScrollBar *control, + int flag, + bool doIt) +{ + if ( m_htLast > wxHT_SCROLLBAR_FIRST && m_htLast < wxHT_SCROLLBAR_LAST ) + { + wxScrollBar::Element + elem = (wxScrollBar::Element)(m_htLast - wxHT_SCROLLBAR_FIRST - 1); + + int flags = control->GetState(elem); + if ( doIt ) + flags |= flag; + else + flags &= ~flag; + control->SetState(elem, flags); + } +} + +bool wxStdScrollBarInputHandler::OnScrollTimer(wxScrollBar *scrollbar, + const wxControlAction& action) +{ + int oldThumbPos = scrollbar->GetThumbPosition(); + scrollbar->PerformAction(action); + if ( scrollbar->GetThumbPosition() != oldThumbPos ) + return TRUE; + + // we scrolled till the end + m_timerScroll->Stop(); + + return FALSE; +} + +void wxStdScrollBarInputHandler::StopScrolling(wxScrollBar *control) +{ + // return everything to the normal state + if ( m_winCapture ) + { + m_winCapture->ReleaseMouse(); + m_winCapture = NULL; + } + + m_btnCapture = -1; + + if ( m_timerScroll ) + { + delete m_timerScroll; + m_timerScroll = NULL; + } + + // unpress the arrow and highlight the current element + Press(control, FALSE); +} + +wxCoord +wxStdScrollBarInputHandler::GetMouseCoord(const wxScrollBar *scrollbar, + const wxMouseEvent& event) const +{ + wxPoint pt = event.GetPosition(); + return scrollbar->GetWindowStyle() & wxVERTICAL ? pt.y : pt.x; +} + +void wxStdScrollBarInputHandler::HandleThumbMove(wxScrollBar *scrollbar, + const wxMouseEvent& event) +{ + int thumbPos = GetMouseCoord(scrollbar, event) - m_ofsMouse; + thumbPos = m_renderer->PixelToScrollbar(scrollbar, thumbPos); + scrollbar->PerformAction(wxACTION_SCROLL_THUMB_MOVE, thumbPos); +} + +bool wxStdScrollBarInputHandler::HandleKey(wxControl *control, + const wxKeyEvent& event, + bool pressed) +{ + // we only react to the key presses here + if ( pressed ) + { + wxControlAction action; + switch ( event.GetKeyCode() ) + { + case WXK_DOWN: + case WXK_RIGHT: action = wxACTION_SCROLL_LINE_DOWN; break; + case WXK_UP: + case WXK_LEFT: action = wxACTION_SCROLL_LINE_UP; break; + case WXK_HOME: action = wxACTION_SCROLL_START; break; + case WXK_END: action = wxACTION_SCROLL_END; break; + case WXK_PRIOR: action = wxACTION_SCROLL_PAGE_UP; break; + case WXK_NEXT: action = wxACTION_SCROLL_PAGE_DOWN; break; + } + + if ( !!action ) + { + control->PerformAction(action); + + return TRUE; + } + } + + return wxStdInputHandler::HandleKey(control, event, pressed); +} + +bool wxStdScrollBarInputHandler::HandleMouse(wxControl *control, + const wxMouseEvent& event) +{ + // is this a click event from an acceptable button? + int btn = -1; + if ( event.IsButton() ) + { + for ( int i = 1; i <= 3; i++ ) + { + if ( event.Button(i) ) + { + btn = i; + break; + } + } + + wxASSERT_MSG( btn != -1, _T("unknown mouse button") ); + } + + if ( (btn != -1) && IsAllowedButton(btn) ) + { + // determine which part of the window mouse is in + wxScrollBar *scrollbar = wxStaticCast(control, wxScrollBar); + wxHitTest ht = m_renderer->HitTestScrollbar + ( + scrollbar, + event.GetPosition() + ); + + // when the mouse is pressed on any scrollbar element, we capture it + // and hold capture until the same mouse button is released + if ( event.ButtonDown() || event.ButtonDClick() ) + { + if ( !m_winCapture ) + { + m_btnCapture = btn; + m_winCapture = control; + m_winCapture->CaptureMouse(); + + // generate the command + bool hasAction = TRUE; + wxControlAction action; + switch ( ht ) + { + case wxHT_SCROLLBAR_ARROW_LINE_1: + action = wxACTION_SCROLL_LINE_UP; + break; + + case wxHT_SCROLLBAR_ARROW_LINE_2: + action = wxACTION_SCROLL_LINE_DOWN; + break; + + case wxHT_SCROLLBAR_BAR_1: + action = wxACTION_SCROLL_PAGE_UP; + m_ptStartScrolling = event.GetPosition(); + break; + + case wxHT_SCROLLBAR_BAR_2: + action = wxACTION_SCROLL_PAGE_DOWN; + m_ptStartScrolling = event.GetPosition(); + break; + + case wxHT_SCROLLBAR_THUMB: + control->PerformAction(wxACTION_SCROLL_THUMB_DRAG); + m_ofsMouse = GetMouseCoord(scrollbar, event) - + m_renderer->ScrollbarToPixel(scrollbar); + + // fall through: there is no immediate action + + default: + hasAction = FALSE; + } + + // remove highlighting + Highlight(scrollbar, FALSE); + m_htLast = ht; + + // and press the arrow or highlight thumb now instead + if ( m_htLast == wxHT_SCROLLBAR_THUMB ) + Highlight(scrollbar, TRUE); + else + Press(scrollbar, TRUE); + + // start dragging + if ( hasAction ) + { + m_timerScroll = new wxScrollBarTimer(this, + action, + scrollbar); + // start scrolling immediately + m_timerScroll->Notify(); + + // and continue it later + m_timerScroll->Start(50); // FIXME hardcoded delay + } + //else: no (immediate) action + + } + //else: mouse already captured, nothing to do + } + // release mouse if the *same* button went up + else if ( btn == m_btnCapture ) + { + if ( m_winCapture ) + { + StopScrolling(scrollbar); + + // if we were dragging the thumb, send the last event + if ( m_htLast == wxHT_SCROLLBAR_THUMB ) + { + scrollbar->PerformAction(wxACTION_SCROLL_THUMB_RELEASE); + } + + m_htLast = ht; + Highlight(scrollbar, TRUE); + } + else + { + // this is not supposed to happen as the button can't go up + // without going down previously and then we'd have + // m_winCapture by now + wxFAIL_MSG( _T("logic error in mouse capturing code") ); + } + } + } + + return wxStdInputHandler::HandleMouse(control, event); +} + +bool wxStdScrollBarInputHandler::HandleMouseMove(wxControl *control, + const wxMouseEvent& event) +{ + wxScrollBar *scrollbar = wxStaticCast(control, wxScrollBar); + + if ( m_winCapture ) + { + if ( (m_htLast == wxHT_SCROLLBAR_THUMB) && event.Moving() ) + { + // make the thumb follow the mouse by keeping the same offset + // between the mouse position and the top/left of the thumb + HandleThumbMove(scrollbar, event); + + return TRUE; + } + + // no other changes are possible while the mouse is captured + return FALSE; + } + + if ( event.Moving() ) + { + wxHitTest ht = m_renderer->HitTestScrollbar + ( + scrollbar, + event.GetPosition() + ); + if ( ht == m_htLast ) + { + // nothing changed + return FALSE; + } + +#ifdef DEBUG_MOUSE + wxLogDebug("Scrollbar::OnMouseMove: ht = %d", ht); +#endif // DEBUG_MOUSE + + Highlight(scrollbar, FALSE); + m_htLast = ht; + Highlight(scrollbar, TRUE); + } + else if ( event.Leaving() ) + { + Highlight(scrollbar, FALSE); + m_htLast = wxHT_NOWHERE; + } + else + { + // we don't process this event + return FALSE; + } + + // we did something + return TRUE; +} + #endif // wxUSE_SCROLLBAR diff --git a/src/univ/statbmp.cpp b/src/univ/statbmp.cpp index 9574d6ecf4..b10c04ae6a 100644 --- a/src/univ/statbmp.cpp +++ b/src/univ/statbmp.cpp @@ -102,9 +102,9 @@ wxIcon wxStaticBitmap::GetIcon() const // drawing // ---------------------------------------------------------------------------- -wxSize wxStaticBitmap::DoGetBestSize() const +wxSize wxStaticBitmap::DoGetBestClientSize() const { - return AdjustSize(wxStaticBitmapBase::DoGetBestSize()); + return wxStaticBitmapBase::DoGetBestSize(); } void wxStaticBitmap::DoDraw(wxControlRenderer *renderer) diff --git a/src/univ/stattext.cpp b/src/univ/stattext.cpp index ec7dd1c97a..aea9511ac5 100644 --- a/src/univ/stattext.cpp +++ b/src/univ/stattext.cpp @@ -58,13 +58,7 @@ bool wxStaticText::Create(wxWindow *parent, 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); - } + SetBestSize(size); return TRUE; } @@ -78,13 +72,13 @@ void wxStaticText::SetLabel(const wxString& label) wxControl::SetLabel(label); } -wxSize wxStaticText::DoGetBestSize() const +wxSize wxStaticText::DoGetBestClientSize() const { wxClientDC dc(wxConstCast(this, wxStaticText)); wxCoord width, height; dc.GetMultiLineTextExtent(GetLabel(), &width, &height); - return AdjustSize(wxSize(width, height)); + return wxSize(width, height); } // ---------------------------------------------------------------------------- diff --git a/src/univ/themes/gtk.cpp b/src/univ/themes/gtk.cpp index 7a6ab6735a..63267a6bdd 100644 --- a/src/univ/themes/gtk.cpp +++ b/src/univ/themes/gtk.cpp @@ -53,6 +53,7 @@ public: // implement the base class pure virtuals virtual void DrawBackground(wxDC& dc, + const wxColour& col, const wxRect& rect, int flags = 0); virtual void DrawLabel(wxDC& dc, @@ -86,21 +87,29 @@ public: wxDirection dir, const wxRect& rect, int flags = 0); - virtual void DrawScrollbar(wxDC& dc, - wxOrientation orient, - int thumbPosStart, - int thumbPosEnd, - const wxRect& rect, - const int *flags = NULL); + virtual void DrawScrollbarThumb(wxDC& dc, + const wxRect& rect, + int flags = 0); + virtual void DrawScrollbarShaft(wxDC& dc, + const wxRect& rect, + int flags = 0); + virtual void DrawItem(wxDC& dc, + const wxString& label, + const wxRect& rect, + int flags = 0); virtual void AdjustSize(wxSize *size, const wxWindow *window); // hit testing for the input handlers + virtual wxRect GetScrollbarRect(const wxScrollBar *scrollbar, + wxScrollBar::Element elem, + int thumbPos = -1) const; virtual wxHitTest HitTestScrollbar(const wxScrollBar *scrollbar, const wxPoint& pt) const; - virtual wxCoord ScrollbarToPixel(const wxScrollBar *scrollbar); + virtual wxCoord ScrollbarToPixel(const wxScrollBar *scrollbar, + int thumbPos = -1); virtual int PixelToScrollbar(const wxScrollBar *scrollbar, wxCoord coord); - + protected: // DrawBackground() helpers @@ -159,12 +168,12 @@ class wxGTKInputHandler : public wxInputHandler public: wxGTKInputHandler(wxGTKRenderer *renderer); - virtual wxControlActions Map(wxControl *control, - const wxKeyEvent& event, - bool pressed); - virtual wxControlActions Map(wxControl *control, - const wxMouseEvent& event); - virtual bool OnMouseMove(wxControl *control, const wxMouseEvent& event); + virtual bool HandleKey(wxControl *control, + const wxKeyEvent& event, + bool pressed); + virtual bool HandleMouse(wxControl *control, + const wxMouseEvent& event); + virtual bool HandleMouseMove(wxControl *control, const wxMouseEvent& event); protected: wxGTKRenderer *m_renderer; @@ -281,7 +290,7 @@ wxColour wxGTKColourScheme::Get(wxGTKColourScheme::StdColour col, case SHADOW_IN: return wxColour(0xd6d6d6); case SHADOW_OUT: return wxColour(0x969696); - case CONTROL: + case CONTROL: if ( flags & wxCONTROL_PRESSED ) { return wxColour(0xc3c3c3); @@ -592,6 +601,32 @@ void wxGTKRenderer::DrawLabel(wxDC& dc, dc.DrawLabel(label, image, rect, alignment, indexAccel, rectBounds); } +void wxGTKRenderer::DrawItem(wxDC& dc, + const wxString& label, + const wxRect& rect, + int flags) +{ + if ( flags & wxCONTROL_SELECTED ) + { + dc.SetTextBackground(m_scheme->Get(wxColourScheme::HIGHLIGHT)); + dc.SetTextForeground(m_scheme->Get(wxColourScheme::HIGHLIGHT_TEXT)); + dc.SetBackgroundMode(wxSOLID); + } + + dc.DrawLabel(label, wxNullBitmap, rect); + + if ( flags & wxCONTROL_SELECTED ) + { + dc.SetBackgroundMode(wxTRANSPARENT); + } + + if ( flags & wxCONTROL_FOCUSED ) + { + wxRect rectFocus = rect; + DrawRect(dc, &rectFocus, m_penBlack); + } +} + // ---------------------------------------------------------------------------- // background // ---------------------------------------------------------------------------- @@ -607,10 +642,14 @@ void wxGTKRenderer::DoDrawBackground(wxDC& dc, } void wxGTKRenderer::DrawBackground(wxDC& dc, + const wxColour& col, const wxRect& rect, int flags) { - DoDrawBackground(dc, GetBackgroundColour(flags), rect); + DoDrawBackground(dc, + col.Ok() ? col + : GetBackgroundColour(flags), + rect); } // ---------------------------------------------------------------------------- @@ -786,89 +825,35 @@ void wxGTKRenderer::DrawArrow(wxDC& dc, } } -void wxGTKRenderer::DrawScrollbar(wxDC& dc, - wxOrientation orient, - int thumbPosStart, - int thumbPosEnd, - const wxRect& rect, - const int *flags) +void wxGTKRenderer::DrawScrollbarThumb(wxDC& dc, + const wxRect& rect, + int flags) { -#ifdef DEBUG_MOUSE - wxLogDebug("Drawing the scrollbar (orientation = %s):\n" - "\tarrow 1: 0x%04x\n" - "\tarrow 2: 0x%04x\n" - "\tthumb: 0x%04x\n" - "\tthumb from %d to %d", - orient == wxVERTICAL ? "vertical" : "horizontal", - flags[wxScrollBar::Element_Arrow_Line_1], - flags[wxScrollBar::Element_Arrow_Line_2], - flags[wxScrollBar::Element_Thumb], - thumbPosStart, thumbPosEnd); -#endif // DEBUG_MOUSE + // the thumb is never pressed never has focus border under GTK and the + // scrollbar background never changes at all + int flagsThumb = flags & ~(wxCONTROL_PRESSED | wxCONTROL_FOCUSED); - // first draw the scrollbar area background + wxRect rectThumb = rect; + DrawButtonBorder(dc, rectThumb, flagsThumb, &rectThumb); + DrawBackground(dc, wxNullColour, rectThumb, flagsThumb); +} + +void wxGTKRenderer::DrawScrollbarShaft(wxDC& dc, + const wxRect& rect, + int flags) +{ wxRect rectBar = rect; DrawAntiShadedRect(dc, &rectBar, m_penDarkGrey, m_penHighlight); DrawAntiShadedRect(dc, &rectBar, m_penBlack, m_penGrey); DoDrawBackground(dc, m_scheme->Get(wxColourScheme::SCROLLBAR), rectBar); +} - // next draw the arrows at the ends - wxRect rectArrow[2]; - wxDirection arrowDir[2]; - - rectArrow[0] = - rectArrow[1] = rectBar; - if ( orient == wxVERTICAL ) - { - rectArrow[0].height = - rectArrow[1].height = m_sizeScrollbarArrow.y - 1; - rectArrow[1].y = rectBar.GetBottom() - rectArrow[1].height + 1; - - arrowDir[0] = wxUP; - arrowDir[1] = wxDOWN; - } - else // horizontal - { - rectArrow[0].width = - rectArrow[1].width = m_sizeScrollbarArrow.x - 1; - rectArrow[1].x = rectBar.GetRight() - rectArrow[1].width + 1; - - arrowDir[0] = wxLEFT; - arrowDir[1] = wxRIGHT; - } - - for ( size_t nArrow = 0; nArrow < 2; nArrow++ ) - { - DrawArrow(dc, arrowDir[nArrow], rectArrow[nArrow], - flags[wxScrollBar::Element_Arrow_Line_1 + nArrow]); - } - - // and, finally, the thumb, if any - if ( thumbPosStart < thumbPosEnd ) - { - wxRect rectThumb; - if ( orient == wxVERTICAL ) - { - rectBar.Inflate(0, -m_sizeScrollbarArrow.y); - rectThumb = rectBar; - rectThumb.y += (rectBar.height*thumbPosStart)/100; - rectThumb.height = (rectBar.height*(thumbPosEnd - thumbPosStart))/100; - } - else // horizontal - { - rectBar.Inflate(-m_sizeScrollbarArrow.x, 0); - rectThumb = rectBar; - rectThumb.x += (rectBar.width*thumbPosStart)/100; - rectThumb.width = (rectBar.width*(thumbPosEnd - thumbPosStart))/100; - } - - // the thumb is never pressed never has focus border under GTK and the - // scrollbar background never changes at all - int flagsThumb = flags[wxScrollBar::Element_Thumb] & - ~(wxCONTROL_PRESSED | wxCONTROL_FOCUSED); - DrawButtonBorder(dc, rectThumb, flagsThumb, &rectThumb); - DrawBackground(dc, rectThumb, flagsThumb); - } +wxRect wxGTKRenderer::GetScrollbarRect(const wxScrollBar *scrollbar, + wxScrollBar::Element elem, + int thumbPos) const +{ + return StandardGetScrollbarRect(scrollbar, elem, + thumbPos, m_sizeScrollbarArrow); } wxHitTest wxGTKRenderer::HitTestScrollbar(const wxScrollBar *scrollbar, @@ -877,9 +862,10 @@ wxHitTest wxGTKRenderer::HitTestScrollbar(const wxScrollBar *scrollbar, return StandardHitTestScrollbar(scrollbar, pt, m_sizeScrollbarArrow); } -wxCoord wxGTKRenderer::ScrollbarToPixel(const wxScrollBar *scrollbar) +wxCoord wxGTKRenderer::ScrollbarToPixel(const wxScrollBar *scrollbar, + int thumbPos) { - return StandardScrollbarToPixel(scrollbar, m_sizeScrollbarArrow); + return StandardScrollbarToPixel(scrollbar, thumbPos, m_sizeScrollbarArrow); } int wxGTKRenderer::PixelToScrollbar(const wxScrollBar *scrollbar, @@ -962,27 +948,29 @@ wxGTKInputHandler::wxGTKInputHandler(wxGTKRenderer *renderer) m_renderer = renderer; } -wxControlActions wxGTKInputHandler::Map(wxControl *control, - const wxKeyEvent& event, - bool pressed) +bool wxGTKInputHandler::HandleKey(wxControl *control, + const wxKeyEvent& event, + bool pressed) { - return wxACTION_NONE; + return FALSE; } -wxControlActions wxGTKInputHandler::Map(wxControl *control, - const wxMouseEvent& event) +bool wxGTKInputHandler::HandleMouse(wxControl *control, + const wxMouseEvent& event) { // clicking on the control gives it focus if ( event.ButtonDown() ) { control->SetFocus(); + + return TRUE; } - return wxACTION_NONE; + return FALSE; } -bool wxGTKInputHandler::OnMouseMove(wxControl *control, - const wxMouseEvent& event) +bool wxGTKInputHandler::HandleMouseMove(wxControl *control, + const wxMouseEvent& event) { if ( event.Entering() ) { @@ -997,7 +985,6 @@ bool wxGTKInputHandler::OnMouseMove(wxControl *control, return FALSE; } - // highlighting changed return TRUE; } diff --git a/src/univ/themes/win32.cpp b/src/univ/themes/win32.cpp index eaa59d73e6..f9d3b4a460 100644 --- a/src/univ/themes/win32.cpp +++ b/src/univ/themes/win32.cpp @@ -71,6 +71,7 @@ public: // implement the base class pure virtuals virtual void DrawBackground(wxDC& dc, + const wxColour& col, const wxRect& rect, int flags = 0); virtual void DrawLabel(wxDC& dc, @@ -104,21 +105,32 @@ public: wxDirection dir, const wxRect& rect, int flags = 0); - virtual void DrawScrollbar(wxDC& dc, - wxOrientation orient, - int thumbPosStart, - int thumbPosEnd, - const wxRect& rect, - const int *flags = NULL); + virtual void DrawScrollbarThumb(wxDC& dc, + const wxRect& rect, + int flags = 0); + virtual void DrawScrollbarShaft(wxDC& dc, + const wxRect& rect, + int flags = 0); + virtual void DrawItem(wxDC& dc, + const wxString& label, + const wxRect& rect, + int flags = 0); virtual void AdjustSize(wxSize *size, const wxWindow *window); + virtual wxRect GetScrollbarRect(const wxScrollBar *scrollbar, + wxScrollBar::Element elem, + int thumbPos = -1) const; virtual wxHitTest HitTestScrollbar(const wxScrollBar *scrollbar, const wxPoint& pt) const; - virtual wxCoord ScrollbarToPixel(const wxScrollBar *scrollbar); + virtual wxCoord ScrollbarToPixel(const wxScrollBar *scrollbar, + int thumbPos = -1); virtual int PixelToScrollbar(const wxScrollBar *scrollbar, wxCoord coord); protected: + // common part of DrawLabel() and DrawItem() + void DrawFocusRect(wxDC& dc, const wxRect& rect); + // DrawButtonBorder() helper void DoDrawBackground(wxDC& dc, const wxColour& col, @@ -182,11 +194,11 @@ class wxWin32InputHandler : public wxInputHandler public: wxWin32InputHandler(wxWin32Renderer *renderer); - virtual wxControlActions Map(wxControl *control, - const wxKeyEvent& event, - bool pressed); - virtual wxControlActions Map(wxControl *control, - const wxMouseEvent& event); + virtual bool HandleKey(wxControl *control, + const wxKeyEvent& event, + bool pressed); + virtual bool HandleMouse(wxControl *control, + const wxMouseEvent& event); protected: wxWin32Renderer *m_renderer; @@ -198,12 +210,11 @@ public: wxWin32ScrollBarInputHandler(wxWin32Renderer *renderer, wxInputHandler *handler); - virtual wxControlActions Map(wxControl *control, const wxMouseEvent& event); - virtual bool OnMouseMove(wxControl *control, const wxMouseEvent& event); + virtual bool HandleMouse(wxControl *control, const wxMouseEvent& event); + virtual bool HandleMouseMove(wxControl *control, const wxMouseEvent& event); virtual bool OnScrollTimer(wxScrollBar *scrollbar, - const wxControlAction& action, - const wxMouseEvent& event); + const wxControlAction& action); protected: virtual bool IsAllowedButton(int button) { return button == 1; } @@ -294,6 +305,8 @@ wxInputHandler *wxWin32Theme::GetInputHandler(const wxString& control) else if ( control == _T("wxScrollBar") ) handler = new wxWin32ScrollBarInputHandler(m_renderer, GetInputHandler(_T("wxControl"))); + else if ( control == _T("wxListBox") ) + handler = new wxStdListboxInputHandler(GetInputHandler(_T("wxControl"))); else handler = new wxWin32InputHandler(m_renderer); @@ -817,6 +830,40 @@ void wxWin32Renderer::DrawFrame(wxDC& dc, // label // ---------------------------------------------------------------------------- +void wxWin32Renderer::DrawFocusRect(wxDC& dc, const wxRect& rect) +{ + // 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, &rect, wxPen(*wxBLACK, 0, wxDOT)); +#else + // draw the pixels manually + dc.SetPen(wxPen(*wxBLACK, 0, wxSOLID)); + //dc.SetLogicalFunction(wxXOR); + + // 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 = rect.GetRight(); x >= rect.GetLeft(); x -= 2 ) + { + dc.DrawPoint(x, rect.GetTop()); + dc.DrawPoint(x, rect.GetBottom()); + } + + wxCoord shift = rect.width % 2 ? 0 : 1; + for ( wxCoord y = rect.GetTop() + 2; y <= rect.GetBottom(); y+= 2 ) + { + dc.DrawPoint(rect.GetLeft(), y - shift); + dc.DrawPoint(rect.GetRight(), y); + } + + if ( shift ) + { + dc.DrawPoint(rect.GetLeft(), rect.GetBottom() - 1); + } +#endif // 0/1 +} + void wxWin32Renderer::DrawLabel(wxDC& dc, const wxString& label, const wxBitmap& image, @@ -856,35 +903,39 @@ void wxWin32Renderer::DrawLabel(wxDC& dc, 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 - // 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)); + DrawFocusRect(dc, rectText); + } +} - // 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()); - } +void wxWin32Renderer::DrawItem(wxDC& dc, + const wxString& label, + const wxRect& rect, + int flags) +{ + wxColour colFg; + if ( flags & wxCONTROL_SELECTED ) + { + dc.SetBrush(wxBrush(m_scheme->Get(wxColourScheme::HIGHLIGHT), wxSOLID)); + dc.SetPen(*wxTRANSPARENT_PEN); + dc.DrawRectangle(rect); + colFg = dc.GetTextForeground(); + dc.SetTextForeground(m_scheme->Get(wxColourScheme::HIGHLIGHT_TEXT)); + } - 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); - } + wxRect rectText = rect; + rectText.x += 2; + dc.DrawLabel(label, wxNullBitmap, rectText); - if ( shift ) - { - dc.DrawPoint(rectText.GetLeft(), rectText.GetBottom() - 1); - } -#endif // 0/1 + if ( flags & wxCONTROL_FOCUSED ) + { + dc.SetBrush(*wxTRANSPARENT_BRUSH); + DrawFocusRect(dc, rect); + } + + // restore the text colour + if ( colFg.Ok() ) + { + dc.SetTextForeground(colFg); } } @@ -903,11 +954,15 @@ void wxWin32Renderer::DoDrawBackground(wxDC& dc, } void wxWin32Renderer::DrawBackground(wxDC& dc, + const wxColour& col, const wxRect& rect, int flags) { // just fill it with the default bg colour - DoDrawBackground(dc, m_scheme->Get(wxColourScheme::CONTROL, flags), rect); + DoDrawBackground(dc, + col.Ok() ? col + : m_scheme->Get(wxColourScheme::CONTROL, flags), + rect); } // ---------------------------------------------------------------------------- @@ -933,9 +988,18 @@ void wxWin32Renderer::DrawArrow(wxDC& dc, return; } - wxArrowStyle arrowStyle = flags & wxCONTROL_DISABLED ? Arrow_Disabled - : Arrow_Normal; - DrawArrow(dc, rect, arrowDir, arrowStyle); + wxArrowStyle arrowStyle; + if ( flags & wxCONTROL_PRESSED ) + { + // can't be pressed and disabled + arrowStyle = Arrow_Pressed; + } + else + { + arrowStyle = flags & wxCONTROL_DISABLED ? Arrow_Disabled : Arrow_Normal; + } + + DrawArrowButton(dc, rect, arrowDir, arrowStyle); } void wxWin32Renderer::DrawArrow(wxDC& dc, @@ -968,126 +1032,30 @@ void wxWin32Renderer::DrawArrowButton(wxDC& dc, DrawArrow(dc, rect, arrowDir, arrowStyle); } -void wxWin32Renderer::DrawScrollbar(wxDC& dc, - wxOrientation orient, - int thumbPosStart, - int thumbPosEnd, - const wxRect& rect, - const int *flags) +void wxWin32Renderer::DrawScrollbarThumb(wxDC& dc, + const wxRect& rect, + int flags) { - // first, draw the arrows at the ends - wxRect rectArrow[2]; - wxArrowDirection arrowDir[2]; + // we don't use the flags, the thumb never changes appearance + wxRect rectThumb = rect; + DrawArrowBorder(dc, &rectThumb); + DrawBackground(dc, wxNullColour, rectThumb); +} - 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; +void wxWin32Renderer::DrawScrollbarShaft(wxDC& dc, + const wxRect& rectBar, + int flags) +{ + DoDrawBackground(dc, m_scheme->Get(wxColourScheme::SCROLLBAR, flags), + rectBar); +} - 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; - } - - wxArrowStyle arrowStyle; - for ( size_t nArrow = 0; nArrow < 2; nArrow++ ) - { - int flagsArrow = flags[wxScrollBar::Element_Arrow_Line_1 + nArrow]; - if ( flagsArrow & wxCONTROL_PRESSED ) - arrowStyle = Arrow_Pressed; - else if ( flagsArrow & wxCONTROL_DISABLED ) - arrowStyle = Arrow_Disabled; - else - arrowStyle = Arrow_Normal; - - DrawArrowButton(dc, rectArrow[nArrow], arrowDir[nArrow], arrowStyle); - } - - // next draw the scrollbar area: in a normal state, we draw it all in one - // call to DoDrawBackground(), but when either part of the bar is pressed, - // we paint them separately - wxRect rectBar = rect; - if ( orient == wxVERTICAL ) - rectBar.Inflate(0, -(m_sizeScrollbarArrow.y + 1)); - else - rectBar.Inflate(-(m_sizeScrollbarArrow.x + 1), 0); - - // calculate the thumb position - wxRect rectThumb; - if ( thumbPosStart < thumbPosEnd ) - { - 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; - } - } - //else: no thumb - - if ( (flags[wxScrollBar::Element_Bar_1] & wxCONTROL_PRESSED) || - (flags[wxScrollBar::Element_Bar_2] & wxCONTROL_PRESSED) ) - { - // calculate the bounding boxes for each of 2 bar parts - wxRect rectBars[2]; - rectBars[0] = - rectBars[1] = rectBar; - if ( orient == wxVERTICAL ) - { - rectBars[0].SetTop(m_sizeScrollbarArrow.y); - rectBars[0].SetBottom(rectThumb.GetTop() - 1); - rectBars[1].SetTop(rectThumb.GetBottom() + 1); - rectBars[1].SetBottom(rectBar.GetBottom()); - } - else // horizontal - { - rectBars[0].SetLeft(m_sizeScrollbarArrow.x); - rectBars[0].SetRight(rectThumb.GetLeft() - 1); - rectBars[1].SetLeft(rectThumb.GetRight() + 1); - rectBars[1].SetRight(rectBar.GetRight()); - } - - for ( size_t nBar = 0; nBar < 2; nBar++ ) - { - DoDrawBackground( - dc, - m_scheme->Get - ( - wxColourScheme::SCROLLBAR, - flags[wxScrollBar::Element_Bar_1 + nBar] - ), - rectBars[nBar] - ); - } - } - else // nothing is pressed - { - DoDrawBackground(dc, m_scheme->Get(wxColourScheme::SCROLLBAR), rectBar); - } - - // and, finally, the thumb, if any - if ( thumbPosStart < thumbPosEnd ) - { - // we don't use the flags, the thumb never changes appearance - DrawArrowBorder(dc, &rectThumb); - DrawBackground(dc, rectThumb); - } +wxRect wxWin32Renderer::GetScrollbarRect(const wxScrollBar *scrollbar, + wxScrollBar::Element elem, + int thumbPos) const +{ + return StandardGetScrollbarRect(scrollbar, elem, + thumbPos, m_sizeScrollbarArrow); } wxHitTest wxWin32Renderer::HitTestScrollbar(const wxScrollBar *scrollbar, @@ -1096,9 +1064,10 @@ wxHitTest wxWin32Renderer::HitTestScrollbar(const wxScrollBar *scrollbar, return StandardHitTestScrollbar(scrollbar, pt, m_sizeScrollbarArrow); } -wxCoord wxWin32Renderer::ScrollbarToPixel(const wxScrollBar *scrollbar) +wxCoord wxWin32Renderer::ScrollbarToPixel(const wxScrollBar *scrollbar, + int thumbPos) { - return StandardScrollbarToPixel(scrollbar, m_sizeScrollbarArrow); + return StandardScrollbarToPixel(scrollbar, thumbPos, m_sizeScrollbarArrow); } int wxWin32Renderer::PixelToScrollbar(const wxScrollBar *scrollbar, @@ -1179,17 +1148,17 @@ wxWin32InputHandler::wxWin32InputHandler(wxWin32Renderer *renderer) m_renderer = renderer; } -wxControlActions wxWin32InputHandler::Map(wxControl *control, - const wxKeyEvent& event, - bool pressed) +bool wxWin32InputHandler::HandleKey(wxControl *control, + const wxKeyEvent& event, + bool pressed) { - return wxACTION_NONE; + return FALSE; } -wxControlActions wxWin32InputHandler::Map(wxControl *control, - const wxMouseEvent& event) +bool wxWin32InputHandler::HandleMouse(wxControl *control, + const wxMouseEvent& event) { - return wxACTION_NONE; + return FALSE; } // ---------------------------------------------------------------------------- @@ -1206,8 +1175,7 @@ wxWin32ScrollBarInputHandler(wxWin32Renderer *renderer, } bool wxWin32ScrollBarInputHandler::OnScrollTimer(wxScrollBar *scrollbar, - const wxControlAction& action, - const wxMouseEvent& event) + const wxControlAction& action) { // stop if went beyond the position of the original click (this can only // happen when we scroll by pages) @@ -1232,19 +1200,17 @@ bool wxWin32ScrollBarInputHandler::OnScrollTimer(wxScrollBar *scrollbar, return FALSE; } - return wxStdScrollBarInputHandler::OnScrollTimer(scrollbar, - action, - event); + return wxStdScrollBarInputHandler::OnScrollTimer(scrollbar, action); } -wxControlActions wxWin32ScrollBarInputHandler::Map(wxControl *control, - const wxMouseEvent& event) +bool wxWin32ScrollBarInputHandler::HandleMouse(wxControl *control, + const wxMouseEvent& event) { // remember the current state bool wasDraggingThumb = m_htLast == wxHT_SCROLLBAR_THUMB; // do process the message - wxControlActions actions = wxStdScrollBarInputHandler::Map(control, event); + bool rc = wxStdScrollBarInputHandler::HandleMouse(control, event); // analyse the changes if ( !wasDraggingThumb && (m_htLast == wxHT_SCROLLBAR_THUMB) ) @@ -1254,11 +1220,11 @@ wxControlActions wxWin32ScrollBarInputHandler::Map(wxControl *control, m_eventStartDrag = event; } - return actions; + return rc; } -bool wxWin32ScrollBarInputHandler::OnMouseMove(wxControl *control, - const wxMouseEvent& event) +bool wxWin32ScrollBarInputHandler::HandleMouseMove(wxControl *control, + const wxMouseEvent& event) { // we don't highlight scrollbar elements, so there is no need to process // mouse move events normally - only do it while mouse is captured (i.e. @@ -1299,8 +1265,7 @@ bool wxWin32ScrollBarInputHandler::OnMouseMove(wxControl *control, else // we were dragging the thumb { // restore its last location - scrollbar->PerformAction(wxACTION_SCROLL_THUMB_MOVE, - m_eventLastDrag); + HandleThumbMove(scrollbar, m_eventLastDrag); } return TRUE; @@ -1351,13 +1316,12 @@ bool wxWin32ScrollBarInputHandler::OnMouseMove(wxControl *control, // and restore the original position (before dragging) of the // thumb for now - scrollbar->PerformAction(wxACTION_SCROLL_THUMB_MOVE, - m_eventStartDrag); + HandleThumbMove(scrollbar, m_eventStartDrag); } return TRUE; } } - return wxStdScrollBarInputHandler::OnMouseMove(control, event); + return wxStdScrollBarInputHandler::HandleMouseMove(control, event); } diff --git a/src/univ/winuniv.cpp b/src/univ/winuniv.cpp index 0e7e01cd75..ab6183cec8 100644 --- a/src/univ/winuniv.cpp +++ b/src/univ/winuniv.cpp @@ -48,9 +48,14 @@ // event tables // ---------------------------------------------------------------------------- -IMPLEMENT_DYNAMIC_CLASS(wxWindow, wxWindowBase) +// we can't use wxWindowNative here as it won't be expanded inside the macro +#if defined(__WXMSW__) + IMPLEMENT_DYNAMIC_CLASS(wxWindow, wxWindowMSW) +#elif defined(__WXGTK__) + IMPLEMENT_DYNAMIC_CLASS(wxWindow, wxWindowGTK) +#endif -BEGIN_EVENT_TABLE(wxWindow, wxWindowBase) +BEGIN_EVENT_TABLE(wxWindow, wxWindowNative) EVT_SIZE(wxWindow::OnSize) EVT_PAINT(wxWindow::OnPaint) @@ -67,6 +72,8 @@ void wxWindow::Init() m_scrollbarHorz = (wxScrollBar *)NULL; m_isCurrent = FALSE; + + m_renderer = (wxRenderer *)NULL; } // ---------------------------------------------------------------------------- @@ -100,11 +107,6 @@ const wxBitmap& wxWindow::GetBackgroundBitmap(int *alignment, // painting // ---------------------------------------------------------------------------- -wxRenderer *wxWindow::GetRenderer() const -{ - return wxTheme::Get()->GetRenderer(); -} - // the event handler executed when the window background must be painted void wxWindow::OnErase(wxEraseEvent& event) { @@ -121,12 +123,20 @@ void wxWindow::OnErase(wxEraseEvent& event) // the event handler executed when the window must be repainted void wxWindow::OnPaint(wxPaintEvent& event) { - // get the DC to use and create renderer on it - wxPaintDC dc(this); - wxControlRenderer renderer(this, dc, GetRenderer()); + if ( !m_renderer ) + { + // it is a native control which paints itself + event.Skip(); + } + else + { + // get the DC to use and create renderer on it + wxPaintDC dc(this); + wxControlRenderer renderer(this, dc, m_renderer); - // do draw the control! - DoDraw(&renderer); + // do draw the control! + DoDraw(&renderer); + } } bool wxWindow::DoDrawBackground(wxControlRenderer *renderer) @@ -211,10 +221,21 @@ void wxWindow::OnSize(wxSizeEvent& event) event.Skip(); } +wxSize wxWindow::DoGetBestSize() const +{ + return AdjustSize(DoGetBestClientSize()); +} + +wxSize wxWindow::DoGetBestClientSize() const +{ + return wxWindowNative::DoGetBestSize(); +} + wxSize wxWindow::AdjustSize(const wxSize& size) const { wxSize sz = size; - wxTheme::Get()->GetRenderer()->AdjustSize(&sz, this); + if ( m_renderer ) + m_renderer->AdjustSize(&sz, this); return sz; } @@ -344,27 +365,33 @@ void wxWindow::ScrollWindow(int dx, int dy, const wxRect *rect) } else // move the part which doesn't change to the new location { - // positive values mean to scroll to the left/up - if ( dx > 0 ) + // note that when we scroll the canvas in some direction we move the + // block which doesn't need to be refreshed in the opposite direction + + if ( dx < 0 ) { - ptSource.x = dx; + // scroll to the right, move to the left + ptSource.x = -dx; ptDest.x = 0; } else { + // scroll to the left, move to the right ptSource.x = 0; - ptDest.x = -dx; + ptDest.x = dx; } - if ( dy > 0 ) + if ( dy < 0 ) { - ptSource.y = dy; + // scroll down, move up + ptSource.y = -dy; ptDest.y = 0; } else { + // scroll up, move down ptSource.y = 0; - ptDest.y = -dy; + ptDest.y = dy; } // do move @@ -387,12 +414,23 @@ void wxWindow::ScrollWindow(int dx, int dy, const wxRect *rect) // it bad? wxRect rect; - rect.x = ptSource.x; - rect.y = ptSource.y; if ( dx ) { - rect.width = abs(dx); + if ( dx < 0 ) + { + // refresh the area along the right border + rect.x = size.x; + rect.width = -dx; + } + else + { + // refresh the area along the left border + rect.x = 0; + rect.width = dx; + } + + rect.y = 0; rect.height = sizeTotal.y; wxLogTrace(_T("scroll"), _T("refreshing (%d, %d)-(%d, %d)"), @@ -403,8 +441,21 @@ void wxWindow::ScrollWindow(int dx, int dy, const wxRect *rect) if ( dy ) { + if ( dy < 0 ) + { + // refresh the area along the bottom border + rect.y = size.y; + rect.height = -dy; + } + else + { + // refresh the area along the top border + rect.y = 0; + rect.height = dy; + } + + rect.x = 0; rect.width = sizeTotal.x; - rect.height = abs(dy); wxLogTrace(_T("scroll"), _T("refreshing (%d, %d)-(%d, %d)"), rect.x, rect.y, rect.GetRight(), rect.GetBottom());