262 lines
8.3 KiB
C++
262 lines
8.3 KiB
C++
// SuperTuxKart - a fun racing game with go-kart
|
|
// Copyright (C) 2009-2015 Marianne Gagnon
|
|
//
|
|
// This program is free software; you can redistribute it and/or
|
|
// modify it under the terms of the GNU General Public License
|
|
// as published by the Free Software Foundation; either version 3
|
|
// of the License, or (at your option) any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with this program; if not, write to the Free Software
|
|
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
#include "guiengine/engine.hpp"
|
|
#include "guiengine/modaldialog.hpp"
|
|
#include "guiengine/screen_keyboard.hpp"
|
|
#include "guiengine/widgets/text_box_widget.hpp"
|
|
#include "guiengine/widgets/CGUIEditBox.hpp"
|
|
#include "utils/ptr_vector.hpp"
|
|
#include "utils/translation.hpp"
|
|
|
|
#include <IGUIElement.h>
|
|
#include <IGUIEnvironment.h>
|
|
#include <IGUIButton.h>
|
|
|
|
using namespace irr;
|
|
|
|
class MyCGUIEditBox : public CGUIEditBox
|
|
{
|
|
PtrVector<GUIEngine::ITextBoxWidgetListener, REF> m_listeners;
|
|
|
|
public:
|
|
|
|
MyCGUIEditBox(const wchar_t* text, bool border, gui::IGUIEnvironment* environment,
|
|
gui:: IGUIElement* parent, s32 id, const core::rect<s32>& rectangle) :
|
|
CGUIEditBox(text, border, environment, parent, id, rectangle, translations->isRTLLanguage())
|
|
{
|
|
if (translations->isRTLLanguage()) setTextAlignment(irr::gui::EGUIA_LOWERRIGHT, irr::gui::EGUIA_CENTER);
|
|
}
|
|
|
|
void addListener(GUIEngine::ITextBoxWidgetListener* listener)
|
|
{
|
|
m_listeners.push_back(listener);
|
|
}
|
|
|
|
void clearListeners()
|
|
{
|
|
m_listeners.clearWithoutDeleting();
|
|
}
|
|
|
|
virtual bool OnEvent(const SEvent& event)
|
|
{
|
|
bool out = CGUIEditBox::OnEvent(event);
|
|
|
|
if (event.EventType == EET_KEY_INPUT_EVENT && event.KeyInput.PressedDown)
|
|
{
|
|
for (unsigned int n=0; n<m_listeners.size(); n++)
|
|
{
|
|
m_listeners[n].onTextUpdated();
|
|
}
|
|
}
|
|
if (event.EventType == EET_KEY_INPUT_EVENT && event.KeyInput.Key == IRR_KEY_RETURN)
|
|
{
|
|
for (unsigned int n=0; n<m_listeners.size(); n++)
|
|
{
|
|
if (m_listeners[n].onEnterPressed(Text))
|
|
{
|
|
Text = L"";
|
|
CursorPos = 0;
|
|
}
|
|
}
|
|
}
|
|
return out;
|
|
}
|
|
|
|
};
|
|
|
|
using namespace GUIEngine;
|
|
using namespace irr::core;
|
|
using namespace irr::gui;
|
|
using namespace irr;
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
TextBoxWidget::TextBoxWidget() : Widget(WTYPE_TEXTBOX)
|
|
{
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
void TextBoxWidget::add()
|
|
{
|
|
rect<s32> widget_size = rect<s32>(m_x, m_y, m_x + m_w, m_y + m_h);
|
|
|
|
// Don't call TextBoxWidget::getText(), which assumes that the irrlicht
|
|
// widget already exists.
|
|
const stringw& text = Widget::getText();
|
|
|
|
m_element = new MyCGUIEditBox(text.c_str(), true /* border */, GUIEngine::getGUIEnv(),
|
|
(m_parent ? m_parent : GUIEngine::getGUIEnv()->getRootGUIElement()),
|
|
getNewID(), widget_size);
|
|
|
|
if (m_deactivated)
|
|
m_element->setEnabled(false);
|
|
|
|
//m_element = GUIEngine::getGUIEnv()->addEditBox(text.c_str(), widget_size,
|
|
// true /* border */, m_parent, getNewID());
|
|
m_id = m_element->getID();
|
|
m_element->setTabOrder(m_id);
|
|
m_element->setTabGroup(false);
|
|
m_element->setTabStop(true);
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
void TextBoxWidget::addListener(ITextBoxWidgetListener* listener)
|
|
{
|
|
((MyCGUIEditBox*)m_element)->addListener(listener);
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
void TextBoxWidget::clearListeners()
|
|
{
|
|
((MyCGUIEditBox*)m_element)->clearListeners();
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
stringw TextBoxWidget::getText() const
|
|
{
|
|
const IGUIEditBox* textCtrl = Widget::getIrrlichtElement<IGUIEditBox>();
|
|
assert(textCtrl != NULL);
|
|
|
|
return stringw(textCtrl->getText());
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
void TextBoxWidget::setPasswordBox(bool passwordBox, wchar_t passwordChar)
|
|
{
|
|
IGUIEditBox* textCtrl = Widget::getIrrlichtElement<IGUIEditBox>();
|
|
assert(textCtrl != NULL);
|
|
textCtrl->setPasswordBox(passwordBox, passwordChar);
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
EventPropagation TextBoxWidget::focused(const int playerID)
|
|
{
|
|
assert(playerID == 0); // No support for multiple players in text areas!
|
|
|
|
// special case : to work, the text box must receive "irrLicht focus", STK focus is not enough
|
|
GUIEngine::getGUIEnv()->setFocus(m_element);
|
|
setWithinATextBox(true);
|
|
return EVENT_LET;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
void TextBoxWidget::unfocused(const int playerID, Widget* new_focus)
|
|
{
|
|
assert(playerID == 0); // No support for multiple players in text areas!
|
|
|
|
setWithinATextBox(false);
|
|
|
|
GUIEngine::getGUIEnv()->removeFocus(m_element);
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
void TextBoxWidget::elementRemoved()
|
|
{
|
|
// normally at this point normal widgets have been deleted by irrlicht already.
|
|
// but this is a custom widget and the gui env does not appear to want to
|
|
// manage it. so we free it manually
|
|
m_element->drop();
|
|
Widget::elementRemoved();
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
void TextBoxWidget::setActive(bool active)
|
|
{
|
|
Widget::setActive(active);
|
|
|
|
if (m_element != NULL)
|
|
{
|
|
IGUIEditBox* textCtrl = Widget::getIrrlichtElement<IGUIEditBox>();
|
|
assert(textCtrl != NULL);
|
|
textCtrl->setEnabled(active);
|
|
}
|
|
} // setActive
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
EventPropagation TextBoxWidget::onActivationInput(const int playerID)
|
|
{
|
|
if (GUIEngine::ScreenKeyboard::shouldUseScreenKeyboard())
|
|
{
|
|
((MyCGUIEditBox*)m_element)->openScreenKeyboard();
|
|
}
|
|
|
|
// The onWidgetActivated() wasn't used at all before, so always block
|
|
// event to avoid breaking something
|
|
return EVENT_BLOCK;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
EventPropagation TextBoxWidget::rightPressed(const int playerID)
|
|
{
|
|
if (((MyCGUIEditBox*)m_element)->getTextCount() ==
|
|
((MyCGUIEditBox*)m_element)->getCursorPosInBox())
|
|
return EVENT_BLOCK;
|
|
|
|
return EVENT_LET;
|
|
} // rightPressed
|
|
|
|
// -----------------------------------------------------------------------------
|
|
EventPropagation TextBoxWidget::leftPressed (const int playerID)
|
|
{
|
|
if (((MyCGUIEditBox*)m_element)->getCursorPosInBox() == 0)
|
|
return EVENT_BLOCK;
|
|
|
|
return EVENT_LET;
|
|
} // leftPressed
|
|
|
|
// ============================================================================
|
|
/* This callback will allow copying android edittext data directly to editbox,
|
|
* which will allow composing text to be auto updated. */
|
|
#ifdef ANDROID
|
|
#include "jni.h"
|
|
|
|
#if !defined(ANDROID_PACKAGE_CALLBACK_NAME)
|
|
#error
|
|
#endif
|
|
|
|
#define MAKE_EDITTEXT_CALLBACK(x) JNIEXPORT void JNICALL Java_ ## x##_STKEditText_editText2STKEditbox(JNIEnv* env, jobject this_obj, jstring text, jint start, jint end, jint composing_start, jint composing_end)
|
|
#define ANDROID_EDITTEXT_CALLBACK(PKG_NAME) MAKE_EDITTEXT_CALLBACK(PKG_NAME)
|
|
|
|
extern "C"
|
|
ANDROID_EDITTEXT_CALLBACK(ANDROID_PACKAGE_CALLBACK_NAME)
|
|
{
|
|
TextBoxWidget* tb = dynamic_cast<TextBoxWidget*>(getFocusForPlayer(0));
|
|
if (!tb || text == NULL)
|
|
return;
|
|
|
|
const char* utf8_text = env->GetStringUTFChars(text, NULL);
|
|
if (utf8_text == NULL)
|
|
return;
|
|
|
|
core::stringw to_editbox = StringUtils::utf8ToWide(utf8_text);
|
|
tb->getIrrlichtElement<MyCGUIEditBox>()->fromAndroidEditText(
|
|
to_editbox, start, end, composing_start, composing_end);
|
|
env->ReleaseStringUTFChars(text, utf8_text);
|
|
}
|
|
#endif
|