1. wxInputHandler now knows about wxRenderer and uses it

2. wxInputHandler::OnMouseMove() added
3. wxGTKRenderer (almost) draws scrollbars
4. scrollbar mouse handling starts to work


git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/branches/wxUNIVERSAL@8160 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
2000-08-22 17:02:00 +00:00
parent efe51556de
commit 2c0eba5f88
14 changed files with 716 additions and 226 deletions

View File

@@ -2016,7 +2016,7 @@ if test "$wxUSE_GUI" = "yes"; then
fi
if test "$wxUSE_UNIVERSAL" = "yes"; then
ALL_DEPFILES="\$(GUI_LOWLEVEL_DEPS)"
ALL_DEPFILES="\$(GUI_LOWLEVEL_DEPS) \$(UNIVDEPS)"
else
ALL_DEPFILES="\$(GUIDEPS)"
fi

View File

@@ -31,9 +31,6 @@ class WXDLLEXPORT wxInputHandler;
// wxButton: a push button
// ----------------------------------------------------------------------------
// class name
#define wxCONTROL_BUTTON _T("button")
class WXDLLEXPORT wxButton : public wxButtonBase
{
public:
@@ -75,7 +72,6 @@ public:
void Click();
protected:
virtual wxInputHandler *CreateInputHandler() const;
virtual bool PerformAction(const wxControlAction& action,
const wxEvent& event);
virtual wxSize DoGetBestSize() const;

View File

@@ -70,16 +70,12 @@ public:
// in the controls headers)
#define wxACTION_NONE _T("") // no action to perform
#define wxACTION_HIGHLIGHT _T("focus") // highlight the control
#define wxACTION_UNHIGHLIGHT _T("unfocus") // remove highlight
#define wxACTION_FOCUS _T("focus") // make control focused
// ----------------------------------------------------------------------------
// wxControl: the base class for all GUI controls
// ----------------------------------------------------------------------------
// class name
#define wxCONTROL_DEFAULT _T("")
class WXDLLEXPORT wxControl : public wxControlBase
{
public:
@@ -140,6 +136,12 @@ 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
virtual bool PerformAction(const wxControlAction& action,
const wxEvent& event);
protected:
// create the event translator object for this control: the base class
// action creates the default one which doesn't do anything
@@ -151,12 +153,6 @@ protected:
// draw the controls contents
virtual void DoDraw(wxControlRenderer *renderer);
// 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
virtual bool PerformAction(const wxControlAction& action,
const wxEvent& event);
// event handlers
void OnMouse(wxMouseEvent& event);
void OnKeyDown(wxKeyEvent& event);

View File

@@ -28,10 +28,23 @@ 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(const wxKeyEvent& event, bool pressed) = 0;
virtual wxControlActions Map(wxControl *control,
const wxKeyEvent& event,
bool pressed) = 0;
// map a mouse event to one or more actions
virtual wxControlActions Map(const wxMouseEvent& event) = 0;
// map a mouse (click) event to one or more actions
virtual wxControlActions Map(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);
// virtual dtor for any base class
virtual ~wxInputHandler();

View File

@@ -24,11 +24,33 @@
class WXDLLEXPORT wxControl;
class WXDLLEXPORT wxDC;
class WXDLLEXPORT wxScrollBar;
class WXDLLEXPORT wxWindow;
#include "wx/string.h"
#include "wx/gdicmn.h"
// ----------------------------------------------------------------------------
// constants
// ----------------------------------------------------------------------------
// hit test results
enum wxHitTest
{
wxHT_NOWHERE,
// scrollbar
wxHT_SCROLLBAR_ARROW_LINE_1, // left or upper arrow to scroll by line
wxHT_SCROLLBAR_ARROW_LINE_2, // right or down
wxHT_SCROLLBAR_ARROW_PAGE_1, // left or upper arrow to scroll by page
wxHT_SCROLLBAR_ARROW_PAGE_2, // right or down
wxHT_SCROLLBAR_THUMB, // on the thumb
wxHT_SCROLLBAR_BAR_1, // bar to the left/above the thumb
wxHT_SCROLLBAR_BAR_2, // bar to the right/below the thumb
wxHT_MAX
};
// ----------------------------------------------------------------------------
// wxRenderer: abstract renderers interface
// ----------------------------------------------------------------------------
@@ -36,6 +58,9 @@ class WXDLLEXPORT wxWindow;
class WXDLLEXPORT wxRenderer
{
public:
// drawing functions
// -----------------
// draw the controls background
virtual void DrawBackground(wxDC& dc,
const wxRect& rect,
@@ -79,14 +104,14 @@ public:
int flags = 0) = 0;
// draw a scrollbar: thumb positions are in percent of the full scrollbar
// length
// length and the flags array contains the flags corresponding to each of
// wxScrollBar::Elements
virtual void DrawScrollbar(wxDC& dc,
wxOrientation orient,
int thumbPosStart,
int thumbPosEnd,
const wxRect& rect,
int flags = 0,
int extraFlags = 0) = 0;
const int *flags = NULL) = 0;
// TODO: having this is ugly but I don't see how to solve GetBestSize()
// problem without something like this
@@ -97,6 +122,13 @@ public:
// the control looks "nice" if it uses the adjusted rectangle
virtual void AdjustSize(wxSize *size, const wxWindow *window) = 0;
// hit testing functions
// ---------------------
// returns one of wxHT_SCROLLBAR_XXX constants
virtual wxHitTest HitTestScrollbar(wxScrollBar *scrollbar,
const wxPoint& pt) const = 0;
// virtual dtor for any base class
virtual ~wxRenderer();
};
@@ -152,14 +184,17 @@ public:
int thumbPosStart,
int thumbPosEnd,
const wxRect& rect,
int flags = 0,
int extraFlags = 0)
const int *flags = NULL)
{ m_renderer->DrawScrollbar(dc, orient, thumbPosStart,
thumbPosEnd, rect, flags, extraFlags); }
thumbPosEnd, rect, flags); }
virtual void AdjustSize(wxSize *size, const wxWindow *window)
{ m_renderer->AdjustSize(size, window); }
virtual wxHitTest HitTestScrollbar(wxScrollBar *scrollbar,
const wxPoint& pt) const
{ return m_renderer->HitTestScrollbar(scrollbar, pt); }
protected:
wxRenderer *m_renderer;
};
@@ -181,7 +216,7 @@ public:
void DrawButtonBorder();
void DrawFrame();
void DrawBackgroundBitmap();
void DrawScrollbar(int thumbStart, int thumbEnd, int extraFlags = 0);
void DrawScrollbar(wxScrollBar *scrollbar);
// accessors
wxRenderer *GetRenderer() const { return m_renderer; }

