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*) wxStatusLineNameStr;
WXDLLEXPORT_DATA(extern const wxChar*) wxToolBarNameStr;
WXDLLEXPORT_DATA(extern wxWindow*) wxWndHook;
WXDLLEXPORT_DATA(extern wxWindowMSW*) wxWndHook;
class WXDLLEXPORT wxMenuBar;
class WXDLLEXPORT wxStatusBar;

View File

@@ -28,25 +28,31 @@ WXDLLEXPORT_DATA(extern const wxChar*) wxPanelNameStr;
// default scrolled window style
#define wxScrolledWindowStyle (wxHSCROLL | wxVSCROLL)
// avoid triggering this stupid VC++ warning
#ifdef __VISUALC__
#pragma warning(disable:4355) // 'this' used in base member initializer list
#endif
// ----------------------------------------------------------------------------
// wxScrolledWindow
// ----------------------------------------------------------------------------
class WXDLLEXPORT wxScrolledWindow : public wxPanel
class WXDLLEXPORT wxScrolledWindow : public wxPanel, public wxScrollHelper
{
public:
wxScrolledWindow();
wxScrolledWindow() : wxScrollHelper(this) { }
wxScrolledWindow(wxWindow *parent,
wxWindowID id = -1,
const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize,
long style = wxScrolledWindowStyle,
const wxString& name = wxPanelNameStr)
: wxScrollHelper(this)
{
Create(parent, id, pos, size, style, name);
}
~wxScrolledWindow();
virtual ~wxScrolledWindow();
bool Create(wxWindow *parent,
wxWindowID id,
@@ -55,98 +61,15 @@ public:
long style = wxScrolledWindowStyle,
const wxString& name = wxPanelNameStr);
// Normally the wxScrolledWindow will scroll itself, but in
// some rare occasions you might want it to scroll another
// window (e.g. a child of it in order to scroll only a portion
// the area between the scrollbars (spreadsheet: only cell area
// will move).
virtual void SetTargetWindow( wxWindow *target );
virtual wxWindow *GetTargetWindow();
// Number of pixels per user unit (0 or -1 for no scrollbar)
// Length of virtual canvas in user units
// Length of page in user units
virtual void SetScrollbars(int pixelsPerUnitX, int pixelsPerUnitY,
int noUnitsX, int noUnitsY,
int xPos = 0, int yPos = 0,
bool noRefresh = FALSE );
// Physically scroll the window
virtual void Scroll(int x_pos, int y_pos);
#if WXWIN_COMPATIBILITY
virtual void GetScrollUnitsPerPage(int *x_page, int *y_page) const;
virtual void CalcUnscrolledPosition(int x, int y, float *xx, float *yy) const;
#endif
int GetScrollPageSize(int orient) const;
void SetScrollPageSize(int orient, int pageSize);
virtual void GetScrollPixelsPerUnit(int *x_unit, int *y_unit) const;
// Enable/disable Windows scrolling in either direction.
// If TRUE, wxWindows scrolls the canvas and only a bit of
// the canvas is invalidated; no Clear() is necessary.
// If FALSE, the whole canvas is invalidated and a Clear() is
// necessary. Disable for when the scroll increment is used
// to actually scroll a non-constant distance
virtual void EnableScrolling(bool x_scrolling, bool y_scrolling);
// Get the view start
virtual void GetViewStart(int *x, int *y) const;
// Compatibility
void ViewStart(int *x, int *y) const
{ GetViewStart( x, y ); }
// Actual size in pixels when scrolling is taken into account
virtual void GetVirtualSize(int *x, int *y) const;
// Set the scale factor, used in PrepareDC
void SetScale(double xs, double ys) { m_scaleX = xs; m_scaleY = ys; }
double GetScaleX() const { return m_scaleX; }
double GetScaleY() const { return m_scaleY; }
virtual void CalcScrolledPosition(int x, int y, int *xx, int *yy) const;
virtual void CalcUnscrolledPosition(int x, int y, int *xx, int *yy) const;
// Adjust the scrollbars
virtual void AdjustScrollbars(void);
// Override this function to draw the graphic (or just process EVT_PAINT)
virtual void OnDraw(wxDC& WXUNUSED(dc)) {};
// Override this function if you don't want to have wxScrolledWindow
// automatically change the origin according to the scroll position.
virtual void PrepareDC(wxDC& dc);
// implementation from now on
void OnScroll(wxScrollWinEvent& event);
void OnSize(wxSizeEvent& event);
void OnPaint(wxPaintEvent& event);
void OnChar(wxKeyEvent& event);
// Calculate scroll increment
virtual int CalcScrollInc(wxScrollWinEvent& event);
protected:
wxWindow *m_targetWindow;
int m_xScrollPixelsPerLine;
int m_yScrollPixelsPerLine;
bool m_xScrollingEnabled;
bool m_yScrollingEnabled;
int m_xScrollPosition;
int m_yScrollPosition;
int m_xScrollLines;
int m_yScrollLines;
int m_xScrollLinesPerPage;
int m_yScrollLinesPerPage;
double m_scaleX;
double m_scaleY;
virtual void PrepareDC(wxDC& dc) { DoPrepareDC(dc); }
private:
DECLARE_EVENT_TABLE()
DECLARE_ABSTRACT_CLASS(wxScrolledWindow)
};
#ifdef __VISUALC__
#pragma warning(default:4355)
#endif
#endif
// _WX_GENERIC_SCROLLWIN_H_

View File

@@ -78,6 +78,16 @@ public:
void SetFirstItem(int n) { DoSetFirstItem(n); }
void SetFirstItem(const wxString& s);
// return TRUE if the listbox allows multiple selection
bool HasMultipleSelection() const
{
return (m_windowStyle & wxLB_MULTIPLE) ||
(m_windowStyle & wxLB_EXTENDED);
}
// return TRUE if this listbox is sorted
bool IsSorted() const { return (m_windowStyle & wxLB_SORT) != 0; }
// emulate selecting or deselecting the item event.GetInt() (depending on
// event.GetExtraLong())
void Command(wxCommandEvent& event);
@@ -103,7 +113,9 @@ protected:
// include the platform-specific class declaration
// ----------------------------------------------------------------------------
#if defined(__WXMSW__)
#if defined(__WXUNIVERSAL__)
#include "wx/univ/listbox.h"
#elif defined(__WXMSW__)
#include "wx/msw/listbox.h"
#elif defined(__WXMOTIF__)
#include "wx/motif/listbox.h"

View File

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

View File

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

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_
#define _WX_SCROLWIN_H_BASE_
// ----------------------------------------------------------------------------
// wxScrollHelper: this class implements the scrolling logic which is used by
// wxScrolledWindow and wxScrolledControl. It is a mix-in: just derive from it
// to implement scrolling in your class.
// ----------------------------------------------------------------------------
class WXDLLEXPORT wxScrollHelper
{
public:
// ctor and dtor
wxScrollHelper(wxWindow *winToScroll = (wxWindow *)NULL);
void SetWindow(wxWindow *winToScroll);
virtual ~wxScrollHelper();
// configure the scrolling
virtual void SetScrollbars(int pixelsPerUnitX, int pixelsPerUnitY,
int noUnitsX, int noUnitsY,
int xPos = 0, int yPos = 0,
bool noRefresh = FALSE );
// scroll to the given (in logical coords) position
virtual void Scroll(int x, int y);
// get/set the page size for this orientation (wxVERTICAL/wxHORIZONTAL)
int GetScrollPageSize(int orient) const;
void SetScrollPageSize(int orient, int pageSize);
// get the size of one logical unit in physical ones
virtual void GetScrollPixelsPerUnit(int *pixelsPerUnitX,
int *pixelsPerUnitY) const;
// Enable/disable Windows scrolling in either direction. If TRUE, wxWindows
// scrolls the canvas and only a bit of the canvas is invalidated; no
// Clear() is necessary. If FALSE, the whole canvas is invalidated and a
// Clear() is necessary. Disable for when the scroll increment is used to
// actually scroll a non-constant distance
virtual void EnableScrolling(bool x_scrolling, bool y_scrolling);
// Get the view start
virtual void GetViewStart(int *x, int *y) const;
// Actual size in pixels when scrolling is taken into account
virtual void GetVirtualSize(int *x, int *y) const;
// Set the scale factor, used in PrepareDC
void SetScale(double xs, double ys) { m_scaleX = xs; m_scaleY = ys; }
double GetScaleX() const { return m_scaleX; }
double GetScaleY() const { return m_scaleY; }
// translate between scrolled and unscrolled coordinates
virtual void CalcScrolledPosition(int x, int y, int *xx, int *yy) const;
virtual void CalcUnscrolledPosition(int x, int y, int *xx, int *yy) const;
// Adjust the scrollbars
virtual void AdjustScrollbars(void);
// Calculate scroll increment
virtual int CalcScrollInc(wxScrollWinEvent& event);
// Normally the wxScrolledWindow will scroll itself, but in some rare
// occasions you might want it to scroll another window (e.g. a child of it
// in order to scroll only a portion the area between the scrollbars
// (spreadsheet: only cell area will move).
virtual void SetTargetWindow( wxWindow *target );
virtual wxWindow *GetTargetWindow() const;
// Override this function to draw the graphic (or just process EVT_PAINT)
virtual void OnDraw(wxDC& WXUNUSED(dc)) { }
// change the DC origin according to the scroll position.
void DoPrepareDC(wxDC& dc);
// the methods to be called from the window event handlers
void HandleOnScroll(wxScrollWinEvent& event);
void HandleOnSize(wxSizeEvent& event);
void HandleOnPaint(wxPaintEvent& event);
void HandleOnChar(wxKeyEvent& event);
protected:
wxWindow *m_win,
*m_targetWindow;
int m_xScrollPixelsPerLine;
int m_yScrollPixelsPerLine;
int m_xScrollPosition;
int m_yScrollPosition;
int m_xScrollLines;
int m_yScrollLines;
int m_xScrollLinesPerPage;
int m_yScrollLinesPerPage;
bool m_xScrollingEnabled;
bool m_yScrollingEnabled;
double m_scaleX;
double m_scaleY;
};
#include "wx/generic/scrolwin.h"
#endif

