tons of changes:

1. wxListBox class added
2. wxInputHandler rewritten (Map() -> Handle())
3. wxScrollBar redrawing completely changed


git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/branches/wxUNIVERSAL@8228 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
2000-09-01 12:58:36 +00:00
parent 06be91840a
commit 5096d88d2f
32 changed files with 2682 additions and 1388 deletions

View File

@@ -27,7 +27,7 @@
WXDLLEXPORT_DATA(extern const wxChar*) wxFrameNameStr; WXDLLEXPORT_DATA(extern const wxChar*) wxFrameNameStr;
WXDLLEXPORT_DATA(extern const wxChar*) wxStatusLineNameStr; WXDLLEXPORT_DATA(extern const wxChar*) wxStatusLineNameStr;
WXDLLEXPORT_DATA(extern const wxChar*) wxToolBarNameStr; WXDLLEXPORT_DATA(extern const wxChar*) wxToolBarNameStr;
WXDLLEXPORT_DATA(extern wxWindow*) wxWndHook; WXDLLEXPORT_DATA(extern wxWindowMSW*) wxWndHook;
class WXDLLEXPORT wxMenuBar; class WXDLLEXPORT wxMenuBar;
class WXDLLEXPORT wxStatusBar; class WXDLLEXPORT wxStatusBar;

View File

@@ -28,25 +28,31 @@ WXDLLEXPORT_DATA(extern const wxChar*) wxPanelNameStr;
// default scrolled window style // default scrolled window style
#define wxScrolledWindowStyle (wxHSCROLL | wxVSCROLL) #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 // wxScrolledWindow
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
class WXDLLEXPORT wxScrolledWindow : public wxPanel class WXDLLEXPORT wxScrolledWindow : public wxPanel, public wxScrollHelper
{ {
public: public:
wxScrolledWindow(); wxScrolledWindow() : wxScrollHelper(this) { }
wxScrolledWindow(wxWindow *parent, wxScrolledWindow(wxWindow *parent,
wxWindowID id = -1, wxWindowID id = -1,
const wxPoint& pos = wxDefaultPosition, const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize, const wxSize& size = wxDefaultSize,
long style = wxScrolledWindowStyle, long style = wxScrolledWindowStyle,
const wxString& name = wxPanelNameStr) const wxString& name = wxPanelNameStr)
: wxScrollHelper(this)
{ {
Create(parent, id, pos, size, style, name); Create(parent, id, pos, size, style, name);
} }
~wxScrolledWindow(); virtual ~wxScrolledWindow();
bool Create(wxWindow *parent, bool Create(wxWindow *parent,
wxWindowID id, wxWindowID id,
@@ -55,98 +61,15 @@ public:
long style = wxScrolledWindowStyle, long style = wxScrolledWindowStyle,
const wxString& name = wxPanelNameStr); const wxString& name = wxPanelNameStr);
// Normally the wxScrolledWindow will scroll itself, but in virtual void PrepareDC(wxDC& dc) { DoPrepareDC(dc); }
// 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;
private: private:
DECLARE_EVENT_TABLE()
DECLARE_ABSTRACT_CLASS(wxScrolledWindow) DECLARE_ABSTRACT_CLASS(wxScrolledWindow)
}; };
#ifdef __VISUALC__
#pragma warning(default:4355)
#endif
#endif #endif
// _WX_GENERIC_SCROLLWIN_H_ // _WX_GENERIC_SCROLLWIN_H_

View File

@@ -78,6 +78,16 @@ public:
void SetFirstItem(int n) { DoSetFirstItem(n); } void SetFirstItem(int n) { DoSetFirstItem(n); }
void SetFirstItem(const wxString& s); 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 // emulate selecting or deselecting the item event.GetInt() (depending on
// event.GetExtraLong()) // event.GetExtraLong())
void Command(wxCommandEvent& event); void Command(wxCommandEvent& event);
@@ -103,7 +113,9 @@ protected:
// include the platform-specific class declaration // 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" #include "wx/msw/listbox.h"
#elif defined(__WXMOTIF__) #elif defined(__WXMOTIF__)
#include "wx/motif/listbox.h" #include "wx/motif/listbox.h"

View File

@@ -115,9 +115,6 @@ public:
virtual void SetupColours(); virtual void SetupColours();
protected: protected:
// do we have multiple selections?
bool HasMultipleSelection() const;
// free memory (common part of Clear() and dtor) // free memory (common part of Clear() and dtor)
void Free(); void Free();

View File

@@ -1,8 +1,9 @@
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
// Name: window.h // Name: wx/msw/window.h
// Purpose: wxWindow class // Purpose: wxWindow class
// Author: Julian Smart // 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 // Created: 01/02/97
// RCS-ID: $Id$ // RCS-ID: $Id$
// Copyright: (c) Julian Smart and Markus Holzem // Copyright: (c) Julian Smart and Markus Holzem
@@ -20,8 +21,6 @@
#pragma interface "window.h" #pragma interface "window.h"
#endif #endif
// #include "wx/msw/winundef.h"
// VZ: apparently some version of Windows send extra mouse move messages after // 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 // 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 // tempted to think that it was just an effect of a poor mouse and so the
@@ -29,12 +28,6 @@
// to reenable it // to reenable it
#define wxUSE_MOUSEEVENT_HACK 0 #define wxUSE_MOUSEEVENT_HACK 0
// ---------------------------------------------------------------------------
// forward declarations
// ---------------------------------------------------------------------------
class WXDLLEXPORT wxButton;
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// constants // constants
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@@ -50,12 +43,12 @@ enum
// wxWindow declaration for MSW // wxWindow declaration for MSW
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
class WXDLLEXPORT wxWindow : public wxWindowBase class WXDLLEXPORT wxWindowMSW : public wxWindowBase
{ {
public: public:
wxWindow() { Init(); } wxWindowMSW() { Init(); }
wxWindow(wxWindow *parent, wxWindowMSW(wxWindow *parent,
wxWindowID id, wxWindowID id,
const wxPoint& pos = wxDefaultPosition, const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize, const wxSize& size = wxDefaultSize,
@@ -66,7 +59,7 @@ public:
Create(parent, id, pos, size, style, name); Create(parent, id, pos, size, style, name);
} }
virtual ~wxWindow(); virtual ~wxWindowMSW();
bool Create(wxWindow *parent, bool Create(wxWindow *parent,
wxWindowID id, wxWindowID id,
@@ -87,7 +80,7 @@ public:
virtual void SetFocus(); virtual void SetFocus();
virtual bool Reparent( wxWindow *newParent ); virtual bool Reparent(wxWindowBase *newParent);
virtual void WarpPointer(int x, int y); virtual void WarpPointer(int x, int y);
virtual void CaptureMouse(); virtual void CaptureMouse();
@@ -437,8 +430,8 @@ private:
// the helper functions used by HandleChar/KeyXXX methods // the helper functions used by HandleChar/KeyXXX methods
wxKeyEvent CreateKeyEvent(wxEventType evType, int id, WXLPARAM lp) const; wxKeyEvent CreateKeyEvent(wxEventType evType, int id, WXLPARAM lp) const;
DECLARE_DYNAMIC_CLASS(wxWindow); DECLARE_DYNAMIC_CLASS(wxWindowMSW);
DECLARE_NO_COPY_CLASS(wxWindow); DECLARE_NO_COPY_CLASS(wxWindowMSW);
DECLARE_EVENT_TABLE() DECLARE_EVENT_TABLE()
}; };

View File

@@ -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 <zeitlin@dptmaths.ens-cachan.fr>
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
#ifndef _WX_SCROLWIN_H_BASE_ #ifndef _WX_SCROLWIN_H_BASE_
#define _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" #include "wx/generic/scrolwin.h"
#endif #endif

View File

@@ -1008,6 +1008,7 @@ public:
void Remove(const wxChar *sz); void Remove(const wxChar *sz);
// remove item by index // remove item by index
void Remove(size_t nIndex); void Remove(size_t nIndex);
void RemoveAt(size_t nIndex) { Remove(nIndex); }
// sorting // sorting
// sort array elements in alphabetical order (or reversed alphabetical // sort array elements in alphabetical order (or reversed alphabetical

View File

@@ -106,8 +106,9 @@ public:
protected: protected:
virtual bool PerformAction(const wxControlAction& action, virtual bool PerformAction(const wxControlAction& action,
const wxEvent& event); long numArg = 0,
virtual wxSize DoGetBestSize() const; const wxString& strArg = wxEmptyString);
virtual wxSize DoGetBestClientSize() const;
virtual void DoDraw(wxControlRenderer *renderer); virtual void DoDraw(wxControlRenderer *renderer);
// common part of all ctors // common part of all ctors

View File

@@ -22,32 +22,10 @@ class WXDLLEXPORT wxRenderer;
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// wxControlAction: the action is currently just a string which identifies it, // 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 // later it might become an atom (i.e. an opaque handler to string).
// 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.
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
typedef wxString wxControlAction; 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 // the list of actions which apply to all controls (other actions are defined
// in the controls headers) // in the controls headers)
@@ -87,7 +65,7 @@ public:
virtual void SetLabel(const wxString &label); virtual void SetLabel(const wxString &label);
virtual wxString GetLabel() const; 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 // return the index of the accel char in the label or -1 if none
int GetAccelIndex() const { return m_indexAccel; } int GetAccelIndex() const { return m_indexAccel; }
@@ -98,13 +76,24 @@ public:
return m_indexAccel == -1 ? _T('\0') : m_label[m_indexAccel]; return m_indexAccel == -1 ? _T('\0') : m_label[m_indexAccel];
} }
// perform the action which resulted from the translation of the event // perform a control-dependent action: an action may have an optional
// (the exact event type depends on the action), return TRUE if the // numeric and another (also optional) string argument whose interpretation
// control must be updated // 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, virtual bool PerformAction(const wxControlAction& action,
const wxEvent& event); long numArg = 0l,
const wxString& strArg = wxEmptyString);
protected: 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 // create the event translator object for this control: the base class
// action creates the default one which doesn't do anything // action creates the default one which doesn't do anything
virtual wxInputHandler *CreateInputHandler() const; virtual wxInputHandler *CreateInputHandler() const;
@@ -119,9 +108,6 @@ private:
// common part of all ctors // common part of all ctors
void Init(); void Init();
// common part of OnMouse/OnKeyDown/Up
void PerformActions(const wxControlActions& actions, const wxEvent& event);
// input processor // input processor
wxInputHandler *m_handler; wxInputHandler *m_handler;

View File