View File

@@ -22,12 +22,6 @@ class WXDLLEXPORT wxInputHandler;
// the actions supported by this control
// ----------------------------------------------------------------------------
// various parts of scrollbar may be highlighted
#define wxACTION_SCROLL_HIGHLIGHT_ARROW_UP _T("focusarrowup")
#define wxACTION_SCROLL_HIGHLIGHT_ARROW_DOWN _T("focusarrowdown")
#define wxACTION_SCROLL_HIGHLIGHT_THUMB _T("focusthumb")
#define wxACTION_SCROLL_HIGHLIGHT_BAR _T("focusbar")
// scroll the bar
#define wxACTION_SCROLL_START _T("start") // to the beginning
#define wxACTION_SCROLL_END _T("end") // to the end
@@ -45,19 +39,19 @@ class WXDLLEXPORT wxInputHandler;
// wxScrollBar
// ----------------------------------------------------------------------------
// class name
#define wxCONTROL_SCROLLBAR _T("scrollbar")
class WXDLLEXPORT wxScrollBar : public wxScrollBarBase
{
public:
enum
// the parts of the scrollbar
enum Element
{
// which part of scrollbar is currently highlighted?
Highlight_Arrow1 = 0x0001,
Highlight_Arrow2 = 0x0002,
Highlight_Thumb = 0x0004,
Highlight_Bar = 0x0008
Element_Arrow_Line_1,
Element_Arrow_Line_2,
Element_Arrow_Page_1,
Element_Arrow_Page_2,
Element_Thumb,
Element_Bar,
Element_Max
};
wxScrollBar() { Init(); }
@@ -84,26 +78,39 @@ public:
virtual ~wxScrollBar();
// implementate base class pure virtuals
// implement base class pure virtuals
virtual int GetThumbPosition() const;
virtual int GetThumbSize() const;
virtual int GetPageSize() const;
virtual int GetRange() const;
virtual void SetThumbPosition(int viewStart);
virtual void SetThumbPosition(int thumbPos);
virtual void SetScrollbar(int position, int thumbSize,
int range, int pageSize,
bool refresh = TRUE);
// wxScrollBar actions
void ScrollToStart();
void ScrollToEnd();
void ScrollLines(int nLines);
void ScrollPages(int nPages);
protected:
virtual wxInputHandler *CreateInputHandler() const;
virtual bool PerformAction(const wxControlAction& action,
const wxEvent& event);
// wxScrollBar sub elements state (combination of wxCONTROL_XXX)
void SetState(Element elem, int flags)
{ m_elementsState[elem] = flags; }
int GetState(Element elem) const
{ return m_elementsState[elem]; }
protected:
virtual wxSize DoGetBestSize() const;
virtual void DoDraw(wxControlRenderer *renderer);
// SetThumbPosition() helper
void DoSetThumb(int thumbPos);
// common part of all ctors
void Init();
@@ -120,6 +127,9 @@ private:
// up/down action is performed
int m_pageSize;
// the state of the sub elements
int m_elementsState[Element_Max];
DECLARE_DYNAMIC_CLASS(wxScrollBar)
};

View File

