// Sets the string and text settings used for rendering, and breaks the string into lines. void GxTextRenderer::SetText(const GxText& settings, const char* text) { myStr = (const uchar*)text; myLen = GxStrLen(text); GxFontDatabaseImp* database = GxFontDatabaseImp::singleton; myRangeBegin = GxMax(0, settings.rangeBegin); myRangeEnd = GxMin(myLen, settings.rangeEnd); myMaxWidth = (float)settings.maxWidth; myTabWidth = settings.tabWidth; myColorT = settings.top; myColorB = settings.bottom; myColorS = settings.shadow; myFont = database->GetFont(settings.font.GetHandle()); myIsWordWrap = settings.HasFlag(GX_TF_WORD_WRAP); myIsFormatted = settings.HasFlag(GX_TF_FORMATTING); myIsEllipsis = settings.HasFlag(GX_TF_ELLIPSIS) && myMaxWidth >= 0; myIsSingleLine = settings.HasFlag(GX_TF_SINGLELINE); myIsJustified = settings.HasFlag(GX_TF_JUSTIFIED) && myMaxWidth >= 0 && !myIsEllipsis && !myIsSingleLine; myIsKerning = settings.HasFlag(GX_TF_KERNING) && myFont->kernCount > 0; myAlignH = settings.alignH; myAlignV = settings.alignV; myTextW = myTextH = 0; myLines.clear(); myResetPos(); bool softBreaks = myMaxWidth >= 0 && !myIsEllipsis && !myIsSingleLine; softBreaks ? myProcessWithBreaks() : myProcessWithoutBreaks(); myTextH = GxMax(1, (int)myLines.size()) * myFont->fontSize; }
void GxDrawImp::PushScissorRect(int x, int y, int w, int h) { Flush(); GxRenderInterface* renderer = GxRenderInterface::Get(); if(myScissorStack.size() < 256) { if(w < 0 || h < 0) { GxLog(LOG_TAG, GX_LT_WARNING, "PushScissorRect() was called with a negative width or height."); } if(!myScissorStack.empty()) { GxRecti last = myScissorStack.back(); int nx = GxMax(last.x, x); int ny = GxMax(last.y, y); int nw = GxMax(0, GxMin(last.x+last.w, x+w) - nx); int nh = GxMax(0, GxMin(last.y+last.h, y+h) - ny); myScissorStack.push_back(GxRecti(nx, ny, nw, nh)); renderer->SetScissorRect(nx, ny, nw, nh); } else { myScissorStack.push_back(GxRecti(x, y, w, h)); renderer->EnableScissorRect(true); renderer->SetScissorRect(x, y, w, h); } } else { GxLog(LOG_TAG, GX_LT_WARNING, "The ScissorRect stack is overflowing, ignoring push."); } }
void GxDock::myClampFloatPos(GxVec2i view) { int w = myFloatRect.w; int h = myFloatRect.h; myFloatRect.x = GxClamp(myFloatRect.x, 0, GxMax(0, view.x-24)); myFloatRect.y = GxClamp(myFloatRect.y, 0, GxMax(0, view.y-24)); }
// This line adding function is used by myProcessWithBreaks. void GxTextRenderer::myAddLine(int begin, const BreakInfo& b, bool justify) { float lineW = b.lineW - b.trailW; float spaceW = b.spaceW - b.trailW; Line line = { begin, b.end, lineW, 1.f, false, justify }; // If the line is justified, we calculate the whitespace scalar. if(justify && spaceW > 0) { float textW = lineW - spaceW; line.spacemul = GxMax(0.f, myMaxWidth - textW) / spaceW; line.width = textW + spaceW * line.spacemul; } myTextW = GxMax(myTextW, (int)lineW); myLines.push_back(line); }
void GxFreeLayout::Adjust() { GxVec2i dim(0, 0); for(int i=0; i<myItems.Size(); ++i) { GxWidget* w = myItems[i].widget; w->Adjust(); if(w->IsUnarranged()) continue; GxSizePolicyResult pol(w); GxVec2i pos = myItems[i].pos; dim.x = GxMax(dim.x, pos.x + pol.hint.x); dim.y = GxMax(dim.y, pos.y + pol.hint.y); } dim.x += myMargin.l + myMargin.r; dim.y += myMargin.t + myMargin.b; myPreferredSize = dim; myMinimumSize = dim; }
// This line adding function is used by myProcessWithoutBreaks. void GxTextRenderer::myAddLine(int begin, int end, float width, const Ellipsis& ellipsis) { Line line = { begin, end, width, 1.f, ellipsis.add, false }; // Adjust the line if ellipsis are inserted somewhere. if(ellipsis.add) { line.end = GxMin(line.end, ellipsis.end); line.width = ellipsis.x + myFont->ellipsisW; } myTextW = GxMax(myTextW, (int)width); myLines.push_back(line); }
void GxDockBin::Adjust() { myLayout.Adjust(); GxVec2i size = myLayout.GetPreferredSize(); myWidth = GxMax(32, size.x); if(size.y > myRect.h) { myScrollbar->SetDisabled(false); myWidth += scrollbarW; } else { myScrollbar->SetDisabled(true); myScrollbar->SetValue(0); } }
void GxDockArea::myStartDrag(GxDock* dock, int x, int y) { if(!dock->IsFloating()) { GxRecti r = dock->myRect; r.x -= myRect.x; r.y -= myRect.y; GxRecti f = dock->myFloatRect; int dx = (x - r.x) - (x - r.x) * f.w / GxMax(r.w, 1); dock->SetFloatingPos(r.x + dx, r.y); } myUndock(dock); myMoveToTop(dock); myFocusDock = dock; myActionDims = dock->myFloatRect; myActionPos = GxVec2i(x, y); myActionType = FA_DRAG; }
void GxDockBin::SetRect(const GxRecti& rect) { GxRecti r = myRect = rect; if(!myScrollbar->IsHidden()) { GxVec2i size = myLayout.GetPreferredSize(); int end = GxMax(0, size.y - myRect.h); myScrollbar->SetRange(0, end, myRect.h, 32); GxRecti bar(r); bar.x += bar.w - scrollbarW; bar.w = scrollbarW; myScrollbar->SetRect(bar); r.y -= GxInt(myScrollbar->GetValue()); r.w -= scrollbarW; } myLayout.Arrange(r); }
void GxSliderAbstract::myUpdateValue(double value, bool emitEvent) { bool snap = myFlags[F_SNAPPING]; double min = GxMin(myBegin, myEnd); double max = GxMax(myBegin, myEnd); if(snap && abs(myTickInterval) >= 0.001 && value > min && value < max) { value -= myBegin; value = floor(value/myTickInterval + 0.5) * myTickInterval; value += myBegin; } value = GxClamp(value, min, max); if(myValue != value && emitEvent) { EmitEvent(eChanged(), value); myFlags.Set(F_CHANGED); } myValue = value; if(myVarPtr) *myVarPtr = value; }
void GxDockArea::Tick(float dt) { GxVec2i mpos = GxInput::Get()->GetMousePos(); mpos.x = GxClamp(mpos.x, 0, myRect.w); mpos.y = GxClamp(mpos.y, 0, myRect.h); GxVec2i resizeDir = GxVec2i(0, 0); bool draggingAction = false; if(myHoverDock) { GxDock::Item item = myHoverDock->myGetItemAt(mpos.x, mpos.y); if(item == GxDock::I_BAR) draggingAction = true; if(item == GxDock::I_FRAME) resizeDir = myHoverDock->myGetResizeDir(mpos.x, mpos.y); } // Handle floating dock dragging action. if(myActionType == FA_DRAG) { draggingAction = true; GxRecti r = myActionDims; r.x += mpos.x - myActionPos.x; r.y += mpos.y - myActionPos.y; myFocusDock->myFloatRect = r; myFocusDock->myClampFloatSize(GxVec2i()); myFocusDock->myClampFloatPos(GxVec2i(myRect.w, myRect.h)); myDragHl = GxMin(1.f, myDragHl + dt * 2); } else { myDragHl = GxMax(0.f, myDragHl - dt * 4); } // Handle floating dock resize action. if(myActionType == FA_RESIZE) { resizeDir = myResizeDir; GxRecti r = myActionDims; GxVec2i d = mpos - myActionPos; if(myResizeDir.x < 0) r.Expand(-d.x, 0, 0, 0); if(myResizeDir.y < 0) r.Expand(0, -d.y, 0, 0); if(myResizeDir.x > 0) r.Expand(0, 0, +d.x, 0); if(myResizeDir.y > 0) r.Expand(0, 0, 0, +d.y); myFocusDock->myFloatRect = r; myFocusDock->myClampFloatSize(myResizeDir); myFocusDock->myClampFloatPos(GxVec2i(myRect.w, myRect.h)); } // Change the mouse cursor image when resizing. if(resizeDir.x != 0 || resizeDir.y != 0) { GxVec2i d = resizeDir; GxCursorImage c = GX_CI_DRAG; if(d.x != 0 && d.y == 0) c = GX_CI_SIZE_WE; if(d.x == 0 && d.y != 0) c = GX_CI_SIZE_NS; if(d.x < 0 && d.y < 0) c = GX_CI_SIZE_NWSE; if(d.x > 0 && d.y > 0) c = GX_CI_SIZE_NWSE; if(d.x < 0 && d.y > 0) c = GX_CI_SIZE_NESW; if(d.x > 0 && d.y < 0) c = GX_CI_SIZE_NESW; GetContext()->SetCursor(c); } // Change the mouse cursor image when dragging. if(draggingAction) { GetContext()->SetCursor(GX_CI_DRAG); } // Tick the dock bars. for(int i=0; i<binCount; ++i) if(myBins[i]) myBins[i]->Tick(dt); // Tick the floating docks. for(int i=0; i<myDocks.Size(); ++i) if(myDocks[i]->IsFloating() && !myDocks[i]->IsHidden()) myDocks[i]->Tick(dt); }