diff options
Diffstat (limited to 'src/intlGUIEditBox.cpp')
-rw-r--r-- | src/intlGUIEditBox.cpp | 1508 |
1 files changed, 0 insertions, 1508 deletions
diff --git a/src/intlGUIEditBox.cpp b/src/intlGUIEditBox.cpp deleted file mode 100644 index 32cca4866..000000000 --- a/src/intlGUIEditBox.cpp +++ /dev/null @@ -1,1508 +0,0 @@ -// 11.11.2011 11:11 ValkaTR -// -// This is a copy of intlGUIEditBox from the irrlicht, but with a -// fix in the OnEvent function, which doesn't allowed input of -// other keyboard layouts than latin-1 -// -// Characters like: ä ö ü õ ы й ю я ъ № € ° ... -// -// This fix is only needed for linux, because of a bug -// in the CIrrDeviceLinux.cpp:1014-1015 of the irrlicht -// -// Also locale in the programm should not be changed to -// a "C", "POSIX" or whatever, it should be set to "", -// or XLookupString will return nothing for the international -// characters. -// -// From the "man setlocale": -// -// On startup of the main program, the portable "C" locale -// is selected as default. A program may be made -// portable to all locales by calling: -// -// setlocale(LC_ALL, ""); -// -// after program initialization.... -// - -// Copyright (C) 2002-2013 Nikolaus Gebhardt -// This file is part of the "Irrlicht Engine". -// For conditions of distribution and use, see copyright notice in irrlicht.h - -#include "intlGUIEditBox.h" - -#ifdef _IRR_COMPILE_WITH_GUI_ - -#include "IGUISkin.h" -#include "IGUIEnvironment.h" -#include "IGUIFont.h" -#include "IVideoDriver.h" -//#include "rect.h" -//#include "irrlicht/os.cpp" -#include "porting.h" -//#include "Keycodes.h" - -/* - todo: - optional scrollbars - 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 -*/ - -namespace irr -{ -namespace gui -{ - -//! constructor -intlGUIEditBox::intlGUIEditBox(const wchar_t* text, bool border, - IGUIEnvironment* environment, IGUIElement* parent, s32 id, - const core::rect<s32>& rectangle) - : IGUIEditBox(environment, parent, id, rectangle), MouseMarking(false), - Border(border), OverrideColorEnabled(false), MarkBegin(0), MarkEnd(0), - OverrideColor(video::SColor(101,255,255,255)), OverrideFont(0), LastBreakFont(0), - Operator(0), BlinkStartTime(0), CursorPos(0), HScrollPos(0), VScrollPos(0), Max(0), - WordWrap(false), MultiLine(false), AutoScroll(true), PasswordBox(false), - PasswordChar(L'*'), HAlign(EGUIA_UPPERLEFT), VAlign(EGUIA_CENTER), - CurrentTextRect(0,0,1,1), FrameRect(rectangle) -{ - #ifdef _DEBUG - setDebugName("intlintlGUIEditBox"); - #endif - - Text = text; - - if (Environment) - Operator = Environment->getOSOperator(); - - if (Operator) - Operator->grab(); - - // this element can be tabbed to - setTabStop(true); - setTabOrder(-1); - - IGUISkin *skin = 0; - if (Environment) - skin = Environment->getSkin(); - if (Border && skin) - { - FrameRect.UpperLeftCorner.X += skin->getSize(EGDS_TEXT_DISTANCE_X)+1; - FrameRect.UpperLeftCorner.Y += skin->getSize(EGDS_TEXT_DISTANCE_Y)+1; - FrameRect.LowerRightCorner.X -= skin->getSize(EGDS_TEXT_DISTANCE_X)+1; - FrameRect.LowerRightCorner.Y -= skin->getSize(EGDS_TEXT_DISTANCE_Y)+1; - } - - breakText(); - - calculateScrollPos(); -} - - -//! destructor -intlGUIEditBox::~intlGUIEditBox() -{ - if (OverrideFont) - OverrideFont->drop(); - - if (Operator) - Operator->drop(); -} - - -//! Sets another skin independent font. -void intlGUIEditBox::setOverrideFont(IGUIFont* font) -{ - if (OverrideFont == font) - return; - - if (OverrideFont) - OverrideFont->drop(); - - OverrideFont = font; - - if (OverrideFont) - OverrideFont->grab(); - - breakText(); -} - -IGUIFont * intlGUIEditBox::getOverrideFont() const -{ - return OverrideFont; -} - -//! Get the font which is used right now for drawing -IGUIFont* intlGUIEditBox::getActiveFont() const -{ - if ( OverrideFont ) - return OverrideFont; - IGUISkin* skin = Environment->getSkin(); - if (skin) - return skin->getFont(); - return 0; -} - -//! Sets another color for the text. -void intlGUIEditBox::setOverrideColor(video::SColor color) -{ - OverrideColor = color; - OverrideColorEnabled = true; -} - -video::SColor intlGUIEditBox::getOverrideColor() const -{ - return OverrideColor; -} - -//! Turns the border on or off -void intlGUIEditBox::setDrawBorder(bool border) -{ - Border = border; -} - -//! Sets whether to draw the background -void intlGUIEditBox::setDrawBackground(bool draw) -{ -} - -//! Sets if the text should use the overide color or the color in the gui skin. -void intlGUIEditBox::enableOverrideColor(bool enable) -{ - OverrideColorEnabled = enable; -} - -bool intlGUIEditBox::isOverrideColorEnabled() const -{ - _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; - return OverrideColorEnabled; -} - -//! Enables or disables word wrap -void intlGUIEditBox::setWordWrap(bool enable) -{ - WordWrap = enable; - breakText(); -} - - -void intlGUIEditBox::updateAbsolutePosition() -{ - core::rect<s32> oldAbsoluteRect(AbsoluteRect); - IGUIElement::updateAbsolutePosition(); - if ( oldAbsoluteRect != AbsoluteRect ) - { - breakText(); - } -} - - -//! Checks if word wrap is enabled -bool intlGUIEditBox::isWordWrapEnabled() const -{ - _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; - return WordWrap; -} - - -//! Enables or disables newlines. -void intlGUIEditBox::setMultiLine(bool enable) -{ - MultiLine = enable; -} - - -//! Checks if multi line editing is enabled -bool intlGUIEditBox::isMultiLineEnabled() const -{ - _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; - return MultiLine; -} - - -void intlGUIEditBox::setPasswordBox(bool passwordBox, wchar_t passwordChar) -{ - PasswordBox = passwordBox; - if (PasswordBox) - { - PasswordChar = passwordChar; - setMultiLine(false); - setWordWrap(false); - BrokenText.clear(); - } -} - - -bool intlGUIEditBox::isPasswordBox() const -{ - _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; - return PasswordBox; -} - - -//! Sets text justification -void intlGUIEditBox::setTextAlignment(EGUI_ALIGNMENT horizontal, EGUI_ALIGNMENT vertical) -{ - HAlign = horizontal; - VAlign = vertical; -} - - -//! called if an event happened. -bool intlGUIEditBox::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) - { - MouseMarking = false; - setTextMarkers(0,0); - } - } - break; - case EET_KEY_INPUT_EVENT: - { -#if defined(linux) - // ################################################################ - // ValkaTR: - // This part is the difference from the original intlGUIEditBox - // It converts UTF-8 character into a UCS-2 (wchar_t) - wchar_t wc = L'_'; - mbtowc( &wc, (char *) &event.KeyInput.Char, sizeof(event.KeyInput.Char) ); - - //printf( "char: %lc (%u) \r\n", wc, wc ); - - SEvent irrevent(event); - irrevent.KeyInput.Char = wc; - // ################################################################ - - if (processKey(irrevent)) - return true; -#else - if (processKey(event)) - return true; -#endif // defined(linux) - - break; - } - case EET_MOUSE_INPUT_EVENT: - if (processMouse(event)) - return true; - break; - default: - break; - } - } - - return IGUIElement::OnEvent(event); -} - - -bool intlGUIEditBox::processKey(const SEvent& event) -{ - if (!event.KeyInput.PressedDown) - return false; - - bool textChanged = false; - s32 newMarkBegin = MarkBegin; - s32 newMarkEnd = MarkEnd; - - // 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 - newMarkBegin = 0; - newMarkEnd = Text.size(); - break; - case KEY_KEY_C: - // copy to clipboard - if (!PasswordBox && Operator && MarkBegin != MarkEnd) - { - const s32 realmbgn = MarkBegin < MarkEnd ? MarkBegin : MarkEnd; - const s32 realmend = MarkBegin < MarkEnd ? MarkEnd : MarkBegin; - - core::stringc s; - s = Text.subString(realmbgn, realmend - realmbgn).c_str(); - Operator->copyToClipboard(s.c_str()); - } - break; - case KEY_KEY_X: - // cut to the clipboard - if (!PasswordBox && Operator && MarkBegin != MarkEnd) - { - const s32 realmbgn = MarkBegin < MarkEnd ? MarkBegin : MarkEnd; - const s32 realmend = MarkBegin < MarkEnd ? MarkEnd : MarkBegin; - - // copy - core::stringc sc; - sc = Text.subString(realmbgn, realmend - realmbgn).c_str(); - 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; - - CursorPos = realmbgn; - newMarkBegin = 0; - newMarkEnd = 0; - textChanged = true; - } - } - break; - case KEY_KEY_V: - if ( !IsEnabled ) - break; - - // paste from the clipboard - if (Operator) - { - const s32 realmbgn = MarkBegin < MarkEnd ? MarkBegin : MarkEnd; - const s32 realmend = MarkBegin < MarkEnd ? MarkEnd : MarkBegin; - - // add new character - const c8* p = Operator->getTextFromClipboard(); - if (p) - { - if (MarkBegin == MarkEnd) - { - // insert text - core::stringw s = Text.subString(0, CursorPos); - s.append(p); - s.append( Text.subString(CursorPos, Text.size()-CursorPos) ); - - if (!Max || s.size()<=Max) // thx to Fish FH for fix - { - Text = s; - s = p; - CursorPos += s.size(); - } - } - else - { - // replace text - - core::stringw s = Text.subString(0, realmbgn); - s.append(p); - s.append( Text.subString(realmend, Text.size()-realmend) ); - - if (!Max || s.size()<=Max) // thx to Fish FH for fix - { - Text = s; - s = p; - CursorPos = realmbgn + s.size(); - } - } - } - - newMarkBegin = 0; - newMarkEnd = 0; - textChanged = true; - } - break; - case KEY_HOME: - // move/highlight to start of text - if (event.KeyInput.Shift) - { - newMarkEnd = CursorPos; - newMarkBegin = 0; - CursorPos = 0; - } - else - { - CursorPos = 0; - newMarkBegin = 0; - newMarkEnd = 0; - } - break; - case KEY_END: - // move/highlight to end of text - if (event.KeyInput.Shift) - { - newMarkBegin = CursorPos; - newMarkEnd = Text.size(); - CursorPos = 0; - } - else - { - CursorPos = Text.size(); - newMarkBegin = 0; - newMarkEnd = 0; - } - break; - default: - return false; - } - } - // default keyboard handling - else - switch(event.KeyInput.Key) - { - case KEY_END: - { - s32 p = Text.size(); - if (WordWrap || MultiLine) - { - p = getLineFromPos(CursorPos); - p = BrokenTextPositions[p] + (s32)BrokenText[p].size(); - if (p > 0 && (Text[p-1] == L'\r' || Text[p-1] == L'\n' )) - p-=1; - } - - if (event.KeyInput.Shift) - { - if (MarkBegin == MarkEnd) - newMarkBegin = CursorPos; - - newMarkEnd = p; - } - else - { - newMarkBegin = 0; - newMarkEnd = 0; - } - CursorPos = p; - BlinkStartTime = porting::getTimeMs(); - } - break; - case KEY_HOME: - { - - s32 p = 0; - if (WordWrap || MultiLine) - { - p = getLineFromPos(CursorPos); - p = BrokenTextPositions[p]; - } - - if (event.KeyInput.Shift) - { - if (MarkBegin == MarkEnd) - newMarkBegin = CursorPos; - newMarkEnd = p; - } - else - { - newMarkBegin = 0; - newMarkEnd = 0; - } - CursorPos = p; - BlinkStartTime = porting::getTimeMs(); - } - break; - case KEY_RETURN: - if (MultiLine) - { - inputChar(L'\n'); - return true; - } - else - { - sendGuiEvent( EGET_EDITBOX_ENTER ); - } - break; - case KEY_LEFT: - - if (event.KeyInput.Shift) - { - if (CursorPos > 0) - { - if (MarkBegin == MarkEnd) - newMarkBegin = CursorPos; - - newMarkEnd = CursorPos-1; - } - } - else - { - newMarkBegin = 0; - newMarkEnd = 0; - } - - if (CursorPos > 0) CursorPos--; - BlinkStartTime = porting::getTimeMs(); - break; - - case KEY_RIGHT: - if (event.KeyInput.Shift) - { - if (Text.size() > (u32)CursorPos) - { - if (MarkBegin == MarkEnd) - newMarkBegin = CursorPos; - - newMarkEnd = CursorPos+1; - } - } - else - { - newMarkBegin = 0; - newMarkEnd = 0; - } - - if (Text.size() > (u32)CursorPos) CursorPos++; - BlinkStartTime = porting::getTimeMs(); - break; - case KEY_UP: - if (MultiLine || (WordWrap && BrokenText.size() > 1) ) - { - s32 lineNo = getLineFromPos(CursorPos); - s32 mb = (MarkBegin == MarkEnd) ? CursorPos : (MarkBegin > MarkEnd ? MarkBegin : MarkEnd); - if (lineNo > 0) - { - s32 cp = CursorPos - BrokenTextPositions[lineNo]; - if ((s32)BrokenText[lineNo-1].size() < cp) - CursorPos = BrokenTextPositions[lineNo-1] + (s32)BrokenText[lineNo-1].size()-1; - else - CursorPos = BrokenTextPositions[lineNo-1] + cp; - } - - if (event.KeyInput.Shift) - { - newMarkBegin = mb; - newMarkEnd = CursorPos; - } - else - { - newMarkBegin = 0; - newMarkEnd = 0; - } - - } - else - { - return false; - } - break; - case KEY_DOWN: - if (MultiLine || (WordWrap && BrokenText.size() > 1) ) - { - s32 lineNo = getLineFromPos(CursorPos); - s32 mb = (MarkBegin == MarkEnd) ? CursorPos : (MarkBegin < MarkEnd ? MarkBegin : MarkEnd); - if (lineNo < (s32)BrokenText.size()-1) - { - s32 cp = CursorPos - BrokenTextPositions[lineNo]; - if ((s32)BrokenText[lineNo+1].size() < cp) - CursorPos = BrokenTextPositions[lineNo+1] + BrokenText[lineNo+1].size()-1; - else - CursorPos = BrokenTextPositions[lineNo+1] + cp; - } - - if (event.KeyInput.Shift) - { - newMarkBegin = mb; - newMarkEnd = CursorPos; - } - else - { - newMarkBegin = 0; - newMarkEnd = 0; - } - - } - else - { - return false; - } - break; - - case KEY_BACK: - if ( !this->IsEnabled ) - break; - - if (Text.size()) - { - core::stringw s; - - if (MarkBegin != MarkEnd) - { - // delete marked text - const s32 realmbgn = MarkBegin < MarkEnd ? MarkBegin : MarkEnd; - const s32 realmend = MarkBegin < MarkEnd ? MarkEnd : MarkBegin; - - s = Text.subString(0, realmbgn); - s.append( Text.subString(realmend, Text.size()-realmend) ); - Text = s; - - CursorPos = realmbgn; - } - else - { - // delete text behind cursor - if (CursorPos>0) - s = Text.subString(0, CursorPos-1); - else - s = L""; - s.append( Text.subString(CursorPos, Text.size()-CursorPos) ); - Text = s; - --CursorPos; - } - - if (CursorPos < 0) - CursorPos = 0; - BlinkStartTime = porting::getTimeMs(); - newMarkBegin = 0; - newMarkEnd = 0; - textChanged = true; - } - break; - case KEY_DELETE: - if ( !this->IsEnabled ) - break; - - if (Text.size() != 0) - { - core::stringw s; - - if (MarkBegin != MarkEnd) - { - // delete marked text - const s32 realmbgn = MarkBegin < MarkEnd ? MarkBegin : MarkEnd; - const s32 realmend = MarkBegin < MarkEnd ? MarkEnd : MarkBegin; - - s = Text.subString(0, realmbgn); - s.append( Text.subString(realmend, Text.size()-realmend) ); - Text = s; - - CursorPos = realmbgn; - } - else - { - // delete text before cursor - s = Text.subString(0, CursorPos); - s.append( Text.subString(CursorPos+1, Text.size()-CursorPos-1) ); - Text = s; - } - - if (CursorPos > (s32)Text.size()) - CursorPos = (s32)Text.size(); - - BlinkStartTime = porting::getTimeMs(); - newMarkBegin = 0; - newMarkEnd = 0; - textChanged = true; - } - break; - - case KEY_ESCAPE: - case KEY_TAB: - case KEY_SHIFT: - case KEY_F1: - case KEY_F2: - case KEY_F3: - case KEY_F4: - case KEY_F5: - case KEY_F6: - case KEY_F7: - case KEY_F8: - case KEY_F9: - case KEY_F10: - case KEY_F11: - case KEY_F12: - case KEY_F13: - case KEY_F14: - case KEY_F15: - case KEY_F16: - case KEY_F17: - case KEY_F18: - case KEY_F19: - case KEY_F20: - case KEY_F21: - case KEY_F22: - case KEY_F23: - case KEY_F24: - // ignore these keys - return false; - - default: - inputChar(event.KeyInput.Char); - return true; - } - - // Set new text markers - setTextMarkers( newMarkBegin, newMarkEnd ); - - // break the text if it has changed - if (textChanged) - { - breakText(); - sendGuiEvent(EGET_EDITBOX_CHANGED); - } - - calculateScrollPos(); - - return true; -} - - -//! draws the element and its children -void intlGUIEditBox::draw() -{ - if (!IsVisible) - return; - - const bool focus = Environment->hasFocus(this); - - IGUISkin* skin = Environment->getSkin(); - if (!skin) - return; - - FrameRect = AbsoluteRect; - - // draw the border - - if (Border) - { - skin->draw3DSunkenPane(this, skin->getColor(EGDC_WINDOW), - false, true, FrameRect, &AbsoluteClippingRect); - - FrameRect.UpperLeftCorner.X += skin->getSize(EGDS_TEXT_DISTANCE_X)+1; - FrameRect.UpperLeftCorner.Y += skin->getSize(EGDS_TEXT_DISTANCE_Y)+1; - FrameRect.LowerRightCorner.X -= skin->getSize(EGDS_TEXT_DISTANCE_X)+1; - FrameRect.LowerRightCorner.Y -= skin->getSize(EGDS_TEXT_DISTANCE_Y)+1; - } - core::rect<s32> localClipRect = FrameRect; - localClipRect.clipAgainst(AbsoluteClippingRect); - - // draw the text - - IGUIFont* font = OverrideFont; - if (!OverrideFont) - font = skin->getFont(); - - s32 cursorLine = 0; - s32 charcursorpos = 0; - - if (font) - { - if (LastBreakFont != font) - { - breakText(); - } - - // calculate cursor pos - - core::stringw *txtLine = &Text; - s32 startPos = 0; - - core::stringw s, s2; - - // get mark position - const bool ml = (!PasswordBox && (WordWrap || MultiLine)); - const s32 realmbgn = MarkBegin < MarkEnd ? MarkBegin : MarkEnd; - const s32 realmend = MarkBegin < MarkEnd ? MarkEnd : MarkBegin; - const s32 hlineStart = ml ? getLineFromPos(realmbgn) : 0; - const s32 hlineCount = ml ? getLineFromPos(realmend) - hlineStart + 1 : 1; - const s32 lineCount = ml ? BrokenText.size() : 1; - - // Save the override color information. - // Then, alter it if the edit box is disabled. - const bool prevOver = OverrideColorEnabled; - const video::SColor prevColor = OverrideColor; - - if (Text.size()) - { - if (!IsEnabled && !OverrideColorEnabled) - { - OverrideColorEnabled = true; - OverrideColor = skin->getColor(EGDC_GRAY_TEXT); - } - - for (s32 i=0; i < lineCount; ++i) - { - setTextRect(i); - - // clipping test - don't draw anything outside the visible area - core::rect<s32> c = localClipRect; - c.clipAgainst(CurrentTextRect); - if (!c.isValid()) - continue; - - // get current line - if (PasswordBox) - { - if (BrokenText.size() != 1) - { - BrokenText.clear(); - BrokenText.push_back(core::stringw()); - } - if (BrokenText[0].size() != Text.size()) - { - BrokenText[0] = Text; - for (u32 q = 0; q < Text.size(); ++q) - { - BrokenText[0] [q] = PasswordChar; - } - } - txtLine = &BrokenText[0]; - startPos = 0; - } - else - { - txtLine = ml ? &BrokenText[i] : &Text; - startPos = ml ? BrokenTextPositions[i] : 0; - } - - - // draw normal text - font->draw(txtLine->c_str(), CurrentTextRect, - OverrideColorEnabled ? OverrideColor : skin->getColor(EGDC_BUTTON_TEXT), - false, true, &localClipRect); - - // draw mark and marked text - if (focus && MarkBegin != MarkEnd && i >= hlineStart && i < hlineStart + hlineCount) - { - - s32 mbegin = 0, mend = 0; - s32 lineStartPos = 0, lineEndPos = txtLine->size(); - - if (i == hlineStart) - { - // highlight start is on this line - s = txtLine->subString(0, realmbgn - startPos); - mbegin = font->getDimension(s.c_str()).Width; - - // deal with kerning - mbegin += font->getKerningWidth( - &((*txtLine)[realmbgn - startPos]), - realmbgn - startPos > 0 ? &((*txtLine)[realmbgn - startPos - 1]) : 0); - - lineStartPos = realmbgn - startPos; - } - if (i == hlineStart + hlineCount - 1) - { - // highlight end is on this line - s2 = txtLine->subString(0, realmend - startPos); - mend = font->getDimension(s2.c_str()).Width; - lineEndPos = (s32)s2.size(); - } - else - mend = font->getDimension(txtLine->c_str()).Width; - - CurrentTextRect.UpperLeftCorner.X += mbegin; - CurrentTextRect.LowerRightCorner.X = CurrentTextRect.UpperLeftCorner.X + mend - mbegin; - - // draw mark - skin->draw2DRectangle(this, skin->getColor(EGDC_HIGH_LIGHT), CurrentTextRect, &localClipRect); - - // draw marked text - s = txtLine->subString(lineStartPos, lineEndPos - lineStartPos); - - if (s.size()) - font->draw(s.c_str(), CurrentTextRect, - OverrideColorEnabled ? OverrideColor : skin->getColor(EGDC_HIGH_LIGHT_TEXT), - false, true, &localClipRect); - - } - } - - // Return the override color information to its previous settings. - OverrideColorEnabled = prevOver; - OverrideColor = prevColor; - } - - // draw cursor - - if (WordWrap || MultiLine) - { - cursorLine = getLineFromPos(CursorPos); - txtLine = &BrokenText[cursorLine]; - startPos = BrokenTextPositions[cursorLine]; - } - s = txtLine->subString(0,CursorPos-startPos); - charcursorpos = font->getDimension(s.c_str()).Width + - font->getKerningWidth(L"_", CursorPos-startPos > 0 ? &((*txtLine)[CursorPos-startPos-1]) : 0); - - if (focus && (porting::getTimeMs() - BlinkStartTime) % 700 < 350) - { - setTextRect(cursorLine); - CurrentTextRect.UpperLeftCorner.X += charcursorpos; - - font->draw(L"_", CurrentTextRect, - OverrideColorEnabled ? OverrideColor : skin->getColor(EGDC_BUTTON_TEXT), - false, true, &localClipRect); - } - } - - // draw children - IGUIElement::draw(); -} - - -//! Sets the new caption of this element. -void intlGUIEditBox::setText(const wchar_t* text) -{ - Text = text; - if (u32(CursorPos) > Text.size()) - CursorPos = Text.size(); - HScrollPos = 0; - breakText(); -} - - -//! Enables or disables automatic scrolling with cursor position -//! \param enable: If set to true, the text will move around with the cursor position -void intlGUIEditBox::setAutoScroll(bool enable) -{ - AutoScroll = enable; -} - - -//! Checks to see if automatic scrolling is enabled -//! \return true if automatic scrolling is enabled, false if not -bool intlGUIEditBox::isAutoScrollEnabled() const -{ - _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; - return AutoScroll; -} - - -//! Gets the area of the text in the edit box -//! \return Returns the size in pixels of the text -core::dimension2du intlGUIEditBox::getTextDimension() -{ - core::rect<s32> ret; - - setTextRect(0); - ret = CurrentTextRect; - - for (u32 i=1; i < BrokenText.size(); ++i) - { - setTextRect(i); - ret.addInternalPoint(CurrentTextRect.UpperLeftCorner); - ret.addInternalPoint(CurrentTextRect.LowerRightCorner); - } - - return core::dimension2du(ret.getSize()); -} - - -//! Sets the maximum amount of characters which may be entered in the box. -//! \param max: Maximum amount of characters. If 0, the character amount is -//! infinity. -void intlGUIEditBox::setMax(u32 max) -{ - Max = max; - - if (Text.size() > Max && Max != 0) - Text = Text.subString(0, Max); -} - - -//! Returns maximum amount of characters, previously set by setMax(); -u32 intlGUIEditBox::getMax() const -{ - return Max; -} - - -bool intlGUIEditBox::processMouse(const SEvent& event) -{ - switch(event.MouseInput.Event) - { - case irr::EMIE_LMOUSE_LEFT_UP: - if (Environment->hasFocus(this)) - { - CursorPos = getCursorPos(event.MouseInput.X, event.MouseInput.Y); - if (MouseMarking) - { - setTextMarkers( MarkBegin, CursorPos ); - } - MouseMarking = false; - calculateScrollPos(); - return true; - } - break; - case irr::EMIE_MOUSE_MOVED: - { - if (MouseMarking) - { - CursorPos = getCursorPos(event.MouseInput.X, event.MouseInput.Y); - setTextMarkers( MarkBegin, CursorPos ); - calculateScrollPos(); - return true; - } - } - break; - case EMIE_LMOUSE_PRESSED_DOWN: - if (!Environment->hasFocus(this)) - { - BlinkStartTime = porting::getTimeMs(); - MouseMarking = true; - CursorPos = getCursorPos(event.MouseInput.X, event.MouseInput.Y); - setTextMarkers(CursorPos, CursorPos ); - calculateScrollPos(); - return true; - } - else - { - if (!AbsoluteClippingRect.isPointInside( - core::position2d<s32>(event.MouseInput.X, event.MouseInput.Y))) - { - return false; - } - else - { - // move cursor - CursorPos = getCursorPos(event.MouseInput.X, event.MouseInput.Y); - - s32 newMarkBegin = MarkBegin; - if (!MouseMarking) - newMarkBegin = CursorPos; - - MouseMarking = true; - setTextMarkers( newMarkBegin, CursorPos); - calculateScrollPos(); - return true; - } - } - default: - break; - } - - return false; -} - - -s32 intlGUIEditBox::getCursorPos(s32 x, s32 y) -{ - IGUIFont* font = OverrideFont; - IGUISkin* skin = Environment->getSkin(); - if (!OverrideFont) - font = skin->getFont(); - - const u32 lineCount = (WordWrap || MultiLine) ? BrokenText.size() : 1; - - core::stringw *txtLine=0; - s32 startPos=0; - x+=3; - - for (u32 i=0; i < lineCount; ++i) - { - setTextRect(i); - if (i == 0 && y < CurrentTextRect.UpperLeftCorner.Y) - y = CurrentTextRect.UpperLeftCorner.Y; - if (i == lineCount - 1 && y > CurrentTextRect.LowerRightCorner.Y ) - y = CurrentTextRect.LowerRightCorner.Y; - - // is it inside this region? - if (y >= CurrentTextRect.UpperLeftCorner.Y && y <= CurrentTextRect.LowerRightCorner.Y) - { - // we've found the clicked line - txtLine = (WordWrap || MultiLine) ? &BrokenText[i] : &Text; - startPos = (WordWrap || MultiLine) ? BrokenTextPositions[i] : 0; - break; - } - } - - if (x < CurrentTextRect.UpperLeftCorner.X) - x = CurrentTextRect.UpperLeftCorner.X; - - s32 idx = font->getCharacterFromPos(Text.c_str(), x - CurrentTextRect.UpperLeftCorner.X); - - // click was on or left of the line - if (idx != -1) - return idx + startPos; - - // click was off the right edge of the line, go to end. - return txtLine->size() + startPos; -} - - -//! Breaks the single text line. -void intlGUIEditBox::breakText() -{ - IGUISkin* skin = Environment->getSkin(); - - if ((!WordWrap && !MultiLine) || !skin) - return; - - BrokenText.clear(); // need to reallocate :/ - BrokenTextPositions.set_used(0); - - IGUIFont* font = OverrideFont; - if (!OverrideFont) - font = skin->getFont(); - - if (!font) - return; - - LastBreakFont = font; - - core::stringw line; - core::stringw word; - core::stringw whitespace; - s32 lastLineStart = 0; - s32 size = Text.size(); - s32 length = 0; - s32 elWidth = RelativeRect.getWidth() - 6; - wchar_t c; - - for (s32 i=0; i<size; ++i) - { - c = Text[i]; - bool lineBreak = false; - - if (c == L'\r') // Mac or Windows breaks - { - lineBreak = true; - c = ' '; - if (Text[i+1] == L'\n') // Windows breaks - { - Text.erase(i+1); - --size; - } - } - else if (c == L'\n') // Unix breaks - { - lineBreak = true; - c = ' '; - } - - // don't break if we're not a multi-line edit box - if (!MultiLine) - lineBreak = false; - - if (c == L' ' || c == 0 || i == (size-1)) - { - if (word.size()) - { - // here comes the next whitespace, look if - // we can break the last word to the next line. - s32 whitelgth = font->getDimension(whitespace.c_str()).Width; - s32 worldlgth = font->getDimension(word.c_str()).Width; - - if (WordWrap && length + worldlgth + whitelgth > elWidth) - { - // break to next line - length = worldlgth; - BrokenText.push_back(line); - BrokenTextPositions.push_back(lastLineStart); - lastLineStart = i - (s32)word.size(); - line = word; - } - else - { - // add word to line - line += whitespace; - line += word; - length += whitelgth + worldlgth; - } - - word = L""; - whitespace = L""; - } - - whitespace += c; - - // compute line break - if (lineBreak) - { - line += whitespace; - line += word; - BrokenText.push_back(line); - BrokenTextPositions.push_back(lastLineStart); - lastLineStart = i+1; - line = L""; - word = L""; - whitespace = L""; - length = 0; - } - } - else - { - // yippee this is a word.. - word += c; - } - } - - line += whitespace; - line += word; - BrokenText.push_back(line); - BrokenTextPositions.push_back(lastLineStart); -} - - -void intlGUIEditBox::setTextRect(s32 line) -{ - core::dimension2du d; - - IGUISkin* skin = Environment->getSkin(); - if (!skin) - return; - - IGUIFont* font = OverrideFont ? OverrideFont : skin->getFont(); - - if (!font) - return; - - // get text dimension - const u32 lineCount = (WordWrap || MultiLine) ? BrokenText.size() : 1; - if (WordWrap || MultiLine) - { - d = font->getDimension(BrokenText[line].c_str()); - } - else - { - d = font->getDimension(Text.c_str()); - d.Height = AbsoluteRect.getHeight(); - } - d.Height += font->getKerningHeight(); - - // justification - switch (HAlign) - { - case EGUIA_CENTER: - // align to h centre - CurrentTextRect.UpperLeftCorner.X = (FrameRect.getWidth()/2) - (d.Width/2); - CurrentTextRect.LowerRightCorner.X = (FrameRect.getWidth()/2) + (d.Width/2); - break; - case EGUIA_LOWERRIGHT: - // align to right edge - CurrentTextRect.UpperLeftCorner.X = FrameRect.getWidth() - d.Width; - CurrentTextRect.LowerRightCorner.X = FrameRect.getWidth(); - break; - default: - // align to left edge - CurrentTextRect.UpperLeftCorner.X = 0; - CurrentTextRect.LowerRightCorner.X = d.Width; - - } - - switch (VAlign) - { - case EGUIA_CENTER: - // align to v centre - CurrentTextRect.UpperLeftCorner.Y = - (FrameRect.getHeight()/2) - (lineCount*d.Height)/2 + d.Height*line; - break; - case EGUIA_LOWERRIGHT: - // align to bottom edge - CurrentTextRect.UpperLeftCorner.Y = - FrameRect.getHeight() - lineCount*d.Height + d.Height*line; - break; - default: - // align to top edge - CurrentTextRect.UpperLeftCorner.Y = d.Height*line; - break; - } - - CurrentTextRect.UpperLeftCorner.X -= HScrollPos; - CurrentTextRect.LowerRightCorner.X -= HScrollPos; - CurrentTextRect.UpperLeftCorner.Y -= VScrollPos; - CurrentTextRect.LowerRightCorner.Y = CurrentTextRect.UpperLeftCorner.Y + d.Height; - - CurrentTextRect += FrameRect.UpperLeftCorner; - -} - - -s32 intlGUIEditBox::getLineFromPos(s32 pos) -{ - if (!WordWrap && !MultiLine) - return 0; - - s32 i=0; - while (i < (s32)BrokenTextPositions.size()) - { - if (BrokenTextPositions[i] > pos) - return i-1; - ++i; - } - return (s32)BrokenTextPositions.size() - 1; -} - - -void intlGUIEditBox::inputChar(wchar_t c) -{ - if (!IsEnabled) - return; - - if (c != 0) - { - if (Text.size() < Max || Max == 0) - { - core::stringw s; - - if (MarkBegin != MarkEnd) - { - // replace marked text - const s32 realmbgn = MarkBegin < MarkEnd ? MarkBegin : MarkEnd; - const s32 realmend = MarkBegin < MarkEnd ? MarkEnd : MarkBegin; - - s = Text.subString(0, realmbgn); - s.append(c); - s.append( Text.subString(realmend, Text.size()-realmend) ); - Text = s; - CursorPos = realmbgn+1; - } - else - { - // add new character - s = Text.subString(0, CursorPos); - s.append(c); - s.append( Text.subString(CursorPos, Text.size()-CursorPos) ); - Text = s; - ++CursorPos; - } - - BlinkStartTime = porting::getTimeMs(); - setTextMarkers(0, 0); - } - } - breakText(); - sendGuiEvent(EGET_EDITBOX_CHANGED); - calculateScrollPos(); -} - - -void intlGUIEditBox::calculateScrollPos() -{ - if (!AutoScroll) - return; - - // calculate horizontal scroll position - s32 cursLine = getLineFromPos(CursorPos); - setTextRect(cursLine); - - // don't do horizontal scrolling when wordwrap is enabled. - if (!WordWrap) - { - // get cursor position - IGUISkin* skin = Environment->getSkin(); - if (!skin) - return; - IGUIFont* font = OverrideFont ? OverrideFont : skin->getFont(); - if (!font) - return; - - core::stringw *txtLine = MultiLine ? &BrokenText[cursLine] : &Text; - s32 cPos = MultiLine ? CursorPos - BrokenTextPositions[cursLine] : CursorPos; - - s32 cStart = CurrentTextRect.UpperLeftCorner.X + HScrollPos + - font->getDimension(txtLine->subString(0, cPos).c_str()).Width; - - s32 cEnd = cStart + font->getDimension(L"_ ").Width; - - if (FrameRect.LowerRightCorner.X < cEnd) - HScrollPos = cEnd - FrameRect.LowerRightCorner.X; - else if (FrameRect.UpperLeftCorner.X > cStart) - HScrollPos = cStart - FrameRect.UpperLeftCorner.X; - else - HScrollPos = 0; - - // todo: adjust scrollbar - } - - // vertical scroll position - if (FrameRect.LowerRightCorner.Y < CurrentTextRect.LowerRightCorner.Y + VScrollPos) - VScrollPos = CurrentTextRect.LowerRightCorner.Y - FrameRect.LowerRightCorner.Y + VScrollPos; - - else if (FrameRect.UpperLeftCorner.Y > CurrentTextRect.UpperLeftCorner.Y + VScrollPos) - VScrollPos = CurrentTextRect.UpperLeftCorner.Y - FrameRect.UpperLeftCorner.Y + VScrollPos; - else - VScrollPos = 0; - - // todo: adjust scrollbar -} - -//! set text markers -void intlGUIEditBox::setTextMarkers(s32 begin, s32 end) -{ - if ( begin != MarkBegin || end != MarkEnd ) - { - MarkBegin = begin; - MarkEnd = end; - sendGuiEvent(EGET_EDITBOX_MARKING_CHANGED); - } -} - -//! send some gui event to parent -void intlGUIEditBox::sendGuiEvent(EGUI_EVENT_TYPE type) -{ - if ( Parent ) - { - SEvent e; - e.EventType = EET_GUI_EVENT; - e.GUIEvent.Caller = this; - e.GUIEvent.Element = 0; - e.GUIEvent.EventType = type; - - Parent->OnEvent(e); - } -} - -//! Writes attributes of the element. -void intlGUIEditBox::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const -{ - // IGUIEditBox::serializeAttributes(out,options); - - out->addBool ("OverrideColorEnabled",OverrideColorEnabled ); - out->addColor ("OverrideColor", OverrideColor); - // out->addFont("OverrideFont",OverrideFont); - out->addInt ("MaxChars", Max); - out->addBool ("WordWrap", WordWrap); - out->addBool ("MultiLine", MultiLine); - out->addBool ("AutoScroll", AutoScroll); - out->addBool ("PasswordBox", PasswordBox); - core::stringw ch = L" "; - ch[0] = PasswordChar; - out->addString("PasswordChar", ch.c_str()); - out->addEnum ("HTextAlign", HAlign, GUIAlignmentNames); - out->addEnum ("VTextAlign", VAlign, GUIAlignmentNames); - - IGUIEditBox::serializeAttributes(out,options); -} - - -//! Reads attributes of the element -void intlGUIEditBox::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0) -{ - IGUIEditBox::deserializeAttributes(in,options); - - setOverrideColor(in->getAttributeAsColor("OverrideColor")); - enableOverrideColor(in->getAttributeAsBool("OverrideColorEnabled")); - setMax(in->getAttributeAsInt("MaxChars")); - setWordWrap(in->getAttributeAsBool("WordWrap")); - setMultiLine(in->getAttributeAsBool("MultiLine")); - setAutoScroll(in->getAttributeAsBool("AutoScroll")); - core::stringw ch = in->getAttributeAsStringW("PasswordChar"); - - if (!ch.size()) - setPasswordBox(in->getAttributeAsBool("PasswordBox")); - else - setPasswordBox(in->getAttributeAsBool("PasswordBox"), ch[0]); - - setTextAlignment( (EGUI_ALIGNMENT) in->getAttributeAsEnumeration("HTextAlign", GUIAlignmentNames), - (EGUI_ALIGNMENT) in->getAttributeAsEnumeration("VTextAlign", GUIAlignmentNames)); - - // setOverrideFont(in->getAttributeAsFont("OverrideFont")); -} - - -} // end namespace gui -} // end namespace irr - -#endif // _IRR_COMPILE_WITH_GUI_ |