2011-03-20 18:05:19 +00:00
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Name: src/common/uiactioncmn.cpp
|
|
|
|
// Purpose: wxUIActionSimulator common implementation
|
|
|
|
// Author: Kevin Ollivier, Steven Lamerton, Vadim Zeitlin
|
|
|
|
// Modified by:
|
|
|
|
// Created: 2010-03-06
|
|
|
|
// Copyright: (c) Kevin Ollivier
|
|
|
|
// (c) 2010 Steven Lamerton
|
|
|
|
// (c) 2010 Vadim Zeitlin
|
|
|
|
// Licence: wxWindows licence
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
#include "wx/wxprec.h"
|
|
|
|
|
|
|
|
#if wxUSE_UIACTIONSIMULATOR
|
|
|
|
|
|
|
|
#include "wx/uiaction.h"
|
|
|
|
|
2016-06-26 05:25:29 +00:00
|
|
|
#include "wx/ctrlsub.h"
|
|
|
|
|
|
|
|
#ifdef wxNO_RTTI
|
|
|
|
#include "wx/choice.h"
|
|
|
|
#include "wx/combobox.h"
|
|
|
|
#include "wx/listbox.h"
|
|
|
|
#endif // wxNO_RTTI
|
|
|
|
|
|
|
|
|
2011-03-20 18:05:19 +00:00
|
|
|
bool wxUIActionSimulator::MouseClick(int button)
|
|
|
|
{
|
|
|
|
MouseDown(button);
|
|
|
|
MouseUp(button);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2013-09-22 18:44:55 -04:00
|
|
|
#ifndef __WXOSX__
|
|
|
|
|
2011-03-20 18:05:19 +00:00
|
|
|
bool wxUIActionSimulator::MouseDblClick(int button)
|
|
|
|
{
|
|
|
|
MouseDown(button);
|
|
|
|
MouseUp(button);
|
|
|
|
MouseDown(button);
|
|
|
|
MouseUp(button);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2013-09-22 18:44:55 -04:00
|
|
|
bool wxUIActionSimulator::MouseDragDrop(long x1, long y1, long x2, long y2,
|
2011-03-20 18:05:19 +00:00
|
|
|
int button)
|
|
|
|
{
|
|
|
|
MouseMove(x1, y1);
|
|
|
|
MouseDown(button);
|
|
|
|
MouseMove(x2, y2);
|
|
|
|
MouseUp(button);
|
2013-09-22 18:44:55 -04:00
|
|
|
|
2011-03-20 18:05:19 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2013-09-22 18:44:55 -04:00
|
|
|
#endif
|
|
|
|
|
2011-03-20 18:05:19 +00:00
|
|
|
bool
|
|
|
|
wxUIActionSimulator::Key(int keycode, int modifiers, bool isDown)
|
|
|
|
{
|
|
|
|
wxASSERT_MSG( !(modifiers & wxMOD_META ),
|
|
|
|
"wxMOD_META is not implemented" );
|
|
|
|
wxASSERT_MSG( !(modifiers & wxMOD_WIN ),
|
|
|
|
"wxMOD_WIN is not implemented" );
|
|
|
|
|
|
|
|
if ( isDown )
|
|
|
|
SimulateModifiers(modifiers, true);
|
|
|
|
|
|
|
|
bool rc = DoKey(keycode, modifiers, isDown);
|
|
|
|
|
|
|
|
if ( !isDown )
|
|
|
|
SimulateModifiers(modifiers, false);
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
void wxUIActionSimulator::SimulateModifiers(int modifiers, bool isDown)
|
|
|
|
{
|
|
|
|
if ( modifiers & wxMOD_SHIFT )
|
|
|
|
DoKey(WXK_SHIFT, modifiers, isDown);
|
|
|
|
if ( modifiers & wxMOD_ALT )
|
|
|
|
DoKey(WXK_ALT, modifiers, isDown);
|
|
|
|
if ( modifiers & wxMOD_CONTROL )
|
|
|
|
DoKey(WXK_CONTROL, modifiers, isDown);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool wxUIActionSimulator::Char(int keycode, int modifiers)
|
|
|
|
{
|
|
|
|
Key(keycode, modifiers, true);
|
|
|
|
Key(keycode, modifiers, false);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2016-06-26 05:25:29 +00:00
|
|
|
// Helper function checking if a key must be entered with Shift pressed. If it
|
|
|
|
// must, returns true and modifies the key to contain the unshifted version.
|
|
|
|
//
|
|
|
|
// This currently works only for the standard US keyboard layout which is
|
|
|
|
// definitely not ideal, but better than nothing...
|
|
|
|
static bool MapUnshifted(char& ch)
|
|
|
|
{
|
|
|
|
const char* const unshifted =
|
|
|
|
"`1234567890-=\\"
|
|
|
|
"[]"
|
|
|
|
";'"
|
|
|
|
",./"
|
|
|
|
;
|
|
|
|
|
|
|
|
const char* const shifted =
|
|
|
|
"~!@#$%^&*()_+|"
|
|
|
|
"{}"
|
|
|
|
":\""
|
|
|
|
"<>?"
|
|
|
|
;
|
|
|
|
|
|
|
|
wxCOMPILE_TIME_ASSERT( sizeof(unshifted) == sizeof(shifted),
|
|
|
|
ShiftedUnshiftedKeysMismatch );
|
|
|
|
|
|
|
|
const char* const p = strchr(shifted, ch);
|
|
|
|
if ( !p )
|
|
|
|
return false;
|
|
|
|
|
|
|
|
ch = *(unshifted + (p - shifted));
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2011-03-20 18:05:19 +00:00
|
|
|
bool wxUIActionSimulator::Text(const char *s)
|
|
|
|
{
|
|
|
|
while ( *s != '\0' )
|
|
|
|
{
|
2016-06-26 05:25:29 +00:00
|
|
|
char ch = *s++;
|
|
|
|
|
|
|
|
// Map the keys that must be entered with Shift modifier to their
|
|
|
|
// unshifted counterparts.
|
|
|
|
int modifiers = 0;
|
|
|
|
if ( isupper(ch) || MapUnshifted(ch) )
|
|
|
|
modifiers |= wxMOD_SHIFT;
|
|
|
|
|
|
|
|
if ( !Char(ch, modifiers) )
|
2011-03-20 18:05:19 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2016-06-26 05:25:29 +00:00
|
|
|
bool wxUIActionSimulator::Select(const wxString& text)
|
|
|
|
{
|
|
|
|
wxWindow* const focus = wxWindow::FindFocus();
|
|
|
|
if ( !focus )
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// We can only select something in controls inheriting from
|
|
|
|
// wxItemContainer, so check that we have it.
|
|
|
|
#ifdef wxNO_RTTI
|
|
|
|
wxItemContainer* container = NULL;
|
|
|
|
|
|
|
|
if ( wxComboBox* combo = wxDynamicCast(focus, wxComboBox) )
|
|
|
|
container = combo;
|
|
|
|
else if ( wxChoice* choice = wxDynamicCast(focus, wxChoice) )
|
|
|
|
container = choice;
|
|
|
|
else if ( wxListBox* listbox = wxDynamicCast(focus, wxListBox) )
|
|
|
|
container = listbox;
|
|
|
|
#else // !wxNO_RTTI
|
|
|
|
wxItemContainer* const container = dynamic_cast<wxItemContainer*>(focus);
|
|
|
|
#endif // wxNO_RTTI/!wxNO_RTTI
|
|
|
|
|
|
|
|
if ( !container )
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// We prefer to exactly emulate what a (keyboard) user would do, so prefer
|
|
|
|
// to emulate selecting the first item of the control if possible (this
|
|
|
|
// works with wxChoice, wxListBox and wxComboBox with wxCB_READONLY style
|
|
|
|
// under MSW).
|
|
|
|
if ( container->GetSelection() != 0 )
|
|
|
|
{
|
|
|
|
Char(WXK_HOME);
|
|
|
|
wxYield();
|
|
|
|
|
|
|
|
// But if this didn't work, set the selection programmatically.
|
|
|
|
if ( container->GetSelection() != 0 )
|
|
|
|
container->SetSelection(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
// And then go down in the control until we reach the item we want.
|
|
|
|
for ( ;; )
|
|
|
|
{
|
|
|
|
if ( container->GetStringSelection() == text )
|
|
|
|
return true;
|
|
|
|
|
|
|
|
// We could test if the selection becomes equal to its maximal value
|
|
|
|
// (i.e. GetCount() - 1), but if, for some reason, pressing WXK_DOWN
|
|
|
|
// doesn't move it, this would still result in an infinite loop, so
|
|
|
|
// check that the selection changed for additional safety.
|
|
|
|
const int current = container->GetSelection();
|
|
|
|
|
|
|
|
Char(WXK_DOWN);
|
|
|
|
wxYield();
|
|
|
|
|
|
|
|
if ( container->GetSelection() == current )
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2011-03-20 18:05:19 +00:00
|
|
|
#endif // wxUSE_UIACTIONSIMULATOR
|