aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/irrlicht-1.8/source/Irrlicht/CGUIEditBox.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/irrlicht-1.8/source/Irrlicht/CGUIEditBox.cpp')
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/CGUIEditBox.cpp1555
1 files changed, 1555 insertions, 0 deletions
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/CGUIEditBox.cpp b/libraries/irrlicht-1.8/source/Irrlicht/CGUIEditBox.cpp
new file mode 100644
index 0000000..a937cc2
--- /dev/null
+++ b/libraries/irrlicht-1.8/source/Irrlicht/CGUIEditBox.cpp
@@ -0,0 +1,1555 @@
1// Copyright (C) 2002-2012 Nikolaus Gebhardt
2// This file is part of the "Irrlicht Engine".
3// For conditions of distribution and use, see copyright notice in irrlicht.h
4
5#include "CGUIEditBox.h"
6#ifdef _IRR_COMPILE_WITH_GUI_
7
8#include "IGUISkin.h"
9#include "IGUIEnvironment.h"
10#include "IGUIFont.h"
11#include "IVideoDriver.h"
12#include "rect.h"
13#include "os.h"
14#include "Keycodes.h"
15
16/*
17 todo:
18 optional scrollbars
19 ctrl+left/right to select word
20 double click/ctrl click: word select + drag to select whole words, triple click to select line
21 optional? dragging selected text
22 numerical
23*/
24
25namespace irr
26{
27namespace gui
28{
29
30//! constructor
31CGUIEditBox::CGUIEditBox(const wchar_t* text, bool border,
32 IGUIEnvironment* environment, IGUIElement* parent, s32 id,
33 const core::rect<s32>& rectangle)
34 : IGUIEditBox(environment, parent, id, rectangle), MouseMarking(false),
35 Border(border), Background(true), OverrideColorEnabled(false), MarkBegin(0), MarkEnd(0),
36 OverrideColor(video::SColor(101,255,255,255)), OverrideFont(0), LastBreakFont(0),
37 Operator(0), BlinkStartTime(0), CursorPos(0), HScrollPos(0), VScrollPos(0), Max(0),
38 WordWrap(false), MultiLine(false), AutoScroll(true), PasswordBox(false),
39 PasswordChar(L'*'), HAlign(EGUIA_UPPERLEFT), VAlign(EGUIA_CENTER),
40 CurrentTextRect(0,0,1,1), FrameRect(rectangle)
41{
42 #ifdef _DEBUG
43 setDebugName("CGUIEditBox");
44 #endif
45
46 Text = text;
47
48 if (Environment)
49 Operator = Environment->getOSOperator();
50
51 if (Operator)
52 Operator->grab();
53
54 // this element can be tabbed to
55 setTabStop(true);
56 setTabOrder(-1);
57
58 calculateFrameRect();
59 breakText();
60
61 calculateScrollPos();
62}
63
64
65//! destructor
66CGUIEditBox::~CGUIEditBox()
67{
68 if (OverrideFont)
69 OverrideFont->drop();
70
71 if (Operator)
72 Operator->drop();
73}
74
75
76//! Sets another skin independent font.
77void CGUIEditBox::setOverrideFont(IGUIFont* font)
78{
79 if (OverrideFont == font)
80 return;
81
82 if (OverrideFont)
83 OverrideFont->drop();
84
85 OverrideFont = font;
86
87 if (OverrideFont)
88 OverrideFont->grab();
89
90 breakText();
91}
92
93//! Gets the override font (if any)
94IGUIFont * CGUIEditBox::getOverrideFont() const
95{
96 return OverrideFont;
97}
98
99//! Get the font which is used right now for drawing
100IGUIFont* CGUIEditBox::getActiveFont() const
101{
102 if ( OverrideFont )
103 return OverrideFont;
104 IGUISkin* skin = Environment->getSkin();
105 if (skin)
106 return skin->getFont();
107 return 0;
108}
109
110//! Sets another color for the text.
111void CGUIEditBox::setOverrideColor(video::SColor color)
112{
113 OverrideColor = color;
114 OverrideColorEnabled = true;
115}
116
117
118video::SColor CGUIEditBox::getOverrideColor() const
119{
120 return OverrideColor;
121}
122
123
124//! Turns the border on or off
125void CGUIEditBox::setDrawBorder(bool border)
126{
127 Border = border;
128}
129
130//! Sets whether to draw the background
131void CGUIEditBox::setDrawBackground(bool draw)
132{
133 Background = draw;
134}
135
136//! Sets if the text should use the overide color or the color in the gui skin.
137void CGUIEditBox::enableOverrideColor(bool enable)
138{
139 OverrideColorEnabled = enable;
140}
141
142bool CGUIEditBox::isOverrideColorEnabled() const
143{
144 _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
145 return OverrideColorEnabled;
146}
147
148//! Enables or disables word wrap
149void CGUIEditBox::setWordWrap(bool enable)
150{
151 WordWrap = enable;
152 breakText();
153}
154
155
156void CGUIEditBox::updateAbsolutePosition()
157{
158 core::rect<s32> oldAbsoluteRect(AbsoluteRect);
159 IGUIElement::updateAbsolutePosition();
160 if ( oldAbsoluteRect != AbsoluteRect )
161 {
162 calculateFrameRect();
163 breakText();
164 calculateScrollPos();
165 }
166}
167
168
169//! Checks if word wrap is enabled
170bool CGUIEditBox::isWordWrapEnabled() const
171{
172 _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
173 return WordWrap;
174}
175
176
177//! Enables or disables newlines.
178void CGUIEditBox::setMultiLine(bool enable)
179{
180 MultiLine = enable;
181}
182
183
184//! Checks if multi line editing is enabled
185bool CGUIEditBox::isMultiLineEnabled() const
186{
187 _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
188 return MultiLine;
189}
190
191
192void CGUIEditBox::setPasswordBox(bool passwordBox, wchar_t passwordChar)
193{
194 PasswordBox = passwordBox;
195 if (PasswordBox)
196 {
197 PasswordChar = passwordChar;
198 setMultiLine(false);
199 setWordWrap(false);
200 BrokenText.clear();
201 }
202}
203
204
205bool CGUIEditBox::isPasswordBox() const
206{
207 _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
208 return PasswordBox;
209}
210
211
212//! Sets text justification
213void CGUIEditBox::setTextAlignment(EGUI_ALIGNMENT horizontal, EGUI_ALIGNMENT vertical)
214{
215 HAlign = horizontal;
216 VAlign = vertical;
217}
218
219
220//! called if an event happened.
221bool CGUIEditBox::OnEvent(const SEvent& event)
222{
223 if (isEnabled())
224 {
225
226 switch(event.EventType)
227 {
228 case EET_GUI_EVENT:
229 if (event.GUIEvent.EventType == EGET_ELEMENT_FOCUS_LOST)
230 {
231 if (event.GUIEvent.Caller == this)
232 {
233 MouseMarking = false;
234 setTextMarkers(0,0);
235 }
236 }
237 break;
238 case EET_KEY_INPUT_EVENT:
239 if (processKey(event))
240 return true;
241 break;
242 case EET_MOUSE_INPUT_EVENT:
243 if (processMouse(event))
244 return true;
245 break;
246 default:
247 break;
248 }
249 }
250
251 return IGUIElement::OnEvent(event);
252}
253
254
255bool CGUIEditBox::processKey(const SEvent& event)
256{
257 if (!event.KeyInput.PressedDown)
258 return false;
259
260 bool textChanged = false;
261 s32 newMarkBegin = MarkBegin;
262 s32 newMarkEnd = MarkEnd;
263
264 // control shortcut handling
265
266 if (event.KeyInput.Control)
267 {
268 // german backlash '\' entered with control + '?'
269 if ( event.KeyInput.Char == '\\' )
270 {
271 inputChar(event.KeyInput.Char);
272 return true;
273 }
274
275 switch(event.KeyInput.Key)
276 {
277 case KEY_KEY_A:
278 // select all
279 newMarkBegin = 0;
280 newMarkEnd = Text.size();
281 break;
282 case KEY_KEY_C:
283 // copy to clipboard
284 if (!PasswordBox && Operator && MarkBegin != MarkEnd)
285 {
286 const s32 realmbgn = MarkBegin < MarkEnd ? MarkBegin : MarkEnd;
287 const s32 realmend = MarkBegin < MarkEnd ? MarkEnd : MarkBegin;
288
289 core::stringc s;
290 s = Text.subString(realmbgn, realmend - realmbgn).c_str();
291 Operator->copyToClipboard(s.c_str());
292 }
293 break;
294 case KEY_KEY_X:
295 // cut to the clipboard
296 if (!PasswordBox && Operator && MarkBegin != MarkEnd)
297 {
298 const s32 realmbgn = MarkBegin < MarkEnd ? MarkBegin : MarkEnd;
299 const s32 realmend = MarkBegin < MarkEnd ? MarkEnd : MarkBegin;
300
301 // copy
302 core::stringc sc;
303 sc = Text.subString(realmbgn, realmend - realmbgn).c_str();
304 Operator->copyToClipboard(sc.c_str());
305
306 if (isEnabled())
307 {
308 // delete
309 core::stringw s;
310 s = Text.subString(0, realmbgn);
311 s.append( Text.subString(realmend, Text.size()-realmend) );
312 Text = s;
313
314 CursorPos = realmbgn;
315 newMarkBegin = 0;
316 newMarkEnd = 0;
317 textChanged = true;
318 }
319 }
320 break;
321 case KEY_KEY_V:
322 if ( !isEnabled() )
323 break;
324
325 // paste from the clipboard
326 if (Operator)
327 {
328 const s32 realmbgn = MarkBegin < MarkEnd ? MarkBegin : MarkEnd;
329 const s32 realmend = MarkBegin < MarkEnd ? MarkEnd : MarkBegin;
330
331 // add new character
332 const c8* p = Operator->getTextFromClipboard();
333 if (p)
334 {
335 if (MarkBegin == MarkEnd)
336 {
337 // insert text
338 core::stringw s = Text.subString(0, CursorPos);
339 s.append(p);
340 s.append( Text.subString(CursorPos, Text.size()-CursorPos) );
341
342 if (!Max || s.size()<=Max) // thx to Fish FH for fix
343 {
344 Text = s;
345 s = p;
346 CursorPos += s.size();
347 }
348 }
349 else
350 {
351 // replace text
352
353 core::stringw s = Text.subString(0, realmbgn);
354 s.append(p);
355 s.append( Text.subString(realmend, Text.size()-realmend) );
356
357 if (!Max || s.size()<=Max) // thx to Fish FH for fix
358 {
359 Text = s;
360 s = p;
361 CursorPos = realmbgn + s.size();
362 }
363 }
364 }
365
366 newMarkBegin = 0;
367 newMarkEnd = 0;
368 textChanged = true;
369 }
370 break;
371 case KEY_HOME:
372 // move/highlight to start of text
373 if (event.KeyInput.Shift)
374 {
375 newMarkEnd = CursorPos;
376 newMarkBegin = 0;
377 CursorPos = 0;
378 }
379 else
380 {
381 CursorPos = 0;
382 newMarkBegin = 0;
383 newMarkEnd = 0;
384 }
385 break;
386 case KEY_END:
387 // move/highlight to end of text
388 if (event.KeyInput.Shift)
389 {
390 newMarkBegin = CursorPos;
391 newMarkEnd = Text.size();
392 CursorPos = 0;
393 }
394 else
395 {
396 CursorPos = Text.size();
397 newMarkBegin = 0;
398 newMarkEnd = 0;
399 }
400 break;
401 default:
402 return false;
403 }
404 }
405 // default keyboard handling
406 else
407 switch(event.KeyInput.Key)
408 {
409 case KEY_END:
410 {
411 s32 p = Text.size();
412 if (WordWrap || MultiLine)
413 {
414 p = getLineFromPos(CursorPos);
415 p = BrokenTextPositions[p] + (s32)BrokenText[p].size();
416 if (p > 0 && (Text[p-1] == L'\r' || Text[p-1] == L'\n' ))
417 p-=1;
418 }
419
420 if (event.KeyInput.Shift)
421 {
422 if (MarkBegin == MarkEnd)
423 newMarkBegin = CursorPos;
424
425 newMarkEnd = p;
426 }
427 else
428 {
429 newMarkBegin = 0;
430 newMarkEnd = 0;
431 }
432 CursorPos = p;
433 BlinkStartTime = os::Timer::getTime();
434 }
435 break;
436 case KEY_HOME:
437 {
438
439 s32 p = 0;
440 if (WordWrap || MultiLine)
441 {
442 p = getLineFromPos(CursorPos);
443 p = BrokenTextPositions[p];
444 }
445
446 if (event.KeyInput.Shift)
447 {
448 if (MarkBegin == MarkEnd)
449 newMarkBegin = CursorPos;
450 newMarkEnd = p;
451 }
452 else
453 {
454 newMarkBegin = 0;
455 newMarkEnd = 0;
456 }
457 CursorPos = p;
458 BlinkStartTime = os::Timer::getTime();
459 }
460 break;
461 case KEY_RETURN:
462 if (MultiLine)
463 {
464 inputChar(L'\n');
465 }
466 else
467 {
468 calculateScrollPos();
469 sendGuiEvent( EGET_EDITBOX_ENTER );
470 }
471 return true;
472 case KEY_LEFT:
473
474 if (event.KeyInput.Shift)
475 {
476 if (CursorPos > 0)
477 {
478 if (MarkBegin == MarkEnd)
479 newMarkBegin = CursorPos;
480
481 newMarkEnd = CursorPos-1;
482 }
483 }
484 else
485 {
486 newMarkBegin = 0;
487 newMarkEnd = 0;
488 }
489
490 if (CursorPos > 0) CursorPos--;
491 BlinkStartTime = os::Timer::getTime();
492 break;
493
494 case KEY_RIGHT:
495 if (event.KeyInput.Shift)
496 {
497 if (Text.size() > (u32)CursorPos)
498 {
499 if (MarkBegin == MarkEnd)
500 newMarkBegin = CursorPos;
501
502 newMarkEnd = CursorPos+1;
503 }
504 }
505 else
506 {
507 newMarkBegin = 0;
508 newMarkEnd = 0;
509 }
510
511 if (Text.size() > (u32)CursorPos) CursorPos++;
512 BlinkStartTime = os::Timer::getTime();
513 break;
514 case KEY_UP:
515 if (MultiLine || (WordWrap && BrokenText.size() > 1) )
516 {
517 s32 lineNo = getLineFromPos(CursorPos);
518 s32 mb = (MarkBegin == MarkEnd) ? CursorPos : (MarkBegin > MarkEnd ? MarkBegin : MarkEnd);
519 if (lineNo > 0)
520 {
521 s32 cp = CursorPos - BrokenTextPositions[lineNo];
522 if ((s32)BrokenText[lineNo-1].size() < cp)
523 CursorPos = BrokenTextPositions[lineNo-1] + core::max_((u32)1, BrokenText[lineNo-1].size())-1;
524 else
525 CursorPos = BrokenTextPositions[lineNo-1] + cp;
526 }
527
528 if (event.KeyInput.Shift)
529 {
530 newMarkBegin = mb;
531 newMarkEnd = CursorPos;
532 }
533 else
534 {
535 newMarkBegin = 0;
536 newMarkEnd = 0;
537 }
538
539 }
540 else
541 {
542 return false;
543 }
544 break;
545 case KEY_DOWN:
546 if (MultiLine || (WordWrap && BrokenText.size() > 1) )
547 {
548 s32 lineNo = getLineFromPos(CursorPos);
549 s32 mb = (MarkBegin == MarkEnd) ? CursorPos : (MarkBegin < MarkEnd ? MarkBegin : MarkEnd);
550 if (lineNo < (s32)BrokenText.size()-1)
551 {
552 s32 cp = CursorPos - BrokenTextPositions[lineNo];
553 if ((s32)BrokenText[lineNo+1].size() < cp)
554 CursorPos = BrokenTextPositions[lineNo+1] + core::max_((u32)1, BrokenText[lineNo+1].size())-1;
555 else
556 CursorPos = BrokenTextPositions[lineNo+1] + cp;
557 }
558
559 if (event.KeyInput.Shift)
560 {
561 newMarkBegin = mb;
562 newMarkEnd = CursorPos;
563 }
564 else
565 {
566 newMarkBegin = 0;
567 newMarkEnd = 0;
568 }
569
570 }
571 else
572 {
573 return false;
574 }
575 break;
576
577 case KEY_BACK:
578 if ( !isEnabled() )
579 break;
580
581 if (Text.size())
582 {
583 core::stringw s;
584
585 if (MarkBegin != MarkEnd)
586 {
587 // delete marked text
588 const s32 realmbgn = MarkBegin < MarkEnd ? MarkBegin : MarkEnd;
589 const s32 realmend = MarkBegin < MarkEnd ? MarkEnd : MarkBegin;
590
591 s = Text.subString(0, realmbgn);
592 s.append( Text.subString(realmend, Text.size()-realmend) );
593 Text = s;
594
595 CursorPos = realmbgn;
596 }
597 else
598 {
599 // delete text behind cursor
600 if (CursorPos>0)
601 s = Text.subString(0, CursorPos-1);
602 else
603 s = L"";
604 s.append( Text.subString(CursorPos, Text.size()-CursorPos) );
605 Text = s;
606 --CursorPos;
607 }
608
609 if (CursorPos < 0)
610 CursorPos = 0;
611 BlinkStartTime = os::Timer::getTime();
612 newMarkBegin = 0;
613 newMarkEnd = 0;
614 textChanged = true;
615 }
616 break;
617 case KEY_DELETE:
618 if ( !isEnabled() )
619 break;
620
621 if (Text.size() != 0)
622 {
623 core::stringw s;
624
625 if (MarkBegin != MarkEnd)
626 {
627 // delete marked text
628 const s32 realmbgn = MarkBegin < MarkEnd ? MarkBegin : MarkEnd;
629 const s32 realmend = MarkBegin < MarkEnd ? MarkEnd : MarkBegin;
630
631 s = Text.subString(0, realmbgn);
632 s.append( Text.subString(realmend, Text.size()-realmend) );
633 Text = s;
634
635 CursorPos = realmbgn;
636 }
637 else
638 {
639 // delete text before cursor
640 s = Text.subString(0, CursorPos);
641 s.append( Text.subString(CursorPos+1, Text.size()-CursorPos-1) );
642 Text = s;
643 }
644
645 if (CursorPos > (s32)Text.size())
646 CursorPos = (s32)Text.size();
647
648 BlinkStartTime = os::Timer::getTime();
649 newMarkBegin = 0;
650 newMarkEnd = 0;
651 textChanged = true;
652 }
653 break;
654
655 case KEY_ESCAPE:
656 case KEY_TAB:
657 case KEY_SHIFT:
658 case KEY_F1:
659 case KEY_F2:
660 case KEY_F3:
661 case KEY_F4:
662 case KEY_F5:
663 case KEY_F6:
664 case KEY_F7:
665 case KEY_F8:
666 case KEY_F9:
667 case KEY_F10:
668 case KEY_F11:
669 case KEY_F12:
670 case KEY_F13:
671 case KEY_F14:
672 case KEY_F15:
673 case KEY_F16:
674 case KEY_F17:
675 case KEY_F18:
676 case KEY_F19:
677 case KEY_F20:
678 case KEY_F21:
679 case KEY_F22:
680 case KEY_F23:
681 case KEY_F24:
682 // ignore these keys
683 return false;
684
685 default:
686 inputChar(event.KeyInput.Char);
687 return true;
688 }
689
690 // Set new text markers
691 setTextMarkers( newMarkBegin, newMarkEnd );
692
693 // break the text if it has changed
694 if (textChanged)
695 {
696 breakText();
697 calculateScrollPos();
698 sendGuiEvent(EGET_EDITBOX_CHANGED);
699 }
700 else
701 {
702 calculateScrollPos();
703 }
704
705 return true;
706}
707
708
709//! draws the element and its children
710void CGUIEditBox::draw()
711{
712 if (!IsVisible)
713 return;
714
715 const bool focus = Environment->hasFocus(this);
716
717 IGUISkin* skin = Environment->getSkin();
718 if (!skin)
719 return;
720
721 EGUI_DEFAULT_COLOR bgCol = EGDC_GRAY_EDITABLE;
722 if ( isEnabled() )
723 bgCol = focus ? EGDC_FOCUSED_EDITABLE : EGDC_EDITABLE;
724
725 if (!Border && Background)
726 {
727 skin->draw2DRectangle(this, skin->getColor(bgCol), AbsoluteRect, &AbsoluteClippingRect);
728 }
729
730 if (Border)
731 {
732 // draw the border
733 skin->draw3DSunkenPane(this, skin->getColor(bgCol), false, Background, AbsoluteRect, &AbsoluteClippingRect);
734
735 calculateFrameRect();
736 }
737
738 core::rect<s32> localClipRect = FrameRect;
739 localClipRect.clipAgainst(AbsoluteClippingRect);
740
741 // draw the text
742
743 IGUIFont* font = getActiveFont();
744
745 s32 cursorLine = 0;
746 s32 charcursorpos = 0;
747
748 if (font)
749 {
750 if (LastBreakFont != font)
751 {
752 breakText();
753 }
754
755 // calculate cursor pos
756
757 core::stringw *txtLine = &Text;
758 s32 startPos = 0;
759
760 core::stringw s, s2;
761
762 // get mark position
763 const bool ml = (!PasswordBox && (WordWrap || MultiLine));
764 const s32 realmbgn = MarkBegin < MarkEnd ? MarkBegin : MarkEnd;
765 const s32 realmend = MarkBegin < MarkEnd ? MarkEnd : MarkBegin;
766 const s32 hlineStart = ml ? getLineFromPos(realmbgn) : 0;
767 const s32 hlineCount = ml ? getLineFromPos(realmend) - hlineStart + 1 : 1;
768 const s32 lineCount = ml ? BrokenText.size() : 1;
769
770 // Save the override color information.
771 // Then, alter it if the edit box is disabled.
772 const bool prevOver = OverrideColorEnabled;
773 const video::SColor prevColor = OverrideColor;
774
775 if (Text.size())
776 {
777 if (!isEnabled() && !OverrideColorEnabled)
778 {
779 OverrideColorEnabled = true;
780 OverrideColor = skin->getColor(EGDC_GRAY_TEXT);
781 }
782
783 for (s32 i=0; i < lineCount; ++i)
784 {
785 setTextRect(i);
786
787 // clipping test - don't draw anything outside the visible area
788 core::rect<s32> c = localClipRect;
789 c.clipAgainst(CurrentTextRect);
790 if (!c.isValid())
791 continue;
792
793 // get current line
794 if (PasswordBox)
795 {
796 if (BrokenText.size() != 1)
797 {
798 BrokenText.clear();
799 BrokenText.push_back(core::stringw());
800 }
801 if (BrokenText[0].size() != Text.size())
802 {
803 BrokenText[0] = Text;
804 for (u32 q = 0; q < Text.size(); ++q)
805 {
806 BrokenText[0] [q] = PasswordChar;
807 }
808 }
809 txtLine = &BrokenText[0];
810 startPos = 0;
811 }
812 else
813 {
814 txtLine = ml ? &BrokenText[i] : &Text;
815 startPos = ml ? BrokenTextPositions[i] : 0;
816 }
817
818
819 // draw normal text
820 font->draw(txtLine->c_str(), CurrentTextRect,
821 OverrideColorEnabled ? OverrideColor : skin->getColor(EGDC_BUTTON_TEXT),
822 false, true, &localClipRect);
823
824 // draw mark and marked text
825 if (focus && MarkBegin != MarkEnd && i >= hlineStart && i < hlineStart + hlineCount)
826 {
827
828 s32 mbegin = 0, mend = 0;
829 s32 lineStartPos = 0, lineEndPos = txtLine->size();
830
831 if (i == hlineStart)
832 {
833 // highlight start is on this line
834 s = txtLine->subString(0, realmbgn - startPos);
835 mbegin = font->getDimension(s.c_str()).Width;
836
837 // deal with kerning
838 mbegin += font->getKerningWidth(
839 &((*txtLine)[realmbgn - startPos]),
840 realmbgn - startPos > 0 ? &((*txtLine)[realmbgn - startPos - 1]) : 0);
841
842 lineStartPos = realmbgn - startPos;
843 }
844 if (i == hlineStart + hlineCount - 1)
845 {
846 // highlight end is on this line
847 s2 = txtLine->subString(0, realmend - startPos);
848 mend = font->getDimension(s2.c_str()).Width;
849 lineEndPos = (s32)s2.size();
850 }
851 else
852 mend = font->getDimension(txtLine->c_str()).Width;
853
854 CurrentTextRect.UpperLeftCorner.X += mbegin;
855 CurrentTextRect.LowerRightCorner.X = CurrentTextRect.UpperLeftCorner.X + mend - mbegin;
856
857 // draw mark
858 skin->draw2DRectangle(this, skin->getColor(EGDC_HIGH_LIGHT), CurrentTextRect, &localClipRect);
859
860 // draw marked text
861 s = txtLine->subString(lineStartPos, lineEndPos - lineStartPos);
862
863 if (s.size())
864 font->draw(s.c_str(), CurrentTextRect,
865 OverrideColorEnabled ? OverrideColor : skin->getColor(EGDC_HIGH_LIGHT_TEXT),
866 false, true, &localClipRect);
867
868 }
869 }
870
871 // Return the override color information to its previous settings.
872 OverrideColorEnabled = prevOver;
873 OverrideColor = prevColor;
874 }
875
876 // draw cursor
877 if ( IsEnabled )
878 {
879 if (WordWrap || MultiLine)
880 {
881 cursorLine = getLineFromPos(CursorPos);
882 txtLine = &BrokenText[cursorLine];
883 startPos = BrokenTextPositions[cursorLine];
884 }
885 s = txtLine->subString(0,CursorPos-startPos);
886 charcursorpos = font->getDimension(s.c_str()).Width +
887 font->getKerningWidth(L"_", CursorPos-startPos > 0 ? &((*txtLine)[CursorPos-startPos-1]) : 0);
888
889 if (focus && (os::Timer::getTime() - BlinkStartTime) % 700 < 350)
890 {
891 setTextRect(cursorLine);
892 CurrentTextRect.UpperLeftCorner.X += charcursorpos;
893
894 font->draw(L"_", CurrentTextRect,
895 OverrideColorEnabled ? OverrideColor : skin->getColor(EGDC_BUTTON_TEXT),
896 false, true, &localClipRect);
897 }
898 }
899 }
900
901 // draw children
902 IGUIElement::draw();
903}
904
905
906//! Sets the new caption of this element.
907void CGUIEditBox::setText(const wchar_t* text)
908{
909 Text = text;
910 if (u32(CursorPos) > Text.size())
911 CursorPos = Text.size();
912 HScrollPos = 0;
913 breakText();
914}
915
916
917//! Enables or disables automatic scrolling with cursor position
918//! \param enable: If set to true, the text will move around with the cursor position
919void CGUIEditBox::setAutoScroll(bool enable)
920{
921 AutoScroll = enable;
922}
923
924
925//! Checks to see if automatic scrolling is enabled
926//! \return true if automatic scrolling is enabled, false if not
927bool CGUIEditBox::isAutoScrollEnabled() const
928{
929 _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
930 return AutoScroll;
931}
932
933
934//! Gets the area of the text in the edit box
935//! \return Returns the size in pixels of the text
936core::dimension2du CGUIEditBox::getTextDimension()
937{
938 core::rect<s32> ret;
939
940 setTextRect(0);
941 ret = CurrentTextRect;
942
943 for (u32 i=1; i < BrokenText.size(); ++i)
944 {
945 setTextRect(i);
946 ret.addInternalPoint(CurrentTextRect.UpperLeftCorner);
947 ret.addInternalPoint(CurrentTextRect.LowerRightCorner);
948 }
949
950 return core::dimension2du(ret.getSize());
951}
952
953
954//! Sets the maximum amount of characters which may be entered in the box.
955//! \param max: Maximum amount of characters. If 0, the character amount is
956//! infinity.
957void CGUIEditBox::setMax(u32 max)
958{
959 Max = max;
960
961 if (Text.size() > Max && Max != 0)
962 Text = Text.subString(0, Max);
963}
964
965
966//! Returns maximum amount of characters, previously set by setMax();
967u32 CGUIEditBox::getMax() const
968{
969 return Max;
970}
971
972
973bool CGUIEditBox::processMouse(const SEvent& event)
974{
975 switch(event.MouseInput.Event)
976 {
977 case irr::EMIE_LMOUSE_LEFT_UP:
978 if (Environment->hasFocus(this))
979 {
980 CursorPos = getCursorPos(event.MouseInput.X, event.MouseInput.Y);
981 if (MouseMarking)
982 {
983 setTextMarkers( MarkBegin, CursorPos );
984 }
985 MouseMarking = false;
986 calculateScrollPos();
987 return true;
988 }
989 break;
990 case irr::EMIE_MOUSE_MOVED:
991 {
992 if (MouseMarking)
993 {
994 CursorPos = getCursorPos(event.MouseInput.X, event.MouseInput.Y);
995 setTextMarkers( MarkBegin, CursorPos );
996 calculateScrollPos();
997 return true;
998 }
999 }
1000 break;
1001 case EMIE_LMOUSE_PRESSED_DOWN:
1002 if (!Environment->hasFocus(this))
1003 {
1004 BlinkStartTime = os::Timer::getTime();
1005 MouseMarking = true;
1006 CursorPos = getCursorPos(event.MouseInput.X, event.MouseInput.Y);
1007 setTextMarkers(CursorPos, CursorPos );
1008 calculateScrollPos();
1009 return true;
1010 }
1011 else
1012 {
1013 if (!AbsoluteClippingRect.isPointInside(
1014 core::position2d<s32>(event.MouseInput.X, event.MouseInput.Y)))
1015 {
1016 return false;
1017 }
1018 else
1019 {
1020 // move cursor
1021 CursorPos = getCursorPos(event.MouseInput.X, event.MouseInput.Y);
1022
1023 s32 newMarkBegin = MarkBegin;
1024 if (!MouseMarking)
1025 newMarkBegin = CursorPos;
1026
1027 MouseMarking = true;
1028 setTextMarkers( newMarkBegin, CursorPos);
1029 calculateScrollPos();
1030 return true;
1031 }
1032 }
1033 default:
1034 break;
1035 }
1036
1037 return false;
1038}
1039
1040
1041s32 CGUIEditBox::getCursorPos(s32 x, s32 y)
1042{
1043 IGUIFont* font = getActiveFont();
1044
1045 const u32 lineCount = (WordWrap || MultiLine) ? BrokenText.size() : 1;
1046
1047 core::stringw *txtLine=0;
1048 s32 startPos=0;
1049 x+=3;
1050
1051 for (u32 i=0; i < lineCount; ++i)
1052 {
1053 setTextRect(i);
1054 if (i == 0 && y < CurrentTextRect.UpperLeftCorner.Y)
1055 y = CurrentTextRect.UpperLeftCorner.Y;
1056 if (i == lineCount - 1 && y > CurrentTextRect.LowerRightCorner.Y )
1057 y = CurrentTextRect.LowerRightCorner.Y;
1058
1059 // is it inside this region?
1060 if (y >= CurrentTextRect.UpperLeftCorner.Y && y <= CurrentTextRect.LowerRightCorner.Y)
1061 {
1062 // we've found the clicked line
1063 txtLine = (WordWrap || MultiLine) ? &BrokenText[i] : &Text;
1064 startPos = (WordWrap || MultiLine) ? BrokenTextPositions[i] : 0;
1065 break;
1066 }
1067 }
1068
1069 if (x < CurrentTextRect.UpperLeftCorner.X)
1070 x = CurrentTextRect.UpperLeftCorner.X;
1071
1072 if ( !txtLine )
1073 return 0;
1074
1075 s32 idx = font->getCharacterFromPos(txtLine->c_str(), x - CurrentTextRect.UpperLeftCorner.X);
1076
1077 // click was on or left of the line
1078 if (idx != -1)
1079 return idx + startPos;
1080
1081 // click was off the right edge of the line, go to end.
1082 return txtLine->size() + startPos;
1083}
1084
1085
1086//! Breaks the single text line.
1087void CGUIEditBox::breakText()
1088{
1089 if ((!WordWrap && !MultiLine))
1090 return;
1091
1092 BrokenText.clear(); // need to reallocate :/
1093 BrokenTextPositions.set_used(0);
1094
1095 IGUIFont* font = getActiveFont();
1096 if (!font)
1097 return;
1098
1099 LastBreakFont = font;
1100
1101 core::stringw line;
1102 core::stringw word;
1103 core::stringw whitespace;
1104 s32 lastLineStart = 0;
1105 s32 size = Text.size();
1106 s32 length = 0;
1107 s32 elWidth = RelativeRect.getWidth() - 6;
1108 wchar_t c;
1109
1110 for (s32 i=0; i<size; ++i)
1111 {
1112 c = Text[i];
1113 bool lineBreak = false;
1114
1115 if (c == L'\r') // Mac or Windows breaks
1116 {
1117 lineBreak = true;
1118 c = 0;
1119 if (Text[i+1] == L'\n') // Windows breaks
1120 {
1121 // TODO: I (Michael) think that we shouldn't change the text given by the user for whatever reason.
1122 // Instead rework the cursor positioning to be able to handle this (but not in stable release
1123 // branch as users might already expect this behavior).
1124 Text.erase(i+1);
1125 --size;
1126 if ( CursorPos > i )
1127 --CursorPos;
1128 }
1129 }
1130 else if (c == L'\n') // Unix breaks
1131 {
1132 lineBreak = true;
1133 c = 0;
1134 }
1135
1136 // don't break if we're not a multi-line edit box
1137 if (!MultiLine)
1138 lineBreak = false;
1139
1140 if (c == L' ' || c == 0 || i == (size-1))
1141 {
1142 // here comes the next whitespace, look if
1143 // we can break the last word to the next line
1144 // We also break whitespace, otherwise cursor would vanish beside the right border.
1145 s32 whitelgth = font->getDimension(whitespace.c_str()).Width;
1146 s32 worldlgth = font->getDimension(word.c_str()).Width;
1147
1148 if (WordWrap && length + worldlgth + whitelgth > elWidth && line.size() > 0)
1149 {
1150 // break to next line
1151 length = worldlgth;
1152 BrokenText.push_back(line);
1153 BrokenTextPositions.push_back(lastLineStart);
1154 lastLineStart = i - (s32)word.size();
1155 line = word;
1156 }
1157 else
1158 {
1159 // add word to line
1160 line += whitespace;
1161 line += word;
1162 length += whitelgth + worldlgth;
1163 }
1164
1165 word = L"";
1166 whitespace = L"";
1167
1168
1169 if ( c )
1170 whitespace += c;
1171
1172 // compute line break
1173 if (lineBreak)
1174 {
1175 line += whitespace;
1176 line += word;
1177 BrokenText.push_back(line);
1178 BrokenTextPositions.push_back(lastLineStart);
1179 lastLineStart = i+1;
1180 line = L"";
1181 word = L"";
1182 whitespace = L"";
1183 length = 0;
1184 }
1185 }
1186 else
1187 {
1188 // yippee this is a word..
1189 word += c;
1190 }
1191 }
1192
1193 line += whitespace;
1194 line += word;
1195 BrokenText.push_back(line);
1196 BrokenTextPositions.push_back(lastLineStart);
1197}
1198
1199// TODO: that function does interpret VAlign according to line-index (indexed line is placed on top-center-bottom)
1200// but HAlign according to line-width (pixels) and not by row.
1201// Intuitively I suppose HAlign handling is better as VScrollPos should handle the line-scrolling.
1202// But please no one change this without also rewriting (and this time fucking testing!!!) autoscrolling (I noticed this when fixing the old autoscrolling).
1203void CGUIEditBox::setTextRect(s32 line)
1204{
1205 if ( line < 0 )
1206 return;
1207
1208 IGUIFont* font = getActiveFont();
1209 if (!font)
1210 return;
1211
1212 core::dimension2du d;
1213
1214 // get text dimension
1215 const u32 lineCount = (WordWrap || MultiLine) ? BrokenText.size() : 1;
1216 if (WordWrap || MultiLine)
1217 {
1218 d = font->getDimension(BrokenText[line].c_str());
1219 }
1220 else
1221 {
1222 d = font->getDimension(Text.c_str());
1223 d.Height = AbsoluteRect.getHeight();
1224 }
1225 d.Height += font->getKerningHeight();
1226
1227 // justification
1228 switch (HAlign)
1229 {
1230 case EGUIA_CENTER:
1231 // align to h centre
1232 CurrentTextRect.UpperLeftCorner.X = (FrameRect.getWidth()/2) - (d.Width/2);
1233 CurrentTextRect.LowerRightCorner.X = (FrameRect.getWidth()/2) + (d.Width/2);
1234 break;
1235 case EGUIA_LOWERRIGHT:
1236 // align to right edge
1237 CurrentTextRect.UpperLeftCorner.X = FrameRect.getWidth() - d.Width;
1238 CurrentTextRect.LowerRightCorner.X = FrameRect.getWidth();
1239 break;
1240 default:
1241 // align to left edge
1242 CurrentTextRect.UpperLeftCorner.X = 0;
1243 CurrentTextRect.LowerRightCorner.X = d.Width;
1244
1245 }
1246
1247 switch (VAlign)
1248 {
1249 case EGUIA_CENTER:
1250 // align to v centre
1251 CurrentTextRect.UpperLeftCorner.Y =
1252 (FrameRect.getHeight()/2) - (lineCount*d.Height)/2 + d.Height*line;
1253 break;
1254 case EGUIA_LOWERRIGHT:
1255 // align to bottom edge
1256 CurrentTextRect.UpperLeftCorner.Y =
1257 FrameRect.getHeight() - lineCount*d.Height + d.Height*line;
1258 break;
1259 default:
1260 // align to top edge
1261 CurrentTextRect.UpperLeftCorner.Y = d.Height*line;
1262 break;
1263 }
1264
1265 CurrentTextRect.UpperLeftCorner.X -= HScrollPos;
1266 CurrentTextRect.LowerRightCorner.X -= HScrollPos;
1267 CurrentTextRect.UpperLeftCorner.Y -= VScrollPos;
1268 CurrentTextRect.LowerRightCorner.Y = CurrentTextRect.UpperLeftCorner.Y + d.Height;
1269
1270 CurrentTextRect += FrameRect.UpperLeftCorner;
1271
1272}
1273
1274
1275s32 CGUIEditBox::getLineFromPos(s32 pos)
1276{
1277 if (!WordWrap && !MultiLine)
1278 return 0;
1279
1280 s32 i=0;
1281 while (i < (s32)BrokenTextPositions.size())
1282 {
1283 if (BrokenTextPositions[i] > pos)
1284 return i-1;
1285 ++i;
1286 }
1287 return (s32)BrokenTextPositions.size() - 1;
1288}
1289
1290
1291void CGUIEditBox::inputChar(wchar_t c)
1292{
1293 if (!isEnabled())
1294 return;
1295
1296 if (c != 0)
1297 {
1298 if (Text.size() < Max || Max == 0)
1299 {
1300 core::stringw s;
1301
1302 if (MarkBegin != MarkEnd)
1303 {
1304 // replace marked text
1305 const s32 realmbgn = MarkBegin < MarkEnd ? MarkBegin : MarkEnd;
1306 const s32 realmend = MarkBegin < MarkEnd ? MarkEnd : MarkBegin;
1307
1308 s = Text.subString(0, realmbgn);
1309 s.append(c);
1310 s.append( Text.subString(realmend, Text.size()-realmend) );
1311 Text = s;
1312 CursorPos = realmbgn+1;
1313 }
1314 else
1315 {
1316 // add new character
1317 s = Text.subString(0, CursorPos);
1318 s.append(c);
1319 s.append( Text.subString(CursorPos, Text.size()-CursorPos) );
1320 Text = s;
1321 ++CursorPos;
1322 }
1323
1324 BlinkStartTime = os::Timer::getTime();
1325 setTextMarkers(0, 0);
1326 }
1327 }
1328 breakText();
1329 calculateScrollPos();
1330 sendGuiEvent(EGET_EDITBOX_CHANGED);
1331}
1332
1333// calculate autoscroll
1334void CGUIEditBox::calculateScrollPos()
1335{
1336 if (!AutoScroll)
1337 return;
1338
1339 IGUISkin* skin = Environment->getSkin();
1340 if (!skin)
1341 return;
1342 IGUIFont* font = OverrideFont ? OverrideFont : skin->getFont();
1343 if (!font)
1344 return;
1345
1346 s32 cursLine = getLineFromPos(CursorPos);
1347 if ( cursLine < 0 )
1348 return;
1349 setTextRect(cursLine);
1350 const bool hasBrokenText = MultiLine || WordWrap;
1351
1352 // Check horizonal scrolling
1353 // NOTE: Calculations different to vertical scrolling because setTextRect interprets VAlign relative to line but HAlign not relative to row
1354 {
1355 // get cursor position
1356 IGUIFont* font = getActiveFont();
1357 if (!font)
1358 return;
1359
1360 // get cursor area
1361 irr::u32 cursorWidth = font->getDimension(L"_").Width;
1362 core::stringw *txtLine = hasBrokenText ? &BrokenText[cursLine] : &Text;
1363 s32 cPos = hasBrokenText ? CursorPos - BrokenTextPositions[cursLine] : CursorPos; // column
1364 s32 cStart = font->getDimension(txtLine->subString(0, cPos).c_str()).Width; // pixels from text-start
1365 s32 cEnd = cStart + cursorWidth;
1366 s32 txtWidth = font->getDimension(txtLine->c_str()).Width;
1367
1368 if ( txtWidth < FrameRect.getWidth() )
1369 {
1370 // TODO: Needs a clean left and right gap removal depending on HAlign, similar to vertical scrolling tests for top/bottom.
1371 // This check just fixes the case where it was most noticable (text smaller than clipping area).
1372
1373 HScrollPos = 0;
1374 setTextRect(cursLine);
1375 }
1376
1377 if ( CurrentTextRect.UpperLeftCorner.X+cStart < FrameRect.UpperLeftCorner.X )
1378 {
1379 // cursor to the left of the clipping area
1380 HScrollPos -= FrameRect.UpperLeftCorner.X-(CurrentTextRect.UpperLeftCorner.X+cStart);
1381 setTextRect(cursLine);
1382
1383 // TODO: should show more characters to the left when we're scrolling left
1384 // and the cursor reaches the border.
1385 }
1386 else if ( CurrentTextRect.UpperLeftCorner.X+cEnd > FrameRect.LowerRightCorner.X)
1387 {
1388 // cursor to the right of the clipping area
1389 HScrollPos += (CurrentTextRect.UpperLeftCorner.X+cEnd)-FrameRect.LowerRightCorner.X;
1390 setTextRect(cursLine);
1391 }
1392 }
1393
1394 // calculate vertical scrolling
1395 if (hasBrokenText)
1396 {
1397 irr::u32 lineHeight = font->getDimension(L"A").Height + font->getKerningHeight();
1398 // only up to 1 line fits?
1399 if ( lineHeight >= (irr::u32)FrameRect.getHeight() )
1400 {
1401 VScrollPos = 0;
1402 setTextRect(cursLine);
1403 s32 unscrolledPos = CurrentTextRect.UpperLeftCorner.Y;
1404 s32 pivot = FrameRect.UpperLeftCorner.Y;
1405 switch (VAlign)
1406 {
1407 case EGUIA_CENTER:
1408 pivot += FrameRect.getHeight()/2;
1409 unscrolledPos += lineHeight/2;
1410 break;
1411 case EGUIA_LOWERRIGHT:
1412 pivot += FrameRect.getHeight();
1413 unscrolledPos += lineHeight;
1414 break;
1415 default:
1416 break;
1417 }
1418 VScrollPos = unscrolledPos-pivot;
1419 setTextRect(cursLine);
1420 }
1421 else
1422 {
1423 // First 2 checks are necessary when people delete lines
1424 setTextRect(0);
1425 if ( CurrentTextRect.UpperLeftCorner.Y > FrameRect.UpperLeftCorner.Y && VAlign != EGUIA_LOWERRIGHT)
1426 {
1427 // first line is leaving a gap on top
1428 VScrollPos = 0;
1429 }
1430 else if (VAlign != EGUIA_UPPERLEFT)
1431 {
1432 u32 lastLine = BrokenTextPositions.empty() ? 0 : BrokenTextPositions.size()-1;
1433 setTextRect(lastLine);
1434 if ( CurrentTextRect.LowerRightCorner.Y < FrameRect.LowerRightCorner.Y)
1435 {
1436 // last line is leaving a gap on bottom
1437 VScrollPos -= FrameRect.LowerRightCorner.Y-CurrentTextRect.LowerRightCorner.Y;
1438 }
1439 }
1440
1441 setTextRect(cursLine);
1442 if ( CurrentTextRect.UpperLeftCorner.Y < FrameRect.UpperLeftCorner.Y )
1443 {
1444 // text above valid area
1445 VScrollPos -= FrameRect.UpperLeftCorner.Y-CurrentTextRect.UpperLeftCorner.Y;
1446 setTextRect(cursLine);
1447 }
1448 else if ( CurrentTextRect.LowerRightCorner.Y > FrameRect.LowerRightCorner.Y)
1449 {
1450 // text below valid area
1451 VScrollPos += CurrentTextRect.LowerRightCorner.Y-FrameRect.LowerRightCorner.Y;
1452 setTextRect(cursLine);
1453 }
1454 }
1455 }
1456}
1457
1458void CGUIEditBox::calculateFrameRect()
1459{
1460 FrameRect = AbsoluteRect;
1461 IGUISkin *skin = 0;
1462 if (Environment)
1463 skin = Environment->getSkin();
1464 if (Border && skin)
1465 {
1466 FrameRect.UpperLeftCorner.X += skin->getSize(EGDS_TEXT_DISTANCE_X)+1;
1467 FrameRect.UpperLeftCorner.Y += skin->getSize(EGDS_TEXT_DISTANCE_Y)+1;
1468 FrameRect.LowerRightCorner.X -= skin->getSize(EGDS_TEXT_DISTANCE_X)+1;
1469 FrameRect.LowerRightCorner.Y -= skin->getSize(EGDS_TEXT_DISTANCE_Y)+1;
1470 }
1471}
1472
1473//! set text markers
1474void CGUIEditBox::setTextMarkers(s32 begin, s32 end)
1475{
1476 if ( begin != MarkBegin || end != MarkEnd )
1477 {
1478 MarkBegin = begin;
1479 MarkEnd = end;
1480 sendGuiEvent(EGET_EDITBOX_MARKING_CHANGED);
1481 }
1482}
1483
1484//! send some gui event to parent
1485void CGUIEditBox::sendGuiEvent(EGUI_EVENT_TYPE type)
1486{
1487 if ( Parent )
1488 {
1489 SEvent e;
1490 e.EventType = EET_GUI_EVENT;
1491 e.GUIEvent.Caller = this;
1492 e.GUIEvent.Element = 0;
1493 e.GUIEvent.EventType = type;
1494
1495 Parent->OnEvent(e);
1496 }
1497}
1498
1499//! Writes attributes of the element.
1500void CGUIEditBox::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const
1501{
1502 // IGUIEditBox::serializeAttributes(out,options);
1503
1504 out->addBool ("Border", Border);
1505 out->addBool ("Background", Background);
1506 out->addBool ("OverrideColorEnabled", OverrideColorEnabled );
1507 out->addColor ("OverrideColor", OverrideColor);
1508 // out->addFont("OverrideFont", OverrideFont);
1509 out->addInt ("MaxChars", Max);
1510 out->addBool ("WordWrap", WordWrap);
1511 out->addBool ("MultiLine", MultiLine);
1512 out->addBool ("AutoScroll", AutoScroll);
1513 out->addBool ("PasswordBox", PasswordBox);
1514 core::stringw ch = L" ";
1515 ch[0] = PasswordChar;
1516 out->addString("PasswordChar", ch.c_str());
1517 out->addEnum ("HTextAlign", HAlign, GUIAlignmentNames);
1518 out->addEnum ("VTextAlign", VAlign, GUIAlignmentNames);
1519
1520 IGUIEditBox::serializeAttributes(out,options);
1521}
1522
1523
1524//! Reads attributes of the element
1525void CGUIEditBox::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0)
1526{
1527 IGUIEditBox::deserializeAttributes(in,options);
1528
1529 setDrawBorder( in->getAttributeAsBool("Border") );
1530 setDrawBackground( in->getAttributeAsBool("Background") );
1531 setOverrideColor(in->getAttributeAsColor("OverrideColor"));
1532 enableOverrideColor(in->getAttributeAsBool("OverrideColorEnabled"));
1533 setMax(in->getAttributeAsInt("MaxChars"));
1534 setWordWrap(in->getAttributeAsBool("WordWrap"));
1535 setMultiLine(in->getAttributeAsBool("MultiLine"));
1536 setAutoScroll(in->getAttributeAsBool("AutoScroll"));
1537 core::stringw ch = in->getAttributeAsStringW("PasswordChar");
1538
1539 if (!ch.size())
1540 setPasswordBox(in->getAttributeAsBool("PasswordBox"));
1541 else
1542 setPasswordBox(in->getAttributeAsBool("PasswordBox"), ch[0]);
1543
1544 setTextAlignment( (EGUI_ALIGNMENT) in->getAttributeAsEnumeration("HTextAlign", GUIAlignmentNames),
1545 (EGUI_ALIGNMENT) in->getAttributeAsEnumeration("VTextAlign", GUIAlignmentNames));
1546
1547 // setOverrideFont(in->getAttributeAsFont("OverrideFont"));
1548}
1549
1550
1551} // end namespace gui
1552} // end namespace irr
1553
1554#endif // _IRR_COMPILE_WITH_GUI_
1555