MyGUI 3.4.3
MyGUI_EditText.cpp
Go to the documentation of this file.
1/*
2 * This source file is part of MyGUI. For the latest info, see http://mygui.info/
3 * Distributed under the MIT License
4 * (See accompanying file COPYING.MIT or copy at http://opensource.org/licenses/MIT)
5 */
6
7#include "MyGUI_Precompiled.h"
8#include "MyGUI_EditText.h"
9#include "MyGUI_RenderItem.h"
10#include "MyGUI_FontManager.h"
11#include "MyGUI_RenderManager.h"
13#include "MyGUI_TextIterator.h"
14#include "MyGUI_IRenderTarget.h"
15#include "MyGUI_FontData.h"
17
18namespace MyGUI
19{
20
22
28
29 void EditText::setVisible(bool _visible)
30 {
31 if (mVisible == _visible)
32 return;
33 mVisible = _visible;
34
35 if (nullptr != mNode)
36 mNode->outOfDate(mRenderItem);
37 }
38
40 {
41 if (nullptr != mNode)
42 mNode->outOfDate(mRenderItem);
43 }
44
45 void EditText::_setAlign(const IntSize& _oldsize)
46 {
47 if (mWordWrap)
48 {
49 // передается старая координата всегда
50 int width = mCroppedParent->getWidth();
51 if (mOldWidth != width)
52 {
53 mOldWidth = width;
54 mTextOutDate = true;
55 }
56 }
57
58 // первоначальное выравнивание
59 if (mAlign.isHStretch())
60 {
61 // растягиваем
62 mCoord.width = mCoord.width + (mCroppedParent->getWidth() - _oldsize.width);
63 mIsMargin = true; // при изменении размеров все пересчитывать
64 }
65 else if (mAlign.isRight())
66 {
67 // двигаем по правому краю
68 mCoord.left = mCoord.left + (mCroppedParent->getWidth() - _oldsize.width);
69 }
70 else if (mAlign.isHCenter())
71 {
72 // выравнивание по горизонтали без растяжения
73 mCoord.left = (mCroppedParent->getWidth() - mCoord.width) / 2;
74 }
75
76 if (mAlign.isVStretch())
77 {
78 // растягиваем
79 mCoord.height = mCoord.height + (mCroppedParent->getHeight() - _oldsize.height);
80 mIsMargin = true; // при изменении размеров все пересчитывать
81 }
82 else if (mAlign.isBottom())
83 {
84 // двигаем по нижнему краю
85 mCoord.top = mCoord.top + (mCroppedParent->getHeight() - _oldsize.height);
86 }
87 else if (mAlign.isVCenter())
88 {
89 // выравнивание по вертикали без растяжения
90 mCoord.top = (mCroppedParent->getHeight() - mCoord.height) / 2;
91 }
92
95 }
96
98 {
99 bool margin = _checkMargin();
100
101 mEmptyView = ((0 >= _getViewWidth()) || (0 >= _getViewHeight()));
102
103 mCurrentCoord.left = mCoord.left + mMargin.left;
104 mCurrentCoord.top = mCoord.top + mMargin.top;
105
106 // вьюпорт стал битым
107 if (margin)
108 {
109 // проверка на полный выход за границу
110 if (_checkOutside())
111 {
112 // запоминаем текущее состояние
113 mIsMargin = margin;
114
115 // обновить перед выходом
116 if (nullptr != mNode)
117 mNode->outOfDate(mRenderItem);
118 return;
119 }
120 }
121
122 // мы обрезаны или были обрезаны
123 if (mIsMargin || margin)
124 {
126 mCurrentCoord.height = _getViewHeight();
127 }
128
129 // запоминаем текущее состояние
130 mIsMargin = margin;
131
132 if (nullptr != mNode)
133 mNode->outOfDate(mRenderItem);
134 }
135
136 void EditText::setCaption(const UString& _value)
137 {
138 mCaption = _value;
139 mUtf32Caption = mCaption.asUTF32();
140 mTextOutDate = true;
141
142 checkVertexSize();
143
144 if (nullptr != mNode)
145 mNode->outOfDate(mRenderItem);
146 }
147
148 void EditText::checkVertexSize()
149 {
150 // reallocate if we need more vertices (extra vertices for selection * 2 and cursor)
151 size_t need = (mUtf32Caption.size() * (mShadow ? 3 : 2) + 2) * VertexQuad::VertexCount;
152 if (mCountVertex < need)
153 {
155 if (nullptr != mRenderItem)
157 }
158 }
159
160 unsigned int EditText::getMixedNativeAlpha(float secondAlpha) const
161 {
162 return (uint8)(mAlpha * secondAlpha * 255) << 24;
163 }
164
166 {
167 return mCaption;
168 }
169
170 void EditText::setTextColour(const Colour& _value)
171 {
172 mManualColour = true;
173 _setTextColour(_value);
174 }
175
176 void EditText::_setTextColour(const Colour& _value)
177 {
178 if (mColour == _value)
179 return;
180
181 mColour = _value;
183
184 mCurrentColourNative = (mCurrentColourNative & 0x00FFFFFF) | getMixedNativeAlpha(mColour.alpha);
186
187 if (nullptr != mNode)
189 }
190
192 {
193 return mColour;
194 }
195
196 void EditText::setAlpha(float _value)
197 {
198 if (mAlpha == _value)
199 return;
200 mAlpha = _value;
201
202 mCurrentColourNative = (mCurrentColourNative & 0x00FFFFFF) | getMixedNativeAlpha(mColour.alpha);
203 mShadowColourNative = (mShadowColourNative & 0x00FFFFFF) | getMixedNativeAlpha(mShadowColour.alpha);
205
206 if (nullptr != mNode)
207 mNode->outOfDate(mRenderItem);
208 }
209
210 void EditText::setFontName(std::string_view _value)
211 {
212 mTexture = nullptr;
214 if (mFont != nullptr)
215 {
216 mTexture = mFont->getTextureFont();
217
218 // set default font height
219 if (mFont->getDefaultHeight() != 0 && !mCustomFontHeight)
220 {
221 mFontHeight = mFont->getDefaultHeight();
222 }
223 }
224
225 mTextOutDate = true;
226
227 // если мы были приаттаченны, то удаляем себя
228 if (nullptr != mRenderItem)
229 {
230 mRenderItem->removeDrawItem(this);
231 mRenderItem = nullptr;
232 }
233
234 // если есть текстура, то приаттачиваемся
235 if (nullptr != mTexture && nullptr != mNode)
236 {
237 mRenderItem = mNode->addToRenderItem(mTexture, false, false);
238 mRenderItem->addDrawItem(this, mCountVertex);
239 }
240
241 if (nullptr != mNode)
242 mNode->outOfDate(mRenderItem);
243 }
244
245 std::string_view EditText::getFontName() const
246 {
247 return mFont->getResourceName();
248 }
249
250 void EditText::setFontHeight(int _value)
251 {
252 mCustomFontHeight = _value;
253 if (!mCustomFontHeight && mFont)
254 mFontHeight = mFont->getDefaultHeight();
255 else
256 mFontHeight = _value;
257 mTextOutDate = true;
258
259 if (nullptr != mNode)
260 mNode->outOfDate(mRenderItem);
261 }
262
264 {
265 return mFontHeight;
266 }
267
269 {
270 mNode = _node;
271 // если уже есть текстура, то атачимся, актуально для смены леера
272 if (nullptr != mTexture)
273 {
274 MYGUI_ASSERT(!mRenderItem, "mRenderItem must be nullptr");
275
276 mRenderItem = mNode->addToRenderItem(mTexture, false, false);
277 mRenderItem->addDrawItem(this, mCountVertex);
278 }
279 }
280
282 {
283 if (nullptr != mRenderItem)
284 {
285 mRenderItem->removeDrawItem(this);
286 mRenderItem = nullptr;
287 }
288 mNode = nullptr;
289 }
290
292 {
293 return mStartSelect;
294 }
295
297 {
298 return mEndSelect;
299 }
300
301 void EditText::setTextSelection(size_t _start, size_t _end)
302 {
303 mStartSelect = _start;
304 mEndSelect = _end;
305
306 if (nullptr != mNode)
307 mNode->outOfDate(mRenderItem);
308 }
309
311 {
312 return mBackgroundNormal;
313 }
314
316 {
317 if (mBackgroundNormal == _normal)
318 return;
319 mBackgroundNormal = _normal;
320
321 if (nullptr != mNode)
322 mNode->outOfDate(mRenderItem);
323 }
324
326 {
327 return mVisibleCursor;
328 }
329
331 {
332 if (mVisibleCursor == _value)
333 return;
334 mVisibleCursor = _value;
335
336 if (nullptr != mNode)
337 mNode->outOfDate(mRenderItem);
338 }
339
341 {
342 return mCursorPosition;
343 }
344
345 void EditText::setCursorPosition(size_t _index)
346 {
347 if (mCursorPosition == _index)
348 return;
349 mCursorPosition = _index;
350
351 if (nullptr != mNode)
352 mNode->outOfDate(mRenderItem);
353 }
354
356 {
357 mTextAlign = _value;
358
359 if (nullptr != mNode)
360 mNode->outOfDate(mRenderItem);
361 }
362
364 {
365 return mTextAlign;
366 }
367
369 {
370 // если нуно обновить, или изменились пропорции экрана
371 if (mTextOutDate)
373
374 IntSize size = mTextView.getViewSize();
375 // плюс размер курсора
377 size.width += 2;
378
379 if (mShadow)
380 {
382 size.width++;
383 size.height++;
384 }
385
386 return size;
387 }
388
390 {
391 return mTextView.getData();
392 }
393
395 {
396 mViewOffset = _point;
397
398 if (nullptr != mNode)
399 mNode->outOfDate(mRenderItem);
400 }
401
403 {
404 return mViewOffset;
405 }
406
407 size_t EditText::getCursorPosition(const IntPoint& _point) const
408 {
409 if (nullptr == mFont)
410 return 0;
411
412 if (mTextOutDate)
414
415 IntPoint point = _point;
416 point -= mCroppedParent->getAbsolutePosition();
417 point += mViewOffset;
418 point -= mCoord.point();
419
420 return mTextView.getCursorPosition(point);
421 }
422
423 IntCoord EditText::getCursorCoord(size_t _position) const
424 {
425 if (nullptr == mFont)
426 return {};
427
428 if (mTextOutDate)
430
431 IntPoint point = mTextView.getCursorPoint(_position);
432 point += mCroppedParent->getAbsolutePosition();
433 point -= mViewOffset;
434 point += mCoord.point();
435
436 return {point.left, point.top, 2, mFontHeight};
437 }
438
439 void EditText::setShiftText(bool _value)
440 {
441 if (mShiftText == _value)
442 return;
443 mShiftText = _value;
444
445 if (nullptr != mNode)
446 mNode->outOfDate(mRenderItem);
447 }
448
449 void EditText::setWordWrap(bool _value)
450 {
451 mWordWrap = _value;
452 mTextOutDate = true;
453
454 if (nullptr != mNode)
455 mNode->outOfDate(mRenderItem);
456 }
457
459 {
460 if (nullptr == mFont)
461 return;
462 // сбрасывам флаги
463 mTextOutDate = false;
464
465 int width = -1;
466 if (mWordWrap)
467 {
468 width = mCoord.width;
469 // обрезать слова нужно по шарине, которую мы реально используем
471 width -= 2;
472 }
473
475 }
476
478 {
480 if (!mManualColour && data->getColour() != Colour::Zero)
481 _setTextColour(data->getColour());
482 setShiftText(data->getShift());
483 }
484
486 {
487 if (nullptr == mFont || !mVisible || mEmptyView)
488 return;
489
490 if (mRenderItem->getCurrentUpdate() || mTextOutDate)
492
493 Vertex* vertex = mRenderItem->getCurrentVertexBuffer();
494
495 const RenderTargetInfo& renderTargetInfo = mRenderItem->getRenderTarget()->getInfo();
496
497 // колличество отрисованных вершин
498 size_t vertexCount = 0;
499
500 // текущие цвета
502 uint32 inverseColour = mInverseColourNative;
503 uint32 selectedColour = mInvertSelect ? inverseColour : colour | 0x00FFFFFF;
504
505 const VectorLineInfo& textViewData = mTextView.getData();
506
507 float top = (float)(-mViewOffset.top + mCoord.top);
508
509 FloatRect vertexRect;
510
511 const FloatRect& selectedUVRect =
513
514 size_t index = 0;
515
516 for (const auto& line : textViewData)
517 {
518 float left = (float)(line.offset - mViewOffset.left + mCoord.left);
519
520 for (const auto& sym : line.symbols)
521 {
522 if (sym.isColour())
523 {
524 colour = sym.getColour() | (colour & 0xFF000000);
525 inverseColour = colour ^ 0x00FFFFFF;
526 selectedColour = mInvertSelect ? inverseColour : colour | 0x00FFFFFF;
527 continue;
528 }
529
530 // смещение текстуры для фона
531 bool select = index >= mStartSelect && index < mEndSelect;
532
533 float fullAdvance = sym.getBearingX() + sym.getAdvance();
534
535 // Render the selection, if any, first.
536 if (select)
537 {
538 vertexRect.set(left, top, left + fullAdvance, top + (float)mFontHeight);
539
540 drawGlyph(renderTargetInfo, vertex, vertexCount, vertexRect, selectedUVRect, selectedColour);
541 }
542
543 // Render the glyph shadow, if any.
544 if (mShadow)
545 {
546 vertexRect.left = left + sym.getBearingX() + 1.0f;
547 vertexRect.top = top + sym.getBearingY() + 1.0f;
548 vertexRect.right = vertexRect.left + sym.getWidth();
549 vertexRect.bottom = vertexRect.top + sym.getHeight();
550
551 drawGlyph(renderTargetInfo, vertex, vertexCount, vertexRect, sym.getUVRect(), mShadowColourNative);
552 }
553
554 // Render the glyph itself.
555 vertexRect.left = left + sym.getBearingX();
556 vertexRect.top = top + sym.getBearingY();
557 vertexRect.right = vertexRect.left + sym.getWidth();
558 vertexRect.bottom = vertexRect.top + sym.getHeight();
559
560 drawGlyph(
561 renderTargetInfo,
562 vertex,
563 vertexCount,
564 vertexRect,
565 sym.getUVRect(),
566 (!select || !mInvertSelect) ? colour : inverseColour);
567
568 left += fullAdvance;
569 ++index;
570 }
571
572 top += mFontHeight;
573 ++index;
574 }
575
576 // Render the cursor, if any, last.
577 if (mVisibleCursor)
578 {
579 IntPoint point = mTextView.getCursorPoint(mCursorPosition) - mViewOffset + mCoord.point();
580 const GlyphInfo* cursorGlyph = mFont->getGlyphInfo(static_cast<Char>(FontCodeType::Cursor));
581 vertexRect.set(
582 (float)point.left,
583 (float)point.top,
584 (float)point.left + cursorGlyph->width,
585 (float)(point.top + mFontHeight));
586
587 drawGlyph(
588 renderTargetInfo,
589 vertex,
590 vertexCount,
591 vertexRect,
592 cursorGlyph->uvRect,
593 mCurrentColourNative | 0x00FFFFFF);
594 }
595
596 // колличество реально отрисованных вершин
597 mRenderItem->setLastVertexCount(vertexCount);
598 }
599
601 {
602 if (mInvertSelect == _value)
603 return;
604 mInvertSelect = _value;
605
606 if (nullptr != mNode)
607 mNode->outOfDate(mRenderItem);
608 }
609
611 {
612 return mInvertSelect;
613 }
614
616 {
617 return mShadow;
618 }
619
620 void EditText::setShadow(bool _value)
621 {
622 mShadow = _value;
623 mTextOutDate = true;
624
625 checkVertexSize();
626
627 if (nullptr != mNode)
628 mNode->outOfDate(mRenderItem);
629 }
630
632 {
633 mShadowColour = _value;
635
636 mShadowColourNative = (mShadowColourNative & 0x00FFFFFF) | getMixedNativeAlpha(mShadowColour.alpha);
637
638 if (nullptr != mNode)
639 mNode->outOfDate(mRenderItem);
640 }
641
643 {
644 return mShadowColour;
645 }
646
647 void EditText::drawQuad(
648 Vertex*& _vertex,
649 size_t& _vertexCount,
650 const FloatRect& _vertexRect,
651 float _vertexZ,
652 const FloatRect& _textureRect,
653 uint32 _colour) const
654 {
655 _vertex[0].x = _vertexRect.left;
656 _vertex[0].y = _vertexRect.top;
657 _vertex[0].z = _vertexZ;
658 _vertex[0].colour = _colour;
659 _vertex[0].u = _textureRect.left;
660 _vertex[0].v = _textureRect.top;
661
662 _vertex[2].x = _vertexRect.left;
663 _vertex[2].y = _vertexRect.bottom;
664 _vertex[2].z = _vertexZ;
665 _vertex[2].colour = _colour;
666 _vertex[2].u = _textureRect.left;
667 _vertex[2].v = _textureRect.bottom;
668
669 _vertex[1].x = _vertexRect.right;
670 _vertex[1].y = _vertexRect.top;
671 _vertex[1].z = _vertexZ;
672 _vertex[1].colour = _colour;
673 _vertex[1].u = _textureRect.right;
674 _vertex[1].v = _textureRect.top;
675
676 _vertex[3].x = _vertexRect.right;
677 _vertex[3].y = _vertexRect.top;
678 _vertex[3].z = _vertexZ;
679 _vertex[3].colour = _colour;
680 _vertex[3].u = _textureRect.right;
681 _vertex[3].v = _textureRect.top;
682
683 _vertex[5].x = _vertexRect.left;
684 _vertex[5].y = _vertexRect.bottom;
685 _vertex[5].z = _vertexZ;
686 _vertex[5].colour = _colour;
687 _vertex[5].u = _textureRect.left;
688 _vertex[5].v = _textureRect.bottom;
689
690 _vertex[4].x = _vertexRect.right;
691 _vertex[4].y = _vertexRect.bottom;
692 _vertex[4].z = _vertexZ;
693 _vertex[4].colour = _colour;
694 _vertex[4].u = _textureRect.right;
695 _vertex[4].v = _textureRect.bottom;
696
697 _vertex += VertexQuad::VertexCount;
698 _vertexCount += VertexQuad::VertexCount;
699 }
700
701 void EditText::drawGlyph(
702 const RenderTargetInfo& _renderTargetInfo,
703 Vertex*& _vertex,
704 size_t& _vertexCount,
705 FloatRect _vertexRect,
706 FloatRect _textureRect,
707 uint32 _colour) const
708 {
709 // символ залазиет влево
710 float leftClip = (float)mCurrentCoord.left - _vertexRect.left;
711 if (leftClip > 0.0f)
712 {
713 if ((float)mCurrentCoord.left < _vertexRect.right)
714 {
715 _textureRect.left += _textureRect.width() * leftClip / _vertexRect.width();
716 _vertexRect.left += leftClip;
717 }
718 else
719 {
720 return;
721 }
722 }
723
724 // символ залазиет вправо
725 float rightClip = _vertexRect.right - (float)mCurrentCoord.right();
726 if (rightClip > 0.0f)
727 {
728 if (_vertexRect.left < (float)mCurrentCoord.right())
729 {
730 _textureRect.right -= _textureRect.width() * rightClip / _vertexRect.width();
731 _vertexRect.right -= rightClip;
732 }
733 else
734 {
735 return;
736 }
737 }
738
739 // символ залазиет вверх
740 float topClip = (float)mCurrentCoord.top - _vertexRect.top;
741 if (topClip > 0.0f)
742 {
743 if ((float)mCurrentCoord.top < _vertexRect.bottom)
744 {
745 _textureRect.top += _textureRect.height() * topClip / _vertexRect.height();
746 _vertexRect.top += topClip;
747 }
748 else
749 {
750 return;
751 }
752 }
753
754 // символ залазиет вниз
755 float bottomClip = _vertexRect.bottom - (float)mCurrentCoord.bottom();
756 if (bottomClip > 0.0f)
757 {
758 if (_vertexRect.top < (float)mCurrentCoord.bottom())
759 {
760 _textureRect.bottom -= _textureRect.height() * bottomClip / _vertexRect.height();
761 _vertexRect.bottom -= bottomClip;
762 }
763 else
764 {
765 return;
766 }
767 }
768
769 float pix_left = mCroppedParent->getAbsoluteLeft() - _renderTargetInfo.leftOffset + _vertexRect.left;
770 float pix_top = mCroppedParent->getAbsoluteTop() - _renderTargetInfo.topOffset + (mShiftText ? 1.0f : 0.0f) +
771 _vertexRect.top;
772
773 FloatRect vertexRect(
774 ((_renderTargetInfo.pixScaleX * pix_left + _renderTargetInfo.hOffset) * 2.0f) - 1.0f,
775 -(((_renderTargetInfo.pixScaleY * pix_top + _renderTargetInfo.vOffset) * 2.0f) - 1.0f),
776 ((_renderTargetInfo.pixScaleX * (pix_left + _vertexRect.width()) + _renderTargetInfo.hOffset) * 2.0f) -
777 1.0f,
778 -(((_renderTargetInfo.pixScaleY * (pix_top + _vertexRect.height()) + _renderTargetInfo.vOffset) * 2.0f) -
779 1.0f));
780
781 drawQuad(_vertex, _vertexCount, vertexRect, mNode->getNodeDepth(), _textureRect, _colour);
782 }
783
784} // namespace MyGUI
#define MYGUI_ASSERT(exp, dest)
void setTextColour(const Colour &_value) override
VertexColourType mVertexFormat
size_t getTextSelectionEnd() const override
void setAlpha(float _value) override
uint32 mCurrentColourNative
void setFontName(std::string_view _value) override
void setSelectBackground(bool _normal) override
void setTextSelection(size_t _start, size_t _end) override
void setWordWrap(bool _value) override
void _setAlign(const IntSize &_oldsize) override
bool isVisibleCursor() const override
bool getShadow() const override
IntCoord getCursorCoord(size_t _position) const override
void _correctView() override
void setVisible(bool _visible) override
virtual const VectorLineInfo & getLineInfo() const
void setInvertSelected(bool _value) override
const Colour & getTextColour() const override
void setFontHeight(int _value) override
uint32 mInverseColourNative
const Colour & getShadowColour() const override
ITexture * mTexture
void setShadowColour(const Colour &_value) override
ILayerNode * mNode
const UString & getCaption() const override
bool getInvertSelected() const override
void setCaption(const UString &_value) override
void setTextAlign(Align _value) override
void setStateData(IStateInfo *_data) override
int getFontHeight() const override
size_t getTextSelectionStart() const override
void doRender() override
IntPoint getViewOffset() const override
void setVisibleCursor(bool _value) override
std::string_view getFontName() const override
bool getSelectBackground() const override
IntSize getTextSize() const override
size_t getCursorPosition() const override
void setViewOffset(const IntPoint &_point) override
Align getTextAlign() const override
void _updateView() override
RenderItem * mRenderItem
void setShiftText(bool _value) override
UString::utf32string mUtf32Caption
void createDrawItem(ITexture *_texture, ILayerNode *_node) override
void setCursorPosition(size_t _index) override
void setShadow(bool _value) override
void updateRawData() const
void destroyDrawItem() override
const Colour & getColour() const
static FontManager & getInstance()
IFont * getByName(std::string_view _name) const
virtual void outOfDate(RenderItem *_item)=0
Type * castType(bool _throw=true)
void reallockDrawItem(ISubWidget *_item, size_t _count)
virtual VertexColourType getVertexFormat() const =0
static RenderManager & getInstance()
A UTF-16 string with implicit conversion to/from std::string and std::wstring.
uint32 toNativeColour(const Colour &_colour, VertexColourType _format)
Convert Colour to 32-bit representation.
uint32_t uint32
Definition MyGUI_Types.h:48
uint8_t uint8
Definition MyGUI_Types.h:46
std::vector< LineInfo > VectorLineInfo
types::TPoint< int > IntPoint
Definition MyGUI_Types.h:27
types::TRect< float > FloatRect
Definition MyGUI_Types.h:34
unsigned int Char
Definition MyGUI_Types.h:50
const size_t SIMPLETEXT_COUNT_VERTEX
types::TCoord< int > IntCoord
Definition MyGUI_Types.h:36
types::TSize< int > IntSize
Definition MyGUI_Types.h:30
static const Colour Zero
void set(T const &_left, T const &_top, T const &_right, T const &_bottom)
Definition MyGUI_TRect.h:98