@@ -118,11 +118,6 @@ void wxButton::DoDraw(wxControlRenderer *renderer)
// input processing
// ----------------------------------------------------------------------------
wxInputHandler *wxButton::CreateInputHandler() const
{
return wxTheme::Get()->GetInputHandler(wxCONTROL_BUTTON);
}
void wxButton::Press()
{
m_isPressed = TRUE;

View File

@@ -271,22 +271,32 @@ void wxControl::OnFocus(wxFocusEvent& event)
wxInputHandler *wxControl::CreateInputHandler() const
{
return wxTheme::Get()->GetInputHandler(wxCONTROL_DEFAULT);
return wxTheme::Get()->GetInputHandler(GetName());
}
void wxControl::OnKeyDown(wxKeyEvent& event)
{
PerformActions(m_handler->Map(event, TRUE), event);
PerformActions(m_handler->Map(this, event, TRUE), event);
}
void wxControl::OnKeyUp(wxKeyEvent& event)
{
PerformActions(m_handler->Map(event, FALSE), event);
PerformActions(m_handler->Map(this, event, FALSE), event);
}
void wxControl::OnMouse(wxMouseEvent& event)
{
PerformActions(m_handler->Map(event), event);
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();
}
else // a click action
{
PerformActions(m_handler->Map(this, event), event);
}
}
// ----------------------------------------------------------------------------
@@ -311,17 +321,14 @@ void wxControl::PerformActions(const wxControlActions& actions,
bool wxControl::PerformAction(const wxControlAction& action,
const wxEvent& event)
{
if ( (action == wxACTION_NONE) || !AcceptsFocus() )
return FALSE;
if ( action == wxACTION_HIGHLIGHT )
SetCurrent(TRUE);
else if ( action == wxACTION_UNHIGHLIGHT )
SetCurrent(FALSE);
else
return FALSE;
if ( (action == wxACTION_FOCUS) && AcceptsFocus() )
{
SetFocus();
return TRUE;
}
return FALSE;
}
#endif // wxUSE_CONTROLS

View File

@@ -11,4 +11,15 @@ UNIVOBJS = \
gtk.o \
win32.o
# winuniv.o
UNIVDEPS = \
button.d \
colschem.d \
control.d \
inphand.d \
renderer.d \
scrolbar.d \
statbox.d \
stattext.d \
theme.d \
gtk.d \
win32.d

View File

@@ -37,6 +37,12 @@
// implementation
// ============================================================================
bool wxInputHandler::OnMouseMove(wxControl * WXUNUSED(control),
const wxMouseEvent& WXUNUSED(event))
{
return FALSE;
}
wxInputHandler::~wxInputHandler()
{
}

View File

@@ -31,6 +31,7 @@
#ifndef WX_PRECOMP
#include "wx/app.h"
#include "wx/control.h"
#include "wx/scrolbar.h"
#include "wx/dc.h"
#endif // WX_PRECOMP
@@ -176,12 +177,34 @@ void wxControlRenderer::DrawBackgroundBitmap()
m_dc.DrawBitmap(bmp, x, y);
}
void wxControlRenderer::DrawScrollbar(int thumbStart, int thumbEnd)
void wxControlRenderer::DrawScrollbar(wxScrollBar *scrollbar)
{
int thumbStart, thumbEnd;
int range = scrollbar->GetRange();
if ( range )
{
int thumbPos = scrollbar->GetThumbPosition(),
thumbSize = scrollbar->GetThumbSize();
thumbStart = (100*thumbPos) / range;
thumbEnd = (100*(thumbPos + thumbSize)) / range;
}
else // no range
{
thumbStart =
thumbEnd = 0;
}
int flags[wxScrollBar::Element_Max];
for ( size_t n = 0; n < WXSIZEOF(flags); n++ )
{
flags[n] = scrollbar->GetState((wxScrollBar::Element)n);
}
m_renderer->DrawScrollbar(m_dc,
m_ctrl->GetWindowStyle() & wxVERTICAL
? wxVERTICAL
: wxHORIZONTAL,
thumbStart, thumbEnd, m_rect,
m_ctrl->GetStateFlags());
flags);
}

View File