View File

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

View File

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

View File

@@ -22,32 +22,10 @@ class WXDLLEXPORT wxRenderer;
// ----------------------------------------------------------------------------
// wxControlAction: the action is currently just a string which identifies it,
// later it might become an atom (i.e. an opaque handler to string). As one
// input event may result in several control actions (e.g. a macro expansion
// in the text control) we define an array of actions as well.
// later it might become an atom (i.e. an opaque handler to string).
// ----------------------------------------------------------------------------
typedef wxString wxControlAction;
class WXDLLEXPORT wxControlActions : public wxArrayString
{
public:
wxControlActions() { }
wxControlActions(const wxControlAction& action)
{ wxArrayString::Add(action); }
wxControlActions(const wxChar *action)
{ wxArrayString::Add(action); }
wxControlActions& Add(const wxControlActions& other)
{
size_t count = other.GetCount();
for ( size_t n = 0; n < count; n++ )
{
wxArrayString::Add(other[n]);
}
return *this;
}
};
// the list of actions which apply to all controls (other actions are defined
// in the controls headers)
@@ -87,7 +65,7 @@ public:
virtual void SetLabel(const wxString &label);
virtual wxString GetLabel() const;
// implementation only from now on
// wxUniversal-specific methods
// return the index of the accel char in the label or -1 if none
int GetAccelIndex() const { return m_indexAccel; }
@@ -98,13 +76,24 @@ public:
return m_indexAccel == -1 ? _T('\0') : m_label[m_indexAccel];
}
// perform the action which resulted from the translation of the event
// (the exact event type depends on the action), return TRUE if the
// control must be updated
// perform a control-dependent action: an action may have an optional
// numeric and another (also optional) string argument whose interpretation
// depends on the action
//
// NB: we might use ellipsis in PerformAction() declaration but this
// wouldn't be more efficient than always passing 2 unused parameters
// but would be more difficult. Another solution would be to have
// several overloaded versions but this will expose the problem of
// virtual function hiding we don't have here.
virtual bool PerformAction(const wxControlAction& action,
const wxEvent& event);
long numArg = 0l,
const wxString& strArg = wxEmptyString);
protected:
// by default static controls don't have the border and all the others do
// have it
virtual wxBorder GetDefaultBorder() const;
// create the event translator object for this control: the base class
// action creates the default one which doesn't do anything
virtual wxInputHandler *CreateInputHandler() const;
@@ -119,9 +108,6 @@ private:
// common part of all ctors
void Init();
// common part of OnMouse/OnKeyDown/Up
void PerformActions(const wxControlActions& actions, const wxEvent& event);
// input processor
wxInputHandler *m_handler;

View File

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

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -36,8 +36,14 @@ enum
wxCONTROL_PRESSED = 0x00000004, // (button) is pressed
wxCONTROL_ISDEFAULT = 0x00000008, // only applies to the buttons
wxCONTROL_CURRENT = 0x00000010, // mouse is currently over the control
wxCONTROL_SELECTED = 0x00000020, // selected item in e.g. listbox
wxCONTROL_CHECKED = 0x00000040, // (check/radio button) is checked
wxCONTROL_FLAGS_MASK = 0x0000001f
wxCONTROL_FLAGS_MASK = 0x0000007f,
// this is a pseudo flag not used directly by wxRenderer but rather by some
// controls internally
wxCONTROL_DIRTY = 0x80000000
};
// ----------------------------------------------------------------------------
@@ -119,7 +125,7 @@ protected:
// returns the (low level) renderer to use for drawing the control by
// querying the current theme
wxRenderer *GetRenderer() const;
wxRenderer *GetRenderer() const { return m_renderer; }
// draw the control background, return TRUE if done
virtual bool DoDrawBackground(wxControlRenderer *renderer);
@@ -127,6 +133,12 @@ protected:
// draw the controls contents
virtual void DoDraw(wxControlRenderer *renderer);
// calculate the best size for the client area of the window: default
// implementation of DoGetBestSize() uses this method and adds the border
// width to the result
virtual wxSize DoGetBestClientSize() const;
virtual wxSize DoGetBestSize() const;
// adjust the size of the window to take into account its borders
wxSize AdjustSize(const wxSize& size) const;
@@ -139,6 +151,9 @@ protected:
// put the scrollbars along the edges of the window
void PositionScrollbars();
// the renderer we use
wxRenderer *m_renderer;
// background bitmap info
wxBitmap m_bitmapBg;
int m_alignBgBitmap;

View File

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

View File

@@ -696,7 +696,8 @@ bool wxEvtHandler::ProcessEvent(wxEvent& event)
{
#if wxUSE_GUI
// check that our flag corresponds to reality
wxASSERT( m_isWindow == IsKindOf(CLASSINFO(wxWindow)) );
wxASSERT_MSG( m_isWindow == IsKindOf(CLASSINFO(wxWindowBase)),
_T("this should [not] be a window but it is [not]") );
#endif // wxUSE_GUI
// An event handler can be enabled or disabled

View File

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

File diff suppressed because it is too large Load Diff

View File

@@ -6,7 +6,7 @@
// Created: 14.08.00
// RCS-ID: $Id$
// Copyright: (c) 2000 Vadim Zeitlin
// Licence: wxWindows license
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
// ============================================================================
@@ -97,7 +97,7 @@ wxButton::~wxButton()
// size management
// ----------------------------------------------------------------------------
wxSize wxButton::DoGetBestSize() const
wxSize wxButton::DoGetBestClientSize() const
{
wxClientDC dc(wxConstCast(this, wxButton));
wxCoord width, height;
@@ -113,7 +113,7 @@ wxSize wxButton::DoGetBestSize() const
width += m_bitmap.GetWidth() + 2*m_marginBmpX;
}
return AdjustSize(wxSize(width, height));
return wxSize(width, height);
}
// ----------------------------------------------------------------------------
@@ -131,13 +131,23 @@ void wxButton::DoDraw(wxControlRenderer *renderer)
// ----------------------------------------------------------------------------
void wxButton::Press()
{
if ( !m_isPressed )
{
m_isPressed = TRUE;
Refresh();
}
}
void wxButton::Release()
{
if ( m_isPressed )
{
m_isPressed = FALSE;
Refresh();
}
}
void wxButton::Toggle()
@@ -162,10 +172,9 @@ void wxButton::Click()
}
bool wxButton::PerformAction(const wxControlAction& action,
const wxEvent& event)
long numArg,
const wxString& strArg)
{
bool wasPressed = IsPressed();
if ( action == wxACTION_BUTTON_TOGGLE )
Toggle();
else if ( action == wxACTION_BUTTON_CLICK )
@@ -175,9 +184,9 @@ bool wxButton::PerformAction(const wxControlAction& action,
else if ( action == wxACTION_BUTTON_RELEASE )
Release();
else
return wxControl::PerformAction(action, event);
return wxControl::PerformAction(action, numArg, strArg);
return wasPressed != IsPressed();
return TRUE;
}
// ----------------------------------------------------------------------------
@@ -202,5 +211,121 @@ void wxButton::SetDefault()
m_isDefault = TRUE;
}
// ============================================================================
// wxStdButtonInputHandler
// ============================================================================
wxStdButtonInputHandler::wxStdButtonInputHandler(wxInputHandler *handler)
: wxStdInputHandler(handler)
{
m_winCapture = NULL;
}
bool wxStdButtonInputHandler::HandleKey(wxControl *control,
const wxKeyEvent& event,
bool pressed)
{
int keycode = event.GetKeyCode();
if ( keycode == WXK_SPACE || keycode == WXK_RETURN )
{
control->PerformAction(wxACTION_BUTTON_TOGGLE);
return TRUE;
}
return wxStdInputHandler::HandleKey(control, event, pressed);
}
bool wxStdButtonInputHandler::HandleMouse(wxControl *control,
const wxMouseEvent& event)
{
// the button has 2 states: pressed and normal with the following
// transitions between them:
//
// normal -> left down -> capture mouse and go to pressed state
// pressed -> left up inside -> generate click -> go to normal
// outside ------------------>
//
// the other mouse buttons are ignored
if ( event.Button(1) )
{
if ( event.ButtonDown(1) )
{
m_winCapture = control;
m_winCapture->CaptureMouse();
m_winHasMouse = TRUE;
control->PerformAction(wxACTION_BUTTON_PRESS);
return TRUE;
}
else // up
{
if ( m_winCapture )
{
m_winCapture->ReleaseMouse();
m_winCapture = NULL;
}
if ( m_winHasMouse )
{
// this will generate a click event
control->PerformAction(wxACTION_BUTTON_TOGGLE);
return TRUE;
}
//else: the mouse was released outside the window, this doesn't
// count as a click
}
}
return wxStdInputHandler::HandleMouse(control, event);
}
bool wxStdButtonInputHandler::HandleMouseMove(wxControl *control,
const wxMouseEvent& event)
{
// we only have to do something when the mouse leaves/enters the pressed
// button and don't care about the other ones
if ( event.GetEventObject() == m_winCapture )
{
// leaving the button should remove its pressed state
if ( event.Leaving() )
{
// remember that the mouse is now outside
m_winHasMouse = FALSE;
// we do have a pressed button, so release it
control->PerformAction(wxACTION_BUTTON_RELEASE);
return TRUE;
}
// and entering it back should make it pressed again if it had been
// pressed
else if ( event.Entering() )
{
// the mouse is (back) inside the button
m_winHasMouse = TRUE;
// we did have a pressed button which we released when leaving the
// window, press it again
control->PerformAction(wxACTION_BUTTON_PRESS);
return TRUE;
}
}
return wxStdInputHandler::HandleMouseMove(control, event);
}
bool wxStdButtonInputHandler::HandleFocus(wxControl *control,
const wxFocusEvent& event)
{
// buttons change appearance when they get/lose focus
control->Refresh();
return TRUE;
}
#endif // wxUSE_BUTTON