@@ -19,6 +19,8 @@
#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 wxRenderer;
class WXDLLEXPORT wxScrollBar; class WXDLLEXPORT wxScrollBar;
@@ -30,31 +32,27 @@ class WXDLLEXPORT wxInputHandler
{ {
public: public:
// map a keyboard event to one or more actions (pressed == TRUE if the key // map a keyboard event to one or more actions (pressed == TRUE if the key
// was pressed, FALSE if released) // was pressed, FALSE if released), returns TRUE if something was done
virtual wxControlActions Map(wxControl *control, virtual bool HandleKey(wxControl *control,
const wxKeyEvent& event, const wxKeyEvent& event,
bool pressed) = 0; bool pressed) = 0;
// map a mouse (click) event to one or more actions // map a mouse (click) event to one or more actions
virtual wxControlActions Map(wxControl *control, virtual bool HandleMouse(wxControl *control,
const wxMouseEvent& event) = 0; const wxMouseEvent& event) = 0;
// do something with mouse move/enter/leave: unlike the Map() functions, // handle mouse movement (or enter/leave) event: it is separated from
// this doesn't translate the event into an action but, normally, uses the // HandleMouse() for convenience as many controls don't care about mouse
// renderer directly to change the controls appearance as needed // movements at all
// virtual bool HandleMouseMove(wxControl *control,
// this is faster than using Map() which is important for mouse move const wxMouseEvent& event);
// 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);
// do something with focus set/kill event: this is different from // 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 // focus
// //
// return TRUE to refresh the control, FALSE otherwise // 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 dtor for any base class
virtual ~wxInputHandler(); virtual ~wxInputHandler();
@@ -76,17 +74,17 @@ class WXDLLEXPORT wxStdInputHandler : public wxInputHandler
public: public:
wxStdInputHandler(wxInputHandler *handler) : m_handler(handler) { } wxStdInputHandler(wxInputHandler *handler) : m_handler(handler) { }
virtual wxControlActions Map(wxControl *control, virtual bool HandleKey(wxControl *control,
const wxKeyEvent& event, const wxKeyEvent& event,
bool pressed) bool pressed)
{ return m_handler->Map(control, event, pressed); } { return m_handler->HandleKey(control, event, pressed); }
virtual wxControlActions Map(wxControl *control, virtual bool HandleMouse(wxControl *control,
const wxMouseEvent& event) const wxMouseEvent& event)
{ return m_handler->Map(control, event); } { return m_handler->HandleMouse(control, event); }
virtual bool OnMouseMove(wxControl *control, const wxMouseEvent& event) virtual bool HandleMouseMove(wxControl *control, const wxMouseEvent& event)
{ return m_handler->OnMouseMove(control, event); } { return m_handler->HandleMouseMove(control, event); }
virtual bool OnFocus(wxControl *control, const wxFocusEvent& event) virtual bool HandleFocus(wxControl *control, const wxFocusEvent& event)
{ return m_handler->OnFocus(control, event); } { return m_handler->HandleFocus(control, event); }
private: private:
wxInputHandler *m_handler; wxInputHandler *m_handler;
@@ -102,13 +100,13 @@ class WXDLLEXPORT wxStdButtonInputHandler : public wxStdInputHandler
public: public:
wxStdButtonInputHandler(wxInputHandler *inphand); wxStdButtonInputHandler(wxInputHandler *inphand);
virtual wxControlActions Map(wxControl *control, virtual bool HandleKey(wxControl *control,
const wxKeyEvent& event, const wxKeyEvent& event,
bool pressed); bool pressed);
virtual wxControlActions Map(wxControl *control, virtual bool HandleMouse(wxControl *control,
const wxMouseEvent& event); const wxMouseEvent& event);
virtual bool OnMouseMove(wxControl *control, const wxMouseEvent& event); virtual bool HandleMouseMove(wxControl *control, const wxMouseEvent& event);
virtual bool OnFocus(wxControl *control, const wxFocusEvent& event); virtual bool HandleFocus(wxControl *control, const wxFocusEvent& event);
private: private:
// the window (button) which has capture or NULL and the flag telling if // the window (button) which has capture or NULL and the flag telling if
@@ -130,12 +128,12 @@ public:
wxStdScrollBarInputHandler(wxRenderer *renderer, wxStdScrollBarInputHandler(wxRenderer *renderer,
wxInputHandler *inphand); wxInputHandler *inphand);
virtual wxControlActions Map(wxControl *control, virtual bool HandleKey(wxControl *control,
const wxKeyEvent& event, const wxKeyEvent& event,
bool pressed); bool pressed);
virtual wxControlActions Map(wxControl *control, virtual bool HandleMouse(wxControl *control,
const wxMouseEvent& event); const wxMouseEvent& event);
virtual bool OnMouseMove(wxControl *control, const wxMouseEvent& event); virtual bool HandleMouseMove(wxControl *control, const wxMouseEvent& event);
virtual ~wxStdScrollBarInputHandler(); virtual ~wxStdScrollBarInputHandler();
@@ -143,8 +141,7 @@ public:
// //
// return TRUE to continue scrolling, FALSE to stop the timer // return TRUE to continue scrolling, FALSE to stop the timer
virtual bool OnScrollTimer(wxScrollBar *scrollbar, virtual bool OnScrollTimer(wxScrollBar *scrollbar,
const wxControlAction& action, const wxControlAction& action);
const wxMouseEvent& event);
protected: protected:
// the methods which must be overridden in the derived class // the methods which must be overridden in the derived class
@@ -169,6 +166,13 @@ protected:
// stop scrolling because we reached the end point // stop scrolling because we reached the end point
void StopScrolling(wxScrollBar *scrollbar); 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 window (scrollbar) which has capture or NULL and the flag telling if
// the mouse is inside the element which captured it or not // the mouse is inside the element which captured it or not
wxWindow *m_winCapture; wxWindow *m_winCapture;
@@ -184,9 +188,32 @@ protected:
// the renderer (we use it only for hit testing) // the renderer (we use it only for hit testing)
wxRenderer *m_renderer; 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 // the timer for generating scroll events when the mouse stays pressed on
// a scrollbar // a scrollbar
class wxTimer *m_timerScroll; 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_ #endif // _WX_UNIV_INPHAND_H_

191
include/wx/univ/listbox.h Normal file
View File

@@ -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 <zeitlin@dptmaths.ens-cachan.fr>
// 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_

View File

@@ -29,11 +29,13 @@
#define _WX_UNIV_RENDERER_H_ #define _WX_UNIV_RENDERER_H_
class WXDLLEXPORT wxDC; class WXDLLEXPORT wxDC;
class WXDLLEXPORT wxListBox;
class WXDLLEXPORT wxScrollBar; class WXDLLEXPORT wxScrollBar;
class WXDLLEXPORT wxWindow; class WXDLLEXPORT wxWindow;
#include "wx/string.h" #include "wx/string.h"
#include "wx/gdicmn.h" #include "wx/gdicmn.h"
#include "wx/scrolbar.h" // for wxScrollBar::Element
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// constants // constants
@@ -70,6 +72,7 @@ public:
// draw the controls background // draw the controls background
virtual void DrawBackground(wxDC& dc, virtual void DrawBackground(wxDC& dc,
const wxColour& col,
const wxRect& rect, const wxRect& rect,
int flags) = 0; int flags) = 0;
@@ -120,18 +123,24 @@ public:
const wxRect& rect, const wxRect& rect,
int flags = 0) = 0; int flags = 0) = 0;
// draw a scrollbar: thumb positions are in percent of the full scrollbar // draw the scrollbar thumb
// length and the flags array contains the flags corresponding to each of virtual void DrawScrollbarThumb(wxDC& dc,
// wxScrollBar::Elements
virtual void DrawScrollbar(wxDC& dc,
wxOrientation orient,
int thumbPosStart,
int thumbPosEnd,
const wxRect& rect, const wxRect& rect,
const int *flags = NULL) = 0; int flags = 0) = 0;
// TODO: having this is ugly but I don't see how to solve GetBestSize() // draw a (part of) scrollbar shaft
// problem without something like this 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, // 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 // this just takes into account the border, but for some (buttons, for
@@ -142,13 +151,20 @@ public:
// hit testing functions // 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 // returns one of wxHT_SCROLLBAR_XXX constants
virtual wxHitTest HitTestScrollbar(const wxScrollBar *scrollbar, virtual wxHitTest HitTestScrollbar(const wxScrollBar *scrollbar,
const wxPoint& pt) const = 0; const wxPoint& pt) const = 0;
// translate the scrollbar position (in logical units) into physical // translate the scrollbar position (in logical units) into physical
// coordinate (in pixels) and the other way round // 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, virtual int PixelToScrollbar(const wxScrollBar *scrollbar,
wxCoord coord) = 0; wxCoord coord) = 0;
@@ -165,10 +181,15 @@ protected:
// standard scrollbar hit testing: this assumes that it only has 2 arrows // 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. // and a thumb, so the themes which have more complicated scrollbars (e.g.
// BeOS) can't use this method // 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, static wxHitTest StandardHitTestScrollbar(const wxScrollBar *scrollbar,
const wxPoint& pt, const wxPoint& pt,
const wxSize& sizeArrow); const wxSize& sizeArrow);
static wxCoord StandardScrollbarToPixel(const wxScrollBar *scrollbar, static wxCoord StandardScrollbarToPixel(const wxScrollBar *scrollbar,
int thumbPos,
const wxSize& sizeArrow); const wxSize& sizeArrow);
static int StandardPixelToScrollbar(const wxScrollBar *scrollbar, static int StandardPixelToScrollbar(const wxScrollBar *scrollbar,
wxCoord coord, wxCoord coord,
@@ -190,9 +211,10 @@ public:
wxDelegateRenderer(wxRenderer *renderer) : m_renderer(renderer) { } wxDelegateRenderer(wxRenderer *renderer) : m_renderer(renderer) { }
virtual void DrawBackground(wxDC& dc, virtual void DrawBackground(wxDC& dc,
const wxColour& col,
const wxRect& rect, const wxRect& rect,
int flags) int flags)
{ m_renderer->DrawBackground(dc, rect, flags); } { m_renderer->DrawBackground(dc, col, rect, flags); }
virtual void DrawLabel(wxDC& dc, virtual void DrawLabel(wxDC& dc,
const wxString& label, const wxString& label,
const wxBitmap& image, const wxBitmap& image,
@@ -232,23 +254,33 @@ public:
const wxRect& rect, const wxRect& rect,
int flags = 0) int flags = 0)
{ m_renderer->DrawArrow(dc, dir, rect, flags); } { m_renderer->DrawArrow(dc, dir, rect, flags); }
virtual void DrawScrollbar(wxDC& dc, virtual void DrawScrollbarThumb(wxDC& dc,
wxOrientation orient,
int thumbPosStart,
int thumbPosEnd,
const wxRect& rect, const wxRect& rect,
const int *flags = NULL) int flags = 0)
{ m_renderer->DrawScrollbar(dc, orient, thumbPosStart, { m_renderer->DrawScrollbarThumb(dc, rect, flags); }
thumbPosEnd, 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) virtual void AdjustSize(wxSize *size, const wxWindow *window)
{ m_renderer->AdjustSize(size, 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, virtual wxHitTest HitTestScrollbar(const wxScrollBar *scrollbar,
const wxPoint& pt) const const wxPoint& pt) const
{ return m_renderer->HitTestScrollbar(scrollbar, pt); } { return m_renderer->HitTestScrollbar(scrollbar, pt); }
virtual wxCoord ScrollbarToPixel(const wxScrollBar *scrollbar) virtual wxCoord ScrollbarToPixel(const wxScrollBar *scrollbar,
{ return m_renderer->ScrollbarToPixel(scrollbar); } int thumbPos = -1)
{ return m_renderer->ScrollbarToPixel(scrollbar, thumbPos); }
virtual int PixelToScrollbar(const wxScrollBar *scrollbar, virtual int PixelToScrollbar(const wxScrollBar *scrollbar,
wxCoord coord) wxCoord coord)
{ return m_renderer->PixelToScrollbar(scrollbar, coord); } { return m_renderer->PixelToScrollbar(scrollbar, coord); }
@@ -271,6 +303,8 @@ public:
// operations // operations
void DrawLabel(const wxBitmap& bitmap = wxNullBitmap, void DrawLabel(const wxBitmap& bitmap = wxNullBitmap,
wxCoord marginX = 0, wxCoord marginY = 0); wxCoord marginX = 0, wxCoord marginY = 0);
void DrawItems(const wxListBox *listbox,
size_t itemFirst, size_t itemLast);
void DrawBorder(); void DrawBorder();
void DrawButtonBorder(); void DrawButtonBorder();
// the line must be either horizontal or vertical // the line must be either horizontal or vertical
@@ -282,7 +316,7 @@ public:
int alignment = wxALIGN_CENTRE | wxALIGN_CENTRE_VERTICAL, int alignment = wxALIGN_CENTRE | wxALIGN_CENTRE_VERTICAL,
wxStretch stretch = wxSTRETCH_NOT); wxStretch stretch = wxSTRETCH_NOT);
void DrawBackgroundBitmap(); void DrawBackgroundBitmap();
void DrawScrollbar(const wxScrollBar *scrollbar); void DrawScrollbar(const wxScrollBar *scrollbar, int thumbPosOld);
// accessors // accessors
wxWindow *GetWindow() const { return m_window; } wxWindow *GetWindow() const { return m_window; }

View File

@@ -16,8 +16,6 @@
#pragma interface "univscrolbar.h" #pragma interface "univscrolbar.h"
#endif #endif
#include "wx/univ/renderer.h" // for wxHitTest
class WXDLLEXPORT wxInputHandler; class WXDLLEXPORT wxInputHandler;
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@@ -100,16 +98,20 @@ public:
void ScrollPages(int nPages); void ScrollPages(int nPages);
virtual bool PerformAction(const wxControlAction& action, virtual bool PerformAction(const wxControlAction& action,
const wxEvent& event); long numArg = 0,
const wxString& strArg = wxEmptyString);
// wxScrollBar sub elements state (combination of wxCONTROL_XXX) // 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]; } int GetState(Element which) const { return m_elementsState[which]; }
protected: protected:
virtual wxSize DoGetBestSize() const; virtual wxSize DoGetBestClientSize() const;
virtual void DoDraw(wxControlRenderer *renderer); virtual void DoDraw(wxControlRenderer *renderer);
// event handler
void OnIdle(wxIdleEvent& event);
// SetThumbPosition() helper // SetThumbPosition() helper
void DoSetThumb(int thumbPos); void DoSetThumb(int thumbPos);
@@ -117,17 +119,15 @@ protected:
void Init(); void Init();
private: 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 // total range of the scrollbar in logical units
int m_range; int m_range;
// the size of the thumb in logical units (from 0 to m_range) and its // the current and previous (after last refresh - this is used for
// position (from 0 to m_range - m_thumbSize) // 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, int m_thumbSize,
m_thumbPos; m_thumbPos,
m_thumbPosOld;
// the page size, i.e. the number of lines by which to scroll when page // the page size, i.e. the number of lines by which to scroll when page
// up/down action is performed // up/down action is performed
@@ -136,10 +136,10 @@ private:
// the state of the sub elements // the state of the sub elements
int m_elementsState[Element_Max]; int m_elementsState[Element_Max];
// the offset of the top/left of the scrollbar relative to the mouse to // the dirty flag: if set, scrollbar must be updated
// keep during the thumb drag bool m_dirty;
int m_ofsMouse;
DECLARE_EVENT_TABLE()
DECLARE_DYNAMIC_CLASS(wxScrollBar) DECLARE_DYNAMIC_CLASS(wxScrollBar)
}; };

