/************************************************************************* Processing to move carat down a line. *************************************************************************/ void MultiLineEditbox::handleLineDown(uint sysKeys) { size_t caratLine = getLineNumberFromIndex(d_caratPos); if ((d_lines.size() > 1) && (caratLine < (d_lines.size() - 1))) { float caratPixelOffset = getFont()->getTextExtent(d_text.substr(d_lines[caratLine].d_startIdx, d_caratPos - d_lines[caratLine].d_startIdx)); ++caratLine; size_t newLineIndex = getFont()->getCharAtPixel(d_text.substr(d_lines[caratLine].d_startIdx, d_lines[caratLine].d_length), caratPixelOffset); setCaratIndex(d_lines[caratLine].d_startIdx + newLineIndex); } if (sysKeys & Shift) { setSelection(d_caratPos, d_dragAnchorIdx); } else { clearSelection(); } }
/************************************************************************* Processing to move carat to the end of the current line *************************************************************************/ void MultiLineEditbox::handleLineEnd(uint sysKeys) { size_t line = getLineNumberFromIndex(d_caratPos); if (line < d_lines.size()) { size_t lineEndIdx = d_lines[line].d_startIdx + d_lines[line].d_length - 1; if (d_caratPos < lineEndIdx) { setCaratIndex(lineEndIdx); } if (sysKeys & Shift) { setSelection(d_caratPos, d_dragAnchorIdx); } else { clearSelection(); } } }
/************************************************************************* Handler for when mouse moves in the window. *************************************************************************/ void MultiLineEditbox::onMouseMove(MouseEventArgs& e) { // base class processing Window::onMouseMove(e); if (d_dragging) { setCaratIndex(getTextIndexFromPosition(e.position)); setSelection(d_caratPos, d_dragAnchorIdx); } e.handled = true; }
/************************************************************************* Processing to move carat one character right *************************************************************************/ void MultiLineEditbox::handleCharRight(uint sysKeys) { if (d_caratPos < d_text.length() - 1) { setCaratIndex(d_caratPos + 1); } if (sysKeys & Shift) { setSelection(d_caratPos, d_dragAnchorIdx); } else { clearSelection(); } }
/************************************************************************* Processing to move carat one word left *************************************************************************/ void MultiLineEditbox::handleWordLeft(uint sysKeys) { if (d_caratPos > 0) { setCaratIndex(TextUtils::getWordStartIdx(d_text, getCaratIndex())); } if (sysKeys & Shift) { setSelection(d_caratPos, d_dragAnchorIdx); } else { clearSelection(); } }
/************************************************************************* Processing to move carat one character left *************************************************************************/ void MultiLineEditbox::handleCharLeft(uint sysKeys) { if (d_caratPos > 0) { setCaratIndex(d_caratPos - 1); } if (sysKeys & Shift) { setSelection(d_caratPos, d_dragAnchorIdx); } else { clearSelection(); } }
/************************************************************************* Processing to move carat to the start of the text. *************************************************************************/ void MultiLineEditbox::handleDocHome(UINT sysKeys) { if (d_caratPos > 0) { setCaratIndex(0); } if (sysKeys & Shift) { setSelection(d_caratPos, d_dragAnchorIdx); } else { clearSelection(); } }
/************************************************************************* Processing to move carat one word right *************************************************************************/ void MultiLineEditbox::handleWordRight(UINT sysKeys) { if (d_caratPos < d_text.length() - 1) { setCaratIndex(TextUtils::getNextWordStartIdx(d_text, getCaratIndex())); } if (sysKeys & Shift) { setSelection(d_caratPos, d_dragAnchorIdx); } else { clearSelection(); } }
/************************************************************************* 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); } } }
/************************************************************************* 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(); } }
/************************************************************************* Handler for when a mouse button is pushed *************************************************************************/ void MultiLineEditbox::onMouseButtonDown(MouseEventArgs& e) { // base class handling Window::onMouseButtonDown(e); if (e.button == LeftButton) { // grab inputs if (captureInput()) { // handle mouse down clearSelection(); d_dragging = true; d_dragAnchorIdx = getTextIndexFromPosition(e.position); setCaratIndex(d_dragAnchorIdx); } e.handled = true; } }
/************************************************************************* Handler for when mouse button is triple-clicked. *************************************************************************/ void MultiLineEditbox::onMouseTripleClicked(MouseEventArgs& e) { // base class processing Window::onMouseTripleClicked(e); if (e.button == LeftButton) { size_t caratLine = getLineNumberFromIndex(d_caratPos); size_t lineStart = d_lines[caratLine].d_startIdx; // find end of last paragraph String::size_type paraStart = d_text.find_last_of(d_lineBreakChars, lineStart); // if no previous paragraph, selection will start at the beginning. if (paraStart == String::npos) { paraStart = 0; } // find end of this paragraph String::size_type paraEnd = d_text.find_first_of(d_lineBreakChars, lineStart); // if paragraph has no end, which actually should never happen, fix the // erroneous situation and select up to end at end of text. if (paraEnd == String::npos) { d_text.append(1, '\n'); paraEnd = d_text.length() - 1; } // set up selection using new values. d_dragAnchorIdx = paraStart; setCaratIndex(paraEnd); setSelection(d_dragAnchorIdx, d_caratPos); e.handled = true; } }
/************************************************************************* Handler for when text is programmatically changed. *************************************************************************/ void MultiLineEditbox::onTextChanged(WindowEventArgs& e) { // ensure last character is a new line if ((d_text.length() == 0) || (d_text[d_text.length() - 1] != '\n')) d_text.append(1, '\n'); // base class processing Window::onTextChanged(e); // clear selection clearSelection(); // layout new text formatText(); // layout child windows (scrollbars) since text layout may have changed performChildWindowLayout(); // ensure carat is still within the text setCaratIndex(getCaratIndex()); // ensure carat is visible // NB: this will already have been called at least once, but since we // may have changed the formatting of the text, it needs to be called again. ensureCaratIsVisible(); e.handled = true; }