unsigned int TextBox::drawImages(Form* form, const Rectangle& clip) { Control::State state = getState(); if (_caretImage && (state == ACTIVE || hasFocus())) { // Draw the cursor at its current location. const Rectangle& region = _caretImage->getRegion(); if (!region.isEmpty()) { const Theme::UVs& uvs = _caretImage->getUVs(); Vector4 color = _caretImage->getColor(); color.w *= _opacity; float caretWidth = region.width * _fontSize / region.height; Font* font = getFont(state); unsigned int fontSize = getFontSize(state); Vector2 point; font->getLocationAtIndex(getDisplayedText().c_str(), _textBounds, fontSize, &point, _caretLocation, getTextAlignment(state), true, getTextRightToLeft(state)); SpriteBatch* batch = _style->getTheme()->getSpriteBatch(); startBatch(form, batch); batch->draw(point.x - caretWidth * 0.5f, point.y, caretWidth, fontSize, uvs.u1, uvs.v1, uvs.u2, uvs.v2, color, _viewportClipBounds); finishBatch(form, batch); return 1; } } return 0; }
void TextBox::setCaretLocation(int x, int y) { // Get index into string and cursor location from the latest touch location. _prevCaretLocation.set(_caretLocation); _caretLocation.set(x + _absoluteBounds.x, y + _absoluteBounds.y); Font* font = getFont(_state); unsigned int fontSize = getFontSize(_state); Font::Justify textAlignment = getTextAlignment(_state); bool rightToLeft = getTextRightToLeft(_state); int index = font->getIndexAtLocation(_text.c_str(), _textBounds, fontSize, _caretLocation, &_caretLocation, textAlignment, true, rightToLeft); if (index == -1) { // Attempt to find the nearest valid caret location. Rectangle textBounds; font->measureText(_text.c_str(), _textBounds, fontSize, &textBounds, textAlignment, true, true); if (_caretLocation.x > textBounds.x + textBounds.width && _caretLocation.y > textBounds.y + textBounds.height) { font->getLocationAtIndex(_text.c_str(), _textBounds, fontSize, &_caretLocation, (unsigned int)_text.length(), textAlignment, true, rightToLeft); return; } if (_caretLocation.x < textBounds.x) { _caretLocation.x = textBounds.x; } else if (_caretLocation.x > textBounds.x + textBounds.width) { _caretLocation.x = textBounds.x + textBounds.width; } if (_caretLocation.y < textBounds.y) { _caretLocation.y = textBounds.y; } else if (_caretLocation.y > textBounds.y + textBounds.height) { Font* font = getFont(_state); GP_ASSERT(font); unsigned int fontSize = getFontSize(_state); _caretLocation.y = textBounds.y + textBounds.height - fontSize; } index = font->getIndexAtLocation(_text.c_str(), _textBounds, fontSize, _caretLocation, &_caretLocation, textAlignment, true, rightToLeft); if (index == -1) { // We failed to find a valid location; just put the caret back to where it was. _caretLocation.set(_prevCaretLocation); } } }
void TextBox::setCaretLocation(int x, int y) { Control::State state = getState(); Vector2 point(x + _absoluteBounds.x, y + _absoluteBounds.y); // Get index into string and cursor location from the latest touch location. Font* font = getFont(state); unsigned int fontSize = getFontSize(state); Font::Justify textAlignment = getTextAlignment(state); bool rightToLeft = getTextRightToLeft(state); const std::string displayedText = getDisplayedText(); int index = font->getIndexAtLocation(displayedText.c_str(), _textBounds, fontSize, point, &point, textAlignment, true, rightToLeft); if (index == -1) { // Attempt to find the nearest valid caret location. Rectangle textBounds; font->measureText(displayedText.c_str(), _textBounds, fontSize, &textBounds, textAlignment, true, true); if (point.x > textBounds.x + textBounds.width && point.y > textBounds.y + textBounds.height) { font->getLocationAtIndex(displayedText.c_str(), _textBounds, fontSize, &point, (unsigned int)_text.length(), textAlignment, true, rightToLeft); return; } if (point.x < textBounds.x) { point.x = textBounds.x; } else if (point.x > textBounds.x + textBounds.width) { point.x = textBounds.x + textBounds.width; } if (point.y < textBounds.y) { point.y = textBounds.y; } else if (point.y > textBounds.y + textBounds.height) { Font* font = getFont(state); GP_ASSERT(font); unsigned int fontSize = getFontSize(state); point.y = textBounds.y + textBounds.height - fontSize; } index = font->getIndexAtLocation(displayedText.c_str(), _textBounds, fontSize, point, &point, textAlignment, true, rightToLeft); } if (index != -1) _caretLocation = index; }
void TextBox::setCaretLocation(int x, int y) { // Get index into string and cursor location from the latest touch location. _prevCaretLocation.set(_caretLocation); _caretLocation.set(x + _absoluteBounds.x, y + _absoluteBounds.y); Font* font = getFont(_state); unsigned int fontSize = getFontSize(_state); Font::Justify textAlignment = getTextAlignment(_state); bool rightToLeft = getTextRightToLeft(_state); int index = font->getIndexAtLocation(_text.c_str(), _textBounds, fontSize, _caretLocation, &_caretLocation, textAlignment, true, rightToLeft); if (index == -1) { _caretLocation.set(_prevCaretLocation); } }
bool TextBox::keyEvent(Keyboard::KeyEvent evt, int key) { if (_state == FOCUS) { switch (evt) { case Keyboard::KEY_PRESS: { switch (key) { case Keyboard::KEY_HOME: { // TODO: Move cursor to beginning of line. // This only works for left alignment... //_caretLocation.x = _viewportClipBounds.x; //_dirty = true; break; } case Keyboard::KEY_END: { // TODO: Move cursor to end of line. break; } case Keyboard::KEY_DELETE: { Font* font = getFont(_state); GP_ASSERT(font); unsigned int fontSize = getFontSize(_state); Font::Justify textAlignment = getTextAlignment(_state); bool rightToLeft = getTextRightToLeft(_state); int textIndex = font->getIndexAtLocation(_text.c_str(), _textBounds, fontSize, _caretLocation, &_caretLocation, textAlignment, true, rightToLeft); _text.erase(textIndex, 1); font->getLocationAtIndex(_text.c_str(), _textBounds, fontSize, &_caretLocation, textIndex, textAlignment, true, rightToLeft); _dirty = true; notifyListeners(Listener::TEXT_CHANGED); break; } case Keyboard::KEY_LEFT_ARROW: { Font* font = getFont(_state); GP_ASSERT(font); unsigned int fontSize = getFontSize(_state); Font::Justify textAlignment = getTextAlignment(_state); bool rightToLeft = getTextRightToLeft(_state); int textIndex = font->getIndexAtLocation(_text.c_str(), _textBounds, fontSize, _caretLocation, &_caretLocation, textAlignment, true, rightToLeft); font->getLocationAtIndex(_text.c_str(), _textBounds, fontSize, &_caretLocation, textIndex - 1, textAlignment, true, rightToLeft); _dirty = true; break; } case Keyboard::KEY_RIGHT_ARROW: { Font* font = getFont(_state); GP_ASSERT(font); unsigned int fontSize = getFontSize(_state); Font::Justify textAlignment = getTextAlignment(_state); bool rightToLeft = getTextRightToLeft(_state); int textIndex = font->getIndexAtLocation(_text.c_str(), _textBounds, fontSize, _caretLocation, &_caretLocation, textAlignment, true, rightToLeft); font->getLocationAtIndex(_text.c_str(), _textBounds, fontSize, &_caretLocation, textIndex + 1, textAlignment, true, rightToLeft); _dirty = true; break; } case Keyboard::KEY_UP_ARROW: { Font* font = getFont(_state); GP_ASSERT(font); unsigned int fontSize = getFontSize(_state); Font::Justify textAlignment = getTextAlignment(_state); bool rightToLeft = getTextRightToLeft(_state); _prevCaretLocation.set(_caretLocation); _caretLocation.y -= fontSize; int textIndex = font->getIndexAtLocation(_text.c_str(), _textBounds, fontSize, _caretLocation, &_caretLocation, textAlignment, true, rightToLeft); if (textIndex == -1) { _caretLocation.set(_prevCaretLocation); } _dirty = true; break; } case Keyboard::KEY_DOWN_ARROW: { Font* font = getFont(_state); GP_ASSERT(font); unsigned int fontSize = getFontSize(_state); Font::Justify textAlignment = getTextAlignment(_state); bool rightToLeft = getTextRightToLeft(_state); _prevCaretLocation.set(_caretLocation); _caretLocation.y += fontSize; int textIndex = font->getIndexAtLocation(_text.c_str(), _textBounds, fontSize, _caretLocation, &_caretLocation, textAlignment, true, rightToLeft); if (textIndex == -1) { _caretLocation.set(_prevCaretLocation); } _dirty = true; break; } } break; } case Keyboard::KEY_CHAR: { Font* font = getFont(_state); GP_ASSERT(font); unsigned int fontSize = getFontSize(_state); Font::Justify textAlignment = getTextAlignment(_state); bool rightToLeft = getTextRightToLeft(_state); int textIndex = font->getIndexAtLocation(_text.c_str(), _textBounds, fontSize, _caretLocation, &_caretLocation, textAlignment, true, rightToLeft); if (textIndex == -1) { textIndex = 0; font->getLocationAtIndex(_text.c_str(), _textBounds, fontSize, &_caretLocation, 0, textAlignment, true, rightToLeft); } switch (key) { case Keyboard::KEY_BACKSPACE: { if (textIndex > 0) { --textIndex; _text.erase(textIndex, 1); font->getLocationAtIndex(_text.c_str(), _textBounds, fontSize, &_caretLocation, textIndex, textAlignment, true, rightToLeft); _dirty = true; } break; } case Keyboard::KEY_RETURN: // TODO: Handle line-break insertion correctly. break; case Keyboard::KEY_ESCAPE: break; case Keyboard::KEY_TAB: break; default: { // Insert character into string. _text.insert(textIndex, 1, (char)key); // Get new location of caret. font->getLocationAtIndex(_text.c_str(), _textBounds, fontSize, &_caretLocation, textIndex + 1, textAlignment, true, rightToLeft); if (key == ' ') { // If a space was entered, check that caret is still within bounds. if (_caretLocation.x >= _textBounds.x + _textBounds.width || _caretLocation.y >= _textBounds.y + _textBounds.height) { // If not, undo the character insertion. _text.erase(textIndex, 1); font->getLocationAtIndex(_text.c_str(), _textBounds, fontSize, &_caretLocation, textIndex, textAlignment, true, rightToLeft); // No need to check again. break; } } // Always check that the text still fits within the clip region. Rectangle textBounds; font->measureText(_text.c_str(), _textBounds, fontSize, &textBounds, textAlignment, true, true); if (textBounds.x <= _textBounds.x || textBounds.y <= _textBounds.y || textBounds.width >= _textBounds.width || textBounds.height >= _textBounds.height) { // If not, undo the character insertion. _text.erase(textIndex, 1); font->getLocationAtIndex(_text.c_str(), _textBounds, fontSize, &_caretLocation, textIndex, textAlignment, true, rightToLeft); // TextBox is not dirty. break; } _dirty = true; break; } break; } notifyListeners(Listener::TEXT_CHANGED); break; } } } _lastKeypress = key; return _consumeInputEvents; }
void TextBox::getCaretLocation(Vector2* p) { GP_ASSERT(p); State state = getState(); getFont(state)->getLocationAtIndex(getDisplayedText().c_str(), _textBounds, getFontSize(state), p, _caretLocation, getTextAlignment(state), true, getTextRightToLeft(state)); }
unsigned int TextBox::drawText(Form* form, const Rectangle& clip) { if (_text.size() <= 0) return 0; // Draw the text. if (_font) { Control::State state = getState(); const std::string displayedText = getDisplayedText(); unsigned int fontSize = getFontSize(state); SpriteBatch* batch = _font->getSpriteBatch(fontSize); startBatch(form, batch); _font->drawText(displayedText.c_str(), _textBounds, _textColor, fontSize, getTextAlignment(state), true, getTextRightToLeft(state), _viewportClipBounds); finishBatch(form, batch); return 1; } return 0; }
void Slider::drawText(const Rectangle& clip) { Label::drawText(clip); if (_valueTextVisible && _font) { _font->start(); _font->drawText(_valueText.c_str(), _textBounds, _textColor, getFontSize(_state), _valueTextAlignment, true, getTextRightToLeft(_state), &_viewportClipBounds); _font->finish(); } }
unsigned int Slider::drawText(Form* form, const Rectangle& clip) { unsigned int drawCalls = Label::drawText(form, clip); if (_valueTextVisible && _font) { Control::State state = getState(); unsigned int fontSize = getFontSize(state); SpriteBatch* batch = _font->getSpriteBatch(fontSize); startBatch(form, batch); _font->drawText(_valueText.c_str(), _textBounds, _textColor, fontSize, _valueTextAlignment, true, getTextRightToLeft(state), _viewportClipBounds); finishBatch(form, batch); ++drawCalls; } return drawCalls; }