more scrollbar input handling: extracted common bits to wxStdScrollBarHandler
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/branches/wxUNIVERSAL@8174 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -50,4 +50,115 @@ public:
|
|||||||
virtual ~wxInputHandler();
|
virtual ~wxInputHandler();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// The classes below provide the standard input handling for some controls so
|
||||||
|
// that the code can be reused in different themes. All of these classes chain
|
||||||
|
// to an existing input handler (which must be given to the ctor) and so allow
|
||||||
|
// custom processing of the events which they don't handle themselves.
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// wxStdInputHandler is just a base class for all other "standard" handlers
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class WXDLLEXPORT wxStdInputHandler : public wxInputHandler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
wxStdInputHandler(wxInputHandler *handler) : m_handler(handler) { }
|
||||||
|
|
||||||
|
virtual wxControlActions Map(wxControl *control,
|
||||||
|
const wxKeyEvent& event,
|
||||||
|
bool pressed)
|
||||||
|
{ return m_handler->Map(control, event, pressed); }
|
||||||
|
virtual wxControlActions Map(wxControl *control,
|
||||||
|
const wxMouseEvent& event)
|
||||||
|
{ return m_handler->Map(control, event); }
|
||||||
|
virtual bool OnMouseMove(wxControl *control, const wxMouseEvent& event)
|
||||||
|
{ return m_handler->OnMouseMove(control, event); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
wxInputHandler *m_handler;
|
||||||
|
};
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// wxStdButtonInputHandler: translates SPACE and ENTER keys and the left mouse
|
||||||
|
// click into button press/release actions
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class WXDLLEXPORT wxStdButtonInputHandler : public wxStdInputHandler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
wxStdButtonInputHandler(wxInputHandler *inphand);
|
||||||
|
|
||||||
|
virtual wxControlActions Map(wxControl *control,
|
||||||
|
const wxKeyEvent& event,
|
||||||
|
bool pressed);
|
||||||
|
virtual wxControlActions Map(wxControl *control,
|
||||||
|
const wxMouseEvent& event);
|
||||||
|
virtual bool OnMouseMove(wxControl *control, const wxMouseEvent& event);
|
||||||
|
|
||||||
|
private:
|
||||||
|
// the window (button) which has capture or NULL and the flag telling if
|
||||||
|
// the mouse is inside the button which captured it or not
|
||||||
|
wxWindow *m_winCapture;
|
||||||
|
bool m_winHasMouse;
|
||||||
|
};
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// common scrollbar input handler: it manages clicks on the standard scrollbar
|
||||||
|
// elements (line arrows, bar, thumb)
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class WXDLLEXPORT wxStdScrollBarInputHandler : public wxStdInputHandler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// constructor takes a renderer (used for scrollbar hit testing) and the
|
||||||
|
// base handler to which all unhandled events are forwarded
|
||||||
|
wxStdScrollBarInputHandler(wxRenderer *renderer,
|
||||||
|
wxInputHandler *inphand);
|
||||||
|
|
||||||
|
virtual wxControlActions Map(wxControl *control,
|
||||||
|
const wxKeyEvent& event,
|
||||||
|
bool pressed);
|
||||||
|
virtual wxControlActions Map(wxControl *control,
|
||||||
|
const wxMouseEvent& event);
|
||||||
|
virtual bool OnMouseMove(wxControl *control, const wxMouseEvent& event);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// the methods which must be overridden in the derived class
|
||||||
|
|
||||||
|
// return TRUE to stop scrolling when the mouse leaves the scrollbar (Win32
|
||||||
|
// behaviour) or FALSE to continue (GTK+)
|
||||||
|
virtual bool OnMouseLeave() = 0;
|
||||||
|
|
||||||
|
// return TRUE if the mouse button can be used to activate scrollbar, FALSE
|
||||||
|
// if not (only left mouse button can do it under Windows, any button under
|
||||||
|
// GTK+)
|
||||||
|
virtual bool IsAllowedButton(int button) = 0;
|
||||||
|
|
||||||
|
// 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); }
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
bool m_winHasMouse;
|
||||||
|
int m_btnCapture; // the mouse button which has captured mouse
|
||||||
|
|
||||||
|
// one of wxHT_SCROLLBAR_XXX value: where has the mouse been last time?
|
||||||
|
wxHitTest m_htLast;
|
||||||
|
|
||||||
|
// the renderer (we use it only for hit testing)
|
||||||
|
wxRenderer *m_renderer;
|
||||||
|
};
|
||||||
|
|
||||||
#endif // _WX_UNIV_INPHAND_H_
|
#endif // _WX_UNIV_INPHAND_H_
|
||||||
|
@@ -46,6 +46,7 @@ enum wxHitTest
|
|||||||
wxHT_NOWHERE,
|
wxHT_NOWHERE,
|
||||||
|
|
||||||
// scrollbar
|
// scrollbar
|
||||||
|
wxHT_SCROLLBAR_FIRST = wxHT_NOWHERE,
|
||||||
wxHT_SCROLLBAR_ARROW_LINE_1, // left or upper arrow to scroll by line
|
wxHT_SCROLLBAR_ARROW_LINE_1, // left or upper arrow to scroll by line
|
||||||
wxHT_SCROLLBAR_ARROW_LINE_2, // right or down
|
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_1, // left or upper arrow to scroll by page
|
||||||
@@ -53,6 +54,7 @@ enum wxHitTest
|
|||||||
wxHT_SCROLLBAR_THUMB, // on the thumb
|
wxHT_SCROLLBAR_THUMB, // on the thumb
|
||||||
wxHT_SCROLLBAR_BAR_1, // bar to the left/above 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_SCROLLBAR_BAR_2, // bar to the right/below the thumb
|
||||||
|
wxHT_SCROLLBAR_LAST,
|
||||||
|
|
||||||
wxHT_MAX
|
wxHT_MAX
|
||||||
};
|
};
|
||||||
|
@@ -16,6 +16,8 @@
|
|||||||
#pragma interface "univscrolbar.h"
|
#pragma interface "univscrolbar.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "wx/univ/renderer.h" // for wxHitTest
|
||||||
|
|
||||||
class WXDLLEXPORT wxInputHandler;
|
class WXDLLEXPORT wxInputHandler;
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@@ -42,15 +44,17 @@ class WXDLLEXPORT wxInputHandler;
|
|||||||
class WXDLLEXPORT wxScrollBar : public wxScrollBarBase
|
class WXDLLEXPORT wxScrollBar : public wxScrollBarBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// the parts of the scrollbar
|
// scrollbar elements: they correspond to wxHT_SCROLLBAR_XXX constants but
|
||||||
|
// start from 0 which allows to use them as array indices
|
||||||
enum Element
|
enum Element
|
||||||
{
|
{
|
||||||
Element_Arrow_Line_1,
|
Element_Arrow_Line_1,
|
||||||
Element_Arrow_Line_2,
|
Element_Arrow_Line_2,
|
||||||
Element_Arrow_Page_1,
|
Element_Arrow_Page_1,
|
||||||
Element_Arrow_Page_2,
|
Element_Arrow_Page_2,
|
||||||
Element_Thumb,
|
Element_Arrow_Thumb,
|
||||||
Element_Bar,
|
Element_Bar_1,
|
||||||
|
Element_Bar_2,
|
||||||
Element_Max
|
Element_Max
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -99,10 +103,8 @@ public:
|
|||||||
const wxEvent& event);
|
const wxEvent& event);
|
||||||
|
|
||||||
// wxScrollBar sub elements state (combination of wxCONTROL_XXX)
|
// wxScrollBar sub elements state (combination of wxCONTROL_XXX)
|
||||||
void SetState(Element elem, int flags)
|
void SetState(Element which, int flags) { m_elementsState[which] = flags; }
|
||||||
{ m_elementsState[elem] = flags; }
|
int GetState(Element which) const { return m_elementsState[which]; }
|
||||||
int GetState(Element elem) const
|
|
||||||
{ return m_elementsState[elem]; }
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual wxSize DoGetBestSize() const;
|
virtual wxSize DoGetBestSize() const;
|
||||||
@@ -110,7 +112,7 @@ protected:
|
|||||||
|
|
||||||
// SetThumbPosition() helper
|
// SetThumbPosition() helper
|
||||||
void DoSetThumb(int thumbPos);
|
void DoSetThumb(int thumbPos);
|
||||||
|
|
||||||
// common part of all ctors
|
// common part of all ctors
|
||||||
void Init();
|
void Init();
|
||||||
|
|
||||||
|
@@ -1015,7 +1015,7 @@ void wxWindow::OnIdle(wxIdleEvent& event)
|
|||||||
state |= MK_MBUTTON;
|
state |= MK_MBUTTON;
|
||||||
if ( GetKeyState( VK_RBUTTON ) )
|
if ( GetKeyState( VK_RBUTTON ) )
|
||||||
state |= MK_RBUTTON;
|
state |= MK_RBUTTON;
|
||||||
|
|
||||||
wxMouseEvent event(wxEVT_LEAVE_WINDOW);
|
wxMouseEvent event(wxEVT_LEAVE_WINDOW);
|
||||||
InitMouseEvent(event, pt.x, pt.y, state);
|
InitMouseEvent(event, pt.x, pt.y, state);
|
||||||
|
|
||||||
@@ -3273,13 +3273,22 @@ bool wxWindow::HandleMouseMove(int x, int y, WXUINT flags)
|
|||||||
{
|
{
|
||||||
if ( !m_mouseInWindow )
|
if ( !m_mouseInWindow )
|
||||||
{
|
{
|
||||||
// Generate an ENTER event
|
// it would be wrogn to assume that just because we get a mouse move
|
||||||
m_mouseInWindow = TRUE;
|
// event the mouse is inside the window: although this is usually true,
|
||||||
|
// it is not if we had captured the mouse, so we need to check the
|
||||||
|
// mouse coordinates here
|
||||||
|
POINT pt;
|
||||||
|
::GetCursorPos(&pt);
|
||||||
|
if ( ::WindowFromPoint(pt) == GetHwnd() )
|
||||||
|
{
|
||||||
|
// Generate an ENTER event
|
||||||
|
m_mouseInWindow = TRUE;
|
||||||
|
|
||||||
wxMouseEvent event(wxEVT_ENTER_WINDOW);
|
wxMouseEvent event(wxEVT_ENTER_WINDOW);
|
||||||
InitMouseEvent(event, x, y, flags);
|
InitMouseEvent(event, x, y, flags);
|
||||||
|
|
||||||
(void)GetEventHandler()->ProcessEvent(event);
|
(void)GetEventHandler()->ProcessEvent(event);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if wxUSE_MOUSEEVENT_HACK
|
#if wxUSE_MOUSEEVENT_HACK
|
||||||
|
@@ -37,6 +37,10 @@
|
|||||||
// implementation
|
// implementation
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// wxInputHandler
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
bool wxInputHandler::OnMouseMove(wxControl * WXUNUSED(control),
|
bool wxInputHandler::OnMouseMove(wxControl * WXUNUSED(control),
|
||||||
const wxMouseEvent& WXUNUSED(event))
|
const wxMouseEvent& WXUNUSED(event))
|
||||||
{
|
{
|
||||||
@@ -46,3 +50,308 @@ bool wxInputHandler::OnMouseMove(wxControl * WXUNUSED(control),
|
|||||||
wxInputHandler::~wxInputHandler()
|
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
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// wxStdScrollBarInputHandler
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
wxStdScrollBarInputHandler::wxStdScrollBarInputHandler(wxRenderer *renderer,
|
||||||
|
wxInputHandler *handler)
|
||||||
|
: wxStdInputHandler(handler)
|
||||||
|
{
|
||||||
|
m_renderer = renderer;
|
||||||
|
m_winCapture = NULL;
|
||||||
|
m_htLast = wxHT_NOWHERE;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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() )
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
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);
|
||||||
|
|
||||||
|
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 )
|
||||||
|
{
|
||||||
|
m_winCapture->ReleaseMouse();
|
||||||
|
m_winCapture = NULL;
|
||||||
|
m_btnCapture = -1;
|
||||||
|
|
||||||
|
// unpress the arrow and highlight the current element
|
||||||
|
Press(scrollbar, FALSE);
|
||||||
|
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 )
|
||||||
|
{
|
||||||
|
// everything is locked while the mouse is captured, so don't do
|
||||||
|
// anything
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// highlighting changed
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
@@ -56,7 +56,7 @@ void wxScrollBar::Init()
|
|||||||
m_thumbPos =
|
m_thumbPos =
|
||||||
m_pageSize = 0;
|
m_pageSize = 0;
|
||||||
|
|
||||||
for ( size_t n = 0; n < Element_Max; n++ )
|
for ( size_t n = 0; n < WXSIZEOF(m_elementsState); n++ )
|
||||||
{
|
{
|
||||||
m_elementsState[n] = 0;
|
m_elementsState[n] = 0;
|
||||||
}
|
}
|
||||||
|
@@ -162,53 +162,15 @@ protected:
|
|||||||
wxGTKRenderer *m_renderer;
|
wxGTKRenderer *m_renderer;
|
||||||
};
|
};
|
||||||
|
|
||||||
class wxGTKButtonInputHandler : public wxGTKInputHandler
|
class wxGTKScrollBarInputHandler : public wxStdScrollBarInputHandler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
wxGTKButtonInputHandler(wxGTKRenderer *renderer);
|
wxGTKScrollBarInputHandler(wxRenderer *renderer, wxInputHandler *handler)
|
||||||
|
: wxStdScrollBarInputHandler(renderer, handler) { }
|
||||||
|
|
||||||
virtual wxControlActions Map(wxControl *control,
|
protected:
|
||||||
const wxKeyEvent& event,
|
virtual bool OnMouseLeave() { return FALSE; }
|
||||||
bool pressed);
|
virtual bool IsAllowedButton(int WXUNUSED(button)) { return TRUE; }
|
||||||
virtual wxControlActions Map(wxControl *control,
|
|
||||||
const wxMouseEvent& event);
|
|
||||||
virtual bool OnMouseMove(wxControl *control, const wxMouseEvent& event);
|
|
||||||
|
|
||||||
private:
|
|
||||||
wxWindow *m_winCapture;
|
|
||||||
bool m_winHasMouse;
|
|
||||||
};
|
|
||||||
|
|
||||||
class wxGTKScrollBarInputHandler : public wxGTKInputHandler
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
wxGTKScrollBarInputHandler(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);
|
|
||||||
|
|
||||||
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;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@@ -282,9 +244,10 @@ wxInputHandler *wxGTKTheme::GetInputHandler(const wxString& control)
|
|||||||
n = m_handlerNames.Add(control);
|
n = m_handlerNames.Add(control);
|
||||||
|
|
||||||
if ( control == _T("wxButton") )
|
if ( control == _T("wxButton") )
|
||||||
handler = new wxGTKButtonInputHandler(m_renderer);
|
handler = new wxStdButtonInputHandler(GetInputHandler(_T("wxControl")));
|
||||||
else if ( control == _T("wxScrollBar") )
|
else if ( control == _T("wxScrollBar") )
|
||||||
handler = new wxGTKScrollBarInputHandler(m_renderer);
|
handler = new wxGTKScrollBarInputHandler(m_renderer,
|
||||||
|
GetInputHandler(_T("wxControl")));
|
||||||
else
|
else
|
||||||
handler = new wxGTKInputHandler(m_renderer);
|
handler = new wxGTKInputHandler(m_renderer);
|
||||||
|
|
||||||
@@ -810,9 +773,9 @@ void wxGTKRenderer::DrawScrollbar(wxDC& dc,
|
|||||||
"\tthumb: 0x%04x\n"
|
"\tthumb: 0x%04x\n"
|
||||||
"\tthumb from %d to %d",
|
"\tthumb from %d to %d",
|
||||||
orient == wxVERTICAL ? "vertical" : "horizontal",
|
orient == wxVERTICAL ? "vertical" : "horizontal",
|
||||||
flags[wxScrollBar::Element_Arrow_Line_1],
|
flags[wxHT_SCROLLBAR_ARROW_LINE_1],
|
||||||
flags[wxScrollBar::Element_Arrow_Line_2],
|
flags[wxHT_SCROLLBAR_ARROW_LINE_2],
|
||||||
flags[wxScrollBar::Element_Thumb],
|
flags[wxHT_SCROLLBAR_THUMB],
|
||||||
thumbPosStart, thumbPosEnd);
|
thumbPosStart, thumbPosEnd);
|
||||||
#endif // DEBUG_MOUSE
|
#endif // DEBUG_MOUSE
|
||||||
|
|
||||||
@@ -850,7 +813,7 @@ void wxGTKRenderer::DrawScrollbar(wxDC& dc,
|
|||||||
for ( size_t nArrow = 0; nArrow < 2; nArrow++ )
|
for ( size_t nArrow = 0; nArrow < 2; nArrow++ )
|
||||||
{
|
{
|
||||||
DrawArrow(dc, arrowDir[nArrow], rectArrow[nArrow],
|
DrawArrow(dc, arrowDir[nArrow], rectArrow[nArrow],
|
||||||
flags[wxScrollBar::Element_Arrow_Line_1 + nArrow]);
|
flags[wxHT_SCROLLBAR_ARROW_LINE_1 + nArrow]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// and, finally, the thumb, if any
|
// and, finally, the thumb, if any
|
||||||
@@ -874,7 +837,7 @@ void wxGTKRenderer::DrawScrollbar(wxDC& dc,
|
|||||||
|
|
||||||
// the thumb is never pressed never has focus border under GTK and the
|
// the thumb is never pressed never has focus border under GTK and the
|
||||||
// scrollbar background never changes at all
|
// scrollbar background never changes at all
|
||||||
int flagsThumb = flags[wxScrollBar::Element_Thumb] &
|
int flagsThumb = flags[wxHT_SCROLLBAR_THUMB] &
|
||||||
~(wxCONTROL_PRESSED | wxCONTROL_FOCUSED);
|
~(wxCONTROL_PRESSED | wxCONTROL_FOCUSED);
|
||||||
DrawButtonBorder(dc, rectThumb, flagsThumb, &rectThumb);
|
DrawButtonBorder(dc, rectThumb, flagsThumb, &rectThumb);
|
||||||
DrawBackground(dc, rectThumb, flagsThumb);
|
DrawBackground(dc, rectThumb, flagsThumb);
|
||||||
@@ -995,300 +958,3 @@ bool wxGTKInputHandler::OnMouseMove(wxControl *control,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
|
||||||
// wxGTKButtonInputHandler
|
|
||||||
// ----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
wxGTKButtonInputHandler::wxGTKButtonInputHandler(wxGTKRenderer *renderer)
|
|
||||||
: wxGTKInputHandler(renderer)
|
|
||||||
{
|
|
||||||
m_winCapture = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
wxControlActions wxGTKButtonInputHandler::Map(wxControl *control,
|
|
||||||
const wxKeyEvent& event,
|
|
||||||
bool pressed)
|
|
||||||
{
|
|
||||||
int keycode = event.GetKeyCode();
|
|
||||||
if ( keycode == WXK_SPACE || keycode == WXK_RETURN )
|
|
||||||
{
|
|
||||||
return wxACTION_BUTTON_TOGGLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return wxGTKInputHandler::Map(control, event, pressed);
|
|
||||||
}
|
|
||||||
|
|
||||||
wxControlActions wxGTKButtonInputHandler::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
|
|
||||||
{
|
|
||||||
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 wxGTKInputHandler::Map(control, event);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool wxGTKButtonInputHandler::OnMouseMove(wxControl *control,
|
|
||||||
const wxMouseEvent& event)
|
|
||||||
{
|
|
||||||
// leaving the button should remove its pressed state
|
|
||||||
if ( event.Leaving() )
|
|
||||||
{
|
|
||||||
if ( m_winCapture )
|
|
||||||
{
|
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// and entering it back should make it pressed again if it had been
|
|
||||||
// pressed
|
|
||||||
else if ( event.Entering() )
|
|
||||||
{
|
|
||||||
if ( m_winCapture )
|
|
||||||
{
|
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return wxGTKInputHandler::OnMouseMove(control, event);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
|
||||||
// wxGTKScrollBarInputHandler
|
|
||||||
// ----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
wxGTKScrollBarInputHandler::wxGTKScrollBarInputHandler(wxGTKRenderer *renderer)
|
|
||||||
: wxGTKInputHandler(renderer)
|
|
||||||
{
|
|
||||||
m_winCapture = NULL;
|
|
||||||
m_htLast = wxHT_NOWHERE;
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
// 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(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() )
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
// highlighting changed
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
@@ -61,6 +61,7 @@ public:
|
|||||||
{
|
{
|
||||||
Arrow_Normal,
|
Arrow_Normal,
|
||||||
Arrow_Disabled,
|
Arrow_Disabled,
|
||||||
|
Arrow_Pressed,
|
||||||
Arrow_StateMax
|
Arrow_StateMax
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -132,7 +133,7 @@ protected:
|
|||||||
void DrawRaisedBorder(wxDC& dc, wxRect *rect);
|
void DrawRaisedBorder(wxDC& dc, wxRect *rect);
|
||||||
|
|
||||||
// draw the border used for scrollbar arrows
|
// draw the border used for scrollbar arrows
|
||||||
void DrawArrowBorder(wxDC& dc, wxRect *rect);
|
void DrawArrowBorder(wxDC& dc, wxRect *rect, bool isPressed = FALSE);
|
||||||
|
|
||||||
// public DrawArrow()s helper
|
// public DrawArrow()s helper
|
||||||
void DrawArrow(wxDC& dc, const wxRect& rect,
|
void DrawArrow(wxDC& dc, const wxRect& rect,
|
||||||
@@ -182,38 +183,26 @@ protected:
|
|||||||
wxWin32Renderer *m_renderer;
|
wxWin32Renderer *m_renderer;
|
||||||
};
|
};
|
||||||
|
|
||||||
class wxWin32ButtonInputHandler : public wxWin32InputHandler
|
class wxWin32ScrollBarInputHandler : public wxStdScrollBarInputHandler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
wxWin32ButtonInputHandler(wxWin32Renderer *renderer);
|
wxWin32ScrollBarInputHandler(wxWin32Renderer *renderer,
|
||||||
|
wxInputHandler *handler)
|
||||||
|
: wxStdScrollBarInputHandler(renderer, handler) { }
|
||||||
|
|
||||||
virtual wxControlActions Map(wxControl *control,
|
// we don't highlight scrollbar elements, so there is no need to process
|
||||||
const wxKeyEvent& event,
|
// mouse move events
|
||||||
bool pressed);
|
virtual bool OnMouseMove(wxControl *control, const wxMouseEvent& event)
|
||||||
virtual wxControlActions Map(wxControl *control,
|
{
|
||||||
const wxMouseEvent& event);
|
if ( event.Moving() )
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
private:
|
return wxStdScrollBarInputHandler::OnMouseMove(control, event);
|
||||||
wxWindow *m_winCapture;
|
}
|
||||||
};
|
|
||||||
|
|
||||||
class wxWin32ScrollBarInputHandler : public wxWin32InputHandler
|
protected:
|
||||||
{
|
virtual bool OnMouseLeave() { return TRUE; }
|
||||||
public:
|
virtual bool IsAllowedButton(int button) { return button == 1; }
|
||||||
wxWin32ScrollBarInputHandler(wxWin32Renderer *renderer);
|
|
||||||
|
|
||||||
virtual wxControlActions Map(wxControl *control,
|
|
||||||
const wxKeyEvent& event,
|
|
||||||
bool pressed);
|
|
||||||
virtual wxControlActions Map(wxControl *control,
|
|
||||||
const wxMouseEvent& event);
|
|
||||||
|
|
||||||
private:
|
|
||||||
void Press(wxScrollBar *scrollbar, bool doIt) { }
|
|
||||||
|
|
||||||
wxWindow *m_winCapture;
|
|
||||||
int m_btnCapture;
|
|
||||||
wxHitTest m_htLast;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@@ -289,9 +278,10 @@ wxInputHandler *wxWin32Theme::GetInputHandler(const wxString& control)
|
|||||||
n = m_handlerNames.Add(control);
|
n = m_handlerNames.Add(control);
|
||||||
|
|
||||||
if ( control == _T("wxButton") )
|
if ( control == _T("wxButton") )
|
||||||
handler = new wxWin32ButtonInputHandler(m_renderer);
|
handler = new wxStdButtonInputHandler(GetInputHandler(_T("wxControl")));
|
||||||
else if ( control == _T("wxScrollBar") )
|
else if ( control == _T("wxScrollBar") )
|
||||||
handler = new wxWin32ScrollBarInputHandler(m_renderer);
|
handler = new wxWin32ScrollBarInputHandler(m_renderer,
|
||||||
|
GetInputHandler(_T("wxControl")));
|
||||||
else
|
else
|
||||||
handler = new wxWin32InputHandler(m_renderer);
|
handler = new wxWin32InputHandler(m_renderer);
|
||||||
|
|
||||||
@@ -322,6 +312,10 @@ wxColour wxWin32ColourScheme::Get(wxWin32ColourScheme::StdColour col,
|
|||||||
{
|
{
|
||||||
case CONTROL: return wxColour(0xc0c0c0);
|
case CONTROL: return wxColour(0xc0c0c0);
|
||||||
case CONTROL_TEXT: return *wxBLACK;
|
case CONTROL_TEXT: return *wxBLACK;
|
||||||
|
case SCROLLBAR: if ( flags & wxCONTROL_PRESSED )
|
||||||
|
return *wxBLACK;
|
||||||
|
else
|
||||||
|
return wxColour(0xe0e0e0);
|
||||||
|
|
||||||
case HIGHLIGHT: return wxColour(0x800000);
|
case HIGHLIGHT: return wxColour(0x800000);
|
||||||
case HIGHLIGHT_TEXT: return wxColour(0xffffff);
|
case HIGHLIGHT_TEXT: return wxColour(0xffffff);
|
||||||
@@ -500,6 +494,8 @@ wxWin32Renderer::wxWin32Renderer(const wxColourScheme *scheme)
|
|||||||
m_bmpArrows[Arrow_Normal][n].SetMask(mask);
|
m_bmpArrows[Arrow_Normal][n].SetMask(mask);
|
||||||
mask = new wxMask(m_bmpArrows[Arrow_Disabled][n], *wxWHITE);
|
mask = new wxMask(m_bmpArrows[Arrow_Disabled][n], *wxWHITE);
|
||||||
m_bmpArrows[Arrow_Disabled][n].SetMask(mask);
|
m_bmpArrows[Arrow_Disabled][n].SetMask(mask);
|
||||||
|
|
||||||
|
m_bmpArrows[Arrow_Pressed][n] = m_bmpArrows[Arrow_Normal][n];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -624,10 +620,25 @@ void wxWin32Renderer::DrawRaisedBorder(wxDC& dc, wxRect *rect)
|
|||||||
DrawShadedRect(dc, rect, m_penLightGrey, m_penDarkGrey);
|
DrawShadedRect(dc, rect, m_penLightGrey, m_penDarkGrey);
|
||||||
}
|
}
|
||||||
|
|
||||||
void wxWin32Renderer::DrawArrowBorder(wxDC& dc, wxRect *rect)
|
void wxWin32Renderer::DrawArrowBorder(wxDC& dc, wxRect *rect, bool isPressed)
|
||||||
{
|
{
|
||||||
DrawShadedRect(dc, rect, m_penLightGrey, m_penBlack);
|
if ( isPressed )
|
||||||
DrawShadedRect(dc, rect, m_penHighlight, m_penDarkGrey);
|
{
|
||||||
|
DrawRect(dc, rect, m_penDarkGrey);
|
||||||
|
|
||||||
|
// the arrow is usually drawn inside border of width 2 and is offset by
|
||||||
|
// another pixel in both directions when it's pressed - as the border
|
||||||
|
// in this case is more narrow as well, we have to adjust rect like
|
||||||
|
// this:
|
||||||
|
rect->Inflate(-1);
|
||||||
|
rect->x++;
|
||||||
|
rect->y++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DrawShadedRect(dc, rect, m_penLightGrey, m_penBlack);
|
||||||
|
DrawShadedRect(dc, rect, m_penHighlight, m_penDarkGrey);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void wxWin32Renderer::DrawBorder(wxDC& dc,
|
void wxWin32Renderer::DrawBorder(wxDC& dc,
|
||||||
@@ -912,7 +923,7 @@ void wxWin32Renderer::DrawArrowButton(wxDC& dc,
|
|||||||
wxArrowStyle arrowStyle)
|
wxArrowStyle arrowStyle)
|
||||||
{
|
{
|
||||||
wxRect rect = rectAll;
|
wxRect rect = rectAll;
|
||||||
DrawArrowBorder(dc, &rect);
|
DrawArrowBorder(dc, &rect, arrowStyle == Arrow_Pressed);
|
||||||
DrawArrow(dc, rect, arrowDir, arrowStyle);
|
DrawArrow(dc, rect, arrowDir, arrowStyle);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -923,10 +934,6 @@ void wxWin32Renderer::DrawScrollbar(wxDC& dc,
|
|||||||
const wxRect& rect,
|
const wxRect& rect,
|
||||||
const int *flags)
|
const int *flags)
|
||||||
{
|
{
|
||||||
int flagsSb = flags ? flags[0] : 0;
|
|
||||||
wxArrowStyle arrowStyle = flagsSb & wxCONTROL_DISABLED ? Arrow_Disabled
|
|
||||||
: Arrow_Normal;
|
|
||||||
|
|
||||||
// first, draw the arrows at the ends
|
// first, draw the arrows at the ends
|
||||||
wxRect rectArrow[2];
|
wxRect rectArrow[2];
|
||||||
wxArrowDirection arrowDir[2];
|
wxArrowDirection arrowDir[2];
|
||||||
@@ -952,24 +959,34 @@ void wxWin32Renderer::DrawScrollbar(wxDC& dc,
|
|||||||
arrowDir[1] = Arrow_Right;
|
arrowDir[1] = Arrow_Right;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wxArrowStyle arrowStyle;
|
||||||
for ( size_t nArrow = 0; nArrow < 2; nArrow++ )
|
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);
|
DrawArrowButton(dc, rectArrow[nArrow], arrowDir[nArrow], arrowStyle);
|
||||||
}
|
}
|
||||||
|
|
||||||
// next draw the scrollbar area
|
// 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;
|
wxRect rectBar = rect;
|
||||||
if ( orient == wxVERTICAL )
|
if ( orient == wxVERTICAL )
|
||||||
rectBar.Inflate(0, -m_sizeScrollbarArrow.y);
|
rectBar.Inflate(0, -(m_sizeScrollbarArrow.y + 1));
|
||||||
else
|
else
|
||||||
rectBar.Inflate(-m_sizeScrollbarArrow.x, 0);
|
rectBar.Inflate(-(m_sizeScrollbarArrow.x + 1), 0);
|
||||||
|
|
||||||
DoDrawBackground(dc, m_colHighlight, rectBar);
|
// calculate the thumb position
|
||||||
|
wxRect rectThumb;
|
||||||
// and, finally, the thumb, if any
|
|
||||||
if ( thumbPosStart < thumbPosEnd )
|
if ( thumbPosStart < thumbPosEnd )
|
||||||
{
|
{
|
||||||
wxRect rectThumb = rectBar;
|
rectThumb = rectBar;
|
||||||
if ( orient == wxVERTICAL )
|
if ( orient == wxVERTICAL )
|
||||||
{
|
{
|
||||||
rectThumb.y += (rectBar.height*thumbPosStart)/100;
|
rectThumb.y += (rectBar.height*thumbPosStart)/100;
|
||||||
@@ -980,7 +997,53 @@ void wxWin32Renderer::DrawScrollbar(wxDC& dc,
|
|||||||
rectThumb.x += (rectBar.width*thumbPosStart)/100;
|
rectThumb.x += (rectBar.width*thumbPosStart)/100;
|
||||||
rectThumb.width = (rectBar.width*(thumbPosEnd - thumbPosStart))/100;
|
rectThumb.width = (rectBar.width*(thumbPosEnd - thumbPosStart))/100;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
//else: no thumb
|
||||||
|
|
||||||
|
if ( (flags[wxScrollBar::Element_Bar_1] & wxCONTROL_PRESSED) ||
|
||||||
|
(flags[wxScrollBar::Element_Bar_2] & wxCONTROL_PRESSED) )
|
||||||
|
{
|
||||||
|
// calculate the bounding boxes for each of 2 bar parts
|
||||||
|
wxRect rectBars[2];
|
||||||
|
rectBars[0] =
|
||||||
|
rectBars[1] = rectBar;
|
||||||
|
if ( orient == wxVERTICAL )
|
||||||
|
{
|
||||||
|
rectBars[0].SetTop(m_sizeScrollbarArrow.y);
|
||||||
|
rectBars[0].SetBottom(rectThumb.GetTop() - 1);
|
||||||
|
rectBars[1].SetTop(rectThumb.GetBottom() + 1);
|
||||||
|
rectBars[1].SetBottom(rectBar.GetBottom());
|
||||||
|
}
|
||||||
|
else // horizontal
|
||||||
|
{
|
||||||
|
rectBars[0].SetLeft(m_sizeScrollbarArrow.x);
|
||||||
|
rectBars[0].SetRight(rectThumb.GetLeft() - 1);
|
||||||
|
rectBars[1].SetLeft(rectThumb.GetRight() + 1);
|
||||||
|
rectBars[1].SetRight(rectBar.GetRight());
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( size_t nBar = 0; nBar < 2; nBar++ )
|
||||||
|
{
|
||||||
|
DoDrawBackground(
|
||||||
|
dc,
|
||||||
|
m_scheme->Get
|
||||||
|
(
|
||||||
|
wxColourScheme::SCROLLBAR,
|
||||||
|
flags[wxScrollBar::Element_Bar_1 + nBar]
|
||||||
|
),
|
||||||
|
rectBars[nBar]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else // nothing is pressed
|
||||||
|
{
|
||||||
|
DoDrawBackground(dc, m_scheme->Get(wxColourScheme::SCROLLBAR), rectBar);
|
||||||
|
}
|
||||||
|
|
||||||
|
// and, finally, the thumb, if any
|
||||||
|
if ( thumbPosStart < thumbPosEnd )
|
||||||
|
{
|
||||||
|
// we don't use the flags, the thumb never changes appearance
|
||||||
DrawArrowBorder(dc, &rectThumb);
|
DrawArrowBorder(dc, &rectThumb);
|
||||||
DrawBackground(dc, rectThumb);
|
DrawBackground(dc, rectThumb);
|
||||||
}
|
}
|
||||||
@@ -1072,178 +1135,3 @@ wxControlActions wxWin32InputHandler::Map(wxControl *control,
|
|||||||
{
|
{
|
||||||
return wxACTION_NONE;
|
return wxACTION_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
|
||||||
// wxWin32ButtonInputHandler
|
|
||||||
// ----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
wxWin32ButtonInputHandler::wxWin32ButtonInputHandler(wxWin32Renderer *renderer)
|
|
||||||
: wxWin32InputHandler(renderer)
|
|
||||||
{
|
|
||||||
m_winCapture = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
wxControlActions wxWin32ButtonInputHandler::Map(wxControl *control,
|
|
||||||
const wxKeyEvent& event,
|
|
||||||
bool pressed)
|
|
||||||
{
|
|
||||||
int keycode = event.GetKeyCode();
|
|
||||||
if ( keycode == WXK_SPACE || keycode == WXK_RETURN )
|
|
||||||
{
|
|
||||||
return wxACTION_BUTTON_TOGGLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return wxWin32InputHandler::Map(control, event, pressed);
|
|
||||||
}
|
|
||||||
|
|
||||||
wxControlActions wxWin32ButtonInputHandler::Map(wxControl *control,
|
|
||||||
const wxMouseEvent& event)
|
|
||||||
{
|
|
||||||
if ( event.IsButton() )
|
|
||||||
{
|
|
||||||
if ( event.ButtonDown() )
|
|
||||||
{
|
|
||||||
m_winCapture = wxWindow::FindFocus();
|
|
||||||
m_winCapture->CaptureMouse();
|
|
||||||
}
|
|
||||||
else // up
|
|
||||||
{
|
|
||||||
m_winCapture->ReleaseMouse();
|
|
||||||
}
|
|
||||||
|
|
||||||
return wxACTION_BUTTON_TOGGLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return wxWin32InputHandler::Map(control, event);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
|
||||||
// wxWin32ScrollBarInputHandler
|
|
||||||
// ----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
wxWin32ScrollBarInputHandler::wxWin32ScrollBarInputHandler(wxWin32Renderer *renderer)
|
|
||||||
: wxWin32InputHandler(renderer)
|
|
||||||
{
|
|
||||||
m_winCapture = NULL;
|
|
||||||
m_htLast = wxHT_NOWHERE;
|
|
||||||
}
|
|
||||||
|
|
||||||
wxControlActions wxWin32ScrollBarInputHandler::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 wxWin32InputHandler::Map(control, event, pressed);
|
|
||||||
}
|
|
||||||
|
|
||||||
wxControlActions wxWin32ScrollBarInputHandler::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
|
|
||||||
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;
|
|
||||||
|
|
||||||
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 wxWin32InputHandler::Map(control, event);
|
|
||||||
}
|
|
||||||
|
Reference in New Issue
Block a user