// Copyright (C) 2002-2012 Nikolaus Gebhardt
// Modified by Mustapha T.
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
#include "guiEditBoxWithScrollbar.h"
#include "IGUISkin.h"
#include "IGUIEnvironment.h"
#include "IGUIFont.h"
#include "IVideoDriver.h"
#include "rect.h"
#include "porting.h"
#include "Keycodes.h"
/*
todo:
optional scrollbars [done]
ctrl+left/right to select word
double click/ctrl click: word select + drag to select whole words, triple click to select line
optional? dragging selected text
numerical
*/
//! constructor
GUIEditBoxWithScrollBar::GUIEditBoxWithScrollBar(const wchar_t* text, bool border,
IGUIEnvironment* environment, IGUIElement* parent, s32 id,
const core::rect<s32>& rectangle, bool writable, bool has_vscrollbar)
: IGUIEditBox(environment, parent, id, rectangle), m_mouse_marking(false),
m_border(border), m_background(true), m_override_color_enabled(false), m_mark_begin(0), m_mark_end(0),
m_override_color(video::SColor(101, 255, 255, 255)), m_override_font(0), m_last_break_font(0),
m_operator(0), m_blink_start_time(0), m_cursor_pos(0), m_hscroll_pos(0), m_vscroll_pos(0), m_max(0),
m_word_wrap(false), m_multiline(false), m_autoscroll(true), m_passwordbox(false),
m_passwordchar(L'*'), m_halign(EGUIA_UPPERLEFT), m_valign(EGUIA_CENTER),
m_current_text_rect(0, 0, 1, 1), m_frame_rect(rectangle),
m_scrollbar_width(0), m_vscrollbar(NULL), m_writable(writable),
m_bg_color_used(false)
{
#ifdef _DEBUG
setDebugName("GUIEditBoxWithScrollBar");
#endif
Text = text;
if (Environment)
m_operator = Environment->getOSOperator();
if (m_operator)
m_operator->grab();
// this element can be tabbed to
setTabStop(true);
setTabOrder(-1);
if (has_vscrollbar) {
createVScrollBar();
}
calculateFrameRect();
breakText();
calculateScrollPos();
setWritable(writable);
}
//! destructor
GUIEditBoxWithScrollBar::~GUIEditBoxWithScrollBar()
{
if (m_override_font)
m_override_font->drop();
if (m_operator)
m_operator->drop();
if (m_vscrollbar)
m_vscrollbar->drop();
}
//! Sets another skin independent font.
void GUIEditBoxWithScrollBar::setOverrideFont(IGUIFont* font)
{
if (m_override_font == font)
return;
if (m_override_font)
m_override_font->drop();
m_override_font = font;
if (m_override_font)
m_override_font->grab();
breakText();
}
//! Gets the override font (if any)
IGUIFont * GUIEditBoxWithScrollBar::getOverrideFont() const
{
return m_override_font;
}
//! Get the font which is used right now for drawing
IGUIFont* GUIEditBoxWithScrollBar::getActiveFont() const
{
if (m_override_font)
return m_override_font;
IGUISkin* skin = Environment->getSkin();
if (skin)
return skin->getFont();
return 0;
}
//! Sets another color for the text.
void GUIEditBoxWithScrollBar::setOverrideColor(video::SColor color)
{
m_override_color = color;
m_override_color_enabled = true;
}
video::SColor GUIEditBoxWithScrollBar::getOverrideColor() const
{
return m_override_color;
}
//! Turns the border on or off
void GUIEditBoxWithScrollBar::setDrawBorder(bool border)
{
m_border = border;
}
//! Sets whether to draw the background
void GUIEditBoxWithScrollBar::setDrawBackground(bool draw)
{
m_background = draw;
}
//! Sets if the text should use the overide color or the color in the gui skin.
void GUIEditBoxWithScrollBar::enableOverrideColor(bool enable)
{
m_override_color_enabled = enable;
}
bool GUIEditBoxWithScrollBar::isOverrideColorEnabled() const
{
return m_override_color_enabled;
}
//! Enables or disables word wrap
void GUIEditBoxWithScrollBar::setWordWrap(bool enable)
{
m_word_wrap = enable;
breakText();
}
void GUIEditBoxWithScrollBar::updateAbsolutePosition()
{
core::rect<s32> old_absolute_rect(AbsoluteRect);
IGUIElement::updateAbsolutePosition();
if (old_absolute_rect != AbsoluteRect) {
calculateFrameRect();
breakText();
calculateScrollPos();
}
}
//! Checks if word wrap is enabled
bool GUIEditBoxWithScrollBar::isWordWrapEnabled() const
{
return m_word_wrap;
}
//! Enables or disables newlines.
void GUIEditBoxWithScrollBar::setMultiLine(bool enable)
{
m_multiline = enable;
}
//! Checks if multi line editing is enabled
bool GUIEditBoxWithScrollBar::isMultiLineEnabled() const
{
return m_multiline;
}
void GUIEditBoxWithScrollBar::setPasswordBox(bool password_box, wchar_t password_char)
{
m_passwordbox = password_box;
if (m_passwordbox) {
m_passwordchar = password_char;
setMultiLine(false);
setWordWrap(false);
m_broken_text.clear();
}
}
bool GUIEditBoxWithScrollBar::isPasswordBox() const
{
return m_passwordbox;
}
//! Sets text justification
void GUIEditBoxWithScrollBar::setTextAlignment(EGUI_ALIGNMENT horizontal, EGUI_ALIGNMENT vertical)
{
m_halign = horizontal;
m_valign = vertical;
}
//! called if an event happened.
bool GUIEditBoxWithScrollBar::OnEvent(const SEvent& event)
{
if (isEnabled()) {
switch (event.EventType)
{
case EET_GUI_EVENT:
if (event.GUIEvent.EventType == EGET_ELEMENT_FOCUS_LOST) {
if (event.GUIEvent.Caller == this) {
m_mouse_marking = false;
setTextMarkers(0, 0);
}
}
break;
case EET_KEY_INPUT_EVENT:
if (processKey(event))
return true;
break;
case EET_MOUSE_INPUT_EVENT:
if (processMouse(event))
return true;
break;
default:
break;
}
}
return IGUIElement::OnEvent(event);
}
bool GUIEditBoxWithScrollBar::processKey(const SEvent& event)
{
if (!m_writable) {
return false;
}
if (!event.KeyInput.PressedDown)
return false;
bool text_changed = false;
s32 new_mark_begin = m_mark_begin;
s32 new_mark_end = m_mark_end;
// control shortcut handling
if (event.KeyInput.Control) {
// german backlash '\' entered with control + '?'
if (event.KeyInput.Char == '\\') {
inputChar(event.KeyInput.Char);
return true;
}
switch (event.KeyInput.Key) {
case KEY_KEY_A:
// select all
new_mark_begin = 0;
new_mark_end = Text.size();
break;
case KEY_KEY_C:
// copy to clipboard
if (!m_passwordbox && m_operator && m_mark_begin != m_mark_end)
{
const s32 realmbgn = m_mark_begin < m_mark_end ? m_mark_begin : m_mark_end;
const s32 realmend = m_mark_begin < m_mark_end ? m_mark_end : m_mark_begin;
core::stringc s;
s = Text.subString(realmbgn, realmend - realmbgn).c_str();
m_operator->copyToClipboard(s.c_str());
}
break;
case KEY_KEY_X:
// cut to the clipboard
if (!m_passwordbox && m_operator && m_mark_begin != m_mark_end) {
const s32 realmbgn = m_mark_begin < m_mark_end ? m_mark_begin : m_mark_end;
const s32 realmend = m_mark_begin < m_mark_end ? m_mark_end : m_mark_begin;
// copy
core::stringc sc;
sc = Text.subString(realmbgn, realmend - realmbgn).c_str();
m_operator->copyToClipboard(sc.c_str());
if (isEnabled())
{
// delete
core::stringw s;
s = Text.subString(0, realmbgn);
s.append(Text.subString(realmend, Text.size() - realmend));
Text = s;
m_cursor_pos = realmbgn;
new_mark_begin = 0;
new_mark_end = 0;
text_changed = true;
}
}
break;
case KEY_KEY_V:
if (!isEnabled())
break;
// paste from the clipboard
if (m_operator) {
const s32 realmbgn = m_mark_begin < m_mark_end ? m_mark_begin : m_mark_end;
const s32 realmend = m_mark_begin < m_mark_end ? m_mark_end : m_mark_begin;
// add new character
const c8* p = m_operator->getTextFromClipboard();
if (p) {
if (m_mark_begin == m_mark_end) {
// insert text
core::stringw s = Text.subString(0, m_cursor_pos);
s.append(p);
s.append(Text.subString(m_cursor_pos, Text.size() - m_cursor_pos));
if (!m_max || s.size() <= m_max) // thx to Fish FH for fix
{
Text = s;
s = p;
m_cursor_pos += s.size();
}
} else {
// replace text
core::stringw s = Text.subString(0, realmbgn);
s.append(p);
s.append(Text.subString(realmend, Text.size() - realmend));
if (!m_max || s.size() <= m_max) // thx to Fish FH for fix
{
Text = s;
s = p;
m_cursor_pos = realmbgn + s.size();
}
}
|