View File

@@ -74,7 +74,7 @@
#define wxUSE_CHOICE 0 #define wxUSE_CHOICE 0
#define wxUSE_COMBOBOX 0 #define wxUSE_COMBOBOX 0
#define wxUSE_GAUGE 0 #define wxUSE_GAUGE 0
#define wxUSE_LISTBOX 0 #define wxUSE_LISTBOX 1
#define wxUSE_LISTCTRL 0 #define wxUSE_LISTCTRL 0
#define wxUSE_RADIOBOX 0 #define wxUSE_RADIOBOX 0
#define wxUSE_RADIOBTN 0 #define wxUSE_RADIOBTN 0

View File

@@ -64,7 +64,7 @@ public:
wxIcon GetIcon() const; wxIcon GetIcon() const;
private: private:
virtual wxSize DoGetBestSize() const; virtual wxSize DoGetBestClientSize() const;
virtual void DoDraw(wxControlRenderer *renderer); virtual void DoDraw(wxControlRenderer *renderer);
// the bitmap which we show // the bitmap which we show

View File

@@ -55,7 +55,7 @@ public:
protected: protected:
// calculate the optimal size for the label // calculate the optimal size for the label
virtual wxSize DoGetBestSize() const; virtual wxSize DoGetBestClientSize() const;
// draw the control // draw the control
virtual void DoDraw(wxControlRenderer *renderer); virtual void DoDraw(wxControlRenderer *renderer);

View File

@@ -36,8 +36,14 @@ enum
wxCONTROL_PRESSED = 0x00000004, // (button) is pressed wxCONTROL_PRESSED = 0x00000004, // (button) is pressed
wxCONTROL_ISDEFAULT = 0x00000008, // only applies to the buttons wxCONTROL_ISDEFAULT = 0x00000008, // only applies to the buttons
wxCONTROL_CURRENT = 0x00000010, // mouse is currently over the control 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 // returns the (low level) renderer to use for drawing the control by
// querying the current theme // querying the current theme
wxRenderer *GetRenderer() const; wxRenderer *GetRenderer() const { return m_renderer; }
// draw the control background, return TRUE if done // draw the control background, return TRUE if done
virtual bool DoDrawBackground(wxControlRenderer *renderer); virtual bool DoDrawBackground(wxControlRenderer *renderer);
@@ -127,6 +133,12 @@ protected:
// draw the controls contents // draw the controls contents
virtual void DoDraw(wxControlRenderer *renderer); 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 // adjust the size of the window to take into account its borders
wxSize AdjustSize(const wxSize& size) const; wxSize AdjustSize(const wxSize& size) const;
@@ -139,6 +151,9 @@ protected:
// put the scrollbars along the edges of the window // put the scrollbars along the edges of the window
void PositionScrollbars(); void PositionScrollbars();
// the renderer we use
wxRenderer *m_renderer;
// background bitmap info // background bitmap info
wxBitmap m_bitmapBg; wxBitmap m_bitmapBg;
int m_alignBgBitmap; int m_alignBgBitmap;

View File

