/************************************************************************* Recaculate all sub window size. *************************************************************************/ void FalagardChatHistory::performWindowLayout(void) { Rect absarea(getTextRenderArea()); std::list< FalagardChatBoard* >::iterator it; float fHeightNow = 0.0f; for(it=m_listChatBoard.begin(); it!=m_listChatBoard.end(); it++) { FalagardChatBoard& child = *(*it); if(child.getText().empty()) continue; float childHeight = child.resizeSelf(absarea.getWidth()); child.setSize(Absolute, Size(absarea.getWidth(), childHeight)); child.setPosition(Absolute, Point(0.0f, fHeightNow-d_vertScrollbar->getScrollPosition())); child.requestRedraw(); fHeightNow += childHeight; //char dbgmsg[128] = {0}; //_snprintf(dbgmsg, 127, "FalagardChatHistory performWindowLayout fHeightNow:%f ScrollPos:%f, child YPos:%f\n", // fHeightNow,d_vertScrollbar->getScrollPosition(),child.getAbsoluteYPosition()); //::OutputDebugString(dbgmsg); } d_totalHeight = fHeightNow + d_extendHeight; configureScrollbars(); }
void FalagardChatHistory::configureScrollbars() { // no scrollbars? Can't configure then! if(!d_vertScrollbar) return; Rect initialArea(getTextRenderArea()); // // Set up scroll bar values // Rect renderArea(getTextRenderArea()); d_vertScrollbar->setDocumentSize(d_totalHeight); d_vertScrollbar->setPageSize(renderArea.getHeight()); d_vertScrollbar->setStepSize(ceguimax(1.0f, renderArea.getHeight() / 10.0f)); d_vertScrollbar->setScrollPosition(d_vertScrollbar->getScrollPosition()); requestRedraw(); d_parentWindow->requestRedraw(); }
/************************************************************************* 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::render() { MultiLineEditbox* w = (MultiLineEditbox*)d_window; // render general frame and stuff before we handle the text itself cacheEditboxBaseImagery(); // Render edit box text Rectf textarea(getTextRenderArea()); cacheTextLines(textarea); // draw caret if ((w->hasInputFocus() && !w->isReadOnly()) && (!d_blinkCaret || d_showCaret)) cacheCaretImagery(textarea); }
/************************************************************************* Perform the actual rendering for this Window. *************************************************************************/ void MultiLineEditbox::populateRenderCache() { // get the derived class to render general stuff before we handle the text itself cacheEditboxBaseImagery(); // // Render edit box text // Rect textarea(getTextRenderArea()); cacheTextLines(textarea); if (hasInputFocus() && !isReadOnly()) { cacheCaratImagery(textarea); } }
/************************************************************************* Extend a Clear Region in history window. *************************************************************************/ void FalagardChatHistory::extendClearRegion() { if(m_listChatBoard.empty()) { d_extendHeight = 0.0f; return; } //scroll to end before extend scrollToEnd(); Rect absarea(getTextRenderArea()); d_extendHeight = absarea.getHeight(); performWindowLayout(); //set new scroll pos after extend d_vertScrollbar->setScrollPosition( d_vertScrollbar->getDocumentSize()-d_vertScrollbar->getPageSize()+d_extendHeight); }
/************************************************************************* Return the text code point index that is rendered closest to screen position 'pt'. *************************************************************************/ size_t MultiLineEditbox::getTextIndexFromPosition(const Point& pt) const { // // calculate final window position to be checked // Point wndPt = screenToWindow(pt); if (getMetricsMode() == Relative) { wndPt = relativeToAbsolute(wndPt); } Rect textArea(getTextRenderArea()); wndPt.d_x -= textArea.d_left; wndPt.d_y -= textArea.d_top; // factor in scroll bar values if( d_horzScrollbar ) wndPt.d_x += d_horzScrollbar->getScrollPosition(); if( d_vertScrollbar ) wndPt.d_y += d_vertScrollbar->getScrollPosition(); size_t lineNumber = static_cast<size_t>(wndPt.d_y / getFont()->getLineSpacing()); if (lineNumber >= d_lines.size()) { lineNumber = d_lines.size() - 1; } String lineText(d_text.substr(d_lines[lineNumber].d_startIdx, d_lines[lineNumber].d_length)); size_t lineIdx = getFont()->getCharAtPixel(lineText, wndPt.d_x); if (lineIdx >= lineText.length() - 1) { lineIdx = lineText.length() - 1; } return d_lines[lineNumber].d_startIdx + lineIdx; }
void CPFRotatingText::renderRotatingText() { Font* font = d_window->getFont(); // can't render text without a font :) if( font==NULL){ return; } // get destination area for the text. Rect absarea(getTextRenderArea()); Rect clipper(absarea); float textHeight = font->getFormattedLineCount(d_window->getText(), absarea, (TextFormatting)d_horzFormatting) * font->getLineSpacing(); Scrollbar* vertScrollbar = getVertScrollbar(); Scrollbar* horzScrollbar = getHorzScrollbar(); // calculate X offset static float xOffset = horzScrollbar->getPageSize(); if( xOffset<-(horzScrollbar->getDocumentSize()+horzScrollbar->getPageSize()) ){ xOffset = horzScrollbar->getPageSize(); } static boost::system_time previous_time = boost::get_system_time(); boost::system_time time = boost::get_system_time(); boost::system_time::time_duration_type time_step = (time-previous_time); xOffset -= (static_cast<float>(time_step.total_milliseconds())*d_textSpeed); previous_time = time; absarea.offset(Point(xOffset, 0)); // see if we may need to adjust horizontal position if( horzScrollbar->isVisible() ){ switch(d_horzFormatting) { case LeftAligned: case WordWrapLeftAligned: case Justified: case WordWrapJustified: absarea.offset(Point(-horzScrollbar->getScrollPosition(), 0)); break; case Centred: case WordWrapCentred: absarea.setWidth(horzScrollbar->getDocumentSize()); absarea.offset(Point(-horzScrollbar->getScrollPosition(), 0)); break; case RightAligned: case WordWrapRightAligned: absarea.offset(Point(horzScrollbar->getScrollPosition(), 0)); break; } } // adjust y positioning according to formatting option switch(d_vertFormatting) { case TopAligned: absarea.d_top -= vertScrollbar->getScrollPosition(); break; case VertCentred: // if scroll bar is in use, act like TopAligned if( vertScrollbar->isVisible() ){ absarea.d_top -= vertScrollbar->getScrollPosition(); } // no scroll bar, so centre text instead. else{ absarea.d_top += PixelAligned((absarea.getHeight() - textHeight) * 0.5f); } break; case BottomAligned: absarea.d_top = absarea.d_bottom - textHeight; absarea.d_top += vertScrollbar->getScrollPosition(); break; } // offset the font little down so that it's centered within its own spacing absarea.d_top += (font->getLineSpacing() - font->getFontHeight()) * 0.5f; // calculate final colours ColourRect final_cols(d_textCols); final_cols.modulateAlpha(d_window->getEffectiveAlpha()); // cache the text for rendering. d_window->getRenderCache().cacheText(d_window->getText(), font, (TextFormatting)d_horzFormatting, absarea, 0, final_cols, &clipper); }
/************************************************************************* Format the text into lines as needed by the current formatting options. *************************************************************************/ void MultiLineEditbox::formatText(void) { // clear old formatting data d_lines.clear(); d_widestExtent = 0.0f; String paraText; const Font* fnt = getFont(); if (fnt != NULL) { float areaWidth = getTextRenderArea().getWidth(); String::size_type currPos = 0; String::size_type paraLen; LineInfo line; while (currPos < d_text.length()) { if ((paraLen = d_text.find_first_of(d_lineBreakChars, currPos)) == String::npos) { paraLen = d_text.length() - currPos; } else { ++paraLen -= currPos; } paraText = d_text.substr(currPos, paraLen); if (!d_wordWrap || (areaWidth <= 0.0f)) { // no word wrapping, so we are just one long line. line.d_startIdx = currPos; line.d_length = paraLen; line.d_extent = fnt->getTextExtent(paraText); d_lines.push_back(line); // update widest, if needed. if (line.d_extent > d_widestExtent) { d_widestExtent = line.d_extent; } } // must word-wrap the paragraph text else { String::size_type lineIndex = 0; // while there is text in the string while (lineIndex < paraLen) { String::size_type lineLen = 0; float lineExtent = 0.0f; // loop while we have not reached the end of the paragraph string while (lineLen < (paraLen - lineIndex)) { // get cp / char count of next token size_t nextTokenSize = getNextTokenLength(paraText, lineIndex + lineLen); // get pixel width of the token float tokenExtent = fnt->getTextExtent(paraText.substr(lineIndex + lineLen, nextTokenSize)); // would adding this token would overflow the available width if ((lineExtent + tokenExtent) > areaWidth) { // Was this the first token? if (lineLen == 0) { // get point at which to break the token lineLen = fnt->getCharAtPixel(paraText.substr(lineIndex, nextTokenSize), areaWidth); } // text wraps, exit loop early with line info up until wrap point break; } // add this token to current line lineLen += nextTokenSize; lineExtent += tokenExtent; } // set up line info and add to collection line.d_startIdx = currPos + lineIndex; line.d_length = lineLen; line.d_extent = lineExtent; d_lines.push_back(line); // update widest, if needed. if (lineExtent > d_widestExtent) { d_widestExtent = lineExtent; } // update position in string lineIndex += lineLen; } } // skip to next 'paragraph' in text currPos += paraLen; } } configureScrollbars(); requestRedraw(); }
/************************************************************************* display required integrated scroll bars according to current state of the edit box and update their values. *************************************************************************/ void MultiLineEditbox::configureScrollbars(void) { float totalHeight = (float)d_lines.size() * getFont()->getLineSpacing(); float widestItem = d_widestExtent; // // First show or hide the scroll bars as needed (or requested) // // show or hide vertical scroll bar as required (or as specified by option) if ((totalHeight > getTextRenderArea().getHeight()) || d_forceVertScroll) { d_vertScrollbar->show(); // show or hide horizontal scroll bar as required (or as specified by option) if ((widestItem > getTextRenderArea().getWidth()) || d_forceHorzScroll) { d_horzScrollbar->show(); } else { d_horzScrollbar->hide(); } } else { // show or hide horizontal scroll bar as required (or as specified by option) if ((widestItem > getTextRenderArea().getWidth()) || d_forceHorzScroll) { d_horzScrollbar->show(); // show or hide vertical scroll bar as required (or as specified by option) if ((totalHeight > getTextRenderArea().getHeight()) || d_forceVertScroll) { d_vertScrollbar->show(); } else { d_vertScrollbar->hide(); } } else { d_vertScrollbar->hide(); d_horzScrollbar->hide(); } } // // Set up scroll bar values // Rect renderArea(getTextRenderArea()); d_vertScrollbar->setDocumentSize(totalHeight); d_vertScrollbar->setPageSize(renderArea.getHeight()); d_vertScrollbar->setStepSize(ceguimax(1.0f, renderArea.getHeight() / 10.0f)); d_vertScrollbar->setScrollPosition(d_vertScrollbar->getScrollPosition()); d_horzScrollbar->setDocumentSize(widestItem); d_horzScrollbar->setPageSize(renderArea.getWidth()); d_horzScrollbar->setStepSize(ceguimax(1.0f, renderArea.getWidth() / 10.0f)); d_horzScrollbar->setScrollPosition(d_horzScrollbar->getScrollPosition()); }
Window* FalagardChatHistory::insertChatString(int msgid,const String32& strChat, int nTalkerLength, int nOp/* = -1*/) { //2 refresh only. Change for respond speed.[7/13/2006] if(insert_refresh_only == nOp) { performWindowLayout(); return 0; } float topHeight = 0; FalagardChatBoard* pWindow = 0; if(m_listChatBoard.size() == d_chatBoardNum && m_listChatBoard.size() > 0) { /* Change for respond speed.[7/13/2006] FalagardChatBoard* pChild = static_cast<FalagardChatBoard*>(d_parentWindow->getChild((uint)0)); pChild->clearInfoItem(); d_parentWindow->removeChildWindow((uint)0); */ pWindow = *(m_listChatBoard.begin()); if(pWindow->isVisible() == false || pWindow->getText().empty()) topHeight = 0.0f; else topHeight = pWindow->resizeSelf(getTextRenderArea().getWidth()); pWindow->clearInfoItem(); pWindow->clearKillTime(); pWindow->setText(""); pWindow->show(); if ( !d_hollow ) { pWindow->setBoardHollow( d_hollow ); } m_listChatBoard.erase(m_listChatBoard.begin()); } else { pWindow = static_cast<FalagardChatBoard*>(WindowManager::getSingleton().createWindow( m_mapChildType[ "ChatBoard" ] ) ); //pWindow->setText(strChat); pWindow->show(); //pWindow->setMouseLButtonHollow(true); pWindow->subscribeEvent(FalagardChatBoard::EventInfoElementLClick, Event::Subscriber(&FalagardChatHistory::handleInfoItemBtnClick, this)); pWindow->subscribeEvent(FalagardChatBoard::EventInfoElementRClick, Event::Subscriber(&FalagardChatHistory::handleInfoItemBtnClick, this)); pWindow->subscribeEvent(FalagardChatBoard::EventInfoElementDelete, Event::Subscriber(&FalagardChatHistory::handleInfoItemDelete, this)); pWindow->subscribeEvent(FalagardChatBoard::EventInfoElementMoveIn, Event::Subscriber(&FalagardChatHistory::handleInfoItemMoveIn, this)); pWindow->subscribeEvent(FalagardChatBoard::EventInfoElementMoveOut, Event::Subscriber(&FalagardChatHistory::handleInfoItemMoveOut, this)); pWindow->subscribeEvent(FalagardChatBoard::EventKillBoard, Event::Subscriber(&FalagardChatHistory::handleBoardKillTime, this)); if ( !d_hollow ) { pWindow->setBoardHollow( d_hollow ); } d_parentWindow->addChildWindow(pWindow); } setChatBoardString(pWindow, strChat, nTalkerLength); pWindow->setmsgID(msgid); m_listChatBoard.push_back(pWindow); //InsertOperation switch switch(nOp) { case insert_kill_add_only: pWindow->setKillTime(float(d_boardKillTimer)); case insert_add_only: return pWindow; case insert_kill_normal: pWindow->setKillTime(float(d_boardKillTimer)); case insert_refresh_only: case insert_normal: default: break; } float posEnd = d_vertScrollbar->getDocumentSize()-d_vertScrollbar->getPageSize(); bool bPosEnd = (posEnd - d_vertScrollbar->getScrollPosition() < (1e-08f)) && posEnd>0?true:false; float fWinHeight = pWindow->resizeSelf(getTextRenderArea().getWidth()); //use d_extendHeight first. if(d_extendHeight > 0.0f) { d_extendHeight = (d_extendHeight - fWinHeight > 0.0f)?(d_extendHeight - fWinHeight):0.0f; } performWindowLayout(); if(bPosEnd || (d_vertScrollbar->getDocumentSize()-d_vertScrollbar->getPageSize()>0 && d_first)) { //scroll to end d_vertScrollbar->setScrollPosition( d_vertScrollbar->getDocumentSize()-d_vertScrollbar->getPageSize()); d_first = false; } if(!bPosEnd /*&& m_listChatBoard.size() == d_chatBoardNum*/ ) { Rect absarea(getTextRenderArea()); if(d_vertScrollbar->getScrollPosition() - topHeight > (1e-08f)) { //scroll up a new chatboard window's height d_vertScrollbar->setScrollPosition( d_vertScrollbar->getScrollPosition() - topHeight); } else { d_vertScrollbar->setScrollPosition( d_vertScrollbar->getDocumentSize()-d_vertScrollbar->getPageSize()); } } return pWindow; }