/************************************************************************* 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(); } } }
/************************************************************************* 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(); } }
/************************************************************************* Scroll the view so that the current carat position is visible. *************************************************************************/ void MultiLineEditbox::ensureCaratIsVisible(void) { // calculate the location of the carat const FontBase* fnt = getFont(); size_t caratLine = getLineNumberFromIndex(d_caratPos); if (caratLine < d_lines.size()) { Rect textArea(getTextRenderArea()); size_t caratLineIdx = d_caratPos - d_lines[caratLine].d_startIdx; float ypos = caratLine * fnt->getLineSpacing(); float xpos = fnt->getTextExtent(d_text.substr(d_lines[caratLine].d_startIdx, caratLineIdx)); // adjust position for scroll bars if( d_horzScrollbar ) xpos -= d_horzScrollbar->getScrollPosition(); if( d_vertScrollbar ) ypos -= d_vertScrollbar->getScrollPosition(); // if carat is above window, scroll up if (ypos < 0) { if( d_vertScrollbar ) d_vertScrollbar->setScrollPosition(d_vertScrollbar->getScrollPosition() + ypos); } // if carat is below the window, scroll down else if ((ypos += fnt->getLineSpacing()) > textArea.getHeight()) { if( d_vertScrollbar ) d_vertScrollbar->setScrollPosition(d_vertScrollbar->getScrollPosition() + (ypos - textArea.getHeight()) + fnt->getLineSpacing()); } // if carat is left of the window, scroll left if (xpos < 0) { if( d_horzScrollbar ) d_horzScrollbar->setScrollPosition(d_horzScrollbar->getScrollPosition() + xpos - 50); } // if carat is right of the window, scroll right else if (xpos > textArea.getWidth()) { if( d_horzScrollbar ) d_horzScrollbar->setScrollPosition(d_horzScrollbar->getScrollPosition() + (xpos - textArea.getWidth()) + 50); } } }
void FalagardMultiLineEditbox::cacheCaratImagery(const Rect& textArea) { const FontBase* fnt = getFont(); // require a font so that we can calculate carat position. if ( fnt ) { // get line that carat is in size_t caratLine = getLineNumberFromIndex(d_caratPos); // if carat line is valid. if (caratLine < d_lines.size()) { // calculate pixel offsets to where carat should be drawn size_t caratLineIdx = d_caratPos - d_lines[caratLine].d_startIdx; float ypos = caratLine * fnt->getLineSpacing(); float xpos = fnt->getTextExtent(d_text.substr(d_lines[caratLine].d_startIdx, caratLineIdx)); // get base offset to target layer for cursor. Renderer* renderer = System::getSingleton().getRenderer(); float baseZ = renderer->getZLayer(7) - renderer->getCurrentZ(); // get WidgetLookFeel for the assigned look. const WidgetLookFeel& wlf = WidgetLookManager::getSingleton().getWidgetLook(d_lookName); // get carat imagery const ImagerySection& caratImagery = wlf.getImagerySection("Carat"); // calculate finat destination area for carat Rect caratArea; caratArea.d_left = textArea.d_left + xpos; caratArea.d_top = textArea.d_top + ypos; caratArea.setWidth(caratImagery.getBoundingRect(*this).getSize().d_width); caratArea.setHeight(fnt->getLineSpacing()); float fHPosition = 0; if( d_horzScrollbar ) fHPosition = d_horzScrollbar->getScrollPosition(); float fVPosition = 0; if( d_vertScrollbar ) fVPosition = d_vertScrollbar->getScrollPosition(); caratArea.offset( Point(-fHPosition, -fVPosition )); // adjust ime composition window. d_caratRect = caratArea; Ime::SetImeWindowPos(); // cache the carat image for rendering. caratImagery.render(*this, caratArea, baseZ, 0, &textArea); } } }
/************************************************************************* 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; } }