View File

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

View File

@@ -29,77 +29,25 @@
#endif
#ifndef WX_PRECOMP
#include "wx/timer.h"
#include "wx/button.h"
#include "wx/scrolbar.h"
#include "wx/univ/renderer.h"
#endif // WX_PRECOMP
#include "wx/univ/inphand.h"
// ----------------------------------------------------------------------------
// wxScrollBarTimer: this class is used to repeatedly scroll the scrollbar
// when the mouse is help pressed on the arrow or on the bar. It generates the
// given scroll action command periodically.
// ----------------------------------------------------------------------------
class wxScrollBarTimer : public wxTimer
{
public:
wxScrollBarTimer(wxStdScrollBarInputHandler *handler,
const wxControlAction& action,
const wxMouseEvent& event,
wxScrollBar *control);
virtual void Notify();
private:
wxStdScrollBarInputHandler *m_handler;
wxControlAction m_action;
wxMouseEvent m_event;
wxScrollBar *m_control;
};
// ============================================================================
// implementation
// ============================================================================
// ----------------------------------------------------------------------------
// wxScrollBarTimer
// ----------------------------------------------------------------------------
wxScrollBarTimer::wxScrollBarTimer(wxStdScrollBarInputHandler *handler,
const wxControlAction& action,
const wxMouseEvent& event,
wxScrollBar *control)
: m_event(event)
{
m_handler = handler;
m_action = action;
m_control = control;
}
void wxScrollBarTimer::Notify()
{
if ( m_handler->OnScrollTimer(m_control, m_action, m_event) )
{
// keep scrolling
m_control->Refresh();
}
}
// ----------------------------------------------------------------------------
// wxInputHandler
// ----------------------------------------------------------------------------
bool wxInputHandler::OnMouseMove(wxControl * WXUNUSED(control),
bool wxInputHandler::HandleMouseMove(wxControl * WXUNUSED(control),
const wxMouseEvent& WXUNUSED(event))
{
return FALSE;
}
bool wxInputHandler::OnFocus(wxControl *control, const wxFocusEvent& event)
bool wxInputHandler::HandleFocus(wxControl *control, const wxFocusEvent& event)
{
return FALSE;
}
@@ -108,396 +56,3 @@ wxInputHandler::~wxInputHandler()
{
}
// ----------------------------------------------------------------------------
// wxStdButtonInputHandler
// ----------------------------------------------------------------------------
wxStdButtonInputHandler::wxStdButtonInputHandler(wxInputHandler *handler)
: wxStdInputHandler(handler)
{
m_winCapture = NULL;
}
wxControlActions wxStdButtonInputHandler::Map(wxControl *control,
const wxKeyEvent& event,
bool pressed)
{
int keycode = event.GetKeyCode();
if ( keycode == WXK_SPACE || keycode == WXK_RETURN )
{
return wxACTION_BUTTON_TOGGLE;
}
return wxStdInputHandler::Map(control, event, pressed);
}
wxControlActions wxStdButtonInputHandler::Map(wxControl *control,
const wxMouseEvent& event)
{
// the button has 2 states: pressed and normal with the following
// transitions between them:
//
// normal -> left down -> capture mouse and go to pressed state
// pressed -> left up inside -> generate click -> go to normal
// outside ------------------>
//
// the other mouse buttons are ignored
if ( event.Button(1) )
{
if ( event.ButtonDown(1) )
{
m_winCapture = control;
m_winCapture->CaptureMouse();
m_winHasMouse = TRUE;
return wxACTION_BUTTON_PRESS;
}
else // up
{
if ( m_winCapture )
{
m_winCapture->ReleaseMouse();
m_winCapture = NULL;
}
if ( m_winHasMouse )
{
// this will generate a click event
return wxACTION_BUTTON_TOGGLE;
}
//else: the mouse was released outside the window, this doesn't
// count as a click
}
}
return wxStdInputHandler::Map(control, event);
}
bool wxStdButtonInputHandler::OnMouseMove(wxControl *control,
const wxMouseEvent& event)
{
// we only have to do soemthing when the mouse leaves/enters the pressed
// button and don't care about the other ones
if ( event.GetEventObject() == m_winCapture )
{
// leaving the button should remove its pressed state
if ( event.Leaving() )
{
// remember that the mouse is now outside
m_winHasMouse = FALSE;
// we do have a pressed button, so release it
if ( control->PerformAction(wxACTION_BUTTON_RELEASE, event) )
{
// the button state changed, refresh needed
return TRUE;
}
}
// and entering it back should make it pressed again if it had been
// pressed
else if ( event.Entering() )
{
// the mouse is (back) inside the button
m_winHasMouse = TRUE;
// we did have a pressed button which we released when leaving the
// window, press it again
if ( control->PerformAction(wxACTION_BUTTON_PRESS, event) )
{
return TRUE;
}
}
}
return wxStdInputHandler::OnMouseMove(control, event);
}
bool wxStdButtonInputHandler::OnFocus(wxControl *control,
const wxFocusEvent& event)
{
// buttons chaneg appearance when they get/lose focus
return TRUE;
}
// ----------------------------------------------------------------------------
// wxStdScrollBarInputHandler
// ----------------------------------------------------------------------------
wxStdScrollBarInputHandler::wxStdScrollBarInputHandler(wxRenderer *renderer,
wxInputHandler *handler)
: wxStdInputHandler(handler)
{
m_renderer = renderer;
m_winCapture = NULL;
m_htLast = wxHT_NOWHERE;
m_timerScroll = NULL;
}
wxStdScrollBarInputHandler::~wxStdScrollBarInputHandler()
{
// normally, it's NULL by now but just in case the user somehow managed to
// keep the mouse captured until now...
delete m_timerScroll;
}
void wxStdScrollBarInputHandler::SetElementState(wxScrollBar *control,
int flag,
bool doIt)
{
if ( m_htLast > wxHT_SCROLLBAR_FIRST && m_htLast < wxHT_SCROLLBAR_LAST )
{
wxScrollBar::Element
elem = (wxScrollBar::Element)(m_htLast - wxHT_SCROLLBAR_FIRST - 1);
int flags = control->GetState(elem);
if ( doIt )
flags |= flag;
else
flags &= ~flag;
control->SetState(elem, flags);
}
}
bool wxStdScrollBarInputHandler::OnScrollTimer(wxScrollBar *scrollbar,
const wxControlAction& action,
const wxMouseEvent& event)
{
if ( scrollbar->PerformAction(action, event) )
return TRUE;
// we scrolled till the end
m_timerScroll->Stop();
return FALSE;
}
void wxStdScrollBarInputHandler::StopScrolling(wxScrollBar *control)
{
// return everything to the normal state
if ( m_winCapture )
{
m_winCapture->ReleaseMouse();
m_winCapture = NULL;
}
m_btnCapture = -1;
if ( m_timerScroll )
{
delete m_timerScroll;
m_timerScroll = NULL;
}
// unpress the arrow and highlight the current element
Press(control, FALSE);
}
wxControlActions wxStdScrollBarInputHandler::Map(wxControl *control,
const wxKeyEvent& event,
bool pressed)
{
// we only react to the key presses here
if ( pressed )
{
switch ( event.GetKeyCode() )
{
case WXK_DOWN:
case WXK_RIGHT: return wxACTION_SCROLL_LINE_DOWN;
case WXK_UP:
case WXK_LEFT: return wxACTION_SCROLL_LINE_UP;
case WXK_HOME: return wxACTION_SCROLL_START;
case WXK_END: return wxACTION_SCROLL_END;
case WXK_PRIOR: return wxACTION_SCROLL_PAGE_UP;
case WXK_NEXT: return wxACTION_SCROLL_PAGE_DOWN;
}
}
return wxStdInputHandler::Map(control, event, pressed);
}
wxControlActions wxStdScrollBarInputHandler::Map(wxControl *control,
const wxMouseEvent& event)
{
// is this a click event from an acceptable button?
int btn = -1;
if ( event.IsButton() )
{
for ( int i = 1; i <= 3; i++ )
{
if ( event.Button(i) )
{
btn = i;
break;
}
}
wxASSERT_MSG( btn != -1, _T("unknown mouse button") );
}
if ( (btn != -1) && IsAllowedButton(btn) )
{
// determine which part of the window mouse is in
wxScrollBar *scrollbar = wxStaticCast(control, wxScrollBar);
wxHitTest ht = m_renderer->HitTestScrollbar
(
scrollbar,
event.GetPosition()
);
// when the mouse is pressed on any scrollbar element, we capture it
// and hold capture until the same mouse button is released
if ( event.ButtonDown() || event.ButtonDClick() )
{
if ( !m_winCapture )
{
m_btnCapture = btn;
m_winCapture = control;
m_winCapture->CaptureMouse();
// generate the command
bool hasAction = TRUE;
wxControlAction action;
switch ( ht )
{
case wxHT_SCROLLBAR_ARROW_LINE_1:
action = wxACTION_SCROLL_LINE_UP;
break;
case wxHT_SCROLLBAR_ARROW_LINE_2:
action = wxACTION_SCROLL_LINE_DOWN;
break;
case wxHT_SCROLLBAR_BAR_1:
action = wxACTION_SCROLL_PAGE_UP;
m_ptStartScrolling = event.GetPosition();
break;
case wxHT_SCROLLBAR_BAR_2:
action = wxACTION_SCROLL_PAGE_DOWN;
m_ptStartScrolling = event.GetPosition();
break;
case wxHT_SCROLLBAR_THUMB:
control->PerformAction(wxACTION_SCROLL_THUMB_DRAG, event);
// fall through: there is no immediate action
default:
hasAction = FALSE;
}
// remove highlighting
Highlight(scrollbar, FALSE);
m_htLast = ht;
// and press the arrow or highlight thumb now instead
if ( m_htLast == wxHT_SCROLLBAR_THUMB )
Highlight(scrollbar, TRUE);
else
Press(scrollbar, TRUE);
// start dragging
if ( hasAction )
{
m_timerScroll = new wxScrollBarTimer(this,
action,
event,
scrollbar);
// start scrolling immediately
m_timerScroll->Notify();
// and continue it later
m_timerScroll->Start(50); // FIXME hardcoded delay
}
else // no (immediate) action
{
// highlighting still might have changed
control->Refresh();
}
}
//else: mouse already captured, nothing to do
}
// release mouse if the *same* button went up
else if ( btn == m_btnCapture )
{
if ( m_winCapture )
{
StopScrolling(scrollbar);
// if we were dragging the thumb, send the last event
if ( m_htLast == wxHT_SCROLLBAR_THUMB )
{
scrollbar->PerformAction(wxACTION_SCROLL_THUMB_RELEASE, event);
}
m_htLast = ht;
Highlight(scrollbar, TRUE);
control->Refresh();
}
else
{
// this is not supposed to happen as the button can't go up
// without going down previously and then we'd have
// m_winCapture by now
wxFAIL_MSG( _T("logic error in mouse capturing code") );
}
}
}
return wxStdInputHandler::Map(control, event);
}
bool wxStdScrollBarInputHandler::OnMouseMove(wxControl *control,
const wxMouseEvent& event)
{
if ( m_winCapture )
{
if ( (m_htLast == wxHT_SCROLLBAR_THUMB) && event.Moving() )
{
// drag the thumb so that it follows the mouse
if ( control->PerformAction(wxACTION_SCROLL_THUMB_MOVE, event) )
return TRUE;
}
// no other changes are possible while the mouse is captured
return FALSE;
}
wxScrollBar *scrollbar = wxStaticCast(control, wxScrollBar);
if ( event.Moving() )
{
wxHitTest ht = m_renderer->HitTestScrollbar
(
scrollbar,
event.GetPosition()
);
if ( ht == m_htLast )
{
// nothing changed
return FALSE;
}
#ifdef DEBUG_MOUSE
wxLogDebug("Scrollbar::OnMouseMove: ht = %d", ht);
#endif // DEBUG_MOUSE
Highlight(scrollbar, FALSE);
m_htLast = ht;
Highlight(scrollbar, TRUE);
}
else if ( event.Leaving() )
{
Highlight(scrollbar, FALSE);
m_htLast = wxHT_NOWHERE;
}
else
{
// don't refresh
return FALSE;
}
// highlighting changed
return TRUE;
}

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
// ----------------------------------------------------------------------------
/* static */
wxRect wxRenderer::StandardGetScrollbarRect(const wxScrollBar *scrollbar,
wxScrollBar::Element elem,
int thumbPos,
const wxSize& sizeArrow)
{
if ( thumbPos == -1 )
{
thumbPos = scrollbar->GetThumbPosition();
}
wxSize sizeTotal = scrollbar->GetClientSize();
wxCoord *start, *width, length, arrow;
wxRect rect;
if ( scrollbar->IsVertical() )
{
rect.x = 0;
rect.width = sizeTotal.x;
length = sizeTotal.y;
start = &rect.y;
width = &rect.height;
arrow = sizeArrow.y;
}
else // horizontal
{
rect.y = 0;
rect.height = sizeTotal.y;
length = sizeTotal.x;
start = &rect.x;
width = &rect.width;
arrow = sizeArrow.x;
}
switch ( elem )
{
case wxScrollBar::Element_Arrow_Line_1:
*start = 0;
*width = arrow;
break;
case wxScrollBar::Element_Arrow_Line_2:
*start = length - arrow;
*width = arrow;
break;
case wxScrollBar::Element_Arrow_Page_1:
case wxScrollBar::Element_Arrow_Page_2:
// we don't have them at all
break;
case wxScrollBar::Element_Thumb:
case wxScrollBar::Element_Bar_1:
case wxScrollBar::Element_Bar_2:
// we need to calculate the thumb position - do it
{
length -= 2*arrow;
wxCoord thumbStart, thumbEnd;
int range = scrollbar->GetRange();
if ( !range )
{
thumbStart =
thumbEnd = 0;
}
else
{
int thumbSize = scrollbar->GetThumbSize();
thumbStart = (length*thumbPos) / range;
thumbEnd = (length*(thumbPos + thumbSize)) / range;
}
if ( elem == wxScrollBar::Element_Thumb )
{
*start = thumbStart;
*width = thumbEnd - thumbStart;
}
else if ( elem == wxScrollBar::Element_Bar_1 )
{
*start = 0;
*width = thumbStart;
}
else // elem == wxScrollBar::Element_Bar_2
{
*start = thumbEnd;
*width = length - thumbEnd;
}
// everything is relative to the start of the shaft so far
*start += arrow;
}
break;
case wxScrollBar::Element_Max:
default:
wxFAIL_MSG( _T("unknown scrollbar element") );
}
return rect;
}
/* static */
wxCoord wxRenderer::StandardScrollBarSize(const wxScrollBar *scrollbar,
const wxSize& sizeArrowSB)
@@ -91,6 +191,7 @@ wxCoord wxRenderer::StandardScrollBarSize(const wxScrollBar *scrollbar,
/* static */
wxCoord wxRenderer::StandardScrollbarToPixel(const wxScrollBar *scrollbar,
int thumbPos,
const wxSize& sizeArrow)
{
int range = scrollbar->GetRange();
@@ -100,8 +201,13 @@ wxCoord wxRenderer::StandardScrollbarToPixel(const wxScrollBar *scrollbar,
return 0;
}
return ( scrollbar->GetThumbPosition() *
StandardScrollBarSize(scrollbar, sizeArrow) ) / range
if ( thumbPos == -1 )
{
// by default use the current thumb position
thumbPos = scrollbar->GetThumbPosition();
}
return ( thumbPos*StandardScrollBarSize(scrollbar, sizeArrow) ) / range
+ (scrollbar->IsVertical() ? sizeArrow.y : sizeArrow.x);
}
@@ -219,8 +325,13 @@ void wxControlRenderer::DrawBorder()
m_renderer->DrawBorder(m_dc, m_window->GetBorder(),
m_rect, flags, &m_rect);
// fill the inside (TODO: query the theme for bg bitmap)
m_renderer->DrawBackground(m_dc, m_rect, flags);
// fill the inside unless we have the background bitmap as we don't want to
// overwrite it
if ( !m_window->GetBackgroundBitmap().Ok() )
{
m_renderer->DrawBackground(m_dc, m_window->GetBackgroundColour(),
m_rect, flags);
}
}
void wxControlRenderer::DrawLabel(const wxBitmap& bitmap,
@@ -272,7 +383,8 @@ void wxControlRenderer::DrawButtonBorder()
m_renderer->DrawButtonBorder(m_dc, m_rect, flags, &m_rect);
m_renderer->DrawBackground(m_dc, m_rect, flags);
m_renderer->DrawBackground(m_dc, m_window->GetBackgroundColour(),
m_rect, flags);
}
void wxControlRenderer::DrawBitmap(const wxBitmap& bitmap)
@@ -357,36 +469,85 @@ void wxControlRenderer::DrawBitmap(const wxBitmap& bitmap,
m_dc.DrawBitmap(bmp, x, y, TRUE /* use mask */);
}
void wxControlRenderer::DrawScrollbar(const wxScrollBar *scrollbar)
void wxControlRenderer::DrawScrollbar(const wxScrollBar *scrollbar,
int thumbPosOld)
{
int thumbStart, thumbEnd;
int range = scrollbar->GetRange();
if ( range )
{
int thumbPos = scrollbar->GetThumbPosition(),
thumbSize = scrollbar->GetThumbSize();
// we will only redraw the parts which must be redrawn and not everything
wxRegion rgnUpdate = scrollbar->GetUpdateRegion();
thumbStart = (100*thumbPos) / range;
thumbEnd = (100*(thumbPos + thumbSize)) / range;
}
else // no range
// arrows
static const wxDirection arrowDirs[2][2] =
{
thumbStart =
thumbEnd = 0;
{ wxLEFT, wxRIGHT },
{ wxUP, wxDOWN }
};
for ( int nArrow = 0; nArrow < 2; nArrow++ )
{
wxScrollBar::Element elem =
(wxScrollBar::Element)(wxScrollBar::Element_Arrow_Line_1 + nArrow);
wxRect rectArrow = m_renderer->GetScrollbarRect(scrollbar, elem);
if ( rgnUpdate.Contains(rectArrow) )
{
m_renderer->DrawArrow(m_dc,
arrowDirs[scrollbar->IsVertical()][nArrow],
rectArrow,
scrollbar->GetState(elem));
}
}
int flags[wxScrollBar::Element_Max];
for ( size_t n = 0; n < WXSIZEOF(flags); n++ )
// TODO: support for page arrows
// the shaft
for ( int nBar = 0; nBar < 2; nBar++ )
{
flags[n] = scrollbar->GetState((wxScrollBar::Element)n);
wxScrollBar::Element elem =
(wxScrollBar::Element)(wxScrollBar::Element_Bar_1 + nBar);
wxRect rectBar = m_renderer->GetScrollbarRect(scrollbar, elem);
if ( rgnUpdate.Contains(rectBar) )
{
#if 0
// we try to avoid redrawing the entire shaft (which might be quite
// long) if possible by only redrawing the area between the old and
// current positions of the thumb
if ( thumbPosOld != -1 )
{
wxRect rectBarOld = m_renderer->GetScrollbarRect(scrollbar,
elem,
thumbPosOld);
if ( scrollbar->IsVertical() )
{
if ( nBar )
rectBar.SetBottom(rectBar.GetTop());
else
rectBar.SetTop(rectBarOld.GetBottom());
}
else // horizontal
{
if ( nBar )
rectBar.SetRight(rectBar.GetLeft());
else
rectBar.SetLeft(rectBarOld.GetRight());
}
}
#endif // 0
m_renderer->DrawScrollbarShaft(m_dc, rectBar,
scrollbar->GetState(elem));
}
}
m_renderer->DrawScrollbar(m_dc,
m_window->GetWindowStyle() & wxVERTICAL
? wxVERTICAL
: wxHORIZONTAL,
thumbStart, thumbEnd, m_rect,
flags);
// and the thumb
wxScrollBar::Element elem = wxScrollBar::Element_Thumb;
wxRect rectThumb = m_renderer->GetScrollbarRect(scrollbar, elem);
if ( rgnUpdate.Contains(rectThumb) )
{
m_renderer->DrawScrollbarThumb(m_dc, rectThumb,
scrollbar->GetState(elem));
}
}
void wxControlRenderer::DrawLine(wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2)
@@ -399,3 +560,24 @@ void wxControlRenderer::DrawLine(wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2)
else // horizontal
m_renderer->DrawHorizontalLine(m_dc, y1, x1, x2);
}
void wxControlRenderer::DrawItems(const wxListBox *lbox,
size_t itemFirst, size_t itemLast)
{
wxCoord lineHeight = lbox->GetLineHeight();
wxRect rect = m_rect;
rect.y += itemFirst*lineHeight;
rect.height = lineHeight;
for ( size_t n = itemFirst; n < itemLast; n++ )
{
int flags = 0;
if ( (int)n == lbox->GetCurrentItem() )
flags |= wxCONTROL_FOCUSED;
if ( lbox->IsSelected(n) )
flags |= wxCONTROL_SELECTED;
m_renderer->DrawItem(m_dc, lbox->GetString(n), rect, flags);
rect.y += lineHeight;
}
}