@@ -55,6 +55,11 @@ void wxScrollBar::Init()
m_thumbSize =
m_thumbPos =
m_pageSize = 0;
for ( size_t n = 0; n < Element_Max; n++ )
{
m_elementsState[n] = 0;
}
}
bool wxScrollBar::Create(wxWindow *parent,
@@ -90,6 +95,21 @@ wxScrollBar::~wxScrollBar()
// scrollbar API
// ----------------------------------------------------------------------------
void wxScrollBar::DoSetThumb(int pos)
{
// don't do checks here, we're a private function
if ( pos < 0 )
{
pos = 0;
}
else if ( pos > m_range - m_thumbSize )
{
pos = m_range - m_thumbSize;
}
m_thumbPos = pos;
}
int wxScrollBar::GetThumbPosition() const
{
return m_thumbPos;
@@ -114,12 +134,9 @@ void wxScrollBar::SetThumbPosition(int pos)
{
wxCHECK_RET( pos >= 0 && pos <= m_range, _T("thumb position out of range") );
if ( pos >= m_range - m_thumbSize )
{
pos = m_range - m_thumbSize;
}
DoSetThumb(pos);
m_thumbPos = pos;
Refresh();
}
void wxScrollBar::SetScrollbar(int position, int thumbSize,
@@ -156,34 +173,53 @@ wxSize wxScrollBar::DoGetBestSize() const
void wxScrollBar::DoDraw(wxControlRenderer *renderer)
{
int thumbStart, thumbEnd;
if ( m_range )
{
thumbStart = (100*m_thumbPos) / m_range;
thumbEnd = (100*(m_thumbPos + m_thumbSize)) / m_range;
}
else // no range
{
thumbStart =
thumbEnd = 0;
}
renderer->DrawScrollbar(thumbStart, thumbEnd);
renderer->DrawScrollbar(this);
}
// ----------------------------------------------------------------------------
// input processing
// ----------------------------------------------------------------------------
wxInputHandler *wxScrollBar::CreateInputHandler() const
{
return wxTheme::Get()->GetInputHandler(wxCONTROL_SCROLLBAR);
}
bool wxScrollBar::PerformAction(const wxControlAction& action,
const wxEvent& event)
{
if ( action == wxACTION_SCROLL_START )
ScrollToStart();
else if ( action == wxACTION_SCROLL_END )
ScrollToEnd();
else if ( action == wxACTION_SCROLL_LINE_UP )
ScrollLines(-1);
else if ( action == wxACTION_SCROLL_LINE_DOWN )
ScrollLines(1);
else if ( action == wxACTION_SCROLL_PAGE_UP )
ScrollPages(-1);
else if ( action == wxACTION_SCROLL_PAGE_DOWN )
ScrollPages(1);
else
return wxControl::PerformAction(action, event);
// scrollbar position changed - update
return TRUE;
}
void wxScrollBar::ScrollToStart()
{
DoSetThumb(0);
}
void wxScrollBar::ScrollToEnd()
{
DoSetThumb(m_range - m_thumbSize);
}
void wxScrollBar::ScrollLines(int nLines)
{
DoSetThumb(m_thumbPos + nLines);
}
void wxScrollBar::ScrollPages(int nPages)
{
DoSetThumb(m_thumbPos + nPages*m_pageSize);
}
#endif // wxUSE_SCROLLBAR

View File

@@ -26,6 +26,7 @@
#ifndef WX_PRECOMP
#include "wx/intl.h"
#include "wx/log.h"
#include "wx/dc.h"
#include "wx/window.h"
@@ -38,6 +39,9 @@
#include "wx/univ/colschem.h"
#include "wx/univ/theme.h"
// define this for tons of debugging messages
#undef DEBUG_MOUSE
// ----------------------------------------------------------------------------
// wxGTKRenderer: draw the GUI elements in GTK style
// ----------------------------------------------------------------------------
@@ -81,13 +85,22 @@ public:
int thumbPosStart,
int thumbPosEnd,
const wxRect& rect,
int flags = 0,
int extraFlags = 0);
const int *flags = NULL);
virtual void AdjustSize(wxSize *size, const wxWindow *window);
// hit testing for the input handlers
virtual wxHitTest HitTestScrollbar(wxScrollBar *scrollbar,
const wxPoint& pt) const;
protected:
// DrawBackground() helper
// DrawBackground() helpers
// get the colour to use for background
wxColour GetBackgroundColour(int flags) const
{ return m_scheme->Get(wxColourScheme::CONTROL, flags); }
// draw the background with any colour, not only the default one(s)
void DoDrawBackground(wxDC& dc,
const wxColour& col,
const wxRect& rect);
@@ -136,17 +149,30 @@ private:
class wxGTKInputHandler : public wxInputHandler
{
public:
virtual wxControlActions Map(const wxKeyEvent& event, bool pressed);
virtual wxControlActions Map(const wxMouseEvent& event);
wxGTKInputHandler(wxGTKRenderer *renderer);
virtual wxControlActions Map(wxControl *control,
const wxKeyEvent& event,
bool pressed);
virtual wxControlActions Map(wxControl *control,
const wxMouseEvent& event);
virtual bool OnMouseMove(wxControl *control, const wxMouseEvent& event);
protected:
wxGTKRenderer *m_renderer;
};
class wxGTKButtonInputHandler : public wxGTKInputHandler
{
public:
wxGTKButtonInputHandler();
wxGTKButtonInputHandler(wxGTKRenderer *renderer);
virtual wxControlActions Map(const wxKeyEvent& event, bool pressed);
virtual wxControlActions Map(const wxMouseEvent& event);
virtual wxControlActions Map(wxControl *control,
const wxKeyEvent& event,
bool pressed);
virtual wxControlActions Map(wxControl *control,
const wxMouseEvent& event);
virtual bool OnMouseMove(wxControl *control, const wxMouseEvent& event);
private:
wxWindow *m_winCapture;
@@ -156,14 +182,33 @@ private:
class wxGTKScrollBarInputHandler : public wxGTKInputHandler
{
public:
wxGTKScrollBarInputHandler();
wxGTKScrollBarInputHandler(wxGTKRenderer *renderer);
virtual wxControlActions Map(const wxKeyEvent& event, bool pressed);
virtual wxControlActions Map(const wxMouseEvent& event);
virtual wxControlActions Map(wxControl *control,
const wxKeyEvent& event,
bool pressed);
virtual wxControlActions Map(wxControl *control,
const wxMouseEvent& event);
virtual bool OnMouseMove(wxControl *control, const wxMouseEvent& event);
private:
// set or clear the specified flag on the scrollbar element corresponding
// to m_htLast
void SetElementState(wxScrollBar *scrollbar, int flag, bool doIt);
// [un]highlight the scrollbar element corresponding to m_htLast
void Highlight(wxScrollBar *scrollbar, bool doIt)
{ SetElementState(scrollbar, wxCONTROL_CURRENT, doIt); }
// [un]press the scrollbar element corresponding to m_htLast
void Press(wxScrollBar *scrollbar, bool doIt)
{ SetElementState(scrollbar, wxCONTROL_PRESSED, doIt); }
wxWindow *m_winCapture;
int m_btnCapture; // the mouse button which was captured mouse
bool m_winHasMouse;
wxHitTest m_htLast;
};
// ----------------------------------------------------------------------------
@@ -190,7 +235,8 @@ public:
virtual wxRenderer *GetRenderer() { return m_renderer; }
virtual wxInputHandler *GetInputHandler(const wxString& control);
virtual wxColourScheme *GetColourScheme(const wxString& control) { return m_scheme; }
virtual wxColourScheme *GetColourScheme(const wxString& control)
{ return m_scheme; }
private:
wxGTKRenderer *m_renderer;
@@ -235,17 +281,12 @@ wxInputHandler *wxGTKTheme::GetInputHandler(const wxString& control)
// create a new handler
n = m_handlerNames.Add(control);
if ( control == wxCONTROL_BUTTON )
handler = new wxGTKButtonInputHandler;
else if ( control == wxCONTROL_SCROLLBAR )
handler = new wxGTKScrollBarInputHandler;
if ( control == wxButtonNameStr )
handler = new wxGTKButtonInputHandler(m_renderer);
else if ( control == wxScrollBarNameStr )
handler = new wxGTKScrollBarInputHandler(m_renderer);
else
{
wxASSERT_MSG( control == wxCONTROL_DEFAULT,
_T("no input handler defined for this control") );
handler = new wxGTKInputHandler;
}
handler = new wxGTKInputHandler(m_renderer);
m_handlers.Insert(handler, n);
}
@@ -475,8 +516,7 @@ void wxGTKRenderer::DrawButtonBorder(wxDC& dc,
// now draw a normal button
DrawShadedRect(dc, &rect, m_penHighlight, m_penBlack);
DrawAntiShadedRect(dc, &rect,
flags & wxCONTROL_CURRENT ? m_penHighlight
: m_penLightGrey,
wxPen(GetBackgroundColour(flags), 0, wxSOLID),
m_penDarkGrey);
}
@@ -580,7 +620,7 @@ void wxGTKRenderer::DrawBackground(wxDC& dc,
const wxRect& rect,
int flags)
{
DoDrawBackground(dc, m_scheme->Get(wxColourScheme::CONTROL, flags), rect);
DoDrawBackground(dc, GetBackgroundColour(flags), rect);
}
// ----------------------------------------------------------------------------
@@ -604,6 +644,23 @@ void wxGTKRenderer::DrawArrow(wxDC& dc,
wxPoint ptArrow[Point_Max];
wxColour colInside = m_scheme->Get(wxColourScheme::CONTROL, flags);
wxPen penShadow[4];
if ( flags & wxCONTROL_PRESSED )
{
penShadow[0] = m_penDarkGrey;
penShadow[1] = m_penHighlight;
penShadow[2] = wxNullPen;
penShadow[3] = m_penBlack;
}
else // normal arrow
{
penShadow[0] = m_penHighlight;
penShadow[1] = m_penBlack;
penShadow[2] = m_penDarkGrey;
penShadow[3] = wxNullPen;
}
wxCoord middle;
if ( dir == wxUP || dir == wxDOWN )
{
@@ -617,7 +674,7 @@ void wxGTKRenderer::DrawArrow(wxDC& dc,
// draw the arrow interior
dc.SetPen(*wxTRANSPARENT_PEN);
dc.SetBrush(wxBrush(m_scheme->Get(wxColourScheme::CONTROL), wxSOLID));
dc.SetBrush(wxBrush(colInside, wxSOLID));
switch ( dir )
{
@@ -663,33 +720,45 @@ void wxGTKRenderer::DrawArrow(wxDC& dc,
dc.DrawPolygon(WXSIZEOF(ptArrow), ptArrow);
// draw the arrow border
dc.SetPen(m_penHighlight);
dc.SetPen(penShadow[0]);
switch ( dir )
{
case wxUP:
dc.DrawLine(ptArrow[Point_Second], ptArrow[Point_First]);
dc.DrawPoint(ptArrow[Point_First]);
dc.SetPen(m_penBlack);
if ( penShadow[3].Ok() )
{
dc.SetPen(penShadow[3]);
dc.DrawLine(ptArrow[Point_First].x + 1, ptArrow[Point_First].y,
ptArrow[Point_Second].x, ptArrow[Point_Second].y);
}
dc.SetPen(penShadow[1]);
dc.DrawLine(ptArrow[Point_Second].x + 1, ptArrow[Point_Second].y + 1,
ptArrow[Point_Third].x, ptArrow[Point_Third].y);
dc.DrawPoint(ptArrow[Point_Third]);
dc.DrawLine(ptArrow[Point_Third].x - 2, ptArrow[Point_Third].y,
ptArrow[Point_First].x + 1, ptArrow[Point_First].y);
dc.SetPen(m_penDarkGrey);
if ( penShadow[2].Ok() )
{
dc.SetPen(penShadow[2]);
dc.DrawLine(ptArrow[Point_Third].x - 1, ptArrow[Point_Third].y,
ptArrow[Point_Second].x, ptArrow[Point_Second].y + 1);
dc.DrawLine(ptArrow[Point_Third].x - 1, ptArrow[Point_Third].y - 1,
ptArrow[Point_First].x + 2, ptArrow[Point_First].y - 1);
}
break;
case wxDOWN:
dc.DrawLine(ptArrow[Point_First], ptArrow[Point_Second]);
dc.DrawLine(ptArrow[Point_First].x + 2, ptArrow[Point_First].y,
ptArrow[Point_Third].x - 1, ptArrow[Point_Third].y);
dc.SetPen(m_penDarkGrey);
if ( penShadow[2].Ok() )
{
dc.SetPen(penShadow[2]);
dc.DrawLine(ptArrow[Point_Second].x, ptArrow[Point_Second].y - 1,
ptArrow[Point_Third].x - 1, ptArrow[Point_Third].y - 1);
dc.SetPen(m_penBlack);
}
dc.SetPen(penShadow[1]);
dc.DrawLine(ptArrow[Point_Second], ptArrow[Point_Third]);
dc.DrawPoint(ptArrow[Point_Third]);
break;
@@ -697,12 +766,15 @@ void wxGTKRenderer::DrawArrow(wxDC& dc,
case wxLEFT:
dc.DrawLine(ptArrow[Point_Second], ptArrow[Point_First]);
dc.DrawPoint(ptArrow[Point_First]);
dc.SetPen(m_penDarkGrey);
if ( penShadow[2].Ok() )
{
dc.SetPen(penShadow[2]);
dc.DrawLine(ptArrow[Point_Third].x - 1, ptArrow[Point_Third].y,
ptArrow[Point_First].x - 1, ptArrow[Point_First].y + 2);
dc.DrawLine(ptArrow[Point_Third].x, ptArrow[Point_Third].y,
ptArrow[Point_Second].x + 2, ptArrow[Point_Second].y + 1);
dc.SetPen(m_penBlack);
}
dc.SetPen(penShadow[1]);
dc.DrawLine(ptArrow[Point_Third].x, ptArrow[Point_Third].y,
ptArrow[Point_First].x, ptArrow[Point_First].y + 1);
dc.DrawLine(ptArrow[Point_Second].x + 1, ptArrow[Point_Second].y + 1,
@@ -713,7 +785,7 @@ void wxGTKRenderer::DrawArrow(wxDC& dc,
dc.DrawLine(ptArrow[Point_First], ptArrow[Point_Third]);
dc.DrawLine(ptArrow[Point_First].x + 2, ptArrow[Point_First].y + 1,
ptArrow[Point_Second].x, ptArrow[Point_Second].y);
dc.SetPen(m_penBlack);
dc.SetPen(penShadow[1]);
dc.DrawLine(ptArrow[Point_Second], ptArrow[Point_Third]);
dc.DrawPoint(ptArrow[Point_Third]);
break;
@@ -729,25 +801,20 @@ void wxGTKRenderer::DrawScrollbar(wxDC& dc,
int thumbPosStart,
int thumbPosEnd,
const wxRect& rect,
int flags,
int extraFlags)
const int *flags)
{
// handling of wxCONTROL_CURRENT flag is complicated for the scrollbar
// because, though it's only one window, either an arrow or a thumb may be
// highlighted depending on where exactly the mouse is
int flagsArrows[2], flagsThumb;
flagsArrows[0] =
flagsArrows[1] =
flagsThumb = flags & ~wxCONTROL_CURRENT;
if ( flags & wxCONTROL_CURRENT )
{
if ( extraFlags & wxScrollBar::Highlight_Arrow1 )
flagsArrows[0] |= wxCONTROL_CURRENT;
if ( extraFlags & wxScrollBar::Highlight_Arrow2 )
flagsArrows[1] |= wxCONTROL_CURRENT;
if ( extraFlags & wxScrollBar::Highlight_Thumb )
flagsThumb |= wxCONTROL_CURRENT;
}
#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
// first draw the scrollbar area background
wxRect rectBar = rect;
@@ -782,7 +849,8 @@ void wxGTKRenderer::DrawScrollbar(wxDC& dc,
for ( size_t nArrow = 0; nArrow < 2; nArrow++ )
{
DrawArrow(dc, arrowDir[nArrow], rectArrow[nArrow], flags);
DrawArrow(dc, arrowDir[nArrow], rectArrow[nArrow],
flags[wxScrollBar::Element_Arrow_Line_1 + nArrow]);
}
// and, finally, the thumb, if any
@@ -804,9 +872,71 @@ void wxGTKRenderer::DrawScrollbar(wxDC& dc,
rectThumb.width = (rectBar.width*(thumbPosEnd - thumbPosStart))/100;
}
// the thumb never has focus border under GTK
DrawButtonBorder(dc, rectThumb, flags & ~wxCONTROL_FOCUSED, &rectThumb);
DrawBackground(dc, rectThumb, flags);
// the thumb is never pressed never has focus border under GTK and the
// scrollbar background never changes at all
int flagsThumb = flags[wxScrollBar::Element_Thumb] &
~(wxCONTROL_PRESSED | wxCONTROL_FOCUSED);
DrawButtonBorder(dc, rectThumb, flagsThumb, &rectThumb);
DrawBackground(dc, rectThumb, flagsThumb);
}
}
wxHitTest wxGTKRenderer::HitTestScrollbar(wxScrollBar *scrollbar,
const wxPoint& pt) const
{
// we only need to work with tiehr x or y coord depending on the
// orientation, choose one
wxCoord coord, sizeArrow, sizeTotal;
if ( scrollbar->GetWindowStyle() & wxVERTICAL )
{
coord = pt.y;
sizeArrow = m_sizeScrollbarArrow.y;
sizeTotal = scrollbar->GetSize().y;
}
else // horizontal
{
coord = pt.x;
sizeArrow = m_sizeScrollbarArrow.x;
sizeTotal = scrollbar->GetSize().x;
}
// test for the arrows first as it's faster
if ( coord < sizeArrow )
{
return wxHT_SCROLLBAR_ARROW_LINE_1;
}
else if ( coord > sizeTotal - sizeArrow )
{
return wxHT_SCROLLBAR_ARROW_LINE_2;
}
else
{
// calculate the thumb position in pixels
sizeTotal -= 2*sizeArrow;
wxCoord thumbStart, thumbEnd;
int range = scrollbar->GetRange();
if ( !range )
{
thumbStart =
thumbEnd = 0;
}
else
{
int posThumb = scrollbar->GetThumbPosition(),
sizeThumb = scrollbar->GetThumbSize();
thumbStart = (sizeTotal*posThumb) / range;
thumbEnd = (sizeTotal*(posThumb + sizeThumb)) / range;
}
// now compare with the thumb position
coord -= sizeArrow;
if ( coord < thumbStart )
return wxHT_SCROLLBAR_BAR_1;
else if ( coord > thumbEnd )
return wxHT_SCROLLBAR_BAR_2;
else
return wxHT_SCROLLBAR_THUMB;
}
}
@@ -874,31 +1004,62 @@ void wxGTKRenderer::AdjustSize(wxSize *size, const wxWindow *window)
// wxGTKInputHandler
// ----------------------------------------------------------------------------
wxControlActions wxGTKInputHandler::Map(const wxKeyEvent& event, bool pressed)
wxGTKInputHandler::wxGTKInputHandler(wxGTKRenderer *renderer)
{
m_renderer = renderer;
}
wxControlActions wxGTKInputHandler::Map(wxControl *control,
const wxKeyEvent& event,
bool pressed)
{
return wxACTION_NONE;
}
wxControlActions wxGTKInputHandler::Map(const wxMouseEvent& event)
wxControlActions wxGTKInputHandler::Map(wxControl *control,
const wxMouseEvent& event)
{
if ( event.Entering() )
return wxACTION_HIGHLIGHT;
else if ( event.Leaving() )
return wxACTION_UNHIGHLIGHT;
// clicking on the control gives it focus
if ( event.ButtonDown() )
{
return wxACTION_FOCUS;
}
return wxACTION_NONE;
}
bool wxGTKInputHandler::OnMouseMove(wxControl *control,
const wxMouseEvent& event)
{
if ( event.Entering() )
{
control->SetCurrent(TRUE);
}
else if ( event.Leaving() )
{
control->SetCurrent(FALSE);
}
else
{
return FALSE;
}
// highlighting changed
return TRUE;
}
// ----------------------------------------------------------------------------
// wxGTKButtonInputHandler
// ----------------------------------------------------------------------------
wxGTKButtonInputHandler::wxGTKButtonInputHandler()
wxGTKButtonInputHandler::wxGTKButtonInputHandler(wxGTKRenderer *renderer)
: wxGTKInputHandler(renderer)
{
m_winCapture = NULL;
}
wxControlActions wxGTKButtonInputHandler::Map(const wxKeyEvent& event,
wxControlActions wxGTKButtonInputHandler::Map(wxControl *control,
const wxKeyEvent& event,
bool pressed)
{
int keycode = event.GetKeyCode();
@@ -907,95 +1068,280 @@ wxControlActions wxGTKButtonInputHandler::Map(const wxKeyEvent& event,
return wxACTION_BUTTON_TOGGLE;
}
return wxGTKInputHandler::Map(event, pressed);
return wxGTKInputHandler::Map(control, event, pressed);
}
wxControlActions wxGTKButtonInputHandler::Map(const wxMouseEvent& event)
wxControlActions wxGTKButtonInputHandler::Map(wxControl *control,
const wxMouseEvent& event)
{
if ( event.IsButton() )
// 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() )
if ( event.ButtonDown(1) )
{
m_winCapture = wxWindow::FindFocus();
m_winCapture = control;
m_winCapture->CaptureMouse();
m_winHasMouse = TRUE;
return wxACTION_BUTTON_PRESS;
}
else // up
{
m_winCapture->ReleaseMouse();
m_winCapture = NULL;
if ( !m_winHasMouse )
if ( m_winHasMouse )
{
// the mouse was released outside the window, this doesn't
// count as a click
return wxGTKInputHandler::Map(event);
}
}
// 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 wxGTKInputHandler::Map(control, event);
}
bool wxGTKButtonInputHandler::OnMouseMove(wxControl *control,
const wxMouseEvent& event)
{
// leaving the button should remove its pressed state
if ( event.Leaving() )
{
wxControlActions actions;
if ( m_winCapture )
{
// we do have a pressed button
actions.Add(wxACTION_BUTTON_RELEASE);
// we do have a pressed button, so release it
control->PerformAction(wxACTION_BUTTON_RELEASE, event);
// remember that the mouse is now outside
m_winHasMouse = FALSE;
}
actions.Add(wxGTKInputHandler::Map(event));
return actions;
}
// entering it back should make it pressed again if it had been pressed
if ( event.Entering() )
// and entering it back should make it pressed again if it had been
// pressed
else if ( event.Entering() )
{
wxControlActions actions;
if ( m_winCapture )
{
// we do have a pressed button
actions.Add(wxACTION_BUTTON_PRESS);
// we did have a pressed button which we released when leaving the
// window, press it again
control->PerformAction(wxACTION_BUTTON_PRESS, event);
// and the mouse is (back) inside it
m_winHasMouse = TRUE;
}
actions.Add(wxGTKInputHandler::Map(event));
return actions;
}
return wxGTKInputHandler::Map(event);
return wxGTKInputHandler::OnMouseMove(control, event);
}
// ----------------------------------------------------------------------------
// wxGTKScrollBarInputHandler
// ----------------------------------------------------------------------------
wxGTKScrollBarInputHandler::wxGTKScrollBarInputHandler()
wxGTKScrollBarInputHandler::wxGTKScrollBarInputHandler(wxGTKRenderer *renderer)
: wxGTKInputHandler(renderer)
{
m_winCapture = NULL;
m_htLast = wxHT_NOWHERE;
}
wxControlActions wxGTKScrollBarInputHandler::Map(const wxKeyEvent& event,
void wxGTKScrollBarInputHandler::SetElementState(wxScrollBar *control,
int flag,
bool doIt)
{
wxScrollBar::Element elem;
switch ( m_htLast )
{
case wxHT_SCROLLBAR_ARROW_LINE_1:
elem = wxScrollBar::Element_Arrow_Line_1;
break;
case wxHT_SCROLLBAR_ARROW_LINE_2:
elem = wxScrollBar::Element_Arrow_Line_2;
break;
case wxHT_SCROLLBAR_THUMB:
elem = wxScrollBar::Element_Thumb;
break;
/*
we don't highlight nor press the bar
case wxHT_SCROLLBAR_BAR_1:
case wxHT_SCROLLBAR_BAR_2:
*/
default:
elem = wxScrollBar::Element_Max;
}
if ( elem != wxScrollBar::Element_Max )
{
int flags = control->GetState(elem);
if ( doIt )
flags |= flag;
else
flags &= ~flag;
control->SetState(elem, flags);
}
}
wxControlActions wxGTKScrollBarInputHandler::Map(wxControl *control,
const wxKeyEvent& event,
bool pressed)
{
return wxGTKInputHandler::Map(event, pressed);
// weirdly enough, GTK+ scrollbars don't have keyboard support - maybe we
// should still have it though (TODO)?
return wxGTKInputHandler::Map(control, event, pressed);
}
wxControlActions wxGTKScrollBarInputHandler::Map(const wxMouseEvent& event)
wxControlActions wxGTKScrollBarInputHandler::Map(wxControl *control,
const wxMouseEvent& event)
{
if ( event.IsButton() )
{
// 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() )
{
if ( !m_winCapture )
{
m_btnCapture = -1;
for ( int i = 1; i <= 3; i++ )
{
if ( event.ButtonDown(i) )
{
m_btnCapture = i;
break;
}
}
wxASSERT_MSG( m_btnCapture != -1, _T("unknown mouse button") );
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;
break;
case wxHT_SCROLLBAR_BAR_2:
action = wxACTION_SCROLL_PAGE_DOWN;
break;
default:
hasAction = FALSE;
}
if ( hasAction )
{
control->PerformAction(action, event);
}
// remove highlighting and press the arrow instead
Highlight(scrollbar, FALSE);
m_htLast = ht;
Press(scrollbar, TRUE);
}
//else: mouse already captured, nothing to do
}
// release mouse if the *same* button went up
else if ( event.ButtonUp(m_btnCapture) )
{
if ( m_winCapture )
{
m_winCapture->ReleaseMouse();
m_winCapture = NULL;
// unpress the arrow and highlight the current element
Press(scrollbar, TRUE);
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 wxGTKInputHandler::Map(control, event);
}
bool wxGTKScrollBarInputHandler::OnMouseMove(wxControl *control,
const wxMouseEvent& event)
{
if ( m_winCapture )
{
// everything is locked while the mouse is captured, so don't do
// anything
return FALSE;
}
wxScrollBar *scrollbar = wxStaticCast(control, wxScrollBar);
if ( event.Moving() )
{
// determin which part of the window mouse is in
wxHitTest ht = m_renderer->HitTestScrollbar
(
scrollbar,
event.GetPosition()
);
if ( ht == m_htLast )
{
// nothing changed
return FALSE;
}
return wxGTKInputHandler::Map(event);
#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;
}
// highlighting changed
return TRUE;
}

View File

@@ -101,10 +101,13 @@ public:
int thumbPosStart,
int thumbPosEnd,
const wxRect& rect,
int flags = 0);
const int *flags = NULL);
virtual void AdjustSize(wxSize *size, const wxWindow *window);
virtual wxHitTest HitTestScrollbar(wxScrollBar *scrollbar,
const wxPoint& pt) const;
protected:
// DrawButtonBorder() helper
void DoDrawBackground(wxDC& dc,
@@ -167,8 +170,11 @@ private:
class wxWin32InputHandler : public wxInputHandler
{
public:
virtual wxControlActions Map(const wxKeyEvent& event, bool pressed);
virtual wxControlActions Map(const wxMouseEvent& event);
virtual wxControlActions Map(wxControl *control,
const wxKeyEvent& event,
bool pressed);
virtual wxControlActions Map(wxControl *control,
const wxMouseEvent& event);
};
class wxWin32ButtonInputHandler : public wxWin32InputHandler
@@ -176,8 +182,11 @@ class wxWin32ButtonInputHandler : public wxWin32InputHandler
public:
wxWin32ButtonInputHandler();
virtual wxControlActions Map(const wxKeyEvent& event, bool pressed);
virtual wxControlActions Map(const wxMouseEvent& event);
virtual wxControlActions Map(wxControl *control,
const wxKeyEvent& event,
bool pressed);
virtual wxControlActions Map(wxControl *control,
const wxMouseEvent& event);
private:
wxWindow *m_winCapture;
@@ -255,17 +264,12 @@ wxInputHandler *wxWin32Theme::GetInputHandler(const wxString& control)
// create a new handler
n = m_handlerNames.Add(control);
if ( control == wxCONTROL_BUTTON )
if ( control == wxButtonNameStr )
handler = new wxWin32ButtonInputHandler;
else if ( control == wxCONTROL_SCROLLBAR )
else if ( control == wxScrollBarNameStr )
handler = new wxWin32InputHandler; // TODO
else
{
wxASSERT_MSG( control == wxCONTROL_DEFAULT,
_T("no input handler defined for this control") );
handler = new wxWin32InputHandler;
}
m_handlers.Insert(handler, n);
}
@@ -893,9 +897,10 @@ void wxWin32Renderer::DrawScrollbar(wxDC& dc,
int thumbPosStart,
int thumbPosEnd,
const wxRect& rect,
int flags)
const int *flags)
{
wxArrowStyle arrowStyle = flags & wxCONTROL_DISABLED ? Arrow_Disabled
int flagsSb = flags ? flags[0] : 0;
wxArrowStyle arrowStyle = flagsSb & wxCONTROL_DISABLED ? Arrow_Disabled
: Arrow_Normal;
// first, draw the arrows at the ends
@@ -957,6 +962,12 @@ void wxWin32Renderer::DrawScrollbar(wxDC& dc,
}
}
wxHitTest wxWin32Renderer::HitTestScrollbar(wxScrollBar *scrollbar,
const wxPoint& pt) const
{
return wxHT_NOWHERE;
}
// ----------------------------------------------------------------------------
// size adjustments
// ----------------------------------------------------------------------------
@@ -1020,12 +1031,15 @@ void wxWin32Renderer::AdjustSize(wxSize *size, const wxWindow *window)
// wxWin32InputHandler
// ----------------------------------------------------------------------------
wxControlActions wxWin32InputHandler::Map(const wxKeyEvent& event, bool pressed)
wxControlActions wxWin32InputHandler::Map(wxControl *control,
const wxKeyEvent& event,
bool pressed)
{
return wxACTION_NONE;
}
wxControlActions wxWin32InputHandler::Map(const wxMouseEvent& event)
wxControlActions wxWin32InputHandler::Map(wxControl *control,
const wxMouseEvent& event)
{
return wxACTION_NONE;
}
@@ -1039,7 +1053,8 @@ wxWin32ButtonInputHandler::wxWin32ButtonInputHandler()
m_winCapture = NULL;
}
wxControlActions wxWin32ButtonInputHandler::Map(const wxKeyEvent& event,
wxControlActions wxWin32ButtonInputHandler::Map(wxControl *control,
const wxKeyEvent& event,
bool pressed)
{
int keycode = event.GetKeyCode();
@@ -1048,10 +1063,11 @@ wxControlActions wxWin32ButtonInputHandler::Map(const wxKeyEvent& event,
return wxACTION_BUTTON_TOGGLE;
}
return wxWin32InputHandler::Map(event, pressed);
return wxWin32InputHandler::Map(control, event, pressed);
}
wxControlActions wxWin32ButtonInputHandler::Map(const wxMouseEvent& event)
wxControlActions wxWin32ButtonInputHandler::Map(wxControl *control,
const wxMouseEvent& event)
{
if ( event.IsButton() )
{
@@ -1068,5 +1084,5 @@ wxControlActions wxWin32ButtonInputHandler::Map(const wxMouseEvent& event)
return wxACTION_BUTTON_TOGGLE;
}
return wxWin32InputHandler::Map(event);
return wxWin32InputHandler::Map(control, event);
}