Files
wxWidgets/src/common/uiactioncmn.cpp
Vadim Zeitlin f412007f61 Make wxUIActionSimulator::Text() to work with punctuation characters.
Currently this only really works when using the standard US keyboard layout as
we don't have information about the mapping from the characters to the keyboard
keys for the other layouts, which is not ideal but better than nothing as it
allows e.g. Text("foo_bar") to really produce "foo_bar" in the currently
focused text control instead of "foo-bar" as before.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@78495 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
2015-02-15 00:02:00 +00:00

211 lines
5.3 KiB
C++

/////////////////////////////////////////////////////////////////////////////
// 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"
#include "wx/ctrlsub.h"
#ifdef wxNO_RTTI
#include "wx/choice.h"
#include "wx/combobox.h"
#include "wx/listbox.h"
#endif // wxNO_RTTI
bool wxUIActionSimulator::MouseClick(int button)
{
MouseDown(button);
MouseUp(button);
return true;
}
#ifndef __WXOSX__
bool wxUIActionSimulator::MouseDblClick(int button)
{
MouseDown(button);
MouseUp(button);
MouseDown(button);
MouseUp(button);
return true;
}
bool wxUIActionSimulator::MouseDragDrop(long x1, long y1, long x2, long y2,
int button)
{
MouseMove(x1, y1);
MouseDown(button);
MouseMove(x2, y2);
MouseUp(button);
return true;
}
#endif
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;
}
// 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;
}
bool wxUIActionSimulator::Text(const char *s)
{
while ( *s != '\0' )
{
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) )
return false;
}
return true;
}
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;
}
#endif // wxUSE_UIACTIONSIMULATOR