@@ -36,6 +36,7 @@
#include "wx/bmpbuttn.h" #include "wx/bmpbuttn.h"
#include "wx/button.h" #include "wx/button.h"
#include "wx/listbox.h"
#include "wx/scrolbar.h" #include "wx/scrolbar.h"
#include "wx/scrolwin.h" #include "wx/scrolwin.h"
#include "wx/statbox.h" #include "wx/statbox.h"
@@ -47,6 +48,8 @@
#include "wx/univ/theme.h" #include "wx/univ/theme.h"
//#define DEBUG_SCROLL
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// resources // resources
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@@ -184,7 +187,10 @@ bool MyUnivApp::OnInit()
wxFrame *frame = new MyUnivFrame(_T("wxUniversal demo")); wxFrame *frame = new MyUnivFrame(_T("wxUniversal demo"));
frame->Show(); frame->Show();
#ifdef DEBUG_SCROLL
wxLog::AddTraceMask(_T("scroll")); wxLog::AddTraceMask(_T("scroll"));
#endif
wxLog::AddTraceMask(_T("listbox"));
return TRUE; return TRUE;
} }
@@ -194,7 +200,7 @@ bool MyUnivApp::OnInit()
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
MyUnivFrame::MyUnivFrame(const wxString& title) MyUnivFrame::MyUnivFrame(const wxString& title)
: wxFrame(NULL, -1, title, wxDefaultPosition, wxSize(600, 600)) : wxFrame(NULL, -1, title, wxDefaultPosition, wxSize(700, 600))
{ {
SetBackgroundColour(wxGetApp().GetBgColour()); SetBackgroundColour(wxGetApp().GetBgColour());
@@ -295,6 +301,17 @@ MyUnivFrame::MyUnivFrame(const wxString& title)
); );
bmpBtn->SetBitmapSelected(bmp2); bmpBtn->SetBitmapSelected(bmp2);
bmpBtn->SetBitmapFocus(bmp3); 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) void MyUnivFrame::OnButton(wxCommandEvent& event)
@@ -331,10 +348,14 @@ void MyUnivCanvas::OnPaint(wxPaintEvent& event)
s_oddRepaint = !s_oddRepaint; s_oddRepaint = !s_oddRepaint;
wxCoord x, y; wxCoord x, y;
GetViewStart(&x, &y); GetViewStart(&x, &y);
#ifdef DEBUG_SCROLL
wxLogDebug("Repainting with %s pen (at %dx%d)", wxLogDebug("Repainting with %s pen (at %dx%d)",
s_oddRepaint ? "red" : "green", s_oddRepaint ? "red" : "green",
x, y); x, y);
#endif // DEBUG_SCROLL
dc.SetPen(s_oddRepaint ? *wxRED_PEN: *wxGREEN_PEN); dc.SetPen(s_oddRepaint ? *wxRED_PEN: *wxGREEN_PEN);
dc.SetTextForeground(s_oddRepaint ? *wxRED : *wxGREEN);
dc.DrawLine(0, 0, 1000, 1000); dc.DrawLine(0, 0, 1000, 1000);
dc.DrawText(_T("This is the top of the canvas"), 10, 10); dc.DrawText(_T("This is the top of the canvas"), 10, 10);
dc.DrawLabel(_T("This is the bottom of the canvas"), dc.DrawLabel(_T("This is the bottom of the canvas"),

View File

@@ -696,7 +696,8 @@ bool wxEvtHandler::ProcessEvent(wxEvent& event)
{ {
#if wxUSE_GUI #if wxUSE_GUI
// check that our flag corresponds to reality // 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 #endif // wxUSE_GUI
// An event handler can be enabled or disabled // An event handler can be enabled or disabled

View File

@@ -2,10 +2,11 @@
// Name: generic/scrolwin.cpp // Name: generic/scrolwin.cpp
// Purpose: wxScrolledWindow implementation // Purpose: wxScrolledWindow implementation
// Author: Julian Smart // 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 // Created: 01/02/97
// RCS-ID: $Id$ // RCS-ID: $Id$
// Copyright: (c) Julian Smart and Markus Holzem // Copyright: (c) wxWindows team
// Licence: wxWindows license // Licence: wxWindows license
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
@@ -51,90 +52,119 @@
#endif #endif
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// event tables // wxScrollHelperEvtHandler: intercept the events from the window and forward
// them to wxScrollHelper
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
BEGIN_EVENT_TABLE(wxScrolledWindow, wxPanel) class wxScrollHelperEvtHandler : public wxEvtHandler
EVT_SCROLLWIN(wxScrolledWindow::OnScroll) {
EVT_SIZE(wxScrolledWindow::OnSize) public:
EVT_PAINT(wxScrolledWindow::OnPaint) wxScrollHelperEvtHandler(wxScrollHelper *scrollHelper)
EVT_CHAR(wxScrolledWindow::OnChar) {
END_EVENT_TABLE() 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 // implementation
// ============================================================================ // ============================================================================
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// wxScrolledWindow creation // wxScrollHelper construction
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
wxScrolledWindow::wxScrolledWindow() wxScrollHelper::wxScrollHelper(wxWindow *win)
{ {
m_xScrollPixelsPerLine = 0; m_xScrollPixelsPerLine =
m_yScrollPixelsPerLine = 0; m_yScrollPixelsPerLine =
m_xScrollingEnabled = TRUE; m_xScrollPosition =
m_yScrollingEnabled = TRUE; m_yScrollPosition =
m_xScrollPosition = 0; m_xScrollLines =
m_yScrollPosition = 0; m_yScrollLines =
m_xScrollLines = 0; m_xScrollLinesPerPage =
m_yScrollLines = 0;
m_xScrollLinesPerPage = 0;
m_yScrollLinesPerPage = 0; m_yScrollLinesPerPage = 0;
m_scaleX = 1.0;
m_xScrollingEnabled =
m_yScrollingEnabled = TRUE;
m_scaleX =
m_scaleY = 1.0; m_scaleY = 1.0;
m_win =
m_targetWindow = (wxWindow *)NULL; m_targetWindow = (wxWindow *)NULL;
if ( win )
SetWindow(win);
} }
bool wxScrolledWindow::Create(wxWindow *parent, void wxScrollHelper::SetWindow(wxWindow *win)
wxWindowID id,
const wxPoint& pos,
const wxSize& size,
long style,
const wxString& name)
{ {
m_xScrollPixelsPerLine = 0; wxCHECK_RET( win, _T("wxScrollHelper needs a window to scroll") );
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_yScrollLinesPerPage = 0;
m_scaleX = 1.0;
m_scaleY = 1.0;
m_targetWindow = this; m_targetWindow = m_win = win;
bool ok = wxPanel::Create(parent, id, pos, size, style, name); // install the event handler which will intercept the events we're
// interested in
#ifdef __WXMSW__ m_win->PushEventHandler(new wxScrollHelperEvtHandler(this));
// we need to process arrows ourselves for scrolling
m_lDlgCode |= DLGC_WANTARROWS;
#endif // __WXMSW__
return ok;
} }
wxScrolledWindow::~wxScrolledWindow() wxScrollHelper::~wxScrollHelper()
{ {
if ( m_targetWindow )
m_targetWindow->PopEventHandler(TRUE /* do delete it */);
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// setting scrolling parameters // setting scrolling parameters
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
/* void wxScrollHelper::SetScrollbars(int pixelsPerUnitX,
* pixelsPerUnitX/pixelsPerUnitY: number of pixels per unit (e.g. pixels per text line) int pixelsPerUnitY,
* noUnitsX/noUnitsY: : no. units per scrollbar int noUnitsX,
*/ int noUnitsY,
void wxScrolledWindow::SetScrollbars (int pixelsPerUnitX, int pixelsPerUnitY, int xPos,
int noUnitsX, int noUnitsY, int yPos,
int xPos, int yPos, bool noRefresh ) bool noRefresh)
{ {
int xpos, ypos; int xpos, ypos;
@@ -148,8 +178,6 @@ void wxScrolledWindow::SetScrollbars (int pixelsPerUnitX, int pixelsPerUnitY,
(noUnitsY < m_yScrollLines && ypos > pixelsPerUnitY*noUnitsY) || (noUnitsY < m_yScrollLines && ypos > pixelsPerUnitY*noUnitsY) ||
(xPos != m_xScrollPosition) || (xPos != m_xScrollPosition) ||
(yPos != m_yScrollPosition) (yPos != m_yScrollPosition)
// (pixelsPerUnitX != m_xScrollPixelsPerLine) ||
// (pixelsPerUnitY != m_yScrollPixelsPerLine)
); );
m_xScrollPixelsPerLine = pixelsPerUnitX; m_xScrollPixelsPerLine = pixelsPerUnitX;
@@ -165,21 +193,21 @@ void wxScrolledWindow::SetScrollbars (int pixelsPerUnitX, int pixelsPerUnitY,
// be entirely generic because it relies on the wxWindowDC implementation // be entirely generic because it relies on the wxWindowDC implementation
// to duplicate X drawing calls for the backing pixmap. // 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 totalPixelWidth = m_xScrollLines * m_xScrollPixelsPerLine;
int totalPixelHeight = m_yScrollLines * m_yScrollPixelsPerLine; int totalPixelHeight = m_yScrollLines * m_yScrollPixelsPerLine;
if (m_backingPixmap && if (m_targetWindow->m_backingPixmap &&
!((m_pixmapWidth == totalPixelWidth) && !((m_targetWindow->m_pixmapWidth == totalPixelWidth) &&
(m_pixmapHeight == totalPixelHeight))) (m_targetWindow->m_pixmapHeight == totalPixelHeight)))
{ {
XFreePixmap (dpy, (Pixmap) m_backingPixmap); XFreePixmap (dpy, (Pixmap) m_targetWindow->m_backingPixmap);
m_backingPixmap = (WXPixmap) 0; m_targetWindow->m_backingPixmap = (WXPixmap) 0;
} }
if (!m_backingPixmap && if (!m_targetWindow->m_backingPixmap &&
(noUnitsX != 0) && (noUnitsY != 0)) (noUnitsX != 0) && (noUnitsY != 0))
{ {
int depth = wxDisplayDepth(); int depth = wxDisplayDepth();
@@ -197,16 +225,6 @@ void wxScrolledWindow::SetScrollbars (int pixelsPerUnitX, int pixelsPerUnitY,
if (do_refresh && !noRefresh) if (do_refresh && !noRefresh)
m_targetWindow->Refresh(); 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__ #ifdef __WXMAC__
m_targetWindow->MacUpdateImmediately() ; m_targetWindow->MacUpdateImmediately() ;
#endif #endif
@@ -216,13 +234,13 @@ void wxScrolledWindow::SetScrollbars (int pixelsPerUnitX, int pixelsPerUnitY,
// target window handling // target window handling
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
void wxScrolledWindow::SetTargetWindow( wxWindow *target ) void wxScrollHelper::SetTargetWindow( wxWindow *target )
{ {
wxASSERT_MSG( target, wxT("target window must not be NULL") ); wxASSERT_MSG( target, wxT("target window must not be NULL") );
m_targetWindow = target; m_targetWindow = target;
} }
wxWindow *wxScrolledWindow::GetTargetWindow() wxWindow *wxScrollHelper::GetTargetWindow() const
{ {
return m_targetWindow; return m_targetWindow;
} }
@@ -231,7 +249,7 @@ wxWindow *wxScrolledWindow::GetTargetWindow()
// scrolling implementation itself // scrolling implementation itself
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
void wxScrolledWindow::OnScroll(wxScrollWinEvent& event) void wxScrollHelper::HandleOnScroll(wxScrollWinEvent& event)
{ {
int orient = event.GetOrientation(); int orient = event.GetOrientation();
@@ -241,12 +259,12 @@ void wxScrolledWindow::OnScroll(wxScrollWinEvent& event)
if (orient == wxHORIZONTAL) if (orient == wxHORIZONTAL)
{ {
int newPos = m_xScrollPosition + nScrollInc; int newPos = m_xScrollPosition + nScrollInc;
SetScrollPos(wxHORIZONTAL, newPos, FALSE ); m_win->SetScrollPos(wxHORIZONTAL, newPos, FALSE );
} }
else else
{ {
int newPos = m_yScrollPosition + nScrollInc; int newPos = m_yScrollPosition + nScrollInc;
SetScrollPos(wxVERTICAL, newPos, FALSE ); m_win->SetScrollPos(wxVERTICAL, newPos, FALSE );
} }
if (orient == wxHORIZONTAL) if (orient == wxHORIZONTAL)
@@ -277,7 +295,7 @@ void wxScrolledWindow::OnScroll(wxScrollWinEvent& event)
#endif #endif
} }
int wxScrolledWindow::CalcScrollInc(wxScrollWinEvent& event) int wxScrollHelper::CalcScrollInc(wxScrollWinEvent& event)
{ {
int pos = event.GetPosition(); int pos = event.GetPosition();
int orient = event.GetOrientation(); int orient = event.GetOrientation();
@@ -387,7 +405,7 @@ int wxScrolledWindow::CalcScrollInc(wxScrollWinEvent& event)
} }
// Adjust the scrollbars - new version. // Adjust the scrollbars - new version.
void wxScrolledWindow::AdjustScrollbars() void wxScrollHelper::AdjustScrollbars()
{ {
int w, h; int w, h;
m_targetWindow->GetClientSize(&w, &h); m_targetWindow->GetClientSize(&w, &h);
@@ -407,14 +425,14 @@ void wxScrolledWindow::AdjustScrollbars()
m_xScrollPosition = wxMin( m_xScrollLines-noPagePositions, m_xScrollPosition); m_xScrollPosition = wxMin( m_xScrollLines-noPagePositions, m_xScrollPosition);
m_xScrollPosition = wxMax( 0, 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 // The amount by which we scroll when paging
SetScrollPageSize(wxHORIZONTAL, noPagePositions); SetScrollPageSize(wxHORIZONTAL, noPagePositions);
} }
else else
{ {
m_xScrollPosition = 0; m_xScrollPosition = 0;
SetScrollbar (wxHORIZONTAL, 0, 0, 0, FALSE); m_win->SetScrollbar (wxHORIZONTAL, 0, 0, 0, FALSE);
} }
if (m_yScrollLines > 0) if (m_yScrollLines > 0)
@@ -429,14 +447,14 @@ void wxScrolledWindow::AdjustScrollbars()
m_yScrollPosition = wxMin( m_yScrollLines-noPagePositions, m_yScrollPosition ); m_yScrollPosition = wxMin( m_yScrollLines-noPagePositions, m_yScrollPosition );
m_yScrollPosition = wxMax( 0, 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 // The amount by which we scroll when paging
SetScrollPageSize(wxVERTICAL, noPagePositions); SetScrollPageSize(wxVERTICAL, noPagePositions);
} }
else else
{ {
m_yScrollPosition = 0; m_yScrollPosition = 0;
SetScrollbar (wxVERTICAL, 0, 0, 0, FALSE); m_win->SetScrollbar (wxVERTICAL, 0, 0, 0, FALSE);
} }
if (oldXScroll != m_xScrollPosition) if (oldXScroll != m_xScrollPosition)
@@ -456,9 +474,7 @@ void wxScrolledWindow::AdjustScrollbars()
} }
} }
// Override this function if you don't want to have wxScrolledWindow void wxScrollHelper::DoPrepareDC(wxDC& dc)
// automatically change the origin according to the scroll position.
void wxScrolledWindow::PrepareDC(wxDC& dc)
{ {
dc.SetDeviceOrigin( -m_xScrollPosition * m_xScrollPixelsPerLine, dc.SetDeviceOrigin( -m_xScrollPosition * m_xScrollPixelsPerLine,
-m_yScrollPosition * m_yScrollPixelsPerLine ); -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 // for wxUniversal we need to set the clipping region to avoid overwriting
// the scrollbars with the user drawing // the scrollbars with the user drawing
#ifdef __WXUNIVERSAL__ #ifdef __WXUNIVERSAL__
wxSize size = GetClientSize(); wxSize size = m_win->GetClientSize();
dc.SetClippingRegion(m_xScrollPosition * m_xScrollPixelsPerLine, dc.SetClippingRegion(m_xScrollPosition * m_xScrollPixelsPerLine,
m_yScrollPosition * m_yScrollPixelsPerLine, m_yScrollPosition * m_yScrollPixelsPerLine,
size.x, size.y); size.x, size.y);
#endif // __WXUNIVERSAL__ #endif // __WXUNIVERSAL__
} }
#if WXWIN_COMPATIBILITY void wxScrollHelper::GetScrollPixelsPerUnit (int *x_unit, int *y_unit) const
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
{ {
if ( x_unit ) if ( x_unit )
*x_unit = m_xScrollPixelsPerLine; *x_unit = m_xScrollPixelsPerLine;
@@ -498,7 +498,7 @@ void wxScrolledWindow::GetScrollPixelsPerUnit (int *x_unit, int *y_unit) const
*y_unit = m_yScrollPixelsPerLine; *y_unit = m_yScrollPixelsPerLine;
} }
int wxScrolledWindow::GetScrollPageSize(int orient) const int wxScrollHelper::GetScrollPageSize(int orient) const
{ {
if ( orient == wxHORIZONTAL ) if ( orient == wxHORIZONTAL )
return m_xScrollLinesPerPage; return m_xScrollLinesPerPage;
@@ -506,7 +506,7 @@ int wxScrolledWindow::GetScrollPageSize(int orient) const
return m_yScrollLinesPerPage; return m_yScrollLinesPerPage;
} }
void wxScrolledWindow::SetScrollPageSize(int orient, int pageSize) void wxScrollHelper::SetScrollPageSize(int orient, int pageSize)
{ {
if ( orient == wxHORIZONTAL ) if ( orient == wxHORIZONTAL )
m_xScrollLinesPerPage = pageSize; m_xScrollLinesPerPage = pageSize;
@@ -517,7 +517,7 @@ void wxScrolledWindow::SetScrollPageSize(int orient, int pageSize)
/* /*
* Scroll to given position (scroll position, not pixel position) * 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) if (!m_targetWindow)
return; return;
@@ -574,13 +574,13 @@ void wxScrolledWindow::Scroll( int x_pos, int y_pos )
#endif #endif
} }
void wxScrolledWindow::EnableScrolling (bool x_scroll, bool y_scroll) void wxScrollHelper::EnableScrolling (bool x_scroll, bool y_scroll)
{ {
m_xScrollingEnabled = x_scroll; m_xScrollingEnabled = x_scroll;
m_yScrollingEnabled = y_scroll; m_yScrollingEnabled = y_scroll;
} }
void wxScrolledWindow::GetVirtualSize (int *x, int *y) const void wxScrollHelper::GetVirtualSize (int *x, int *y) const
{ {
if ( x ) if ( x )
*x = m_xScrollPixelsPerLine * m_xScrollLines; *x = m_xScrollPixelsPerLine * m_xScrollLines;
@@ -589,7 +589,7 @@ void wxScrolledWindow::GetVirtualSize (int *x, int *y) const
} }
// Where the current view starts from // Where the current view starts from
void wxScrolledWindow::GetViewStart (int *x, int *y) const void wxScrollHelper::GetViewStart (int *x, int *y) const
{ {
if ( x ) if ( x )
*x = m_xScrollPosition; *x = m_xScrollPosition;
@@ -597,7 +597,7 @@ void wxScrolledWindow::GetViewStart (int *x, int *y) const
*y = m_yScrollPosition; *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 ) if ( xx )
*xx = x - m_xScrollPosition * m_xScrollPixelsPerLine; *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; *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 ) if ( xx )
*xx = x + m_xScrollPosition * m_xScrollPixelsPerLine; *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 // Default OnSize resets scrollbars, if any
void wxScrolledWindow::OnSize(wxSizeEvent& WXUNUSED(event)) void wxScrollHelper::HandleOnSize(wxSizeEvent& WXUNUSED(event))
{ {
#if wxUSE_CONSTRAINTS #if wxUSE_CONSTRAINTS
if (GetAutoLayout()) if ( m_targetWindow->GetAutoLayout() )
Layout(); m_targetWindow->Layout();
#endif #endif
AdjustScrollbars(); AdjustScrollbars();
@@ -630,10 +630,10 @@ void wxScrolledWindow::OnSize(wxSizeEvent& WXUNUSED(event))
// This calls OnDraw, having adjusted the origin according to the current // This calls OnDraw, having adjusted the origin according to the current
// scroll position // scroll position
void wxScrolledWindow::OnPaint(wxPaintEvent& WXUNUSED(event)) void wxScrollHelper::HandleOnPaint(wxPaintEvent& WXUNUSED(event))
{ {
wxPaintDC dc(this); wxPaintDC dc(m_targetWindow);
PrepareDC(dc); DoPrepareDC(dc);
OnDraw(dc); OnDraw(dc);
} }
@@ -642,14 +642,14 @@ void wxScrolledWindow::OnPaint(wxPaintEvent& WXUNUSED(event))
// compatibility here - if we used OnKeyDown(), the programs which process // compatibility here - if we used OnKeyDown(), the programs which process
// arrows themselves in their OnChar() would never get the message and like // arrows themselves in their OnChar() would never get the message and like
// this they always have the priority // this they always have the priority
void wxScrolledWindow::OnChar(wxKeyEvent& event) void wxScrollHelper::HandleOnChar(wxKeyEvent& event)
{ {
int stx, sty, // view origin int stx, sty, // view origin
szx, szy, // view size (total) szx, szy, // view size (total)
clix, cliy; // view size (on screen) clix, cliy; // view size (on screen)
ViewStart(&stx, &sty); GetViewStart(&stx, &sty);
GetClientSize(&clix, &cliy); m_win->GetClientSize(&clix, &cliy);
GetVirtualSize(&szx, &szy); GetVirtualSize(&szx, &szy);
if( m_xScrollPixelsPerLine ) if( m_xScrollPixelsPerLine )
@@ -716,3 +716,49 @@ void wxScrolledWindow::OnChar(wxKeyEvent& event)
event.Skip(); 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

File diff suppressed because it is too large Load Diff

View File

@@ -6,7 +6,7 @@
// Created: 14.08.00 // Created: 14.08.00
// RCS-ID: $Id$ // RCS-ID: $Id$
// Copyright: (c) 2000 Vadim Zeitlin // Copyright: (c) 2000 Vadim Zeitlin
// Licence: wxWindows license // Licence: wxWindows licence
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
// ============================================================================ // ============================================================================
@@ -97,7 +97,7 @@ wxButton::~wxButton()
// size management // size management
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
wxSize wxButton::DoGetBestSize() const wxSize wxButton::DoGetBestClientSize() const
{ {
wxClientDC dc(wxConstCast(this, wxButton)); wxClientDC dc(wxConstCast(this, wxButton));
wxCoord width, height; wxCoord width, height;
@@ -113,7 +113,7 @@ wxSize wxButton::DoGetBestSize() const
width += m_bitmap.GetWidth() + 2*m_marginBmpX; width += m_bitmap.GetWidth() + 2*m_marginBmpX;
} }
return AdjustSize(wxSize(width, height)); return wxSize(width, height);
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@@ -131,13 +131,23 @@ void wxButton::DoDraw(wxControlRenderer *renderer)
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
void wxButton::Press() void wxButton::Press()
{
if ( !m_isPressed )
{ {
m_isPressed = TRUE; m_isPressed = TRUE;
Refresh();
}
} }
void wxButton::Release() void wxButton::Release()
{
if ( m_isPressed )
{ {
m_isPressed = FALSE; m_isPressed = FALSE;
Refresh();
}
} }
void wxButton::Toggle() void wxButton::Toggle()
@@ -162,10 +172,9 @@ void wxButton::Click()
} }
bool wxButton::PerformAction(const wxControlAction& action, bool wxButton::PerformAction(const wxControlAction& action,
const wxEvent& event) long numArg,
const wxString& strArg)
{ {
bool wasPressed = IsPressed();
if ( action == wxACTION_BUTTON_TOGGLE ) if ( action == wxACTION_BUTTON_TOGGLE )
Toggle(); Toggle();
else if ( action == wxACTION_BUTTON_CLICK ) else if ( action == wxACTION_BUTTON_CLICK )
@@ -175,9 +184,9 @@ bool wxButton::PerformAction(const wxControlAction& action,
else if ( action == wxACTION_BUTTON_RELEASE ) else if ( action == wxACTION_BUTTON_RELEASE )
Release(); Release();
else 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; 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 #endif // wxUSE_BUTTON

View File

@@ -62,6 +62,8 @@ END_EVENT_TABLE()
void wxControl::Init() void wxControl::Init()
{ {
m_indexAccel = -1; m_indexAccel = -1;
m_handler = (wxInputHandler *)NULL;
} }
bool wxControl::Create(wxWindow *parent, bool wxControl::Create(wxWindow *parent,
@@ -75,10 +77,11 @@ bool wxControl::Create(wxWindow *parent,
if ( !wxControlBase::Create(parent, id, pos, size, style, validator, name) ) if ( !wxControlBase::Create(parent, id, pos, size, style, validator, name) )
return FALSE; return FALSE;
SetBackgroundColour(parent->GetBackgroundColour()); m_renderer = wxTheme::Get()->GetRenderer();
m_handler = CreateInputHandler(); m_handler = CreateInputHandler();
SetBackgroundColour(parent->GetBackgroundColour());
return TRUE; return TRUE;
} }
@@ -135,8 +138,8 @@ wxString wxControl::GetLabel() const
void wxControl::OnFocus(wxFocusEvent& event) void wxControl::OnFocus(wxFocusEvent& event)
{ {
if ( m_handler->OnFocus(this, event) ) if ( !m_handler || !m_handler->HandleFocus(this, event) )
Refresh(); event.Skip();
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@@ -150,56 +153,53 @@ wxInputHandler *wxControl::CreateInputHandler() const
void wxControl::OnKeyDown(wxKeyEvent& event) 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) 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) void wxControl::OnMouse(wxMouseEvent& event)
{
if ( m_handler )
{ {
if ( event.Moving() || event.Entering() || event.Leaving() ) if ( event.Moving() || event.Entering() || event.Leaving() )
{ {
// don't process it at all for static controls which are not supposed if ( m_handler->HandleMouseMove(this, event) )
// to react to the mouse in any way at all return;
if ( AcceptsFocus() && m_handler->OnMouseMove(this, event) )
Refresh();
} }
else // a click action else // a click action
{ {
PerformActions(m_handler->Map(this, event), event); if ( m_handler->HandleMouse(this, event) )
return;
} }
} }
event.Skip();
}
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// the actions // 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, bool wxControl::PerformAction(const wxControlAction& action,
const wxEvent& event) long numArg,
const wxString& strArg)
{ {
return FALSE; return FALSE;
} }
// ----------------------------------------------------------------------------
// border
// ----------------------------------------------------------------------------
wxBorder wxControl::GetDefaultBorder() const
{
return AcceptsFocus() ? wxBORDER_SUNKEN : wxBORDER_NONE;
}
#endif // wxUSE_CONTROLS #endif // wxUSE_CONTROLS

View File

@@ -29,77 +29,25 @@
#endif #endif
#ifndef WX_PRECOMP #ifndef WX_PRECOMP
#include "wx/timer.h"
#include "wx/button.h"
#include "wx/scrolbar.h"
#include "wx/univ/renderer.h"
#endif // WX_PRECOMP #endif // WX_PRECOMP
#include "wx/univ/inphand.h" #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 // 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 // wxInputHandler
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
bool wxInputHandler::OnMouseMove(wxControl * WXUNUSED(control), bool wxInputHandler::HandleMouseMove(wxControl * WXUNUSED(control),
const wxMouseEvent& WXUNUSED(event)) const wxMouseEvent& WXUNUSED(event))
{ {
return FALSE; return FALSE;
} }
bool wxInputHandler::OnFocus(wxControl *control, const wxFocusEvent& event) bool wxInputHandler::HandleFocus(wxControl *control, const wxFocusEvent& event)
{ {
return FALSE; 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;
}

675
src/univ/listbox.cpp Normal file
View File

@@ -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 <zeitlin@dptmaths.ens-cachan.fr>
// 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

View File

@@ -70,6 +70,106 @@ void wxRenderer::StandardDrawFrame(wxDC& dc,
// wxRenderer: scrollbar geometry // 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 */ /* static */
wxCoord wxRenderer::StandardScrollBarSize(const wxScrollBar *scrollbar, wxCoord wxRenderer::StandardScrollBarSize(const wxScrollBar *scrollbar,
const wxSize& sizeArrowSB) const wxSize& sizeArrowSB)
@@ -91,6 +191,7 @@ wxCoord wxRenderer::StandardScrollBarSize(const wxScrollBar *scrollbar,
/* static */ /* static */
wxCoord wxRenderer::StandardScrollbarToPixel(const wxScrollBar *scrollbar, wxCoord wxRenderer::StandardScrollbarToPixel(const wxScrollBar *scrollbar,
int thumbPos,
const wxSize& sizeArrow) const wxSize& sizeArrow)
{ {
int range = scrollbar->GetRange(); int range = scrollbar->GetRange();
@@ -100,8 +201,13 @@ wxCoord wxRenderer::StandardScrollbarToPixel(const wxScrollBar *scrollbar,
return 0; return 0;
} }
return ( scrollbar->GetThumbPosition() * if ( thumbPos == -1 )
StandardScrollBarSize(scrollbar, sizeArrow) ) / range {
// by default use the current thumb position
thumbPos = scrollbar->GetThumbPosition();
}
return ( thumbPos*StandardScrollBarSize(scrollbar, sizeArrow) ) / range
+ (scrollbar->IsVertical() ? sizeArrow.y : sizeArrow.x); + (scrollbar->IsVertical() ? sizeArrow.y : sizeArrow.x);
} }
@@ -219,8 +325,13 @@ void wxControlRenderer::DrawBorder()
m_renderer->DrawBorder(m_dc, m_window->GetBorder(), m_renderer->DrawBorder(m_dc, m_window->GetBorder(),
m_rect, flags, &m_rect); m_rect, flags, &m_rect);
// fill the inside (TODO: query the theme for bg bitmap) // fill the inside unless we have the background bitmap as we don't want to
m_renderer->DrawBackground(m_dc, m_rect, flags); // overwrite it
if ( !m_window->GetBackgroundBitmap().Ok() )
{
m_renderer->DrawBackground(m_dc, m_window->GetBackgroundColour(),
m_rect, flags);
}
} }
void wxControlRenderer::DrawLabel(const wxBitmap& bitmap, 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->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) 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 */); 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; // we will only redraw the parts which must be redrawn and not everything
int range = scrollbar->GetRange(); wxRegion rgnUpdate = scrollbar->GetUpdateRegion();
if ( range )
{
int thumbPos = scrollbar->GetThumbPosition(),
thumbSize = scrollbar->GetThumbSize();
thumbStart = (100*thumbPos) / range; // arrows
thumbEnd = (100*(thumbPos + thumbSize)) / range; static const wxDirection arrowDirs[2][2] =
}
else // no range
{ {
thumbStart = { wxLEFT, wxRIGHT },
thumbEnd = 0; { 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]; // TODO: support for page arrows
for ( size_t n = 0; n < WXSIZEOF(flags); n++ )
// 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, // and the thumb
m_window->GetWindowStyle() & wxVERTICAL wxScrollBar::Element elem = wxScrollBar::Element_Thumb;
? wxVERTICAL wxRect rectThumb = m_renderer->GetScrollbarRect(scrollbar, elem);
: wxHORIZONTAL, if ( rgnUpdate.Contains(rectThumb) )
thumbStart, thumbEnd, m_rect, {
flags); m_renderer->DrawScrollbarThumb(m_dc, rectThumb,
scrollbar->GetState(elem));
}
} }
void wxControlRenderer::DrawLine(wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2) 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 else // horizontal
m_renderer->DrawHorizontalLine(m_dc, y1, x1, x2); 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;
}
}

View File

@@ -30,6 +30,8 @@
#if wxUSE_SCROLLBAR #if wxUSE_SCROLLBAR
#ifndef WX_PRECOMP #ifndef WX_PRECOMP
#include "wx/timer.h"
#include "wx/dcclient.h" #include "wx/dcclient.h"
#include "wx/scrolbar.h" #include "wx/scrolbar.h"
#include "wx/validate.h" #include "wx/validate.h"
@@ -39,12 +41,37 @@
#include "wx/univ/inphand.h" #include "wx/univ/inphand.h"
#include "wx/univ/theme.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 // implementation
// ============================================================================ // ============================================================================
IMPLEMENT_DYNAMIC_CLASS(wxScrollBar, wxControl) IMPLEMENT_DYNAMIC_CLASS(wxScrollBar, wxControl)
BEGIN_EVENT_TABLE(wxScrollBar, wxScrollBarBase)
EVT_IDLE(wxScrollBar::OnIdle)
END_EVENT_TABLE()
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// creation // creation
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@@ -56,10 +83,14 @@ void wxScrollBar::Init()
m_thumbPos = m_thumbPos =
m_pageSize = 0; m_pageSize = 0;
m_thumbPosOld = -1;
for ( size_t n = 0; n < WXSIZEOF(m_elementsState); n++ ) for ( size_t n = 0; n < WXSIZEOF(m_elementsState); n++ )
{ {
m_elementsState[n] = 0; m_elementsState[n] = 0;
} }
m_dirty = FALSE;
} }
bool wxScrollBar::Create(wxWindow *parent, bool wxScrollBar::Create(wxWindow *parent,
@@ -102,7 +133,20 @@ void wxScrollBar::DoSetThumb(int pos)
pos = m_range - m_thumbSize; pos = m_range - m_thumbSize;
} }
if ( m_thumbPosOld == -1 )
{
// remember the old thumb position
m_thumbPosOld = m_thumbPos;
}
m_thumbPos = pos; 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 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") ); wxCHECK_RET( pos >= 0 && pos <= m_range, _T("thumb position out of range") );
DoSetThumb(pos); DoSetThumb(pos);
Refresh();
} }
void wxScrollBar::SetScrollbar(int position, int thumbSize, void wxScrollBar::SetScrollbar(int position, int thumbSize,
@@ -155,34 +197,67 @@ void wxScrollBar::SetScrollbar(int position, int thumbSize,
// size management // size management
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
wxSize wxScrollBar::DoGetBestSize() const wxSize wxScrollBar::DoGetBestClientSize() const
{ {
// completely arbitrary // completely arbitrary
return AdjustSize(wxSize(140, 140)); return wxSize(140, 140);
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// drawing // 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) 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 // input processing
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
wxCoord wxScrollBar::GetMouseCoord(const wxEvent& eventOrig) const void wxScrollBar::SetState(Element which, int flags)
{ {
const wxMouseEvent& event = (const wxMouseEvent&)eventOrig; if ( (m_elementsState[which] & ~wxCONTROL_DIRTY) != flags )
wxPoint pt = event.GetPosition(); {
return GetWindowStyle() & wxVERTICAL ? pt.y : pt.x; m_elementsState[which] = flags | wxCONTROL_DIRTY;
m_dirty = TRUE;
}
} }
bool wxScrollBar::PerformAction(const wxControlAction& action, bool wxScrollBar::PerformAction(const wxControlAction& action,
const wxEvent& event) long numArg,
const wxString& strArg)
{ {
int thumbOld = m_thumbPos; 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 // test for thumb move first as these events happen in quick succession
if ( action == wxACTION_SCROLL_THUMB_MOVE ) if ( action == wxACTION_SCROLL_THUMB_MOVE )
{ {
// make the thumb follow the mouse by keeping the same offset between DoSetThumb(numArg);
// the mouse position and the top/left of the thumb
int thumbPos = GetMouseCoord(event) - m_ofsMouse;
DoSetThumb(GetRenderer()->PixelToScrollbar(this, thumbPos));
scrollType = wxEVT_SCROLLWIN_THUMBTRACK; scrollType = wxEVT_SCROLLWIN_THUMBTRACK;
} }
@@ -232,8 +304,10 @@ bool wxScrollBar::PerformAction(const wxControlAction& action,
} }
else if ( action == wxACTION_SCROLL_THUMB_DRAG ) else if ( action == wxACTION_SCROLL_THUMB_DRAG )
{ {
m_ofsMouse = GetMouseCoord(event) - // we won't use it but this line suppresses the compiler
GetRenderer()->ScrollbarToPixel(this); // warning about "variable may be used without having been
// initialized"
scrollType = wxEVT_NULL;
} }
else if ( action == wxACTION_SCROLL_THUMB_RELEASE ) else if ( action == wxACTION_SCROLL_THUMB_RELEASE )
{ {
@@ -242,7 +316,7 @@ bool wxScrollBar::PerformAction(const wxControlAction& action,
scrollType = wxEVT_SCROLLWIN_THUMBRELEASE; scrollType = wxEVT_SCROLLWIN_THUMBRELEASE;
} }
else else
return wxControl::PerformAction(action, event); return wxControl::PerformAction(action, numArg, strArg);
// has scrollbar position changed? // has scrollbar position changed?
bool changed = m_thumbPos != thumbOld; bool changed = m_thumbPos != thumbOld;
@@ -254,8 +328,7 @@ bool wxScrollBar::PerformAction(const wxControlAction& action,
GetParent()->GetEventHandler()->ProcessEvent(event); GetParent()->GetEventHandler()->ProcessEvent(event);
} }
// refresh if something changed return TRUE;
return changed;
} }
void wxScrollBar::ScrollToStart() void wxScrollBar::ScrollToStart()
@@ -278,5 +351,333 @@ void wxScrollBar::ScrollPages(int nPages)
DoSetThumb(m_thumbPos + nPages*m_pageSize); 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 #endif // wxUSE_SCROLLBAR

View File

@@ -102,9 +102,9 @@ wxIcon wxStaticBitmap::GetIcon() const
// drawing // drawing
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
wxSize wxStaticBitmap::DoGetBestSize() const wxSize wxStaticBitmap::DoGetBestClientSize() const
{ {
return AdjustSize(wxStaticBitmapBase::DoGetBestSize()); return wxStaticBitmapBase::DoGetBestSize();
} }
void wxStaticBitmap::DoDraw(wxControlRenderer *renderer) void wxStaticBitmap::DoDraw(wxControlRenderer *renderer)

View File

@@ -58,13 +58,7 @@ bool wxStaticText::Create(wxWindow *parent,
return FALSE; return FALSE;
SetLabel(label); SetLabel(label);
SetBestSize(size);
if ( size.x == -1 || size.y == -1 )
{
wxSize sizeBest = DoGetBestSize();
SetSize(size.x == -1 ? sizeBest.x : size.x,
size.y == -1 ? sizeBest.y : size.y);
}
return TRUE; return TRUE;
} }
@@ -78,13 +72,13 @@ void wxStaticText::SetLabel(const wxString& label)
wxControl::SetLabel(label); wxControl::SetLabel(label);
} }
wxSize wxStaticText::DoGetBestSize() const wxSize wxStaticText::DoGetBestClientSize() const
{ {
wxClientDC dc(wxConstCast(this, wxStaticText)); wxClientDC dc(wxConstCast(this, wxStaticText));
wxCoord width, height; wxCoord width, height;
dc.GetMultiLineTextExtent(GetLabel(), &width, &height); dc.GetMultiLineTextExtent(GetLabel(), &width, &height);
return AdjustSize(wxSize(width, height)); return wxSize(width, height);
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------

View File

@@ -53,6 +53,7 @@ public:
// implement the base class pure virtuals // implement the base class pure virtuals
virtual void DrawBackground(wxDC& dc, virtual void DrawBackground(wxDC& dc,
const wxColour& col,
const wxRect& rect, const wxRect& rect,
int flags = 0); int flags = 0);
virtual void DrawLabel(wxDC& dc, virtual void DrawLabel(wxDC& dc,
@@ -86,19 +87,27 @@ public:
wxDirection dir, wxDirection dir,
const wxRect& rect, const wxRect& rect,
int flags = 0); int flags = 0);
virtual void DrawScrollbar(wxDC& dc, virtual void DrawScrollbarThumb(wxDC& dc,
wxOrientation orient,
int thumbPosStart,
int thumbPosEnd,
const wxRect& rect, const wxRect& rect,
const int *flags = NULL); 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 void AdjustSize(wxSize *size, const wxWindow *window);
// hit testing for the input handlers // 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, virtual wxHitTest HitTestScrollbar(const wxScrollBar *scrollbar,
const wxPoint& pt) const; 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); virtual int PixelToScrollbar(const wxScrollBar *scrollbar, wxCoord coord);
protected: protected:
@@ -159,12 +168,12 @@ class wxGTKInputHandler : public wxInputHandler
public: public:
wxGTKInputHandler(wxGTKRenderer *renderer); wxGTKInputHandler(wxGTKRenderer *renderer);
virtual wxControlActions Map(wxControl *control, virtual bool HandleKey(wxControl *control,
const wxKeyEvent& event, const wxKeyEvent& event,
bool pressed); bool pressed);
virtual wxControlActions Map(wxControl *control, virtual bool HandleMouse(wxControl *control,
const wxMouseEvent& event); const wxMouseEvent& event);
virtual bool OnMouseMove(wxControl *control, const wxMouseEvent& event); virtual bool HandleMouseMove(wxControl *control, const wxMouseEvent& event);
protected: protected:
wxGTKRenderer *m_renderer; wxGTKRenderer *m_renderer;
@@ -592,6 +601,32 @@ void wxGTKRenderer::DrawLabel(wxDC& dc,
dc.DrawLabel(label, image, rect, alignment, indexAccel, rectBounds); 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 // background
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@@ -607,10 +642,14 @@ void wxGTKRenderer::DoDrawBackground(wxDC& dc,
} }
void wxGTKRenderer::DrawBackground(wxDC& dc, void wxGTKRenderer::DrawBackground(wxDC& dc,
const wxColour& col,
const wxRect& rect, const wxRect& rect,
int flags) 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, void wxGTKRenderer::DrawScrollbarThumb(wxDC& dc,
wxOrientation orient,
int thumbPosStart,
int thumbPosEnd,
const wxRect& rect, const wxRect& rect,
const int *flags) int flags)
{ {
#ifdef DEBUG_MOUSE // the thumb is never pressed never has focus border under GTK and the
wxLogDebug("Drawing the scrollbar (orientation = %s):\n" // scrollbar background never changes at all
"\tarrow 1: 0x%04x\n" int flagsThumb = flags & ~(wxCONTROL_PRESSED | wxCONTROL_FOCUSED);
"\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
// 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; wxRect rectBar = rect;
DrawAntiShadedRect(dc, &rectBar, m_penDarkGrey, m_penHighlight); DrawAntiShadedRect(dc, &rectBar, m_penDarkGrey, m_penHighlight);
DrawAntiShadedRect(dc, &rectBar, m_penBlack, m_penGrey); DrawAntiShadedRect(dc, &rectBar, m_penBlack, m_penGrey);
DoDrawBackground(dc, m_scheme->Get(wxColourScheme::SCROLLBAR), rectBar); 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++ ) wxRect wxGTKRenderer::GetScrollbarRect(const wxScrollBar *scrollbar,
wxScrollBar::Element elem,
int thumbPos) const
{ {
DrawArrow(dc, arrowDir[nArrow], rectArrow[nArrow], return StandardGetScrollbarRect(scrollbar, elem,
flags[wxScrollBar::Element_Arrow_Line_1 + nArrow]); thumbPos, m_sizeScrollbarArrow);
}
// 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);
}
} }
wxHitTest wxGTKRenderer::HitTestScrollbar(const wxScrollBar *scrollbar, wxHitTest wxGTKRenderer::HitTestScrollbar(const wxScrollBar *scrollbar,
@@ -877,9 +862,10 @@ wxHitTest wxGTKRenderer::HitTestScrollbar(const wxScrollBar *scrollbar,
return StandardHitTestScrollbar(scrollbar, pt, m_sizeScrollbarArrow); 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, int wxGTKRenderer::PixelToScrollbar(const wxScrollBar *scrollbar,
@@ -962,26 +948,28 @@ wxGTKInputHandler::wxGTKInputHandler(wxGTKRenderer *renderer)
m_renderer = renderer; m_renderer = renderer;
} }
wxControlActions wxGTKInputHandler::Map(wxControl *control, bool wxGTKInputHandler::HandleKey(wxControl *control,
const wxKeyEvent& event, const wxKeyEvent& event,
bool pressed) bool pressed)
{ {
return wxACTION_NONE; return FALSE;
} }
wxControlActions wxGTKInputHandler::Map(wxControl *control, bool wxGTKInputHandler::HandleMouse(wxControl *control,
const wxMouseEvent& event) const wxMouseEvent& event)
{ {
// clicking on the control gives it focus // clicking on the control gives it focus
if ( event.ButtonDown() ) if ( event.ButtonDown() )
{ {
control->SetFocus(); control->SetFocus();
return TRUE;
} }
return wxACTION_NONE; return FALSE;
} }
bool wxGTKInputHandler::OnMouseMove(wxControl *control, bool wxGTKInputHandler::HandleMouseMove(wxControl *control,
const wxMouseEvent& event) const wxMouseEvent& event)
{ {
if ( event.Entering() ) if ( event.Entering() )
@@ -997,7 +985,6 @@ bool wxGTKInputHandler::OnMouseMove(wxControl *control,
return FALSE; return FALSE;
} }
// highlighting changed
return TRUE; return TRUE;
} }

View File

@@ -71,6 +71,7 @@ public:
// implement the base class pure virtuals // implement the base class pure virtuals
virtual void DrawBackground(wxDC& dc, virtual void DrawBackground(wxDC& dc,
const wxColour& col,
const wxRect& rect, const wxRect& rect,
int flags = 0); int flags = 0);
virtual void DrawLabel(wxDC& dc, virtual void DrawLabel(wxDC& dc,
@@ -104,21 +105,32 @@ public:
wxDirection dir, wxDirection dir,
const wxRect& rect, const wxRect& rect,
int flags = 0); int flags = 0);
virtual void DrawScrollbar(wxDC& dc, virtual void DrawScrollbarThumb(wxDC& dc,
wxOrientation orient,
int thumbPosStart,
int thumbPosEnd,
const wxRect& rect, const wxRect& rect,
const int *flags = NULL); 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 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, virtual wxHitTest HitTestScrollbar(const wxScrollBar *scrollbar,
const wxPoint& pt) const; 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); virtual int PixelToScrollbar(const wxScrollBar *scrollbar, wxCoord coord);
protected: protected:
// common part of DrawLabel() and DrawItem()
void DrawFocusRect(wxDC& dc, const wxRect& rect);
// DrawButtonBorder() helper // DrawButtonBorder() helper
void DoDrawBackground(wxDC& dc, void DoDrawBackground(wxDC& dc,
const wxColour& col, const wxColour& col,
@@ -182,10 +194,10 @@ class wxWin32InputHandler : public wxInputHandler
public: public:
wxWin32InputHandler(wxWin32Renderer *renderer); wxWin32InputHandler(wxWin32Renderer *renderer);
virtual wxControlActions Map(wxControl *control, virtual bool HandleKey(wxControl *control,
const wxKeyEvent& event, const wxKeyEvent& event,
bool pressed); bool pressed);
virtual wxControlActions Map(wxControl *control, virtual bool HandleMouse(wxControl *control,
const wxMouseEvent& event); const wxMouseEvent& event);
protected: protected:
@@ -198,12 +210,11 @@ public:
wxWin32ScrollBarInputHandler(wxWin32Renderer *renderer, wxWin32ScrollBarInputHandler(wxWin32Renderer *renderer,
wxInputHandler *handler); wxInputHandler *handler);
virtual wxControlActions Map(wxControl *control, const wxMouseEvent& event); virtual bool HandleMouse(wxControl *control, const wxMouseEvent& event);
virtual bool OnMouseMove(wxControl *control, const wxMouseEvent& event); virtual bool HandleMouseMove(wxControl *control, const wxMouseEvent& event);
virtual bool OnScrollTimer(wxScrollBar *scrollbar, virtual bool OnScrollTimer(wxScrollBar *scrollbar,
const wxControlAction& action, const wxControlAction& action);
const wxMouseEvent& event);
protected: protected:
virtual bool IsAllowedButton(int button) { return button == 1; } virtual bool IsAllowedButton(int button) { return button == 1; }
@@ -294,6 +305,8 @@ wxInputHandler *wxWin32Theme::GetInputHandler(const wxString& control)
else if ( control == _T("wxScrollBar") ) else if ( control == _T("wxScrollBar") )
handler = new wxWin32ScrollBarInputHandler(m_renderer, handler = new wxWin32ScrollBarInputHandler(m_renderer,
GetInputHandler(_T("wxControl"))); GetInputHandler(_T("wxControl")));
else if ( control == _T("wxListBox") )
handler = new wxStdListboxInputHandler(GetInputHandler(_T("wxControl")));
else else
handler = new wxWin32InputHandler(m_renderer); handler = new wxWin32InputHandler(m_renderer);
@@ -817,6 +830,40 @@ void wxWin32Renderer::DrawFrame(wxDC& dc,
// label // 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, void wxWin32Renderer::DrawLabel(wxDC& dc,
const wxString& label, const wxString& label,
const wxBitmap& image, const wxBitmap& image,
@@ -856,35 +903,39 @@ void wxWin32Renderer::DrawLabel(wxDC& dc,
if ( flags & wxCONTROL_FOCUSED ) if ( flags & wxCONTROL_FOCUSED )
{ {
// VZ: this doesn't work under Windows, the dotted pen has dots of 3 DrawFocusRect(dc, rectText);
// pixels each while we really need dots here... PS_ALTERNATE might }
// work, but it is for NT 5 only
#if 0
DrawRect(dc, &rectText, wxPen(*wxBLACK, 0, wxDOT));
#else
// draw the pixels manually
dc.SetPen(wxPen(*wxBLACK, 0, wxSOLID));
// Windows quirk: appears to draw them like this, from right to left
// (and I don't have Hebrew windows to see what happens there)
for ( wxCoord x = rectText.GetRight(); x >= rectText.GetLeft(); x -= 2 )
{
dc.DrawPoint(x, rectText.GetTop());
dc.DrawPoint(x, rectText.GetBottom());
} }
wxCoord shift = rectText.width % 2 ? 0 : 1; void wxWin32Renderer::DrawItem(wxDC& dc,
for ( wxCoord y = rectText.GetTop() + 2; y <= rectText.GetBottom(); y+= 2 ) const wxString& label,
const wxRect& rect,
int flags)
{ {
dc.DrawPoint(rectText.GetLeft(), y - shift); wxColour colFg;
dc.DrawPoint(rectText.GetRight(), y); 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));
} }
if ( shift ) wxRect rectText = rect;
rectText.x += 2;
dc.DrawLabel(label, wxNullBitmap, rectText);
if ( flags & wxCONTROL_FOCUSED )
{ {
dc.DrawPoint(rectText.GetLeft(), rectText.GetBottom() - 1); dc.SetBrush(*wxTRANSPARENT_BRUSH);
DrawFocusRect(dc, rect);
} }
#endif // 0/1
// restore the text colour
if ( colFg.Ok() )
{
dc.SetTextForeground(colFg);
} }
} }
@@ -903,11 +954,15 @@ void wxWin32Renderer::DoDrawBackground(wxDC& dc,
} }
void wxWin32Renderer::DrawBackground(wxDC& dc, void wxWin32Renderer::DrawBackground(wxDC& dc,
const wxColour& col,
const wxRect& rect, const wxRect& rect,
int flags) int flags)
{ {
// just fill it with the default bg colour // 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; return;
} }
wxArrowStyle arrowStyle = flags & wxCONTROL_DISABLED ? Arrow_Disabled wxArrowStyle arrowStyle;
: Arrow_Normal; if ( flags & wxCONTROL_PRESSED )
DrawArrow(dc, rect, arrowDir, arrowStyle); {
// 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, void wxWin32Renderer::DrawArrow(wxDC& dc,
@@ -968,126 +1032,30 @@ void wxWin32Renderer::DrawArrowButton(wxDC& dc,
DrawArrow(dc, rect, arrowDir, arrowStyle); DrawArrow(dc, rect, arrowDir, arrowStyle);
} }
void wxWin32Renderer::DrawScrollbar(wxDC& dc, void wxWin32Renderer::DrawScrollbarThumb(wxDC& dc,
wxOrientation orient,
int thumbPosStart,
int thumbPosEnd,
const wxRect& rect, const wxRect& rect,
const int *flags) int flags)
{
// first, draw the arrows at the ends
wxRect rectArrow[2];
wxArrowDirection arrowDir[2];
rectArrow[0] =
rectArrow[1] = rect;
if ( orient == wxVERTICAL )
{
rectArrow[0].height =
rectArrow[1].height = m_sizeScrollbarArrow.y;
rectArrow[1].y = rect.GetBottom() - rectArrow[1].height;
arrowDir[0] = Arrow_Up;
arrowDir[1] = Arrow_Down;
}
else // horizontal
{
rectArrow[0].width =
rectArrow[1].width = m_sizeScrollbarArrow.x;
rectArrow[1].x = rect.GetRight() - rectArrow[1].width;
arrowDir[0] = Arrow_Left;
arrowDir[1] = Arrow_Right;
}
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 // we don't use the flags, the thumb never changes appearance
wxRect rectThumb = rect;
DrawArrowBorder(dc, &rectThumb); DrawArrowBorder(dc, &rectThumb);
DrawBackground(dc, rectThumb); DrawBackground(dc, wxNullColour, rectThumb);
} }
void wxWin32Renderer::DrawScrollbarShaft(wxDC& dc,
const wxRect& rectBar,
int flags)
{
DoDrawBackground(dc, m_scheme->Get(wxColourScheme::SCROLLBAR, flags),
rectBar);
}
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, wxHitTest wxWin32Renderer::HitTestScrollbar(const wxScrollBar *scrollbar,
@@ -1096,9 +1064,10 @@ wxHitTest wxWin32Renderer::HitTestScrollbar(const wxScrollBar *scrollbar,
return StandardHitTestScrollbar(scrollbar, pt, m_sizeScrollbarArrow); 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, int wxWin32Renderer::PixelToScrollbar(const wxScrollBar *scrollbar,
@@ -1179,17 +1148,17 @@ wxWin32InputHandler::wxWin32InputHandler(wxWin32Renderer *renderer)
m_renderer = renderer; m_renderer = renderer;
} }
wxControlActions wxWin32InputHandler::Map(wxControl *control, bool wxWin32InputHandler::HandleKey(wxControl *control,
const wxKeyEvent& event, const wxKeyEvent& event,
bool pressed) bool pressed)
{ {
return wxACTION_NONE; return FALSE;
} }
wxControlActions wxWin32InputHandler::Map(wxControl *control, bool wxWin32InputHandler::HandleMouse(wxControl *control,
const wxMouseEvent& event) const wxMouseEvent& event)
{ {
return wxACTION_NONE; return FALSE;
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@@ -1206,8 +1175,7 @@ wxWin32ScrollBarInputHandler(wxWin32Renderer *renderer,
} }
bool wxWin32ScrollBarInputHandler::OnScrollTimer(wxScrollBar *scrollbar, bool wxWin32ScrollBarInputHandler::OnScrollTimer(wxScrollBar *scrollbar,
const wxControlAction& action, const wxControlAction& action)
const wxMouseEvent& event)
{ {
// stop if went beyond the position of the original click (this can only // stop if went beyond the position of the original click (this can only
// happen when we scroll by pages) // happen when we scroll by pages)
@@ -1232,19 +1200,17 @@ bool wxWin32ScrollBarInputHandler::OnScrollTimer(wxScrollBar *scrollbar,
return FALSE; return FALSE;
} }
return wxStdScrollBarInputHandler::OnScrollTimer(scrollbar, return wxStdScrollBarInputHandler::OnScrollTimer(scrollbar, action);
action,
event);
} }
wxControlActions wxWin32ScrollBarInputHandler::Map(wxControl *control, bool wxWin32ScrollBarInputHandler::HandleMouse(wxControl *control,
const wxMouseEvent& event) const wxMouseEvent& event)
{ {
// remember the current state // remember the current state
bool wasDraggingThumb = m_htLast == wxHT_SCROLLBAR_THUMB; bool wasDraggingThumb = m_htLast == wxHT_SCROLLBAR_THUMB;
// do process the message // do process the message
wxControlActions actions = wxStdScrollBarInputHandler::Map(control, event); bool rc = wxStdScrollBarInputHandler::HandleMouse(control, event);
// analyse the changes // analyse the changes
if ( !wasDraggingThumb && (m_htLast == wxHT_SCROLLBAR_THUMB) ) if ( !wasDraggingThumb && (m_htLast == wxHT_SCROLLBAR_THUMB) )
@@ -1254,10 +1220,10 @@ wxControlActions wxWin32ScrollBarInputHandler::Map(wxControl *control,
m_eventStartDrag = event; m_eventStartDrag = event;
} }
return actions; return rc;
} }
bool wxWin32ScrollBarInputHandler::OnMouseMove(wxControl *control, bool wxWin32ScrollBarInputHandler::HandleMouseMove(wxControl *control,
const wxMouseEvent& event) const wxMouseEvent& event)
{ {
// we don't highlight scrollbar elements, so there is no need to process // we don't highlight scrollbar elements, so there is no need to process
@@ -1299,8 +1265,7 @@ bool wxWin32ScrollBarInputHandler::OnMouseMove(wxControl *control,
else // we were dragging the thumb else // we were dragging the thumb
{ {
// restore its last location // restore its last location
scrollbar->PerformAction(wxACTION_SCROLL_THUMB_MOVE, HandleThumbMove(scrollbar, m_eventLastDrag);
m_eventLastDrag);
} }
return TRUE; return TRUE;
@@ -1351,13 +1316,12 @@ bool wxWin32ScrollBarInputHandler::OnMouseMove(wxControl *control,
// and restore the original position (before dragging) of the // and restore the original position (before dragging) of the
// thumb for now // thumb for now
scrollbar->PerformAction(wxACTION_SCROLL_THUMB_MOVE, HandleThumbMove(scrollbar, m_eventStartDrag);
m_eventStartDrag);
} }
return TRUE; return TRUE;
} }
} }
return wxStdScrollBarInputHandler::OnMouseMove(control, event); return wxStdScrollBarInputHandler::HandleMouseMove(control, event);
} }

