//----------------------------------------------------------------------------// void Editbox::handleDelete(void) { if (!isReadOnly()) { String tmp(getText()); if (getSelectionLength() != 0) { tmp.erase(getSelectionStartIndex(), getSelectionLength()); if (handleValidityChangeForString(tmp)) { // erase selection using mode that does not modify getText() // (we just want to update state) eraseSelectedText(false); // set text to the newly modified string setText(tmp); } } else if (getCaretIndex() < tmp.length()) { tmp.erase(d_caretPos, 1); if (handleValidityChangeForString(tmp)) { // set text to the newly modified string setText(tmp); } } } }
void Editbox::eraseSelectedText(bool modify_text) { if (getSelectionLength() != 0) { // setup new caret position and remove selection highlight. setCaretIndex(d_selectionStart); clearSelection(); // erase the selected characters (if required) if (modify_text) { String newText = getText(); UndoHandler::UndoAction undo; undo.d_type = UndoHandler::UAT_DELETE; undo.d_startIdx = getSelectionStart(); undo.d_text = newText.substr(getSelectionStart(), getSelectionLength()); d_undoHandler->addUndoHistory(undo); newText.erase(getSelectionStart(), getSelectionLength()); setText(newText); // trigger notification that text has changed. WindowEventArgs args(this); onTextChanged(args); } } }
//----------------------------------------------------------------------------// bool Editbox::performCopy(Clipboard& clipboard) { if (getSelectionLength() == 0) return false; const String selectedText = getText().substr( getSelectionStartIndex(), getSelectionLength()); clipboard.setText(selectedText); return true; }
void Editbox::handleDelete(void) { if (!isReadOnly()) { String tmp(getText()); if (getSelectionLength() != 0) { UndoHandler::UndoAction undoSelection; undoSelection.d_type = UndoHandler::UAT_DELETE; undoSelection.d_startIdx = getSelectionStart(); undoSelection.d_text = tmp.substr(getSelectionStart(), getSelectionLength()); tmp.erase(getSelectionStart(), getSelectionLength()); if (handleValidityChangeForString(tmp)) { // erase selection using mode that does not modify getText() // (we just want to update state) eraseSelectedText(false); // set text to the newly modified string setText(tmp); d_undoHandler->addUndoHistory(undoSelection); } } else if (getCaretIndex() < tmp.length()) { UndoHandler::UndoAction undo; undo.d_type = UndoHandler::UAT_DELETE; undo.d_startIdx = d_caretPos; #if CEGUI_STRING_CLASS != CEGUI_STRING_CLASS_UTF_8 size_t eraseLength = 1; #else size_t eraseLength = String::getCodePointSize(tmp[d_caretPos]); #endif undo.d_text = tmp.substr(d_caretPos, eraseLength); tmp.erase(d_caretPos, eraseLength); if (handleValidityChangeForString(tmp)) { // set text to the newly modified string setText(tmp); d_undoHandler->addUndoHistory(undo); } } } }
bool Editbox::performPaste(Clipboard& clipboard) { if (isReadOnly()) return false; String clipboardText = clipboard.getText(); if (clipboardText.empty()) return false; // backup current text String tmp(getText()); UndoHandler::UndoAction undoSelection; undoSelection.d_type = UndoHandler::UAT_DELETE; undoSelection.d_startIdx = getSelectionStart(); undoSelection.d_text = tmp.substr(getSelectionStart(), getSelectionLength()); tmp.erase(getSelectionStart(), getSelectionLength()); // if there is room if (tmp.length() < d_maxTextLen) { UndoHandler::UndoAction undo; undo.d_type = UndoHandler::UAT_INSERT; undo.d_startIdx = getCaretIndex(); undo.d_text = clipboardText; tmp.insert(getSelectionStart(), clipboardText); if (handleValidityChangeForString(tmp)) { // erase selection using mode that does not modify getText() // (we just want to update state) eraseSelectedText(false); // advance caret (done first so we can "do stuff" in event // handlers!) d_caretPos += clipboardText.length(); // set text to the newly modified string setText(tmp); d_undoHandler->addUndoHistory(undo); if (getSelectionLength() > 0) d_undoHandler->addUndoHistory(undoSelection); return true; } } return false; }
void TextField::copy() { if(getSelectionLength() > 0) { Clipboard::copy(getSelectedText()); } }
/************************************************************************* Clear the current selection setting *************************************************************************/ void MultiLineEditbox::clearSelection(void) { // perform action only if required. if (getSelectionLength() != 0) { setSelection(0, 0); } }
/************************************************************************* Erase the currently selected text. *************************************************************************/ void MultiLineEditbox::eraseSelectedText(bool modify_text) { if (getSelectionLength() != 0) { // setup new carat position and remove selection highlight. setCaratIndex(getSelectionStartIndex()); // erase the selected characters (if required) if (modify_text) { d_text.erase(getSelectionStartIndex(), getSelectionLength()); // trigger notification that text has changed. WindowEventArgs args(this); onTextChanged(args); } clearSelection(); } }
const std::string TextField::getSelectedText() const { if(getSelectionStart() == getSelectionEnd()) { return std::string(""); } else { return unicodeFunctions.subStr(getText(), getSelectionStart(),getSelectionLength()); } }
//----------------------------------------------------------------------------// void Editbox::onCharacter(KeyEventArgs& e) { // NB: We are not calling the base class handler here because it propogates // inputs back up the window hierarchy, whereas, as a consumer of key // events, we want such propogation to cease with us regardless of whether // we actually handle the event. // fire event. fireEvent(EventCharacterKey, e, Window::EventNamespace); // only need to take notice if we have focus if (e.handled == 0 && hasInputFocus() && !isReadOnly() && getFont()->isCodepointAvailable(e.codepoint)) { // backup current text String tmp(getText()); tmp.erase(getSelectionStartIndex(), getSelectionLength()); // if there is room if (tmp.length() < d_maxTextLen) { tmp.insert(getSelectionStartIndex(), 1, e.codepoint); if (handleValidityChangeForString(tmp)) { // erase selection using mode that does not modify getText() // (we just want to update state) eraseSelectedText(false); // advance caret (done first so we can "do stuff" in event // handlers!) d_caretPos++; // set text to the newly modified string setText(tmp); // char was accepted into the Editbox - mark event as handled. ++e.handled; } } else { // Trigger text box full event WindowEventArgs args(this); onEditboxFullEvent(args); } } // event was (possibly) not handled }
/************************************************************************* Processing for backspace key *************************************************************************/ void MultiLineEditbox::handleBackspace(void) { if (!isReadOnly()) { if (getSelectionLength() != 0) { eraseSelectedText(); } else if (d_caratPos > 0) { d_text.erase(d_caratPos - 1, 1); setCaratIndex(d_caratPos - 1); WindowEventArgs args(this); onTextChanged(args); } } }
void TextField::paste() { if(isReadOnly()) { return; } std::string pasteResult = Clipboard::paste(); if(pasteResult.length() == 0 || getTextLength() - getSelectionLength() == getMaxLength()) { return; } deleteSelection(); int start = getCaretPosition(); std::string noNewLine; for(size_t i = 0; i < pasteResult.size(); ++i) { if(pasteResult[i] != '\n') { noNewLine += pasteResult[i]; } } int length = int(unicodeFunctions.length(noNewLine)); int numRemainingChar = getMaxLength() - getTextLength(); if(numRemainingChar < length) { noNewLine = unicodeFunctions.subStr(noNewLine,0,numRemainingChar); length = numRemainingChar; } if(length > 0) { std::string* cText = (std::string*)&getText(); unicodeFunctions.insert(*cText,start,noNewLine); setThisText(*cText); positionCaret(caretPosition + length); } }
/************************************************************************* Processing for Delete key *************************************************************************/ void MultiLineEditbox::handleDelete(void) { if (!isReadOnly()) { if (getSelectionLength() != 0) { eraseSelectedText(); } else if (getCaratIndex() < d_text.length() - 1) { d_text.erase(d_caratPos, 1); ensureCaratIsVisible(); WindowEventArgs args(this); onTextChanged(args); } } }
void TextField::appendText( const std::string& text, bool atCurrentPosition /*= true*/ ) { if(text.length() == 0 || getTextLength() - getSelectionLength() == getMaxLength()) { return; } deleteSelection(); if(!atCurrentPosition) { positionCaret(getTextLength()); } int start = getCaretPosition(); std::string noNewLine; for(size_t i = 0; i < text.size(); ++i) { if(text[i] != '\n') { noNewLine += text[i]; } } int length = int(unicodeFunctions.length(noNewLine)); int numRemainingChar = getMaxLength() - getTextLength(); if(numRemainingChar < length) { noNewLine = unicodeFunctions.subStr(noNewLine,0,numRemainingChar); length = numRemainingChar; } if(length > 0) { std::string* cText = (std::string*)&getText(); unicodeFunctions.insert(*cText,start,noNewLine); setThisText(*cText); positionCaret(caretPosition + length); } }
//----------------------------------------------------------------------------// bool Editbox::performPaste(Clipboard& clipboard) { if (isReadOnly()) return false; String clipboardText = clipboard.getText(); if (clipboardText.empty()) return false; // backup current text String tmp(getText()); tmp.erase(getSelectionStartIndex(), getSelectionLength()); // if there is room if (tmp.length() < d_maxTextLen) { tmp.insert(getSelectionStartIndex(), clipboardText); if (handleValidityChangeForString(tmp)) { // erase selection using mode that does not modify getText() // (we just want to update state) eraseSelectedText(false); // advance caret (done first so we can "do stuff" in event // handlers!) d_caretPos += clipboardText.length(); // set text to the newly modified string setText(tmp); return true; } } return false; }
void FalagardEditbox::populateRenderCache() { const StateImagery* imagery; // draw container etc // get WidgetLookFeel for the assigned look. const WidgetLookFeel& wlf = WidgetLookManager::getSingleton().getWidgetLook(d_lookName); // try and get imagery for the approprite state. imagery = &wlf.getStateImagery(isDisabled() ? "Disabled" : (isReadOnly() ? "ReadOnly" : "Enabled")); // peform the rendering operation for the container. imagery->render(*this); // get destination area for text const Rect textArea(wlf.getNamedArea("TextArea").getArea().getPixelRect(*this)); // // Required preliminary work for text rendering operations // const Font* font = getFont(); // no font == no more rendering if (!font) return; // This will point to the final string to be used for rendering. Useful because it means we // do not have to have duplicate code or be copying d_text for handling masked/unmasked text. String* editText; // Create a 'masked' version of the string if needed. String maskedText; if (isTextMasked()) { maskedText.insert(0, d_text.length(), getMaskCodePoint()); editText = &maskedText; } // text not masked to editText will be the windows d_text String. else { editText = &d_text; } // calculate best position to render text to ensure carat is always visible float textOffset; float extentToCarat = font->getTextExtent(editText->substr(0, getCaratIndex())); // get carat imagery const ImagerySection& caratImagery = wlf.getImagerySection("Carat"); // store carat width float caratWidth = caratImagery.getBoundingRect(*this, textArea).getWidth(); // if box is inactive if (!hasInputFocus()) { textOffset = d_lastTextOffset; } // if carat is to the left of the box else if ((d_lastTextOffset + extentToCarat) < 0) { textOffset = -extentToCarat; } // if carat is off to the right. else if ((d_lastTextOffset + extentToCarat) >= (textArea.getWidth() - caratWidth)) { textOffset = textArea.getWidth() - extentToCarat - caratWidth; } // else carat is already within the box else { textOffset = d_lastTextOffset; } ColourRect colours; float alpha_comp = getEffectiveAlpha(); // // Draw label text // // setup initial rect for text formatting Rect text_part_rect(textArea); // allow for scroll position text_part_rect.d_left += textOffset; // centre text vertically within the defined text area text_part_rect.d_top += (textArea.getHeight() - font->getLineSpacing()) * 0.5f; // draw pre-highlight text String sect = editText->substr(0, getSelectionStartIndex()); colours.setColours(d_normalTextColour); colours.modulateAlpha(alpha_comp); d_renderCache.cacheText(sect, font, LeftAligned, text_part_rect, 0, colours, &textArea); // adjust rect for next section text_part_rect.d_left += font->getTextExtent(sect); // draw highlight text sect = editText->substr(getSelectionStartIndex(), getSelectionLength()); colours.setColours(d_selectTextColour); colours.modulateAlpha(alpha_comp); d_renderCache.cacheText(sect, font, LeftAligned, text_part_rect, 0, colours, &textArea); // adjust rect for next section text_part_rect.d_left += font->getTextExtent(sect); // draw post-highlight text sect = editText->substr(getSelectionEndIndex()); colours.setColours(d_normalTextColour); colours.modulateAlpha(alpha_comp); d_renderCache.cacheText(sect, font, LeftAligned, text_part_rect, 0, colours, &textArea); // remember this for next time. d_lastTextOffset = textOffset; // see if the editbox is active or inactive. bool active = (!isReadOnly()) && hasInputFocus(); // // Render selection imagery. // if (getSelectionLength() != 0) { // calculate required start and end offsets of selection imagery. float selStartOffset = font->getTextExtent(editText->substr(0, getSelectionStartIndex())); float selEndOffset = font->getTextExtent(editText->substr(0, getSelectionEndIndex())); // calculate area for selection imagery. Rect hlarea(textArea); hlarea.d_left += textOffset + selStartOffset; hlarea.d_right = hlarea.d_left + (selEndOffset - selStartOffset); // render the selection imagery. wlf.getStateImagery(active ? "ActiveSelection" : "InactiveSelection").render(*this, hlarea, 0, &textArea); } // // Render carat // if (active) { Rect caratRect(textArea); caratRect.d_left += extentToCarat + textOffset; caratImagery.render(*this, caratRect, 0, 0, &textArea); } }
void Editbox::handleBackspace(void) { if (!isReadOnly()) { String tmp(getText()); if (getSelectionLength() != 0) { UndoHandler::UndoAction undoSelection; undoSelection.d_type = UndoHandler::UAT_DELETE; undoSelection.d_startIdx = getSelectionStart(); undoSelection.d_text = tmp.substr(getSelectionStart(), getSelectionLength()); tmp.erase(getSelectionStart(), getSelectionLength()); if (handleValidityChangeForString(tmp)) { // erase selection using mode that does not modify getText() // (we just want to update state) eraseSelectedText(false); // set text to the newly modified string setText(tmp); d_undoHandler->addUndoHistory(undoSelection); } } else if (getCaretIndex() > 0) { UndoHandler::UndoAction undo; undo.d_type = UndoHandler::UAT_DELETE; #if CEGUI_STRING_CLASS != CEGUI_STRING_CLASS_UTF_8 size_t deleteStartPos = d_caretPos - 1; size_t deleteLength = 1; #else String::codepoint_iterator caretIter(tmp.begin() + d_caretPos, tmp.begin(), tmp.end()); --caretIter; size_t deleteStartPos = caretIter.getCodeUnitIndexFromStart(); size_t deleteLength = d_caretPos - deleteStartPos; #endif undo.d_startIdx = deleteStartPos; undo.d_text = tmp.substr(deleteStartPos, deleteLength); tmp.erase(deleteStartPos, deleteLength); if (handleValidityChangeForString(tmp)) { setCaretIndex(deleteStartPos); // set text to the newly modified string setText(tmp); d_undoHandler->addUndoHistory(undo); } } } }
//----------------------------------------------------------------------------// void Editbox::onKeyDown(KeyEventArgs& e) { // fire event. fireEvent(EventKeyDown, e, Window::EventNamespace); if (e.handled == 0 && hasInputFocus()) { if (isReadOnly()) { Window::onKeyDown(e); return; } WindowEventArgs args(this); switch (e.scancode) { case Key::LeftShift: case Key::RightShift: if (getSelectionLength() == 0) d_dragAnchorIdx = d_caretPos; break; case Key::Backspace: handleBackspace(); break; case Key::Delete: handleDelete(); break; case Key::Tab: case Key::Return: case Key::NumpadEnter: // Fire 'input accepted' event onTextAcceptedEvent(args); break; case Key::ArrowLeft: if (e.sysKeys & Control) handleWordLeft(e.sysKeys); else handleCharLeft(e.sysKeys); break; case Key::ArrowRight: if (e.sysKeys & Control) handleWordRight(e.sysKeys); else handleCharRight(e.sysKeys); break; case Key::Home: handleHome(e.sysKeys); break; case Key::End: handleEnd(e.sysKeys); break; default: Window::onKeyDown(e); return; } ++e.handled; } }
void Editbox::onSemanticInputEvent(SemanticEventArgs& e) { if (isDisabled()) return; if (e.d_semanticValue == SV_SelectAll && e.d_payload.source == CIS_Left) { d_dragAnchorIdx = 0; setCaretIndex(getText().length()); setSelection(d_dragAnchorIdx, d_caretPos); ++e.handled; } else if (e.d_semanticValue == SV_SelectWord && e.d_payload.source == CIS_Left) { // if masked, set up to select all if (isTextMaskingEnabled()) { d_dragAnchorIdx = 0; setCaretIndex(getText().length()); } // not masked, so select the word that was double-clicked. else { d_dragAnchorIdx = TextUtils::getWordStartIdx(getText(), (d_caretPos == getText().length()) ? d_caretPos : d_caretPos + 1); d_caretPos = TextUtils::getNextWordStartIdx(getText(), d_caretPos); } // perform actual selection operation. setSelection(d_dragAnchorIdx, d_caretPos); ++e.handled; } if (e.handled == 0 && hasInputFocus()) { if (isReadOnly()) { Window::onSemanticInputEvent(e); return; } if (getSelectionLength() == 0 && isSelectionSemanticValue(e.d_semanticValue)) d_dragAnchorIdx = d_caretPos; // Check if the semantic value to be handled is of a general type and can thus be // handled via common EditboxBase handlers bool isSemanticValueHandled = handleBasicSemanticValue(e); // If the semantic value was not handled, check for specific values if (!isSemanticValueHandled) { // We assume it will be handled now, if not it will be set to false in default-case isSemanticValueHandled = true; switch (e.d_semanticValue) { case SV_Confirm: { WindowEventArgs args(this); // Fire 'input accepted' event onTextAcceptedEvent(args); break; } case SV_GoToStartOfLine: handleHome(false); break; case SV_GoToEndOfLine: handleEnd(false); break; case SV_SelectToStartOfLine: handleHome(true); break; case SV_SelectToEndOfLine: handleEnd(true); break; default: Window::onSemanticInputEvent(e); isSemanticValueHandled = false; } } if (isSemanticValueHandled) ++e.handled; } }
/************************************************************************* Handler for when non-printable keys are typed. *************************************************************************/ void MultiLineEditbox::onKeyDown(KeyEventArgs& e) { // base class processing Window::onKeyDown(e); if (hasInputFocus() && !isReadOnly()) { WindowEventArgs args(this); switch (e.scancode) { case Key::LeftShift: case Key::RightShift: if (getSelectionLength() == 0) { d_dragAnchorIdx = getCaratIndex(); } break; case Key::Backspace: handleBackspace(); break; case Key::Delete: handleDelete(); break; case Key::Return: case Key::NumpadEnter: handleNewLine(e.sysKeys); break; case Key::ArrowLeft: if (e.sysKeys & Control) { handleWordLeft(e.sysKeys); } else { handleCharLeft(e.sysKeys); } break; case Key::ArrowRight: if (e.sysKeys & Control) { handleWordRight(e.sysKeys); } else { handleCharRight(e.sysKeys); } break; case Key::ArrowUp: handleLineUp(e.sysKeys); break; case Key::ArrowDown: handleLineDown(e.sysKeys); break; case Key::Home: if (e.sysKeys & Control) { handleDocHome(e.sysKeys); } else { handleLineHome(e.sysKeys); } break; case Key::End: if (e.sysKeys & Control) { handleDocEnd(e.sysKeys); } else { handleLineEnd(e.sysKeys); } break; // default case is now to leave event as (possibly) unhandled. default: return; } e.handled = true; } }