View File

@@ -30,6 +30,8 @@
#if wxUSE_SCROLLBAR
#ifndef WX_PRECOMP
#include "wx/timer.h"
#include "wx/dcclient.h"
#include "wx/scrolbar.h"
#include "wx/validate.h"
@@ -39,12 +41,37 @@
#include "wx/univ/inphand.h"
#include "wx/univ/theme.h"
// ----------------------------------------------------------------------------
// wxScrollBarTimer: this class is used to repeatedly scroll the scrollbar
// when the mouse is help pressed on the arrow or on the bar. It generates the
// given scroll action command periodically.
// ----------------------------------------------------------------------------
class wxScrollBarTimer : public wxTimer
{
public:
wxScrollBarTimer(wxStdScrollBarInputHandler *handler,
const wxControlAction& action,
wxScrollBar *control);
virtual void Notify();
private:
wxStdScrollBarInputHandler *m_handler;
wxControlAction m_action;
wxScrollBar *m_control;
};
// ============================================================================
// implementation
// ============================================================================
IMPLEMENT_DYNAMIC_CLASS(wxScrollBar, wxControl)
BEGIN_EVENT_TABLE(wxScrollBar, wxScrollBarBase)
EVT_IDLE(wxScrollBar::OnIdle)
END_EVENT_TABLE()
// ----------------------------------------------------------------------------
// creation
// ----------------------------------------------------------------------------
@@ -56,10 +83,14 @@ void wxScrollBar::Init()
m_thumbPos =
m_pageSize = 0;
m_thumbPosOld = -1;
for ( size_t n = 0; n < WXSIZEOF(m_elementsState); n++ )
{
m_elementsState[n] = 0;
}
m_dirty = FALSE;
}
bool wxScrollBar::Create(wxWindow *parent,
@@ -102,7 +133,20 @@ void wxScrollBar::DoSetThumb(int pos)
pos = m_range - m_thumbSize;
}
if ( m_thumbPosOld == -1 )
{
// remember the old thumb position
m_thumbPosOld = m_thumbPos;
}
m_thumbPos = pos;
// we have to refresh the part of the bar which was under the thumb and the
// thumb itself
m_elementsState[Element_Thumb] |= wxCONTROL_DIRTY;
m_elementsState[m_thumbPos > m_thumbPosOld
? Element_Bar_1 : Element_Bar_2] |= wxCONTROL_DIRTY;
m_dirty = TRUE;
}
int wxScrollBar::GetThumbPosition() const
@@ -130,8 +174,6 @@ void wxScrollBar::SetThumbPosition(int pos)
wxCHECK_RET( pos >= 0 && pos <= m_range, _T("thumb position out of range") );
DoSetThumb(pos);
Refresh();
}
void wxScrollBar::SetScrollbar(int position, int thumbSize,
@@ -155,34 +197,67 @@ void wxScrollBar::SetScrollbar(int position, int thumbSize,
// size management
// ----------------------------------------------------------------------------
wxSize wxScrollBar::DoGetBestSize() const
wxSize wxScrollBar::DoGetBestClientSize() const
{
// completely arbitrary
return AdjustSize(wxSize(140, 140));
return wxSize(140, 140);
}
// ----------------------------------------------------------------------------
// drawing
// ----------------------------------------------------------------------------
void wxScrollBar::OnIdle(wxIdleEvent& event)
{
if ( m_dirty )
{
for ( size_t n = 0; n < WXSIZEOF(m_elementsState); n++ )
{
if ( m_elementsState[n] & wxCONTROL_DIRTY )
{
wxRect rect = GetRenderer()->GetScrollbarRect(this, (Element)n);
if ( rect.width && rect.height )
{
// don't refresh the background when refreshing the shaft
Refresh(TRUE, //(n != Element_Bar_1) && (n != Element_Bar_2)
&rect);
}
m_elementsState[n] &= ~wxCONTROL_DIRTY;
}
}
m_dirty = FALSE;
}
}
void wxScrollBar::DoDraw(wxControlRenderer *renderer)
{
renderer->DrawScrollbar(this);
renderer->DrawScrollbar(this, m_thumbPosOld);
// clear all dirty flags
m_dirty = FALSE;
m_thumbPosOld = -1;
}
// ----------------------------------------------------------------------------
// input processing
// ----------------------------------------------------------------------------
wxCoord wxScrollBar::GetMouseCoord(const wxEvent& eventOrig) const
void wxScrollBar::SetState(Element which, int flags)
{
const wxMouseEvent& event = (const wxMouseEvent&)eventOrig;
wxPoint pt = event.GetPosition();
return GetWindowStyle() & wxVERTICAL ? pt.y : pt.x;
if ( (m_elementsState[which] & ~wxCONTROL_DIRTY) != flags )
{
m_elementsState[which] = flags | wxCONTROL_DIRTY;
m_dirty = TRUE;
}
}
bool wxScrollBar::PerformAction(const wxControlAction& action,
const wxEvent& event)
long numArg,
const wxString& strArg)
{
int thumbOld = m_thumbPos;
@@ -193,10 +268,7 @@ bool wxScrollBar::PerformAction(const wxControlAction& action,
// test for thumb move first as these events happen in quick succession
if ( action == wxACTION_SCROLL_THUMB_MOVE )
{
// make the thumb follow the mouse by keeping the same offset between
// the mouse position and the top/left of the thumb
int thumbPos = GetMouseCoord(event) - m_ofsMouse;
DoSetThumb(GetRenderer()->PixelToScrollbar(this, thumbPos));
DoSetThumb(numArg);
scrollType = wxEVT_SCROLLWIN_THUMBTRACK;
}
@@ -232,8 +304,10 @@ bool wxScrollBar::PerformAction(const wxControlAction& action,
}
else if ( action == wxACTION_SCROLL_THUMB_DRAG )
{
m_ofsMouse = GetMouseCoord(event) -
GetRenderer()->ScrollbarToPixel(this);
// we won't use it but this line suppresses the compiler
// warning about "variable may be used without having been
// initialized"
scrollType = wxEVT_NULL;
}
else if ( action == wxACTION_SCROLL_THUMB_RELEASE )
{
@@ -242,7 +316,7 @@ bool wxScrollBar::PerformAction(const wxControlAction& action,
scrollType = wxEVT_SCROLLWIN_THUMBRELEASE;
}
else
return wxControl::PerformAction(action, event);
return wxControl::PerformAction(action, numArg, strArg);
// has scrollbar position changed?
bool changed = m_thumbPos != thumbOld;
@@ -254,8 +328,7 @@ bool wxScrollBar::PerformAction(const wxControlAction& action,
GetParent()->GetEventHandler()->ProcessEvent(event);
}
// refresh if something changed
return changed;
return TRUE;
}
void wxScrollBar::ScrollToStart()
@@ -278,5 +351,333 @@ void wxScrollBar::ScrollPages(int nPages)
DoSetThumb(m_thumbPos + nPages*m_pageSize);
}
// ============================================================================
// scroll bar input handler
// ============================================================================
// ----------------------------------------------------------------------------
// wxScrollBarTimer
// ----------------------------------------------------------------------------
wxScrollBarTimer::wxScrollBarTimer(wxStdScrollBarInputHandler *handler,
const wxControlAction& action,
wxScrollBar *control)
{
m_handler = handler;
m_action = action;
m_control = control;
}
void wxScrollBarTimer::Notify()
{
m_handler->OnScrollTimer(m_control, m_action);
}
// ----------------------------------------------------------------------------
// wxStdScrollBarInputHandler
// ----------------------------------------------------------------------------
wxStdScrollBarInputHandler::wxStdScrollBarInputHandler(wxRenderer *renderer,
wxInputHandler *handler)
: wxStdInputHandler(handler)
{
m_renderer = renderer;
m_winCapture = NULL;
m_htLast = wxHT_NOWHERE;
m_timerScroll = NULL;
}
wxStdScrollBarInputHandler::~wxStdScrollBarInputHandler()
{
// normally, it's NULL by now but just in case the user somehow managed to
// keep the mouse captured until now...
delete m_timerScroll;
}
void wxStdScrollBarInputHandler::SetElementState(wxScrollBar *control,
int flag,
bool doIt)
{
if ( m_htLast > wxHT_SCROLLBAR_FIRST && m_htLast < wxHT_SCROLLBAR_LAST )
{
wxScrollBar::Element
elem = (wxScrollBar::Element)(m_htLast - wxHT_SCROLLBAR_FIRST - 1);
int flags = control->GetState(elem);
if ( doIt )
flags |= flag;
else
flags &= ~flag;
control->SetState(elem, flags);
}
}
bool wxStdScrollBarInputHandler::OnScrollTimer(wxScrollBar *scrollbar,
const wxControlAction& action)
{
int oldThumbPos = scrollbar->GetThumbPosition();
scrollbar->PerformAction(action);
if ( scrollbar->GetThumbPosition() != oldThumbPos )
return TRUE;
// we scrolled till the end
m_timerScroll->Stop();
return FALSE;
}
void wxStdScrollBarInputHandler::StopScrolling(wxScrollBar *control)
{
// return everything to the normal state
if ( m_winCapture )
{
m_winCapture->ReleaseMouse();
m_winCapture = NULL;
}
m_btnCapture = -1;
if ( m_timerScroll )
{
delete m_timerScroll;
m_timerScroll = NULL;
}
// unpress the arrow and highlight the current element
Press(control, FALSE);
}
wxCoord
wxStdScrollBarInputHandler::GetMouseCoord(const wxScrollBar *scrollbar,
const wxMouseEvent& event) const
{
wxPoint pt = event.GetPosition();
return scrollbar->GetWindowStyle() & wxVERTICAL ? pt.y : pt.x;
}
void wxStdScrollBarInputHandler::HandleThumbMove(wxScrollBar *scrollbar,
const wxMouseEvent& event)
{
int thumbPos = GetMouseCoord(scrollbar, event) - m_ofsMouse;
thumbPos = m_renderer->PixelToScrollbar(scrollbar, thumbPos);
scrollbar->PerformAction(wxACTION_SCROLL_THUMB_MOVE, thumbPos);
}
bool wxStdScrollBarInputHandler::HandleKey(wxControl *control,
const wxKeyEvent& event,
bool pressed)
{
// we only react to the key presses here
if ( pressed )
{
wxControlAction action;
switch ( event.GetKeyCode() )
{
case WXK_DOWN:
case WXK_RIGHT: action = wxACTION_SCROLL_LINE_DOWN; break;
case WXK_UP:
case WXK_LEFT: action = wxACTION_SCROLL_LINE_UP; break;
case WXK_HOME: action = wxACTION_SCROLL_START; break;
case WXK_END: action = wxACTION_SCROLL_END; break;
case WXK_PRIOR: action = wxACTION_SCROLL_PAGE_UP; break;
case WXK_NEXT: action = wxACTION_SCROLL_PAGE_DOWN; break;
}
if ( !!action )
{
control->PerformAction(action);
return TRUE;
}
}
return wxStdInputHandler::HandleKey(control, event, pressed);
}
bool wxStdScrollBarInputHandler::HandleMouse(wxControl *control,
const wxMouseEvent& event)
{
// is this a click event from an acceptable button?
int btn = -1;
if ( event.IsButton() )
{
for ( int i = 1; i <= 3; i++ )
{
if ( event.Button(i) )
{
btn = i;
break;
}
}
wxASSERT_MSG( btn != -1, _T("unknown mouse button") );
}
if ( (btn != -1) && IsAllowedButton(btn) )
{
// determine which part of the window mouse is in
wxScrollBar *scrollbar = wxStaticCast(control, wxScrollBar);
wxHitTest ht = m_renderer->HitTestScrollbar
(
scrollbar,
event.GetPosition()
);
// when the mouse is pressed on any scrollbar element, we capture it
// and hold capture until the same mouse button is released
if ( event.ButtonDown() || event.ButtonDClick() )
{
if ( !m_winCapture )
{
m_btnCapture = btn;
m_winCapture = control;
m_winCapture->CaptureMouse();
// generate the command
bool hasAction = TRUE;
wxControlAction action;
switch ( ht )
{
case wxHT_SCROLLBAR_ARROW_LINE_1:
action = wxACTION_SCROLL_LINE_UP;
break;
case wxHT_SCROLLBAR_ARROW_LINE_2:
action = wxACTION_SCROLL_LINE_DOWN;
break;
case wxHT_SCROLLBAR_BAR_1:
action = wxACTION_SCROLL_PAGE_UP;
m_ptStartScrolling = event.GetPosition();
break;
case wxHT_SCROLLBAR_BAR_2:
action = wxACTION_SCROLL_PAGE_DOWN;
m_ptStartScrolling = event.GetPosition();
break;
case wxHT_SCROLLBAR_THUMB:
control->PerformAction(wxACTION_SCROLL_THUMB_DRAG);
m_ofsMouse = GetMouseCoord(scrollbar, event) -
m_renderer->ScrollbarToPixel(scrollbar);
// fall through: there is no immediate action
default:
hasAction = FALSE;
}
// remove highlighting
Highlight(scrollbar, FALSE);
m_htLast = ht;
// and press the arrow or highlight thumb now instead
if ( m_htLast == wxHT_SCROLLBAR_THUMB )
Highlight(scrollbar, TRUE);
else
Press(scrollbar, TRUE);
// start dragging
if ( hasAction )
{
m_timerScroll = new wxScrollBarTimer(this,
action,
scrollbar);
// start scrolling immediately
m_timerScroll->Notify();
// and continue it later
m_timerScroll->Start(50); // FIXME hardcoded delay
}
//else: no (immediate) action
}
//else: mouse already captured, nothing to do
}
// release mouse if the *same* button went up
else if ( btn == m_btnCapture )
{
if ( m_winCapture )
{
StopScrolling(scrollbar);
// if we were dragging the thumb, send the last event
if ( m_htLast == wxHT_SCROLLBAR_THUMB )
{
scrollbar->PerformAction(wxACTION_SCROLL_THUMB_RELEASE);
}
m_htLast = ht;
Highlight(scrollbar, TRUE);
}
else
{
// this is not supposed to happen as the button can't go up
// without going down previously and then we'd have
// m_winCapture by now
wxFAIL_MSG( _T("logic error in mouse capturing code") );
}
}
}
return wxStdInputHandler::HandleMouse(control, event);
}
bool wxStdScrollBarInputHandler::HandleMouseMove(wxControl *control,
const wxMouseEvent& event)
{
wxScrollBar *scrollbar = wxStaticCast(control, wxScrollBar);
if ( m_winCapture )
{
if ( (m_htLast == wxHT_SCROLLBAR_THUMB) && event.Moving() )
{
// make the thumb follow the mouse by keeping the same offset
// between the mouse position and the top/left of the thumb
HandleThumbMove(scrollbar, event);
return TRUE;
}
// no other changes are possible while the mouse is captured
return FALSE;
}
if ( event.Moving() )
{
wxHitTest ht = m_renderer->HitTestScrollbar
(
scrollbar,
event.GetPosition()
);
if ( ht == m_htLast )
{
// nothing changed
return FALSE;
}
#ifdef DEBUG_MOUSE
wxLogDebug("Scrollbar::OnMouseMove: ht = %d", ht);
#endif // DEBUG_MOUSE
Highlight(scrollbar, FALSE);
m_htLast = ht;
Highlight(scrollbar, TRUE);
}
else if ( event.Leaving() )
{
Highlight(scrollbar, FALSE);
m_htLast = wxHT_NOWHERE;
}
else
{
// we don't process this event
return FALSE;
}
// we did something
return TRUE;
}
#endif // wxUSE_SCROLLBAR

View File

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

View File

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

View File

@@ -53,6 +53,7 @@ public:
// implement the base class pure virtuals
virtual void DrawBackground(wxDC& dc,
const wxColour& col,
const wxRect& rect,
int flags = 0);
virtual void DrawLabel(wxDC& dc,
@@ -86,19 +87,27 @@ public:
wxDirection dir,
const wxRect& rect,
int flags = 0);
virtual void DrawScrollbar(wxDC& dc,
wxOrientation orient,
int thumbPosStart,
int thumbPosEnd,
virtual void DrawScrollbarThumb(wxDC& dc,
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);
// hit testing for the input handlers
virtual wxRect GetScrollbarRect(const wxScrollBar *scrollbar,
wxScrollBar::Element elem,
int thumbPos = -1) const;
virtual wxHitTest HitTestScrollbar(const wxScrollBar *scrollbar,
const wxPoint& pt) const;
virtual wxCoord ScrollbarToPixel(const wxScrollBar *scrollbar);
virtual wxCoord ScrollbarToPixel(const wxScrollBar *scrollbar,
int thumbPos = -1);
virtual int PixelToScrollbar(const wxScrollBar *scrollbar, wxCoord coord);
protected:
@@ -159,12 +168,12 @@ class wxGTKInputHandler : public wxInputHandler
public:
wxGTKInputHandler(wxGTKRenderer *renderer);
virtual wxControlActions Map(wxControl *control,
virtual bool HandleKey(wxControl *control,
const wxKeyEvent& event,
bool pressed);
virtual wxControlActions Map(wxControl *control,
virtual bool HandleMouse(wxControl *control,
const wxMouseEvent& event);
virtual bool OnMouseMove(wxControl *control, const wxMouseEvent& event);
virtual bool HandleMouseMove(wxControl *control, const wxMouseEvent& event);
protected:
wxGTKRenderer *m_renderer;
@@ -592,6 +601,32 @@ void wxGTKRenderer::DrawLabel(wxDC& dc,
dc.DrawLabel(label, image, rect, alignment, indexAccel, rectBounds);
}
void wxGTKRenderer::DrawItem(wxDC& dc,
const wxString& label,
const wxRect& rect,
int flags)
{
if ( flags & wxCONTROL_SELECTED )
{
dc.SetTextBackground(m_scheme->Get(wxColourScheme::HIGHLIGHT));
dc.SetTextForeground(m_scheme->Get(wxColourScheme::HIGHLIGHT_TEXT));
dc.SetBackgroundMode(wxSOLID);
}
dc.DrawLabel(label, wxNullBitmap, rect);
if ( flags & wxCONTROL_SELECTED )
{
dc.SetBackgroundMode(wxTRANSPARENT);
}
if ( flags & wxCONTROL_FOCUSED )
{
wxRect rectFocus = rect;
DrawRect(dc, &rectFocus, m_penBlack);
}
}
// ----------------------------------------------------------------------------
// background
// ----------------------------------------------------------------------------
@@ -607,10 +642,14 @@ void wxGTKRenderer::DoDrawBackground(wxDC& dc,
}
void wxGTKRenderer::DrawBackground(wxDC& dc,
const wxColour& col,
const wxRect& rect,
int flags)
{
DoDrawBackground(dc, GetBackgroundColour(flags), rect);
DoDrawBackground(dc,
col.Ok() ? col
: GetBackgroundColour(flags),
rect);
}
// ----------------------------------------------------------------------------
@@ -786,89 +825,35 @@ void wxGTKRenderer::DrawArrow(wxDC& dc,
}
}
void wxGTKRenderer::DrawScrollbar(wxDC& dc,
wxOrientation orient,
int thumbPosStart,
int thumbPosEnd,
void wxGTKRenderer::DrawScrollbarThumb(wxDC& dc,
const wxRect& rect,
const int *flags)
int flags)
{
#ifdef DEBUG_MOUSE
wxLogDebug("Drawing the scrollbar (orientation = %s):\n"
"\tarrow 1: 0x%04x\n"
"\tarrow 2: 0x%04x\n"
"\tthumb: 0x%04x\n"
"\tthumb from %d to %d",
orient == wxVERTICAL ? "vertical" : "horizontal",
flags[wxScrollBar::Element_Arrow_Line_1],
flags[wxScrollBar::Element_Arrow_Line_2],
flags[wxScrollBar::Element_Thumb],
thumbPosStart, thumbPosEnd);
#endif // DEBUG_MOUSE
// the thumb is never pressed never has focus border under GTK and the
// scrollbar background never changes at all
int flagsThumb = flags & ~(wxCONTROL_PRESSED | wxCONTROL_FOCUSED);
// first draw the scrollbar area background
wxRect rectThumb = rect;
DrawButtonBorder(dc, rectThumb, flagsThumb, &rectThumb);
DrawBackground(dc, wxNullColour, rectThumb, flagsThumb);
}
void wxGTKRenderer::DrawScrollbarShaft(wxDC& dc,
const wxRect& rect,
int flags)
{
wxRect rectBar = rect;
DrawAntiShadedRect(dc, &rectBar, m_penDarkGrey, m_penHighlight);
DrawAntiShadedRect(dc, &rectBar, m_penBlack, m_penGrey);
DoDrawBackground(dc, m_scheme->Get(wxColourScheme::SCROLLBAR), rectBar);
// next draw the arrows at the ends
wxRect rectArrow[2];
wxDirection arrowDir[2];
rectArrow[0] =
rectArrow[1] = rectBar;
if ( orient == wxVERTICAL )
{
rectArrow[0].height =
rectArrow[1].height = m_sizeScrollbarArrow.y - 1;
rectArrow[1].y = rectBar.GetBottom() - rectArrow[1].height + 1;
arrowDir[0] = wxUP;
arrowDir[1] = wxDOWN;
}
else // horizontal
{
rectArrow[0].width =
rectArrow[1].width = m_sizeScrollbarArrow.x - 1;
rectArrow[1].x = rectBar.GetRight() - rectArrow[1].width + 1;
arrowDir[0] = wxLEFT;
arrowDir[1] = wxRIGHT;
}
for ( size_t nArrow = 0; nArrow < 2; nArrow++ )
wxRect wxGTKRenderer::GetScrollbarRect(const wxScrollBar *scrollbar,
wxScrollBar::Element elem,
int thumbPos) const
{
DrawArrow(dc, arrowDir[nArrow], rectArrow[nArrow],
flags[wxScrollBar::Element_Arrow_Line_1 + nArrow]);
}
// and, finally, the thumb, if any
if ( thumbPosStart < thumbPosEnd )
{
wxRect rectThumb;
if ( orient == wxVERTICAL )
{
rectBar.Inflate(0, -m_sizeScrollbarArrow.y);
rectThumb = rectBar;
rectThumb.y += (rectBar.height*thumbPosStart)/100;
rectThumb.height = (rectBar.height*(thumbPosEnd - thumbPosStart))/100;
}
else // horizontal
{
rectBar.Inflate(-m_sizeScrollbarArrow.x, 0);
rectThumb = rectBar;
rectThumb.x += (rectBar.width*thumbPosStart)/100;
rectThumb.width = (rectBar.width*(thumbPosEnd - thumbPosStart))/100;
}
// the thumb is never pressed never has focus border under GTK and the
// scrollbar background never changes at all
int flagsThumb = flags[wxScrollBar::Element_Thumb] &
~(wxCONTROL_PRESSED | wxCONTROL_FOCUSED);
DrawButtonBorder(dc, rectThumb, flagsThumb, &rectThumb);
DrawBackground(dc, rectThumb, flagsThumb);
}
return StandardGetScrollbarRect(scrollbar, elem,
thumbPos, m_sizeScrollbarArrow);
}
wxHitTest wxGTKRenderer::HitTestScrollbar(const wxScrollBar *scrollbar,
@@ -877,9 +862,10 @@ wxHitTest wxGTKRenderer::HitTestScrollbar(const wxScrollBar *scrollbar,
return StandardHitTestScrollbar(scrollbar, pt, m_sizeScrollbarArrow);
}
wxCoord wxGTKRenderer::ScrollbarToPixel(const wxScrollBar *scrollbar)
wxCoord wxGTKRenderer::ScrollbarToPixel(const wxScrollBar *scrollbar,
int thumbPos)
{
return StandardScrollbarToPixel(scrollbar, m_sizeScrollbarArrow);
return StandardScrollbarToPixel(scrollbar, thumbPos, m_sizeScrollbarArrow);
}
int wxGTKRenderer::PixelToScrollbar(const wxScrollBar *scrollbar,
@@ -962,26 +948,28 @@ wxGTKInputHandler::wxGTKInputHandler(wxGTKRenderer *renderer)
m_renderer = renderer;
}
wxControlActions wxGTKInputHandler::Map(wxControl *control,
bool wxGTKInputHandler::HandleKey(wxControl *control,
const wxKeyEvent& event,
bool pressed)
{
return wxACTION_NONE;
return FALSE;
}
wxControlActions wxGTKInputHandler::Map(wxControl *control,
bool wxGTKInputHandler::HandleMouse(wxControl *control,
const wxMouseEvent& event)
{
// clicking on the control gives it focus
if ( event.ButtonDown() )
{
control->SetFocus();
return TRUE;
}
return wxACTION_NONE;
return FALSE;
}
bool wxGTKInputHandler::OnMouseMove(wxControl *control,
bool wxGTKInputHandler::HandleMouseMove(wxControl *control,
const wxMouseEvent& event)
{
if ( event.Entering() )
@@ -997,7 +985,6 @@ bool wxGTKInputHandler::OnMouseMove(wxControl *control,
return FALSE;
}
// highlighting changed
return TRUE;
}

View File

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

View File

@@ -48,9 +48,14 @@
// event tables
// ----------------------------------------------------------------------------
IMPLEMENT_DYNAMIC_CLASS(wxWindow, wxWindowBase)
// we can't use wxWindowNative here as it won't be expanded inside the macro
#if defined(__WXMSW__)
IMPLEMENT_DYNAMIC_CLASS(wxWindow, wxWindowMSW)
#elif defined(__WXGTK__)
IMPLEMENT_DYNAMIC_CLASS(wxWindow, wxWindowGTK)
#endif
BEGIN_EVENT_TABLE(wxWindow, wxWindowBase)
BEGIN_EVENT_TABLE(wxWindow, wxWindowNative)
EVT_SIZE(wxWindow::OnSize)
EVT_PAINT(wxWindow::OnPaint)
@@ -67,6 +72,8 @@ void wxWindow::Init()
m_scrollbarHorz = (wxScrollBar *)NULL;
m_isCurrent = FALSE;
m_renderer = (wxRenderer *)NULL;
}
// ----------------------------------------------------------------------------
@@ -100,11 +107,6 @@ const wxBitmap& wxWindow::GetBackgroundBitmap(int *alignment,
// painting
// ----------------------------------------------------------------------------
wxRenderer *wxWindow::GetRenderer() const
{
return wxTheme::Get()->GetRenderer();
}
// the event handler executed when the window background must be painted
void wxWindow::OnErase(wxEraseEvent& event)
{
@@ -120,14 +122,22 @@ void wxWindow::OnErase(wxEraseEvent& event)
// the event handler executed when the window must be repainted
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
wxPaintDC dc(this);
wxControlRenderer renderer(this, dc, GetRenderer());
wxControlRenderer renderer(this, dc, m_renderer);
// do draw the control!
DoDraw(&renderer);
}
}
bool wxWindow::DoDrawBackground(wxControlRenderer *renderer)
{
@@ -211,10 +221,21 @@ void wxWindow::OnSize(wxSizeEvent& event)
event.Skip();
}
wxSize wxWindow::DoGetBestSize() const
{
return AdjustSize(DoGetBestClientSize());
}
wxSize wxWindow::DoGetBestClientSize() const
{
return wxWindowNative::DoGetBestSize();
}
wxSize wxWindow::AdjustSize(const wxSize& size) const
{
wxSize sz = size;
wxTheme::Get()->GetRenderer()->AdjustSize(&sz, this);
if ( m_renderer )
m_renderer->AdjustSize(&sz, this);
return sz;
}
@@ -344,27 +365,33 @@ void wxWindow::ScrollWindow(int dx, int dy, const wxRect *rect)
}
else // move the part which doesn't change to the new location
{
// positive values mean to scroll to the left/up
if ( dx > 0 )
// note that when we scroll the canvas in some direction we move the
// block which doesn't need to be refreshed in the opposite direction
if ( dx < 0 )
{
ptSource.x = dx;
// scroll to the right, move to the left
ptSource.x = -dx;
ptDest.x = 0;
}
else
{
// scroll to the left, move to the right
ptSource.x = 0;
ptDest.x = -dx;
ptDest.x = dx;
}
if ( dy > 0 )
if ( dy < 0 )
{
ptSource.y = dy;
// scroll down, move up
ptSource.y = -dy;
ptDest.y = 0;
}
else
{
// scroll up, move down
ptSource.y = 0;
ptDest.y = -dy;
ptDest.y = dy;
}
// do move
@@ -387,12 +414,23 @@ void wxWindow::ScrollWindow(int dx, int dy, const wxRect *rect)
// it bad?
wxRect rect;
rect.x = ptSource.x;
rect.y = ptSource.y;
if ( dx )
{
rect.width = abs(dx);
if ( dx < 0 )
{
// refresh the area along the right border
rect.x = size.x;
rect.width = -dx;
}
else
{
// refresh the area along the left border
rect.x = 0;
rect.width = dx;
}
rect.y = 0;
rect.height = sizeTotal.y;
wxLogTrace(_T("scroll"), _T("refreshing (%d, %d)-(%d, %d)"),
@@ -403,8 +441,21 @@ void wxWindow::ScrollWindow(int dx, int dy, const wxRect *rect)
if ( dy )
{
if ( dy < 0 )
{
// refresh the area along the bottom border
rect.y = size.y;
rect.height = -dy;
}
else
{
// refresh the area along the top border
rect.y = 0;
rect.height = dy;
}
rect.x = 0;
rect.width = sizeTotal.x;
rect.height = abs(dy);
wxLogTrace(_T("scroll"), _T("refreshing (%d, %d)-(%d, %d)"),
rect.x, rect.y, rect.GetRight(), rect.GetBottom());