View File

@@ -48,9 +48,14 @@
// event tables // 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_SIZE(wxWindow::OnSize)
EVT_PAINT(wxWindow::OnPaint) EVT_PAINT(wxWindow::OnPaint)
@@ -67,6 +72,8 @@ void wxWindow::Init()
m_scrollbarHorz = (wxScrollBar *)NULL; m_scrollbarHorz = (wxScrollBar *)NULL;
m_isCurrent = FALSE; m_isCurrent = FALSE;
m_renderer = (wxRenderer *)NULL;
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@@ -100,11 +107,6 @@ const wxBitmap& wxWindow::GetBackgroundBitmap(int *alignment,
// painting // painting
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
wxRenderer *wxWindow::GetRenderer() const
{
return wxTheme::Get()->GetRenderer();
}
// the event handler executed when the window background must be painted // the event handler executed when the window background must be painted
void wxWindow::OnErase(wxEraseEvent& event) void wxWindow::OnErase(wxEraseEvent& event)
{ {
@@ -120,14 +122,22 @@ void wxWindow::OnErase(wxEraseEvent& event)
// the event handler executed when the window must be repainted // the event handler executed when the window must be repainted
void wxWindow::OnPaint(wxPaintEvent& event) void wxWindow::OnPaint(wxPaintEvent& event)
{
if ( !m_renderer )
{
// it is a native control which paints itself
event.Skip();
}
else
{ {
// get the DC to use and create renderer on it // get the DC to use and create renderer on it
wxPaintDC dc(this); wxPaintDC dc(this);
wxControlRenderer renderer(this, dc, GetRenderer()); wxControlRenderer renderer(this, dc, m_renderer);
// do draw the control! // do draw the control!
DoDraw(&renderer); DoDraw(&renderer);
} }
}
bool wxWindow::DoDrawBackground(wxControlRenderer *renderer) bool wxWindow::DoDrawBackground(wxControlRenderer *renderer)
{ {
@@ -211,10 +221,21 @@ void wxWindow::OnSize(wxSizeEvent& event)
event.Skip(); event.Skip();
} }
wxSize wxWindow::DoGetBestSize() const
{
return AdjustSize(DoGetBestClientSize());
}
wxSize wxWindow::DoGetBestClientSize() const
{
return wxWindowNative::DoGetBestSize();
}
wxSize wxWindow::AdjustSize(const wxSize& size) const wxSize wxWindow::AdjustSize(const wxSize& size) const
{ {
wxSize sz = size; wxSize sz = size;
wxTheme::Get()->GetRenderer()->AdjustSize(&sz, this); if ( m_renderer )
m_renderer->AdjustSize(&sz, this);
return sz; 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 else // move the part which doesn't change to the new location
{ {
// positive values mean to scroll to the left/up // note that when we scroll the canvas in some direction we move the
if ( dx > 0 ) // 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; ptDest.x = 0;
} }
else else
{ {
// scroll to the left, move to the right
ptSource.x = 0; 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; ptDest.y = 0;
} }
else else
{ {
// scroll up, move down
ptSource.y = 0; ptSource.y = 0;
ptDest.y = -dy; ptDest.y = dy;
} }
// do move // do move
@@ -387,12 +414,23 @@ void wxWindow::ScrollWindow(int dx, int dy, const wxRect *rect)
// it bad? // it bad?
wxRect rect; wxRect rect;
rect.x = ptSource.x;
rect.y = ptSource.y;
if ( dx ) 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; rect.height = sizeTotal.y;
wxLogTrace(_T("scroll"), _T("refreshing (%d, %d)-(%d, %d)"), 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 )
{ {
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.width = sizeTotal.x;
rect.height = abs(dy);
wxLogTrace(_T("scroll"), _T("refreshing (%d, %d)-(%d, %d)"), wxLogTrace(_T("scroll"), _T("refreshing (%d, %d)-(%d, %d)"),
rect.x, rect.y, rect.GetRight(), rect.GetBottom()); rect.x, rect.y, rect.GetRight(), rect.GetBottom());