Changeset View
Changeset View
Standalone View
Standalone View
ps/trunk/source/gui/CInput.cpp
Show All 32 Lines | |||||
#include "ps/Hotkey.h" | #include "ps/Hotkey.h" | ||||
#include "renderer/Renderer.h" | #include "renderer/Renderer.h" | ||||
#include <sstream> | #include <sstream> | ||||
extern int g_yres; | extern int g_yres; | ||||
CInput::CInput(CGUI& pGUI) | CInput::CInput(CGUI& pGUI) | ||||
: IGUIObject(pGUI), IGUIScrollBarOwner(pGUI), | : | ||||
m_iBufferPos(-1), m_iBufferPos_Tail(-1), m_SelectingText(false), m_HorizontalScroll(0.f), | IGUIObject(pGUI), | ||||
m_PrevTime(0.0), m_CursorVisState(true), m_CursorBlinkRate(0.5), m_ComposingText(false), | IGUIScrollBarOwner(pGUI), | ||||
m_iComposedLength(0), m_iComposedPos(0), m_iInsertPos(0), m_Readonly(false) | m_iBufferPos(-1), | ||||
{ | m_iBufferPos_Tail(-1), | ||||
AddSetting<i32>("buffer_position"); | m_SelectingText(), | ||||
AddSetting<float>("buffer_zone"); | m_HorizontalScroll(), | ||||
AddSetting<CStrW>("caption"); | m_PrevTime(), | ||||
AddSetting<i32>("cell_id"); | m_CursorVisState(true), | ||||
AddSetting<CStrW>("font"); | m_CursorBlinkRate(0.5), | ||||
AddSetting<CStrW>("mask_char"); | m_ComposingText(), | ||||
AddSetting<bool>("mask"); | m_iComposedLength(), | ||||
AddSetting<i32>("max_length"); | m_iComposedPos(), | ||||
AddSetting<bool>("multiline"); | m_iInsertPos(), | ||||
AddSetting<bool>("readonly"); | m_BufferPosition(), | ||||
AddSetting<bool>("scrollbar"); | m_BufferZone(), | ||||
AddSetting<CStr>("scrollbar_style"); | m_Caption(), | ||||
AddSetting<CGUISpriteInstance>("sprite"); | m_CellID(), | ||||
AddSetting<CGUISpriteInstance>("sprite_selectarea"); | m_Font(), | ||||
AddSetting<CGUIColor>("textcolor"); | m_MaskChar(), | ||||
AddSetting<CGUIColor>("textcolor_selected"); | m_Mask(), | ||||
m_MaxLength(), | |||||
m_MultiLine(), | |||||
m_Readonly(), | |||||
m_ScrollBar(), | |||||
m_ScrollBarStyle(), | |||||
m_Sprite(), | |||||
m_SpriteSelectArea(), | |||||
m_TextColor(), | |||||
m_TextColorSelected() | |||||
{ | |||||
RegisterSetting("buffer_position", m_BufferPosition); | |||||
RegisterSetting("buffer_zone", m_BufferZone); | |||||
RegisterSetting("caption", m_Caption); | |||||
RegisterSetting("cell_id", m_CellID); | |||||
RegisterSetting("font", m_Font); | |||||
RegisterSetting("mask_char", m_MaskChar); | |||||
RegisterSetting("mask", m_Mask); | |||||
RegisterSetting("max_length", m_MaxLength); | |||||
RegisterSetting("multiline", m_MultiLine); | |||||
RegisterSetting("readonly", m_Readonly); | |||||
RegisterSetting("scrollbar", m_ScrollBar); | |||||
RegisterSetting("scrollbar_style", m_ScrollBarStyle); | |||||
RegisterSetting("sprite", m_Sprite); | |||||
RegisterSetting("sprite_selectarea", m_SpriteSelectArea); | |||||
RegisterSetting("textcolor", m_TextColor); | |||||
RegisterSetting("textcolor_selected", m_TextColorSelected); | |||||
CFG_GET_VAL("gui.cursorblinkrate", m_CursorBlinkRate); | CFG_GET_VAL("gui.cursorblinkrate", m_CursorBlinkRate); | ||||
CGUIScrollBarVertical* bar = new CGUIScrollBarVertical(pGUI); | CGUIScrollBarVertical* bar = new CGUIScrollBarVertical(pGUI); | ||||
bar->SetRightAligned(true); | bar->SetRightAligned(true); | ||||
AddScrollBar(bar); | AddScrollBar(bar); | ||||
} | } | ||||
CInput::~CInput() | CInput::~CInput() | ||||
{ | { | ||||
} | } | ||||
void CInput::UpdateBufferPositionSetting() | void CInput::UpdateBufferPositionSetting() | ||||
{ | { | ||||
SetSetting<i32>("buffer_position", m_iBufferPos, false); | SetSetting<i32>("buffer_position", m_iBufferPos, false); | ||||
} | } | ||||
void CInput::ClearComposedText() | void CInput::ClearComposedText() | ||||
{ | { | ||||
CStrW& pCaption = GetSetting<CStrW>("caption"); | m_Caption.erase(m_iInsertPos, m_iComposedLength); | ||||
pCaption.erase(m_iInsertPos, m_iComposedLength); | |||||
m_iBufferPos = m_iInsertPos; | m_iBufferPos = m_iInsertPos; | ||||
UpdateBufferPositionSetting(); | UpdateBufferPositionSetting(); | ||||
m_iComposedLength = 0; | m_iComposedLength = 0; | ||||
m_iComposedPos = 0; | m_iComposedPos = 0; | ||||
} | } | ||||
InReaction CInput::ManuallyHandleEvent(const SDL_Event_* ev) | InReaction CInput::ManuallyHandleEvent(const SDL_Event_* ev) | ||||
{ | { | ||||
Show All 11 Lines | InReaction CInput::ManuallyHandleEvent(const SDL_Event_* ev) | ||||
// SDL2 has a new method of text input that better supports Unicode and CJK | // SDL2 has a new method of text input that better supports Unicode and CJK | ||||
// see https://wiki.libsdl.org/Tutorials/TextInput | // see https://wiki.libsdl.org/Tutorials/TextInput | ||||
case SDL_TEXTINPUT: | case SDL_TEXTINPUT: | ||||
{ | { | ||||
if (m_Readonly) | if (m_Readonly) | ||||
return IN_PASS; | return IN_PASS; | ||||
// Text has been committed, either single key presses or through an IME | // Text has been committed, either single key presses or through an IME | ||||
CStrW& pCaption = GetSetting<CStrW>("caption"); | |||||
std::wstring text = wstring_from_utf8(ev->ev.text.text); | std::wstring text = wstring_from_utf8(ev->ev.text.text); | ||||
m_WantedX = 0.0f; | m_WantedX = 0.0f; | ||||
if (SelectingText()) | if (SelectingText()) | ||||
DeleteCurSelection(); | DeleteCurSelection(); | ||||
if (m_ComposingText) | if (m_ComposingText) | ||||
{ | { | ||||
ClearComposedText(); | ClearComposedText(); | ||||
m_ComposingText = false; | m_ComposingText = false; | ||||
} | } | ||||
if (m_iBufferPos == static_cast<int>(pCaption.length())) | if (m_iBufferPos == static_cast<int>(m_Caption.length())) | ||||
pCaption.append(text); | m_Caption.append(text); | ||||
else | else | ||||
pCaption.insert(m_iBufferPos, text); | m_Caption.insert(m_iBufferPos, text); | ||||
UpdateText(m_iBufferPos, m_iBufferPos, m_iBufferPos+1); | UpdateText(m_iBufferPos, m_iBufferPos, m_iBufferPos+1); | ||||
m_iBufferPos += text.length(); | m_iBufferPos += text.length(); | ||||
UpdateBufferPositionSetting(); | UpdateBufferPositionSetting(); | ||||
m_iBufferPos_Tail = -1; | m_iBufferPos_Tail = -1; | ||||
UpdateAutoScroll(); | UpdateAutoScroll(); | ||||
SendEvent(GUIM_TEXTEDIT, "textedit"); | SendEvent(GUIM_TEXTEDIT, "textedit"); | ||||
return IN_HANDLED; | return IN_HANDLED; | ||||
} | } | ||||
case SDL_TEXTEDITING: | case SDL_TEXTEDITING: | ||||
{ | { | ||||
if (m_Readonly) | if (m_Readonly) | ||||
return IN_PASS; | return IN_PASS; | ||||
// Text is being composed with an IME | // Text is being composed with an IME | ||||
// TODO: indicate this by e.g. underlining the uncommitted text | // TODO: indicate this by e.g. underlining the uncommitted text | ||||
CStrW& pCaption = GetSetting<CStrW>("caption"); | |||||
const char* rawText = ev->ev.edit.text; | const char* rawText = ev->ev.edit.text; | ||||
int rawLength = strlen(rawText); | int rawLength = strlen(rawText); | ||||
std::wstring wtext = wstring_from_utf8(rawText); | std::wstring wtext = wstring_from_utf8(rawText); | ||||
debug_printf("SDL_TEXTEDITING: text=%s, start=%d, length=%d\n", rawText, ev->ev.edit.start, ev->ev.edit.length); | debug_printf("SDL_TEXTEDITING: text=%s, start=%d, length=%d\n", rawText, ev->ev.edit.start, ev->ev.edit.length); | ||||
m_WantedX = 0.0f; | m_WantedX = 0.0f; | ||||
if (SelectingText()) | if (SelectingText()) | ||||
DeleteCurSelection(); | DeleteCurSelection(); | ||||
// Remember cursor position when text composition begins | // Remember cursor position when text composition begins | ||||
if (!m_ComposingText) | if (!m_ComposingText) | ||||
m_iInsertPos = m_iBufferPos; | m_iInsertPos = m_iBufferPos; | ||||
else | else | ||||
{ | { | ||||
// Composed text is replaced each time | // Composed text is replaced each time | ||||
ClearComposedText(); | ClearComposedText(); | ||||
} | } | ||||
m_ComposingText = ev->ev.edit.start != 0 || rawLength != 0; | m_ComposingText = ev->ev.edit.start != 0 || rawLength != 0; | ||||
if (m_ComposingText) | if (m_ComposingText) | ||||
{ | { | ||||
pCaption.insert(m_iInsertPos, wtext); | m_Caption.insert(m_iInsertPos, wtext); | ||||
// The text buffer is limited to SDL_TEXTEDITINGEVENT_TEXT_SIZE bytes, yet start | // The text buffer is limited to SDL_TEXTEDITINGEVENT_TEXT_SIZE bytes, yet start | ||||
// increases without limit, so don't let it advance beyond the composed text length | // increases without limit, so don't let it advance beyond the composed text length | ||||
m_iComposedLength = wtext.length(); | m_iComposedLength = wtext.length(); | ||||
m_iComposedPos = ev->ev.edit.start < m_iComposedLength ? ev->ev.edit.start : m_iComposedLength; | m_iComposedPos = ev->ev.edit.start < m_iComposedLength ? ev->ev.edit.start : m_iComposedLength; | ||||
m_iBufferPos = m_iInsertPos + m_iComposedPos; | m_iBufferPos = m_iInsertPos + m_iComposedPos; | ||||
// TODO: composed text selection - what does ev.edit.length do? | // TODO: composed text selection - what does ev.edit.length do? | ||||
Show All 11 Lines | InReaction CInput::ManuallyHandleEvent(const SDL_Event_* ev) | ||||
case SDL_KEYDOWN: | case SDL_KEYDOWN: | ||||
{ | { | ||||
if (m_ComposingText) | if (m_ComposingText) | ||||
return IN_HANDLED; | return IN_HANDLED; | ||||
// Since the GUI framework doesn't handle to set settings | // Since the GUI framework doesn't handle to set settings | ||||
// in Unicode (CStrW), we'll simply retrieve the actual | // in Unicode (CStrW), we'll simply retrieve the actual | ||||
// pointer and edit that. | // pointer and edit that. | ||||
CStrW& pCaption = GetSetting<CStrW>("caption"); | |||||
SDL_Keycode keyCode = ev->ev.key.keysym.sym; | SDL_Keycode keyCode = ev->ev.key.keysym.sym; | ||||
ManuallyImmutableHandleKeyDownEvent(keyCode, pCaption); | ManuallyImmutableHandleKeyDownEvent(keyCode); | ||||
ManuallyMutableHandleKeyDownEvent(keyCode, pCaption); | ManuallyMutableHandleKeyDownEvent(keyCode); | ||||
UpdateBufferPositionSetting(); | UpdateBufferPositionSetting(); | ||||
return IN_HANDLED; | return IN_HANDLED; | ||||
} | } | ||||
default: | default: | ||||
{ | { | ||||
return IN_PASS; | return IN_PASS; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
void CInput::ManuallyMutableHandleKeyDownEvent(const SDL_Keycode keyCode, CStrW& pCaption) | void CInput::ManuallyMutableHandleKeyDownEvent(const SDL_Keycode keyCode) | ||||
{ | { | ||||
if (m_Readonly) | if (m_Readonly) | ||||
return; | return; | ||||
wchar_t cooked = 0; | wchar_t cooked = 0; | ||||
switch (keyCode) | switch (keyCode) | ||||
{ | { | ||||
Show All 9 Lines | case SDLK_BACKSPACE: | ||||
m_WantedX = 0.0f; | m_WantedX = 0.0f; | ||||
if (SelectingText()) | if (SelectingText()) | ||||
DeleteCurSelection(); | DeleteCurSelection(); | ||||
else | else | ||||
{ | { | ||||
m_iBufferPos_Tail = -1; | m_iBufferPos_Tail = -1; | ||||
if (pCaption.empty() || m_iBufferPos == 0) | if (m_Caption.empty() || m_iBufferPos == 0) | ||||
break; | break; | ||||
if (m_iBufferPos == static_cast<int>(pCaption.length())) | if (m_iBufferPos == static_cast<int>(m_Caption.length())) | ||||
pCaption = pCaption.Left(static_cast<long>(pCaption.length()) - 1); | m_Caption = m_Caption.Left(static_cast<long>(m_Caption.length()) - 1); | ||||
else | else | ||||
pCaption = | m_Caption = | ||||
pCaption.Left(m_iBufferPos - 1) + | m_Caption.Left(m_iBufferPos - 1) + | ||||
pCaption.Right(static_cast<long>(pCaption.length()) - m_iBufferPos); | m_Caption.Right(static_cast<long>(m_Caption.length()) - m_iBufferPos); | ||||
--m_iBufferPos; | --m_iBufferPos; | ||||
UpdateText(m_iBufferPos, m_iBufferPos + 1, m_iBufferPos); | UpdateText(m_iBufferPos, m_iBufferPos + 1, m_iBufferPos); | ||||
} | } | ||||
UpdateAutoScroll(); | UpdateAutoScroll(); | ||||
SendEvent(GUIM_TEXTEDIT, "textedit"); | SendEvent(GUIM_TEXTEDIT, "textedit"); | ||||
break; | break; | ||||
} | } | ||||
case SDLK_DELETE: | case SDLK_DELETE: | ||||
{ | { | ||||
m_WantedX = 0.0f; | m_WantedX = 0.0f; | ||||
if (SelectingText()) | if (SelectingText()) | ||||
DeleteCurSelection(); | DeleteCurSelection(); | ||||
else | else | ||||
{ | { | ||||
if (pCaption.empty() || m_iBufferPos == static_cast<int>(pCaption.length())) | if (m_Caption.empty() || m_iBufferPos == static_cast<int>(m_Caption.length())) | ||||
break; | break; | ||||
pCaption = | m_Caption = | ||||
pCaption.Left(m_iBufferPos) + | m_Caption.Left(m_iBufferPos) + | ||||
pCaption.Right(static_cast<long>(pCaption.length()) - (m_iBufferPos + 1)); | m_Caption.Right(static_cast<long>(m_Caption.length()) - (m_iBufferPos + 1)); | ||||
UpdateText(m_iBufferPos, m_iBufferPos + 1, m_iBufferPos); | UpdateText(m_iBufferPos, m_iBufferPos + 1, m_iBufferPos); | ||||
} | } | ||||
UpdateAutoScroll(); | UpdateAutoScroll(); | ||||
SendEvent(GUIM_TEXTEDIT, "textedit"); | SendEvent(GUIM_TEXTEDIT, "textedit"); | ||||
break; | break; | ||||
} | } | ||||
case SDLK_KP_ENTER: | case SDLK_KP_ENTER: | ||||
case SDLK_RETURN: | case SDLK_RETURN: | ||||
{ | { | ||||
// 'Return' should do a Press event for single liners (e.g. submitting forms) | // 'Return' should do a Press event for single liners (e.g. submitting forms) | ||||
// otherwise a '\n' character will be added. | // otherwise a '\n' character will be added. | ||||
if (!GetSetting<bool>("multiline")) | if (!m_MultiLine) | ||||
{ | { | ||||
SendEvent(GUIM_PRESSED, "press"); | SendEvent(GUIM_PRESSED, "press"); | ||||
break; | break; | ||||
} | } | ||||
cooked = '\n'; // Change to '\n' and do default: | cooked = '\n'; // Change to '\n' and do default: | ||||
FALLTHROUGH; | FALLTHROUGH; | ||||
} | } | ||||
default: // Insert a character | default: // Insert a character | ||||
{ | { | ||||
// In SDL2, we no longer get Unicode wchars via SDL_Keysym | // In SDL2, we no longer get Unicode wchars via SDL_Keysym | ||||
// we use text input events instead and they provide UTF-8 chars | // we use text input events instead and they provide UTF-8 chars | ||||
if (cooked == 0) | if (cooked == 0) | ||||
return; | return; | ||||
// check max length | // check max length | ||||
const int max_length = GetSetting<i32>("max_length"); | if (m_MaxLength != 0 && static_cast<int>(m_Caption.length()) >= m_MaxLength) | ||||
if (max_length != 0 && static_cast<int>(pCaption.length()) >= max_length) | |||||
break; | break; | ||||
m_WantedX = 0.0f; | m_WantedX = 0.0f; | ||||
if (SelectingText()) | if (SelectingText()) | ||||
DeleteCurSelection(); | DeleteCurSelection(); | ||||
m_iBufferPos_Tail = -1; | m_iBufferPos_Tail = -1; | ||||
if (m_iBufferPos == static_cast<int>(pCaption.length())) | if (m_iBufferPos == static_cast<int>(m_Caption.length())) | ||||
pCaption += cooked; | m_Caption += cooked; | ||||
else | else | ||||
pCaption = | m_Caption = | ||||
pCaption.Left(m_iBufferPos) + cooked + | m_Caption.Left(m_iBufferPos) + cooked + | ||||
pCaption.Right(static_cast<long>(pCaption.length()) - m_iBufferPos); | m_Caption.Right(static_cast<long>(m_Caption.length()) - m_iBufferPos); | ||||
UpdateText(m_iBufferPos, m_iBufferPos, m_iBufferPos + 1); | UpdateText(m_iBufferPos, m_iBufferPos, m_iBufferPos + 1); | ||||
++m_iBufferPos; | ++m_iBufferPos; | ||||
UpdateAutoScroll(); | UpdateAutoScroll(); | ||||
SendEvent(GUIM_TEXTEDIT, "textedit"); | SendEvent(GUIM_TEXTEDIT, "textedit"); | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
void CInput::ManuallyImmutableHandleKeyDownEvent(const SDL_Keycode keyCode, CStrW& pCaption) | void CInput::ManuallyImmutableHandleKeyDownEvent(const SDL_Keycode keyCode) | ||||
{ | { | ||||
bool shiftKeyPressed = g_keys[SDLK_RSHIFT] || g_keys[SDLK_LSHIFT]; | bool shiftKeyPressed = g_keys[SDLK_RSHIFT] || g_keys[SDLK_LSHIFT]; | ||||
switch (keyCode) | switch (keyCode) | ||||
{ | { | ||||
case SDLK_HOME: | case SDLK_HOME: | ||||
{ | { | ||||
// If there's not a selection, we should create one now | // If there's not a selection, we should create one now | ||||
Show All 23 Lines | if (!shiftKeyPressed) | ||||
m_iBufferPos_Tail = -1; | m_iBufferPos_Tail = -1; | ||||
} | } | ||||
else if (!SelectingText()) | else if (!SelectingText()) | ||||
{ | { | ||||
// Place tail at the current point: | // Place tail at the current point: | ||||
m_iBufferPos_Tail = m_iBufferPos; | m_iBufferPos_Tail = m_iBufferPos; | ||||
} | } | ||||
m_iBufferPos = static_cast<long>(pCaption.length()); | m_iBufferPos = static_cast<long>(m_Caption.length()); | ||||
m_WantedX = 0.0f; | m_WantedX = 0.0f; | ||||
UpdateAutoScroll(); | UpdateAutoScroll(); | ||||
break; | break; | ||||
} | } | ||||
/** | /** | ||||
* Conventions for Left/Right when text is selected: | * Conventions for Left/Right when text is selected: | ||||
* | * | ||||
▲ Show 20 Lines • Show All 46 Lines • ▼ Show 20 Lines | case SDLK_RIGHT: | ||||
if (shiftKeyPressed || !SelectingText()) | if (shiftKeyPressed || !SelectingText()) | ||||
{ | { | ||||
if (!shiftKeyPressed) | if (!shiftKeyPressed) | ||||
m_iBufferPos_Tail = -1; | m_iBufferPos_Tail = -1; | ||||
else if (!SelectingText()) | else if (!SelectingText()) | ||||
m_iBufferPos_Tail = m_iBufferPos; | m_iBufferPos_Tail = m_iBufferPos; | ||||
if (m_iBufferPos < static_cast<int>(pCaption.length())) | if (m_iBufferPos < static_cast<int>(m_Caption.length())) | ||||
++m_iBufferPos; | ++m_iBufferPos; | ||||
} | } | ||||
else | else | ||||
{ | { | ||||
if (m_iBufferPos_Tail > m_iBufferPos) | if (m_iBufferPos_Tail > m_iBufferPos) | ||||
m_iBufferPos = m_iBufferPos_Tail; | m_iBufferPos = m_iBufferPos_Tail; | ||||
m_iBufferPos_Tail = -1; | m_iBufferPos_Tail = -1; | ||||
▲ Show 20 Lines • Show All 116 Lines • ▼ Show 20 Lines | void CInput::ManuallyImmutableHandleKeyDownEvent(const SDL_Keycode keyCode) | ||||
{ | { | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
InReaction CInput::ManuallyHandleHotkeyEvent(const SDL_Event_* ev) | InReaction CInput::ManuallyHandleHotkeyEvent(const SDL_Event_* ev) | ||||
{ | { | ||||
CStrW& pCaption = GetSetting<CStrW>("caption"); | |||||
bool shiftKeyPressed = g_keys[SDLK_RSHIFT] || g_keys[SDLK_LSHIFT]; | bool shiftKeyPressed = g_keys[SDLK_RSHIFT] || g_keys[SDLK_LSHIFT]; | ||||
std::string hotkey = static_cast<const char*>(ev->ev.user.data1); | std::string hotkey = static_cast<const char*>(ev->ev.user.data1); | ||||
if (hotkey == "paste") | if (hotkey == "paste") | ||||
{ | { | ||||
if (m_Readonly) | if (m_Readonly) | ||||
return IN_PASS; | return IN_PASS; | ||||
m_WantedX = 0.0f; | m_WantedX = 0.0f; | ||||
wchar_t* text = sys_clipboard_get(); | wchar_t* text = sys_clipboard_get(); | ||||
if (text) | if (text) | ||||
{ | { | ||||
if (SelectingText()) | if (SelectingText()) | ||||
DeleteCurSelection(); | DeleteCurSelection(); | ||||
if (m_iBufferPos == static_cast<int>(pCaption.length())) | if (m_iBufferPos == static_cast<int>(m_Caption.length())) | ||||
pCaption += text; | m_Caption += text; | ||||
else | else | ||||
pCaption = | m_Caption = | ||||
pCaption.Left(m_iBufferPos) + text + | m_Caption.Left(m_iBufferPos) + text + | ||||
pCaption.Right(static_cast<long>(pCaption.length()) - m_iBufferPos); | m_Caption.Right(static_cast<long>(m_Caption.length()) - m_iBufferPos); | ||||
UpdateText(m_iBufferPos, m_iBufferPos, m_iBufferPos+1); | UpdateText(m_iBufferPos, m_iBufferPos, m_iBufferPos+1); | ||||
m_iBufferPos += (int)wcslen(text); | m_iBufferPos += (int)wcslen(text); | ||||
UpdateAutoScroll(); | UpdateAutoScroll(); | ||||
UpdateBufferPositionSetting(); | UpdateBufferPositionSetting(); | ||||
sys_clipboard_free(text); | sys_clipboard_free(text); | ||||
Show All 21 Lines | if (SelectingText()) | ||||
virtualTo = m_iBufferPos_Tail; | virtualTo = m_iBufferPos_Tail; | ||||
} | } | ||||
else | else | ||||
{ | { | ||||
virtualFrom = m_iBufferPos_Tail; | virtualFrom = m_iBufferPos_Tail; | ||||
virtualTo = m_iBufferPos; | virtualTo = m_iBufferPos; | ||||
} | } | ||||
CStrW text = (pCaption.Left(virtualTo)).Right(virtualTo - virtualFrom); | CStrW text = m_Caption.Left(virtualTo).Right(virtualTo - virtualFrom); | ||||
sys_clipboard_set(&text[0]); | sys_clipboard_set(&text[0]); | ||||
if (hotkey == "cut") | if (hotkey == "cut") | ||||
{ | { | ||||
DeleteCurSelection(); | DeleteCurSelection(); | ||||
UpdateAutoScroll(); | UpdateAutoScroll(); | ||||
SendEvent(GUIM_TEXTEDIT, "textedit"); | SendEvent(GUIM_TEXTEDIT, "textedit"); | ||||
} | } | ||||
} | } | ||||
return IN_HANDLED; | return IN_HANDLED; | ||||
} | } | ||||
else if (hotkey == "text.delete.left") | else if (hotkey == "text.delete.left") | ||||
{ | { | ||||
if (m_Readonly) | if (m_Readonly) | ||||
return IN_PASS; | return IN_PASS; | ||||
m_WantedX = 0.0f; | m_WantedX = 0.0f; | ||||
if (SelectingText()) | if (SelectingText()) | ||||
DeleteCurSelection(); | DeleteCurSelection(); | ||||
if (!pCaption.empty() && m_iBufferPos != 0) | if (!m_Caption.empty() && m_iBufferPos != 0) | ||||
{ | { | ||||
m_iBufferPos_Tail = m_iBufferPos; | m_iBufferPos_Tail = m_iBufferPos; | ||||
CStrW searchString = pCaption.Left(m_iBufferPos); | CStrW searchString = m_Caption.Left(m_iBufferPos); | ||||
// If we are starting in whitespace, adjust position until we get a non whitespace | // If we are starting in whitespace, adjust position until we get a non whitespace | ||||
while (m_iBufferPos > 0) | while (m_iBufferPos > 0) | ||||
{ | { | ||||
if (!iswspace(searchString[m_iBufferPos - 1])) | if (!iswspace(searchString[m_iBufferPos - 1])) | ||||
break; | break; | ||||
m_iBufferPos--; | m_iBufferPos--; | ||||
Show All 26 Lines | else if (hotkey == "text.delete.right") | ||||
if (m_Readonly) | if (m_Readonly) | ||||
return IN_PASS; | return IN_PASS; | ||||
m_WantedX = 0.0f; | m_WantedX = 0.0f; | ||||
if (SelectingText()) | if (SelectingText()) | ||||
DeleteCurSelection(); | DeleteCurSelection(); | ||||
if (!pCaption.empty() && m_iBufferPos < static_cast<int>(pCaption.length())) | if (!m_Caption.empty() && m_iBufferPos < static_cast<int>(m_Caption.length())) | ||||
{ | { | ||||
// Delete the word to the right of the cursor | // Delete the word to the right of the cursor | ||||
m_iBufferPos_Tail = m_iBufferPos; | m_iBufferPos_Tail = m_iBufferPos; | ||||
// Delete chars to the right unit we hit whitespace | // Delete chars to the right unit we hit whitespace | ||||
while (++m_iBufferPos < static_cast<int>(pCaption.length())) | while (++m_iBufferPos < static_cast<int>(m_Caption.length())) | ||||
{ | { | ||||
if (iswspace(pCaption[m_iBufferPos]) || iswpunct(pCaption[m_iBufferPos])) | if (iswspace(m_Caption[m_iBufferPos]) || iswpunct(m_Caption[m_iBufferPos])) | ||||
break; | break; | ||||
} | } | ||||
// Eliminate any whitespace behind the word we just deleted | // Eliminate any whitespace behind the word we just deleted | ||||
while (m_iBufferPos < static_cast<int>(pCaption.length())) | while (m_iBufferPos < static_cast<int>(m_Caption.length())) | ||||
{ | { | ||||
if (!iswspace(pCaption[m_iBufferPos])) | if (!iswspace(m_Caption[m_iBufferPos])) | ||||
break; | break; | ||||
++m_iBufferPos; | ++m_iBufferPos; | ||||
} | } | ||||
UpdateBufferPositionSetting(); | UpdateBufferPositionSetting(); | ||||
DeleteCurSelection(); | DeleteCurSelection(); | ||||
} | } | ||||
UpdateAutoScroll(); | UpdateAutoScroll(); | ||||
SendEvent(GUIM_TEXTEDIT, "textedit"); | SendEvent(GUIM_TEXTEDIT, "textedit"); | ||||
return IN_HANDLED; | return IN_HANDLED; | ||||
} | } | ||||
else if (hotkey == "text.move.left") | else if (hotkey == "text.move.left") | ||||
{ | { | ||||
m_WantedX = 0.0f; | m_WantedX = 0.0f; | ||||
if (shiftKeyPressed || !SelectingText()) | if (shiftKeyPressed || !SelectingText()) | ||||
{ | { | ||||
if (!shiftKeyPressed) | if (!shiftKeyPressed) | ||||
m_iBufferPos_Tail = -1; | m_iBufferPos_Tail = -1; | ||||
else if (!SelectingText()) | else if (!SelectingText()) | ||||
m_iBufferPos_Tail = m_iBufferPos; | m_iBufferPos_Tail = m_iBufferPos; | ||||
if (!pCaption.empty() && m_iBufferPos != 0) | if (!m_Caption.empty() && m_iBufferPos != 0) | ||||
{ | { | ||||
CStrW searchString = pCaption.Left(m_iBufferPos); | CStrW searchString = m_Caption.Left(m_iBufferPos); | ||||
// If we are starting in whitespace, adjust position until we get a non whitespace | // If we are starting in whitespace, adjust position until we get a non whitespace | ||||
while (m_iBufferPos > 0) | while (m_iBufferPos > 0) | ||||
{ | { | ||||
if (!iswspace(searchString[m_iBufferPos - 1])) | if (!iswspace(searchString[m_iBufferPos - 1])) | ||||
break; | break; | ||||
m_iBufferPos--; | m_iBufferPos--; | ||||
Show All 34 Lines | else if (hotkey == "text.move.right") | ||||
if (shiftKeyPressed || !SelectingText()) | if (shiftKeyPressed || !SelectingText()) | ||||
{ | { | ||||
if (!shiftKeyPressed) | if (!shiftKeyPressed) | ||||
m_iBufferPos_Tail = -1; | m_iBufferPos_Tail = -1; | ||||
else if (!SelectingText()) | else if (!SelectingText()) | ||||
m_iBufferPos_Tail = m_iBufferPos; | m_iBufferPos_Tail = m_iBufferPos; | ||||
if (!pCaption.empty() && m_iBufferPos < static_cast<int>(pCaption.length())) | if (!m_Caption.empty() && m_iBufferPos < static_cast<int>(m_Caption.length())) | ||||
{ | { | ||||
// Select chars to the right until we hit whitespace | // Select chars to the right until we hit whitespace | ||||
while (++m_iBufferPos < static_cast<int>(pCaption.length())) | while (++m_iBufferPos < static_cast<int>(m_Caption.length())) | ||||
{ | { | ||||
if (iswspace(pCaption[m_iBufferPos]) || iswpunct(pCaption[m_iBufferPos])) | if (iswspace(m_Caption[m_iBufferPos]) || iswpunct(m_Caption[m_iBufferPos])) | ||||
break; | break; | ||||
} | } | ||||
// Also select any whitespace following the word we just selected | // Also select any whitespace following the word we just selected | ||||
while (m_iBufferPos < static_cast<int>(pCaption.length())) | while (m_iBufferPos < static_cast<int>(m_Caption.length())) | ||||
{ | { | ||||
if (!iswspace(pCaption[m_iBufferPos])) | if (!iswspace(m_Caption[m_iBufferPos])) | ||||
break; | break; | ||||
++m_iBufferPos; | ++m_iBufferPos; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
else | else | ||||
{ | { | ||||
Show All 18 Lines | void CInput::HandleMessage(SGUIMessage& Message) | ||||
IGUIScrollBarOwner::HandleMessage(Message); | IGUIScrollBarOwner::HandleMessage(Message); | ||||
switch (Message.type) | switch (Message.type) | ||||
{ | { | ||||
case GUIM_SETTINGS_UPDATED: | case GUIM_SETTINGS_UPDATED: | ||||
{ | { | ||||
// Update scroll-bar | // Update scroll-bar | ||||
// TODO Gee: (2004-09-01) Is this really updated each time it should? | // TODO Gee: (2004-09-01) Is this really updated each time it should? | ||||
if (GetSetting<bool>("scrollbar") && | if (m_ScrollBar && | ||||
(Message.value == CStr("size") || | (Message.value == "size" || | ||||
Message.value == CStr("z") || | Message.value == "z" || | ||||
Message.value == CStr("absolute"))) | Message.value == "absolute")) | ||||
{ | { | ||||
GetScrollBar(0).SetX(m_CachedActualSize.right); | GetScrollBar(0).SetX(m_CachedActualSize.right); | ||||
GetScrollBar(0).SetY(m_CachedActualSize.top); | GetScrollBar(0).SetY(m_CachedActualSize.top); | ||||
GetScrollBar(0).SetZ(GetBufferedZ()); | GetScrollBar(0).SetZ(GetBufferedZ()); | ||||
GetScrollBar(0).SetLength(m_CachedActualSize.bottom - m_CachedActualSize.top); | GetScrollBar(0).SetLength(m_CachedActualSize.bottom - m_CachedActualSize.top); | ||||
} | } | ||||
// Update scrollbar | // Update scrollbar | ||||
if (Message.value == CStr("scrollbar_style")) | if (Message.value == "scrollbar_style") | ||||
{ | GetScrollBar(0).SetScrollBarStyle(m_ScrollBarStyle); | ||||
GetScrollBar(0).SetScrollBarStyle(GetSetting<CStr>(Message.value)); | |||||
} | |||||
if (Message.value == CStr("buffer_position")) | if (Message.value == "buffer_position") | ||||
{ | { | ||||
m_iBufferPos = GetSetting<i32>(Message.value); | m_iBufferPos = m_BufferPosition; | ||||
m_iBufferPos_Tail = -1; // position change resets selection | m_iBufferPos_Tail = -1; // position change resets selection | ||||
} | } | ||||
if (Message.value == CStr("size") || | if (Message.value == "size" || | ||||
Message.value == CStr("z") || | Message.value == "z" || | ||||
Message.value == CStr("font") || | Message.value == "font" || | ||||
Message.value == CStr("absolute") || | Message.value == "absolute" || | ||||
Message.value == CStr("caption") || | Message.value == "caption" || | ||||
Message.value == CStr("scrollbar") || | Message.value == "scrollbar" || | ||||
Message.value == CStr("scrollbar_style")) | Message.value == "scrollbar_style") | ||||
{ | { | ||||
UpdateText(); | UpdateText(); | ||||
} | } | ||||
if (Message.value == CStr("multiline")) | if (Message.value == "multiline") | ||||
{ | { | ||||
if (!GetSetting<bool>("multiline")) | if (!m_MultiLine) | ||||
GetScrollBar(0).SetLength(0.f); | GetScrollBar(0).SetLength(0.f); | ||||
else | else | ||||
GetScrollBar(0).SetLength(m_CachedActualSize.bottom - m_CachedActualSize.top); | GetScrollBar(0).SetLength(m_CachedActualSize.bottom - m_CachedActualSize.top); | ||||
UpdateText(); | UpdateText(); | ||||
} | } | ||||
UpdateAutoScroll(); | UpdateAutoScroll(); | ||||
if (Message.value == CStr("readonly")) | |||||
m_Readonly = GetSetting<bool>("readonly"); | |||||
break; | break; | ||||
} | } | ||||
case GUIM_MOUSE_PRESS_LEFT: | case GUIM_MOUSE_PRESS_LEFT: | ||||
{ | { | ||||
// Check if we're selecting the scrollbar | // Check if we're selecting the scrollbar | ||||
if (GetSetting<bool>("scrollbar") && | if (m_ScrollBar && | ||||
GetSetting<bool>("multiline") && | m_MultiLine && | ||||
GetScrollBar(0).GetStyle()) | GetScrollBar(0).GetStyle()) | ||||
{ | { | ||||
if (m_pGUI.GetMousePos().x > m_CachedActualSize.right - GetScrollBar(0).GetStyle()->m_Width) | if (m_pGUI.GetMousePos().x > m_CachedActualSize.right - GetScrollBar(0).GetStyle()->m_Width) | ||||
break; | break; | ||||
} | } | ||||
if (m_ComposingText) | if (m_ComposingText) | ||||
break; | break; | ||||
Show All 16 Lines | case GUIM_MOUSE_PRESS_LEFT: | ||||
// for the user though. | // for the user though. | ||||
break; | break; | ||||
} | } | ||||
case GUIM_MOUSE_DBLCLICK_LEFT: | case GUIM_MOUSE_DBLCLICK_LEFT: | ||||
{ | { | ||||
if (m_ComposingText) | if (m_ComposingText) | ||||
break; | break; | ||||
const CStrW& pCaption = GetSetting<CStrW>("caption"); | if (m_Caption.empty()) | ||||
if (pCaption.empty()) | |||||
break; | break; | ||||
m_iBufferPos = m_iBufferPos_Tail = GetMouseHoveringTextPosition(); | m_iBufferPos = m_iBufferPos_Tail = GetMouseHoveringTextPosition(); | ||||
if (m_iBufferPos >= (int)pCaption.length()) | if (m_iBufferPos >= (int)m_Caption.length()) | ||||
m_iBufferPos = m_iBufferPos_Tail = pCaption.length() - 1; | m_iBufferPos = m_iBufferPos_Tail = m_Caption.length() - 1; | ||||
// See if we are clicking over whitespace | // See if we are clicking over whitespace | ||||
if (iswspace(pCaption[m_iBufferPos])) | if (iswspace(m_Caption[m_iBufferPos])) | ||||
{ | { | ||||
// see if we are in a section of whitespace greater than one character | // see if we are in a section of whitespace greater than one character | ||||
if ((m_iBufferPos + 1 < (int) pCaption.length() && iswspace(pCaption[m_iBufferPos + 1])) || | if ((m_iBufferPos + 1 < (int) m_Caption.length() && iswspace(m_Caption[m_iBufferPos + 1])) || | ||||
(m_iBufferPos - 1 > 0 && iswspace(pCaption[m_iBufferPos - 1]))) | (m_iBufferPos - 1 > 0 && iswspace(m_Caption[m_iBufferPos - 1]))) | ||||
{ | { | ||||
// | // | ||||
// We are clicking in an area with more than one whitespace character | // We are clicking in an area with more than one whitespace character | ||||
// so we select both the word to the left and then the word to the right | // so we select both the word to the left and then the word to the right | ||||
// | // | ||||
// [1] First the left | // [1] First the left | ||||
// skip the whitespace | // skip the whitespace | ||||
while (m_iBufferPos > 0) | while (m_iBufferPos > 0) | ||||
{ | { | ||||
if (!iswspace(pCaption[m_iBufferPos - 1])) | if (!iswspace(m_Caption[m_iBufferPos - 1])) | ||||
break; | break; | ||||
m_iBufferPos--; | m_iBufferPos--; | ||||
} | } | ||||
// now go until we hit white space or punctuation | // now go until we hit white space or punctuation | ||||
while (m_iBufferPos > 0) | while (m_iBufferPos > 0) | ||||
{ | { | ||||
if (iswspace(pCaption[m_iBufferPos - 1])) | if (iswspace(m_Caption[m_iBufferPos - 1])) | ||||
break; | break; | ||||
m_iBufferPos--; | m_iBufferPos--; | ||||
if (iswpunct(pCaption[m_iBufferPos])) | if (iswpunct(m_Caption[m_iBufferPos])) | ||||
break; | break; | ||||
} | } | ||||
// [2] Then the right | // [2] Then the right | ||||
// go right until we are not in whitespace | // go right until we are not in whitespace | ||||
while (++m_iBufferPos_Tail < static_cast<int>(pCaption.length())) | while (++m_iBufferPos_Tail < static_cast<int>(m_Caption.length())) | ||||
{ | { | ||||
if (!iswspace(pCaption[m_iBufferPos_Tail])) | if (!iswspace(m_Caption[m_iBufferPos_Tail])) | ||||
break; | break; | ||||
} | } | ||||
if (m_iBufferPos_Tail == static_cast<int>(pCaption.length())) | if (m_iBufferPos_Tail == static_cast<int>(m_Caption.length())) | ||||
break; | break; | ||||
// now go to the right until we hit whitespace or punctuation | // now go to the right until we hit whitespace or punctuation | ||||
while (++m_iBufferPos_Tail < static_cast<int>(pCaption.length())) | while (++m_iBufferPos_Tail < static_cast<int>(m_Caption.length())) | ||||
{ | { | ||||
if (iswspace(pCaption[m_iBufferPos_Tail]) || iswpunct(pCaption[m_iBufferPos_Tail])) | if (iswspace(m_Caption[m_iBufferPos_Tail]) || iswpunct(m_Caption[m_iBufferPos_Tail])) | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
else | else | ||||
{ | { | ||||
// single whitespace so select word to the right | // single whitespace so select word to the right | ||||
while (++m_iBufferPos_Tail < static_cast<int>(pCaption.length())) | while (++m_iBufferPos_Tail < static_cast<int>(m_Caption.length())) | ||||
{ | { | ||||
if (!iswspace(pCaption[m_iBufferPos_Tail])) | if (!iswspace(m_Caption[m_iBufferPos_Tail])) | ||||
break; | break; | ||||
} | } | ||||
if (m_iBufferPos_Tail == static_cast<int>(pCaption.length())) | if (m_iBufferPos_Tail == static_cast<int>(m_Caption.length())) | ||||
break; | break; | ||||
// Don't include the leading whitespace | // Don't include the leading whitespace | ||||
m_iBufferPos = m_iBufferPos_Tail; | m_iBufferPos = m_iBufferPos_Tail; | ||||
// now go to the right until we hit whitespace or punctuation | // now go to the right until we hit whitespace or punctuation | ||||
while (++m_iBufferPos_Tail < static_cast<int>(pCaption.length())) | while (++m_iBufferPos_Tail < static_cast<int>(m_Caption.length())) | ||||
{ | { | ||||
if (iswspace(pCaption[m_iBufferPos_Tail]) || iswpunct(pCaption[m_iBufferPos_Tail])) | if (iswspace(m_Caption[m_iBufferPos_Tail]) || iswpunct(m_Caption[m_iBufferPos_Tail])) | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
else | else | ||||
{ | { | ||||
// clicked on non-whitespace so select current word | // clicked on non-whitespace so select current word | ||||
// go until we hit white space or punctuation | // go until we hit white space or punctuation | ||||
while (m_iBufferPos > 0) | while (m_iBufferPos > 0) | ||||
{ | { | ||||
if (iswspace(pCaption[m_iBufferPos - 1])) | if (iswspace(m_Caption[m_iBufferPos - 1])) | ||||
break; | break; | ||||
m_iBufferPos--; | m_iBufferPos--; | ||||
if (iswpunct(pCaption[m_iBufferPos])) | if (iswpunct(m_Caption[m_iBufferPos])) | ||||
break; | break; | ||||
} | } | ||||
// go to the right until we hit whitespace or punctuation | // go to the right until we hit whitespace or punctuation | ||||
while (++m_iBufferPos_Tail < static_cast<int>(pCaption.length())) | while (++m_iBufferPos_Tail < static_cast<int>(m_Caption.length())) | ||||
if (iswspace(pCaption[m_iBufferPos_Tail]) || iswpunct(pCaption[m_iBufferPos_Tail])) | if (iswspace(m_Caption[m_iBufferPos_Tail]) || iswpunct(m_Caption[m_iBufferPos_Tail])) | ||||
break; | break; | ||||
} | } | ||||
UpdateAutoScroll(); | UpdateAutoScroll(); | ||||
break; | break; | ||||
} | } | ||||
case GUIM_MOUSE_RELEASE_LEFT: | case GUIM_MOUSE_RELEASE_LEFT: | ||||
{ | { | ||||
if (m_SelectingText) | if (m_SelectingText) | ||||
Show All 17 Lines | case GUIM_MOUSE_MOTION: | ||||
break; | break; | ||||
} | } | ||||
case GUIM_LOAD: | case GUIM_LOAD: | ||||
{ | { | ||||
GetScrollBar(0).SetX(m_CachedActualSize.right); | GetScrollBar(0).SetX(m_CachedActualSize.right); | ||||
GetScrollBar(0).SetY(m_CachedActualSize.top); | GetScrollBar(0).SetY(m_CachedActualSize.top); | ||||
GetScrollBar(0).SetZ(GetBufferedZ()); | GetScrollBar(0).SetZ(GetBufferedZ()); | ||||
GetScrollBar(0).SetLength(m_CachedActualSize.bottom - m_CachedActualSize.top); | GetScrollBar(0).SetLength(m_CachedActualSize.bottom - m_CachedActualSize.top); | ||||
GetScrollBar(0).SetScrollBarStyle(GetSetting<CStr>("scrollbar_style")); | GetScrollBar(0).SetScrollBarStyle(m_ScrollBarStyle); | ||||
UpdateText(); | UpdateText(); | ||||
UpdateAutoScroll(); | UpdateAutoScroll(); | ||||
m_Readonly = GetSetting<bool>("readonly"); | |||||
break; | break; | ||||
} | } | ||||
case GUIM_GOT_FOCUS: | case GUIM_GOT_FOCUS: | ||||
{ | { | ||||
m_iBufferPos = 0; | m_iBufferPos = 0; | ||||
m_PrevTime = 0.0; | m_PrevTime = 0.0; | ||||
m_CursorVisState = false; | m_CursorVisState = false; | ||||
Show All 35 Lines | |||||
void CInput::UpdateCachedSize() | void CInput::UpdateCachedSize() | ||||
{ | { | ||||
// If an ancestor's size changed, this will let us intercept the change and | // If an ancestor's size changed, this will let us intercept the change and | ||||
// update our scrollbar positions | // update our scrollbar positions | ||||
IGUIObject::UpdateCachedSize(); | IGUIObject::UpdateCachedSize(); | ||||
if (GetSetting<bool>("scrollbar")) | if (m_ScrollBar) | ||||
{ | { | ||||
GetScrollBar(0).SetX(m_CachedActualSize.right); | GetScrollBar(0).SetX(m_CachedActualSize.right); | ||||
GetScrollBar(0).SetY(m_CachedActualSize.top); | GetScrollBar(0).SetY(m_CachedActualSize.top); | ||||
GetScrollBar(0).SetZ(GetBufferedZ()); | GetScrollBar(0).SetZ(GetBufferedZ()); | ||||
GetScrollBar(0).SetLength(m_CachedActualSize.bottom - m_CachedActualSize.top); | GetScrollBar(0).SetLength(m_CachedActualSize.bottom - m_CachedActualSize.top); | ||||
} | } | ||||
} | } | ||||
Show All 11 Lines | if (currTime - m_PrevTime >= m_CursorBlinkRate) | ||||
m_PrevTime = currTime; | m_PrevTime = currTime; | ||||
} | } | ||||
} | } | ||||
else | else | ||||
// should always be visible | // should always be visible | ||||
m_CursorVisState = true; | m_CursorVisState = true; | ||||
// First call draw on ScrollBarOwner | // First call draw on ScrollBarOwner | ||||
const bool scrollbar = GetSetting<bool>("scrollbar"); | if (m_ScrollBar && m_MultiLine) | ||||
const float buffer_zone = GetSetting<float>("buffer_zone"); | |||||
const bool multiline = GetSetting<bool>("multiline"); | |||||
const bool mask = GetSetting<bool>("mask"); | |||||
if (scrollbar && multiline) | |||||
IGUIScrollBarOwner::Draw(); | IGUIScrollBarOwner::Draw(); | ||||
const CGUIColor& color = GetSetting<CGUIColor>("textcolor"); | CStrIntern font_name(m_Font.ToUTF8()); | ||||
const CGUIColor& color_selected = GetSetting<CGUIColor>("textcolor_selected"); | |||||
CStrIntern font_name(GetSetting<CStrW>("font").ToUTF8()); | |||||
const CStrW& pCaption = GetSetting<CStrW>("caption"); | |||||
wchar_t mask_char = L'*'; | wchar_t mask_char = L'*'; | ||||
if (mask) | if (m_Mask && m_MaskChar.length() > 0) | ||||
{ | mask_char = m_MaskChar[0]; | ||||
const CStrW& maskStr = GetSetting<CStrW>("mask_char"); | |||||
if (maskStr.length() > 0) | |||||
mask_char = maskStr[0]; | |||||
} | |||||
CGUISpriteInstance& sprite = GetSetting<CGUISpriteInstance>("sprite"); | |||||
CGUISpriteInstance& sprite_selectarea = GetSetting<CGUISpriteInstance>("sprite_selectarea"); | |||||
const int cell_id = GetSetting<i32>("cell_id"); | |||||
m_pGUI.DrawSprite(sprite, cell_id, bz, m_CachedActualSize); | m_pGUI.DrawSprite(m_Sprite, m_CellID, bz, m_CachedActualSize); | ||||
float scroll = 0.f; | float scroll = 0.f; | ||||
if (scrollbar && multiline) | if (m_ScrollBar && m_MultiLine) | ||||
scroll = GetScrollBar(0).GetPos(); | scroll = GetScrollBar(0).GetPos(); | ||||
CFontMetrics font(font_name); | CFontMetrics font(font_name); | ||||
// We'll have to setup clipping manually, since we're doing the rendering manually. | // We'll have to setup clipping manually, since we're doing the rendering manually. | ||||
CRect cliparea(m_CachedActualSize); | CRect cliparea(m_CachedActualSize); | ||||
// First we'll figure out the clipping area, which is the cached actual size | // First we'll figure out the clipping area, which is the cached actual size | ||||
// substracted by an optional scrollbar | // substracted by an optional scrollbar | ||||
if (scrollbar) | if (m_ScrollBar) | ||||
{ | { | ||||
scroll = GetScrollBar(0).GetPos(); | scroll = GetScrollBar(0).GetPos(); | ||||
// substract scrollbar from cliparea | // substract scrollbar from cliparea | ||||
if (cliparea.right > GetScrollBar(0).GetOuterRect().left && | if (cliparea.right > GetScrollBar(0).GetOuterRect().left && | ||||
cliparea.right <= GetScrollBar(0).GetOuterRect().right) | cliparea.right <= GetScrollBar(0).GetOuterRect().right) | ||||
cliparea.right = GetScrollBar(0).GetOuterRect().left; | cliparea.right = GetScrollBar(0).GetOuterRect().left; | ||||
Show All 33 Lines | void CInput::Draw() | ||||
CShaderTechniquePtr tech = g_Renderer.GetShaderManager().LoadEffect(str_gui_text); | CShaderTechniquePtr tech = g_Renderer.GetShaderManager().LoadEffect(str_gui_text); | ||||
CTextRenderer textRenderer(tech->GetShader()); | CTextRenderer textRenderer(tech->GetShader()); | ||||
textRenderer.Font(font_name); | textRenderer.Font(font_name); | ||||
// Set the Z to somewhat more, so we can draw a selected area between the | // Set the Z to somewhat more, so we can draw a selected area between the | ||||
// the control and the text. | // the control and the text. | ||||
textRenderer.Translate( | textRenderer.Translate( | ||||
(float)(int)(m_CachedActualSize.left) + buffer_zone, | (float)(int)(m_CachedActualSize.left) + m_BufferZone, | ||||
(float)(int)(m_CachedActualSize.top+h) + buffer_zone, | (float)(int)(m_CachedActualSize.top+h) + m_BufferZone, | ||||
bz+0.1f); | bz+0.1f); | ||||
// U+FE33: PRESENTATION FORM FOR VERTICAL LOW LINE | // U+FE33: PRESENTATION FORM FOR VERTICAL LOW LINE | ||||
// (sort of like a | which is aligned to the left of most characters) | // (sort of like a | which is aligned to the left of most characters) | ||||
float buffered_y = -scroll+buffer_zone; | float buffered_y = -scroll + m_BufferZone; | ||||
// When selecting larger areas, we need to draw a rectangle box | // When selecting larger areas, we need to draw a rectangle box | ||||
// around it, and this is to keep track of where the box | // around it, and this is to keep track of where the box | ||||
// started, because we need to follow the iteration until we | // started, because we need to follow the iteration until we | ||||
// reach the end, before we can actually draw it. | // reach the end, before we can actually draw it. | ||||
bool drawing_box = false; | bool drawing_box = false; | ||||
float box_x = 0.f; | float box_x = 0.f; | ||||
Show All 31 Lines | if (SelectingText()) | ||||
} | } | ||||
bool done = false; | bool done = false; | ||||
for (std::list<SRow>::const_iterator it = m_CharacterPositions.begin(); | for (std::list<SRow>::const_iterator it = m_CharacterPositions.begin(); | ||||
it != m_CharacterPositions.end(); | it != m_CharacterPositions.end(); | ||||
++it, buffered_y += ls, x_pointer = 0.f) | ++it, buffered_y += ls, x_pointer = 0.f) | ||||
{ | { | ||||
if (multiline && buffered_y > m_CachedActualSize.GetHeight()) | if (m_MultiLine && buffered_y > m_CachedActualSize.GetHeight()) | ||||
break; | break; | ||||
// We might as well use 'i' here to iterate, because we need it | // We might as well use 'i' here to iterate, because we need it | ||||
// (often compared against ints, so don't make it size_t) | // (often compared against ints, so don't make it size_t) | ||||
for (int i = 0; i < (int)it->m_ListOfX.size()+2; ++i) | for (int i = 0; i < (int)it->m_ListOfX.size()+2; ++i) | ||||
{ | { | ||||
if (it->m_ListStart + i == VirtualFrom) | if (it->m_ListStart + i == VirtualFrom) | ||||
{ | { | ||||
Show All 12 Lines | for (std::list<SRow>::const_iterator it = m_CharacterPositions.begin(); | ||||
if (drawing_box && (it->m_ListStart + i == VirtualTo || at_end)) | if (drawing_box && (it->m_ListStart + i == VirtualTo || at_end)) | ||||
{ | { | ||||
// Depending on if it's just a row change, or if it's | // Depending on if it's just a row change, or if it's | ||||
// the end of the select box, do slightly different things. | // the end of the select box, do slightly different things. | ||||
if (at_end) | if (at_end) | ||||
{ | { | ||||
if (it->m_ListStart + i != VirtualFrom) | if (it->m_ListStart + i != VirtualFrom) | ||||
// and actually add a white space! yes, this is done in any common input | // and actually add a white space! yes, this is done in any common input | ||||
x_pointer += (float)font.GetCharacterWidth(L' '); | x_pointer += font.GetCharacterWidth(L' '); | ||||
} | } | ||||
else | else | ||||
{ | { | ||||
drawing_box = false; | drawing_box = false; | ||||
done = true; | done = true; | ||||
} | } | ||||
CRect rect; | CRect rect; | ||||
// Set 'rect' depending on if it's a multiline control, or a one-line control | // Set 'rect' depending on if it's a multiline control, or a one-line control | ||||
if (multiline) | if (m_MultiLine) | ||||
{ | { | ||||
rect = CRect( | rect = CRect( | ||||
m_CachedActualSize.left + box_x + buffer_zone, | m_CachedActualSize.left + box_x + m_BufferZone, | ||||
m_CachedActualSize.top + buffered_y + (h - ls) / 2, | m_CachedActualSize.top + buffered_y + (h - ls) / 2, | ||||
m_CachedActualSize.left + x_pointer + buffer_zone, | m_CachedActualSize.left + x_pointer + m_BufferZone, | ||||
m_CachedActualSize.top + buffered_y + (h + ls) / 2); | m_CachedActualSize.top + buffered_y + (h + ls) / 2); | ||||
if (rect.bottom < m_CachedActualSize.top) | if (rect.bottom < m_CachedActualSize.top) | ||||
continue; | continue; | ||||
if (rect.top < m_CachedActualSize.top) | if (rect.top < m_CachedActualSize.top) | ||||
rect.top = m_CachedActualSize.top; | rect.top = m_CachedActualSize.top; | ||||
if (rect.bottom > m_CachedActualSize.bottom) | if (rect.bottom > m_CachedActualSize.bottom) | ||||
rect.bottom = m_CachedActualSize.bottom; | rect.bottom = m_CachedActualSize.bottom; | ||||
} | } | ||||
else // if one-line | else // if one-line | ||||
{ | { | ||||
rect = CRect( | rect = CRect( | ||||
m_CachedActualSize.left + box_x + buffer_zone - m_HorizontalScroll, | m_CachedActualSize.left + box_x + m_BufferZone - m_HorizontalScroll, | ||||
m_CachedActualSize.top + buffered_y + (h - ls) / 2, | m_CachedActualSize.top + buffered_y + (h - ls) / 2, | ||||
m_CachedActualSize.left + x_pointer + buffer_zone - m_HorizontalScroll, | m_CachedActualSize.left + x_pointer + m_BufferZone - m_HorizontalScroll, | ||||
m_CachedActualSize.top + buffered_y + (h + ls) / 2); | m_CachedActualSize.top + buffered_y + (h + ls) / 2); | ||||
if (rect.left < m_CachedActualSize.left) | if (rect.left < m_CachedActualSize.left) | ||||
rect.left = m_CachedActualSize.left; | rect.left = m_CachedActualSize.left; | ||||
if (rect.right > m_CachedActualSize.right) | if (rect.right > m_CachedActualSize.right) | ||||
rect.right = m_CachedActualSize.right; | rect.right = m_CachedActualSize.right; | ||||
} | } | ||||
m_pGUI.DrawSprite(sprite_selectarea, cell_id, bz + 0.05f, rect); | m_pGUI.DrawSprite(m_SpriteSelectArea, m_CellID, bz + 0.05f, rect); | ||||
} | } | ||||
if (i < (int)it->m_ListOfX.size()) | if (i < (int)it->m_ListOfX.size()) | ||||
{ | { | ||||
if (!mask) | if (!m_Mask) | ||||
x_pointer += (float)font.GetCharacterWidth(pCaption[it->m_ListStart + i]); | x_pointer += font.GetCharacterWidth(m_Caption[it->m_ListStart + i]); | ||||
else | else | ||||
x_pointer += (float)font.GetCharacterWidth(mask_char); | x_pointer += font.GetCharacterWidth(mask_char); | ||||
} | } | ||||
} | } | ||||
if (done) | if (done) | ||||
break; | break; | ||||
// If we're about to draw a box, and all of a sudden changes | // If we're about to draw a box, and all of a sudden changes | ||||
// line, we need to draw that line's box, and then reset | // line, we need to draw that line's box, and then reset | ||||
// the box drawing to the beginning of the new line. | // the box drawing to the beginning of the new line. | ||||
if (drawing_box) | if (drawing_box) | ||||
box_x = 0.f; | box_x = 0.f; | ||||
} | } | ||||
} | } | ||||
// Reset some from previous run | // Reset some from previous run | ||||
buffered_y = -scroll; | buffered_y = -scroll; | ||||
// Setup initial color (then it might change and change back, when drawing selected area) | // Setup initial color (then it might change and change back, when drawing selected area) | ||||
textRenderer.Color(color); | textRenderer.Color(m_TextColor); | ||||
tech->BeginPass(); | tech->BeginPass(); | ||||
bool using_selected_color = false; | bool using_selected_color = false; | ||||
for (std::list<SRow>::const_iterator it = m_CharacterPositions.begin(); | for (std::list<SRow>::const_iterator it = m_CharacterPositions.begin(); | ||||
it != m_CharacterPositions.end(); | it != m_CharacterPositions.end(); | ||||
++it, buffered_y += ls) | ++it, buffered_y += ls) | ||||
{ | { | ||||
if (buffered_y + buffer_zone >= -ls || !multiline) | if (buffered_y + m_BufferZone >= -ls || !m_MultiLine) | ||||
{ | { | ||||
if (multiline && buffered_y + buffer_zone > m_CachedActualSize.GetHeight()) | if (m_MultiLine && buffered_y + m_BufferZone > m_CachedActualSize.GetHeight()) | ||||
break; | break; | ||||
CMatrix3D savedTransform = textRenderer.GetTransform(); | CMatrix3D savedTransform = textRenderer.GetTransform(); | ||||
// Text must always be drawn in integer values. So we have to convert scroll | // Text must always be drawn in integer values. So we have to convert scroll | ||||
if (multiline) | if (m_MultiLine) | ||||
textRenderer.Translate(0.f, -(float)(int)scroll, 0.f); | textRenderer.Translate(0.f, -(float)(int)scroll, 0.f); | ||||
else | else | ||||
textRenderer.Translate(-(float)(int)m_HorizontalScroll, 0.f, 0.f); | textRenderer.Translate(-(float)(int)m_HorizontalScroll, 0.f, 0.f); | ||||
// We might as well use 'i' here, because we need it | // We might as well use 'i' here, because we need it | ||||
// (often compared against ints, so don't make it size_t) | // (often compared against ints, so don't make it size_t) | ||||
for (int i = 0; i < (int)it->m_ListOfX.size()+1; ++i) | for (int i = 0; i < (int)it->m_ListOfX.size()+1; ++i) | ||||
{ | { | ||||
if (!multiline && i < (int)it->m_ListOfX.size()) | if (!m_MultiLine && i < (int)it->m_ListOfX.size()) | ||||
{ | { | ||||
if (it->m_ListOfX[i] - m_HorizontalScroll < -buffer_zone) | if (it->m_ListOfX[i] - m_HorizontalScroll < -m_BufferZone) | ||||
{ | { | ||||
// We still need to translate the OpenGL matrix | // We still need to translate the OpenGL matrix | ||||
if (i == 0) | if (i == 0) | ||||
textRenderer.Translate(it->m_ListOfX[i], 0.f, 0.f); | textRenderer.Translate(it->m_ListOfX[i], 0.f, 0.f); | ||||
else | else | ||||
textRenderer.Translate(it->m_ListOfX[i] - it->m_ListOfX[i-1], 0.f, 0.f); | textRenderer.Translate(it->m_ListOfX[i] - it->m_ListOfX[i-1], 0.f, 0.f); | ||||
continue; | continue; | ||||
} | } | ||||
} | } | ||||
// End of selected area, change back color | // End of selected area, change back color | ||||
if (SelectingText() && it->m_ListStart + i == VirtualTo) | if (SelectingText() && it->m_ListStart + i == VirtualTo) | ||||
{ | { | ||||
using_selected_color = false; | using_selected_color = false; | ||||
textRenderer.Color(color); | textRenderer.Color(m_TextColor); | ||||
} | } | ||||
// selecting only one, then we need only to draw a cursor. | // selecting only one, then we need only to draw a cursor. | ||||
if (i != (int)it->m_ListOfX.size() && it->m_ListStart + i == m_iBufferPos && m_CursorVisState) | if (i != (int)it->m_ListOfX.size() && it->m_ListStart + i == m_iBufferPos && m_CursorVisState) | ||||
textRenderer.Put(0.0f, 0.0f, L"_"); | textRenderer.Put(0.0f, 0.0f, L"_"); | ||||
// Drawing selected area | // Drawing selected area | ||||
if (SelectingText() && | if (SelectingText() && | ||||
it->m_ListStart + i >= VirtualFrom && | it->m_ListStart + i >= VirtualFrom && | ||||
it->m_ListStart + i < VirtualTo && | it->m_ListStart + i < VirtualTo && | ||||
!using_selected_color) | !using_selected_color) | ||||
{ | { | ||||
using_selected_color = true; | using_selected_color = true; | ||||
textRenderer.Color(color_selected); | textRenderer.Color(m_TextColorSelected); | ||||
} | } | ||||
if (i != (int)it->m_ListOfX.size()) | if (i != (int)it->m_ListOfX.size()) | ||||
{ | { | ||||
if (!mask) | if (!m_Mask) | ||||
textRenderer.PrintfAdvance(L"%lc", pCaption[it->m_ListStart + i]); | textRenderer.PrintfAdvance(L"%lc", m_Caption[it->m_ListStart + i]); | ||||
else | else | ||||
textRenderer.PrintfAdvance(L"%lc", mask_char); | textRenderer.PrintfAdvance(L"%lc", mask_char); | ||||
} | } | ||||
// check it's now outside a one-liner, then we'll break | // check it's now outside a one-liner, then we'll break | ||||
if (!multiline && i < (int)it->m_ListOfX.size() && | if (!m_MultiLine && i < (int)it->m_ListOfX.size() && | ||||
it->m_ListOfX[i] - m_HorizontalScroll > m_CachedActualSize.GetWidth() - buffer_zone) | it->m_ListOfX[i] - m_HorizontalScroll > m_CachedActualSize.GetWidth() - m_BufferZone) | ||||
break; | break; | ||||
} | } | ||||
if (it->m_ListStart + (int)it->m_ListOfX.size() == m_iBufferPos) | if (it->m_ListStart + (int)it->m_ListOfX.size() == m_iBufferPos) | ||||
{ | { | ||||
textRenderer.Color(color); | textRenderer.Color(m_TextColor); | ||||
if (m_CursorVisState) | if (m_CursorVisState) | ||||
textRenderer.PutAdvance(L"_"); | textRenderer.PutAdvance(L"_"); | ||||
if (using_selected_color) | if (using_selected_color) | ||||
textRenderer.Color(color_selected); | textRenderer.Color(m_TextColorSelected); | ||||
} | } | ||||
textRenderer.SetTransform(savedTransform); | textRenderer.SetTransform(savedTransform); | ||||
} | } | ||||
textRenderer.Translate(0.f, ls, 0.f); | textRenderer.Translate(0.f, ls, 0.f); | ||||
} | } | ||||
textRenderer.Render(); | textRenderer.Render(); | ||||
if (cliparea != CRect()) | if (cliparea != CRect()) | ||||
glDisable(GL_SCISSOR_TEST); | glDisable(GL_SCISSOR_TEST); | ||||
tech->EndPass(); | tech->EndPass(); | ||||
} | } | ||||
void CInput::UpdateText(int from, int to_before, int to_after) | void CInput::UpdateText(int from, int to_before, int to_after) | ||||
{ | { | ||||
const CStrW& caption = GetSetting<CStrW>("caption"); | CStrIntern font_name(m_Font.ToUTF8()); | ||||
const float buffer_zone = GetSetting<float>("buffer_zone"); | |||||
const bool multiline = GetSetting<bool>("multiline"); | |||||
const bool mask = GetSetting<bool>("mask"); | |||||
CStrIntern font_name(GetSetting<CStrW>("font").ToUTF8()); | |||||
wchar_t mask_char = L'*'; | wchar_t mask_char = L'*'; | ||||
if (mask) | if (m_Mask && m_MaskChar.length() > 0) | ||||
{ | mask_char = m_MaskChar[0]; | ||||
const CStrW& maskStr = GetSetting<CStrW>("mask_char"); | |||||
if (maskStr.length() > 0) | |||||
mask_char = maskStr[0]; | |||||
} | |||||
// Ensure positions are valid after caption changes | // Ensure positions are valid after caption changes | ||||
m_iBufferPos = std::min(m_iBufferPos, (int)caption.size()); | m_iBufferPos = std::min(m_iBufferPos, static_cast<int>(m_Caption.size())); | ||||
m_iBufferPos_Tail = std::min(m_iBufferPos_Tail, (int)caption.size()); | m_iBufferPos_Tail = std::min(m_iBufferPos_Tail, static_cast<int>(m_Caption.size())); | ||||
UpdateBufferPositionSetting(); | UpdateBufferPositionSetting(); | ||||
if (font_name.empty()) | if (font_name.empty()) | ||||
{ | { | ||||
// Destroy everything stored, there's no font, so there can be no data. | // Destroy everything stored, there's no font, so there can be no data. | ||||
m_CharacterPositions.clear(); | m_CharacterPositions.clear(); | ||||
return; | return; | ||||
} | } | ||||
SRow row; | SRow row; | ||||
row.m_ListStart = 0; | row.m_ListStart = 0; | ||||
int to = 0; // make sure it's initialized | int to = 0; // make sure it's initialized | ||||
if (to_before == -1) | if (to_before == -1) | ||||
to = (int)caption.length(); | to = static_cast<int>(m_Caption.length()); | ||||
CFontMetrics font(font_name); | CFontMetrics font(font_name); | ||||
std::list<SRow>::iterator current_line; | std::list<SRow>::iterator current_line; | ||||
// Used to ... TODO | // Used to ... TODO | ||||
int check_point_row_start = -1; | int check_point_row_start = -1; | ||||
int check_point_row_end = -1; | int check_point_row_end = -1; | ||||
▲ Show 20 Lines • Show All 86 Lines • ▼ Show 20 Lines | else | ||||
// set 'from' to the row we'll destroy from | // set 'from' to the row we'll destroy from | ||||
// and 'to' to the row we'll destroy to | // and 'to' to the row we'll destroy to | ||||
from = destroy_row_from->m_ListStart; | from = destroy_row_from->m_ListStart; | ||||
if (destroy_row_to != m_CharacterPositions.end()) | if (destroy_row_to != m_CharacterPositions.end()) | ||||
to = destroy_row_to->m_ListStart; // notice it will iterate [from, to), so it will never reach to. | to = destroy_row_to->m_ListStart; // notice it will iterate [from, to), so it will never reach to. | ||||
else | else | ||||
to = (int)caption.length(); | to = static_cast<int>(m_Caption.length()); | ||||
// Setup the first row | // Setup the first row | ||||
row.m_ListStart = destroy_row_from->m_ListStart; | row.m_ListStart = destroy_row_from->m_ListStart; | ||||
std::list<SRow>::iterator temp_it = destroy_row_to; | std::list<SRow>::iterator temp_it = destroy_row_to; | ||||
--temp_it; | --temp_it; | ||||
Show All 10 Lines | if (delta != 0) | ||||
it != m_CharacterPositions.end(); | it != m_CharacterPositions.end(); | ||||
++it) | ++it) | ||||
it->m_ListStart += delta; | it->m_ListStart += delta; | ||||
// Update our check point too! | // Update our check point too! | ||||
check_point_row_start += delta; | check_point_row_start += delta; | ||||
check_point_row_end += delta; | check_point_row_end += delta; | ||||
if (to != (int)caption.length()) | if (to != static_cast<int>(m_Caption.length())) | ||||
to += delta; | to += delta; | ||||
} | } | ||||
} | } | ||||
int last_word_started = from; | int last_word_started = from; | ||||
float x_pos = 0.f; | float x_pos = 0.f; | ||||
//if (to_before != -1) | //if (to_before != -1) | ||||
// return; | // return; | ||||
for (int i = from; i < to; ++i) | for (int i = from; i < to; ++i) | ||||
{ | { | ||||
if (caption[i] == L'\n' && multiline) | if (m_Caption[i] == L'\n' && m_MultiLine) | ||||
{ | { | ||||
if (i == to-1 && to != (int)caption.length()) | if (i == to-1 && to != static_cast<int>(m_Caption.length())) | ||||
break; // it will be added outside | break; // it will be added outside | ||||
current_line = m_CharacterPositions.insert(current_line, row); | current_line = m_CharacterPositions.insert(current_line, row); | ||||
++current_line; | ++current_line; | ||||
// Setup the next row: | // Setup the next row: | ||||
row.m_ListOfX.clear(); | row.m_ListOfX.clear(); | ||||
row.m_ListStart = i+1; | row.m_ListStart = i+1; | ||||
x_pos = 0.f; | x_pos = 0.f; | ||||
} | } | ||||
else | else | ||||
{ | { | ||||
if (caption[i] == L' '/* || TODO Gee (2004-10-13): the '-' disappears, fix. | if (m_Caption[i] == L' '/* || TODO Gee (2004-10-13): the '-' disappears, fix. | ||||
caption[i] == L'-'*/) | m_Caption[i] == L'-'*/) | ||||
last_word_started = i+1; | last_word_started = i+1; | ||||
if (!mask) | if (!m_Mask) | ||||
x_pos += (float)font.GetCharacterWidth(caption[i]); | x_pos += font.GetCharacterWidth(m_Caption[i]); | ||||
else | else | ||||
x_pos += (float)font.GetCharacterWidth(mask_char); | x_pos += font.GetCharacterWidth(mask_char); | ||||
if (x_pos >= GetTextAreaWidth() && multiline) | if (x_pos >= GetTextAreaWidth() && m_MultiLine) | ||||
{ | { | ||||
// The following decides whether it will word-wrap a word, | // The following decides whether it will word-wrap a word, | ||||
// or if it's only one word on the line, where it has to | // or if it's only one word on the line, where it has to | ||||
// break the word apart. | // break the word apart. | ||||
if (last_word_started == row.m_ListStart) | if (last_word_started == row.m_ListStart) | ||||
{ | { | ||||
last_word_started = i; | last_word_started = i; | ||||
row.m_ListOfX.resize(row.m_ListOfX.size() - (i-last_word_started)); | row.m_ListOfX.resize(row.m_ListOfX.size() - (i-last_word_started)); | ||||
▲ Show 20 Lines • Show All 104 Lines • ▼ Show 20 Lines | if (to_before != -1 && i == to-1 && current_line != m_CharacterPositions.end()) | ||||
{ | { | ||||
destroy_row_to = m_CharacterPositions.end(); | destroy_row_to = m_CharacterPositions.end(); | ||||
check_point_row_start = check_point_row_end = -1; | check_point_row_start = check_point_row_end = -1; | ||||
} | } | ||||
if (destroy_row_to != m_CharacterPositions.end()) | if (destroy_row_to != m_CharacterPositions.end()) | ||||
to = destroy_row_to->m_ListStart; // notice it will iterate [from, to[, so it will never reach to. | to = destroy_row_to->m_ListStart; // notice it will iterate [from, to[, so it will never reach to. | ||||
else | else | ||||
to = (int)caption.length(); | to = static_cast<int>(m_Caption.length()); | ||||
// Set current line, new rows will be added before current_line, so | // Set current line, new rows will be added before current_line, so | ||||
// we'll choose the destroy_row_to, because it won't be deleted | // we'll choose the destroy_row_to, because it won't be deleted | ||||
// in the coming erase. | // in the coming erase. | ||||
current_line = destroy_row_to; | current_line = destroy_row_to; | ||||
m_CharacterPositions.erase(destroy_row_from, destroy_row_to); | m_CharacterPositions.erase(destroy_row_from, destroy_row_to); | ||||
Show All 9 Lines | void CInput::UpdateText(int from, int to_before, int to_after) | ||||
{ | { | ||||
if (row.m_ListStart + (int)row.m_ListOfX.size() == current_line->m_ListStart) | if (row.m_ListStart + (int)row.m_ListOfX.size() == current_line->m_ListStart) | ||||
row.m_ListOfX.resize(row.m_ListOfX.size()-1); | row.m_ListOfX.resize(row.m_ListOfX.size()-1); | ||||
} | } | ||||
// add the final row (even if empty) | // add the final row (even if empty) | ||||
m_CharacterPositions.insert(current_line, row); | m_CharacterPositions.insert(current_line, row); | ||||
if (GetSetting<bool>("scrollbar")) | if (m_ScrollBar) | ||||
{ | { | ||||
GetScrollBar(0).SetScrollRange(m_CharacterPositions.size() * font.GetLineSpacing() + buffer_zone*2.f); | GetScrollBar(0).SetScrollRange(m_CharacterPositions.size() * font.GetLineSpacing() + m_BufferZone * 2.f); | ||||
GetScrollBar(0).SetScrollSpace(m_CachedActualSize.GetHeight()); | GetScrollBar(0).SetScrollSpace(m_CachedActualSize.GetHeight()); | ||||
} | } | ||||
} | } | ||||
int CInput::GetMouseHoveringTextPosition() const | int CInput::GetMouseHoveringTextPosition() const | ||||
{ | { | ||||
if (m_CharacterPositions.empty()) | if (m_CharacterPositions.empty()) | ||||
return 0; | return 0; | ||||
const float buffer_zone = GetSetting<float>("buffer_zone"); | |||||
const bool multiline = GetSetting<bool>("multiline"); | |||||
// Return position | // Return position | ||||
int retPosition; | int retPosition; | ||||
std::list<SRow>::const_iterator current = m_CharacterPositions.begin(); | std::list<SRow>::const_iterator current = m_CharacterPositions.begin(); | ||||
CPos mouse = m_pGUI.GetMousePos(); | CPos mouse = m_pGUI.GetMousePos(); | ||||
if (multiline) | if (m_MultiLine) | ||||
{ | { | ||||
float scroll = 0.f; | float scroll = 0.f; | ||||
if (GetSetting<bool>("scrollbar")) | if (m_ScrollBar) | ||||
scroll = GetScrollBarPos(0); | scroll = GetScrollBarPos(0); | ||||
// Now get the height of the font. | // Now get the height of the font. | ||||
// TODO: Get the real font | // TODO: Get the real font | ||||
CFontMetrics font(CStrIntern(GetSetting<CStrW>("font").ToUTF8())); | CFontMetrics font(CStrIntern(m_Font.ToUTF8())); | ||||
float spacing = (float)font.GetLineSpacing(); | float spacing = (float)font.GetLineSpacing(); | ||||
// Change mouse position relative to text. | // Change mouse position relative to text. | ||||
mouse -= m_CachedActualSize.TopLeft(); | mouse -= m_CachedActualSize.TopLeft(); | ||||
mouse.x -= buffer_zone; | mouse.x -= m_BufferZone; | ||||
mouse.y += scroll - buffer_zone; | mouse.y += scroll - m_BufferZone; | ||||
int row = (int)((mouse.y) / spacing); | int row = (int)((mouse.y) / spacing); | ||||
if (row < 0) | if (row < 0) | ||||
row = 0; | row = 0; | ||||
if (row > (int)m_CharacterPositions.size()-1) | if (row > (int)m_CharacterPositions.size()-1) | ||||
row = (int)m_CharacterPositions.size()-1; | row = (int)m_CharacterPositions.size()-1; | ||||
// TODO Gee (2004-11-21): Okay, I need a 'std::list' for some reasons, but I would really like to | // TODO Gee (2004-11-21): Okay, I need a 'std::list' for some reasons, but I would really like to | ||||
// be able to get the specific element here. This is hopefully a temporary hack. | // be able to get the specific element here. This is hopefully a temporary hack. | ||||
for (int i = 0; i < row; ++i) | for (int i = 0; i < row; ++i) | ||||
++current; | ++current; | ||||
} | } | ||||
else | else | ||||
{ | { | ||||
// current is already set to begin, | // current is already set to begin, | ||||
// but we'll change the mouse.x to fit our horizontal scrolling | // but we'll change the mouse.x to fit our horizontal scrolling | ||||
mouse -= m_CachedActualSize.TopLeft(); | mouse -= m_CachedActualSize.TopLeft(); | ||||
mouse.x -= buffer_zone - m_HorizontalScroll; | mouse.x -= m_BufferZone - m_HorizontalScroll; | ||||
// mouse.y is moot | // mouse.y is moot | ||||
} | } | ||||
retPosition = current->m_ListStart; | retPosition = current->m_ListStart; | ||||
// Okay, now loop through the glyphs to find the appropriate X position | // Okay, now loop through the glyphs to find the appropriate X position | ||||
float dummy; | float dummy; | ||||
retPosition += GetXTextPosition(current, mouse.x, dummy); | retPosition += GetXTextPosition(current, mouse.x, dummy); | ||||
Show All 33 Lines | int CInput::GetXTextPosition(const std::list<SRow>::const_iterator& current, const float& x, float& wanted) const | ||||
else | else | ||||
wanted = 0.f; | wanted = 0.f; | ||||
return ret; | return ret; | ||||
} | } | ||||
void CInput::DeleteCurSelection() | void CInput::DeleteCurSelection() | ||||
{ | { | ||||
CStrW& pCaption = GetSetting<CStrW>("caption"); | |||||
int virtualFrom; | int virtualFrom; | ||||
int virtualTo; | int virtualTo; | ||||
if (m_iBufferPos_Tail >= m_iBufferPos) | if (m_iBufferPos_Tail >= m_iBufferPos) | ||||
{ | { | ||||
virtualFrom = m_iBufferPos; | virtualFrom = m_iBufferPos; | ||||
virtualTo = m_iBufferPos_Tail; | virtualTo = m_iBufferPos_Tail; | ||||
} | } | ||||
else | else | ||||
{ | { | ||||
virtualFrom = m_iBufferPos_Tail; | virtualFrom = m_iBufferPos_Tail; | ||||
virtualTo = m_iBufferPos; | virtualTo = m_iBufferPos; | ||||
} | } | ||||
pCaption = | m_Caption = | ||||
pCaption.Left(virtualFrom) + | m_Caption.Left(virtualFrom) + | ||||
pCaption.Right(static_cast<long>(pCaption.length()) - virtualTo); | m_Caption.Right(static_cast<long>(m_Caption.length()) - virtualTo); | ||||
UpdateText(virtualFrom, virtualTo, virtualFrom); | UpdateText(virtualFrom, virtualTo, virtualFrom); | ||||
// Remove selection | // Remove selection | ||||
m_iBufferPos_Tail = -1; | m_iBufferPos_Tail = -1; | ||||
m_iBufferPos = virtualFrom; | m_iBufferPos = virtualFrom; | ||||
UpdateBufferPositionSetting(); | UpdateBufferPositionSetting(); | ||||
} | } | ||||
bool CInput::SelectingText() const | bool CInput::SelectingText() const | ||||
{ | { | ||||
return m_iBufferPos_Tail != -1 && | return m_iBufferPos_Tail != -1 && | ||||
m_iBufferPos_Tail != m_iBufferPos; | m_iBufferPos_Tail != m_iBufferPos; | ||||
} | } | ||||
float CInput::GetTextAreaWidth() | float CInput::GetTextAreaWidth() | ||||
{ | { | ||||
const float buffer_zone = GetSetting<float>("buffer_zone"); | if (m_ScrollBar && GetScrollBar(0).GetStyle()) | ||||
return m_CachedActualSize.GetWidth() - m_BufferZone * 2.f - GetScrollBar(0).GetStyle()->m_Width; | |||||
if (GetSetting<bool>("scrollbar") && GetScrollBar(0).GetStyle()) | return m_CachedActualSize.GetWidth() - m_BufferZone * 2.f; | ||||
return m_CachedActualSize.GetWidth() - buffer_zone*2.f - GetScrollBar(0).GetStyle()->m_Width; | |||||
else | |||||
return m_CachedActualSize.GetWidth() - buffer_zone*2.f; | |||||
} | } | ||||
void CInput::UpdateAutoScroll() | void CInput::UpdateAutoScroll() | ||||
{ | { | ||||
const float buffer_zone = GetSetting<float>("buffer_zone"); | |||||
// Autoscrolling up and down | // Autoscrolling up and down | ||||
if (GetSetting<bool>("multiline")) | if (m_MultiLine) | ||||
{ | { | ||||
if (!GetSetting<bool>("scrollbar")) | if (!m_ScrollBar) | ||||
return; | return; | ||||
const float scroll = GetScrollBar(0).GetPos(); | const float scroll = GetScrollBar(0).GetPos(); | ||||
// Now get the height of the font. | // Now get the height of the font. | ||||
// TODO: Get the real font | // TODO: Get the real font | ||||
CFontMetrics font(CStrIntern(GetSetting<CStrW>("font").ToUTF8())); | CFontMetrics font(CStrIntern(m_Font.ToUTF8())); | ||||
float spacing = (float)font.GetLineSpacing(); | float spacing = (float)font.GetLineSpacing(); | ||||
//float height = font.GetHeight(); | //float height = font.GetHeight(); | ||||
// TODO Gee (2004-11-21): Okay, I need a 'std::list' for some reasons, but I would really like to | // TODO Gee (2004-11-21): Okay, I need a 'std::list' for some reasons, but I would really like to | ||||
// be able to get the specific element here. This is hopefully a temporary hack. | // be able to get the specific element here. This is hopefully a temporary hack. | ||||
std::list<SRow>::iterator current = m_CharacterPositions.begin(); | std::list<SRow>::iterator current = m_CharacterPositions.begin(); | ||||
int row = 0; | int row = 0; | ||||
while (current != m_CharacterPositions.end()) | while (current != m_CharacterPositions.end()) | ||||
{ | { | ||||
if (m_iBufferPos >= current->m_ListStart && | if (m_iBufferPos >= current->m_ListStart && | ||||
m_iBufferPos <= current->m_ListStart + (int)current->m_ListOfX.size()) | m_iBufferPos <= current->m_ListStart + (int)current->m_ListOfX.size()) | ||||
break; | break; | ||||
++current; | ++current; | ||||
++row; | ++row; | ||||
} | } | ||||
// If scrolling down | // If scrolling down | ||||
if (-scroll + (float)(row+1) * spacing + buffer_zone*2.f > m_CachedActualSize.GetHeight()) | if (-scroll + static_cast<float>(row + 1) * spacing + m_BufferZone * 2.f > m_CachedActualSize.GetHeight()) | ||||
{ | { | ||||
// Scroll so the selected row is shown completely, also with buffer_zone length to the edge. | // Scroll so the selected row is shown completely, also with m_BufferZone length to the edge. | ||||
GetScrollBar(0).SetPos((float)(row+1) * spacing - m_CachedActualSize.GetHeight() + buffer_zone*2.f); | GetScrollBar(0).SetPos(static_cast<float>(row + 1) * spacing - m_CachedActualSize.GetHeight() + m_BufferZone * 2.f); | ||||
} | } | ||||
// If scrolling up | // If scrolling up | ||||
else if (-scroll + (float)row * spacing < 0.f) | else if (-scroll + (float)row * spacing < 0.f) | ||||
{ | { | ||||
// Scroll so the selected row is shown completely, also with buffer_zone length to the edge. | // Scroll so the selected row is shown completely, also with m_BufferZone length to the edge. | ||||
GetScrollBar(0).SetPos((float)row * spacing); | GetScrollBar(0).SetPos((float)row * spacing); | ||||
} | } | ||||
} | } | ||||
else // autoscrolling left and right | else // autoscrolling left and right | ||||
{ | { | ||||
// Get X position of position: | // Get X position of position: | ||||
if (m_CharacterPositions.empty()) | if (m_CharacterPositions.empty()) | ||||
return; | return; | ||||
float x_position = 0.f; | float x_position = 0.f; | ||||
float x_total = 0.f; | float x_total = 0.f; | ||||
if (!m_CharacterPositions.begin()->m_ListOfX.empty()) | if (!m_CharacterPositions.begin()->m_ListOfX.empty()) | ||||
{ | { | ||||
// Get position of m_iBufferPos | // Get position of m_iBufferPos | ||||
if ((int)m_CharacterPositions.begin()->m_ListOfX.size() >= m_iBufferPos && | if ((int)m_CharacterPositions.begin()->m_ListOfX.size() >= m_iBufferPos && | ||||
m_iBufferPos > 0) | m_iBufferPos > 0) | ||||
x_position = m_CharacterPositions.begin()->m_ListOfX[m_iBufferPos-1]; | x_position = m_CharacterPositions.begin()->m_ListOfX[m_iBufferPos-1]; | ||||
// Get complete length: | // Get complete length: | ||||
x_total = m_CharacterPositions.begin()->m_ListOfX[m_CharacterPositions.begin()->m_ListOfX.size()-1]; | x_total = m_CharacterPositions.begin()->m_ListOfX[m_CharacterPositions.begin()->m_ListOfX.size()-1]; | ||||
} | } | ||||
// Check if outside to the right | // Check if outside to the right | ||||
if (x_position - m_HorizontalScroll + buffer_zone*2.f > m_CachedActualSize.GetWidth()) | if (x_position - m_HorizontalScroll + m_BufferZone * 2.f > m_CachedActualSize.GetWidth()) | ||||
m_HorizontalScroll = x_position - m_CachedActualSize.GetWidth() + buffer_zone*2.f; | m_HorizontalScroll = x_position - m_CachedActualSize.GetWidth() + m_BufferZone * 2.f; | ||||
// Check if outside to the left | // Check if outside to the left | ||||
if (x_position - m_HorizontalScroll < 0.f) | if (x_position - m_HorizontalScroll < 0.f) | ||||
m_HorizontalScroll = x_position; | m_HorizontalScroll = x_position; | ||||
// Check if the text doesn't even fill up to the right edge even though scrolling is done. | // Check if the text doesn't even fill up to the right edge even though scrolling is done. | ||||
if (m_HorizontalScroll != 0.f && | if (m_HorizontalScroll != 0.f && | ||||
x_total - m_HorizontalScroll + buffer_zone*2.f < m_CachedActualSize.GetWidth()) | x_total - m_HorizontalScroll + m_BufferZone * 2.f < m_CachedActualSize.GetWidth()) | ||||
m_HorizontalScroll = x_total - m_CachedActualSize.GetWidth() + buffer_zone*2.f; | m_HorizontalScroll = x_total - m_CachedActualSize.GetWidth() + m_BufferZone * 2.f; | ||||
// Now this is the fail-safe, if x_total isn't even the length of the control, | // Now this is the fail-safe, if x_total isn't even the length of the control, | ||||
// remove all scrolling | // remove all scrolling | ||||
if (x_total + buffer_zone*2.f < m_CachedActualSize.GetWidth()) | if (x_total + m_BufferZone * 2.f < m_CachedActualSize.GetWidth()) | ||||
m_HorizontalScroll = 0.f; | m_HorizontalScroll = 0.f; | ||||
} | } | ||||
} | } |
Wildfire Games · Phabricator