22 BEGIN_IGRAPHICS_NAMESPACE
51 IBubbleControl(
const IText& text = DEFAULT_TEXT.WithAlign(EAlign::Center),
const IColor& fillColor = COLOR_WHITE,
const IColor& strokeColor = COLOR_BLACK,
float roundness = 5.f)
53 , mRoundness(roundness)
54 , mFillColor(fillColor)
55 , mStrokeColor(strokeColor)
61 auto animationFunc = [&](
IControl* pCaller) {
62 auto progress = pCaller->GetAnimationProgress();
65 if(mState == kExpanding)
67 mBlend.mWeight = mOpacity;
70 else if(mState == kExpanded)
72 if(
GetUI()->ControlIsCaptured(mCaller))
79 mBlend.mWeight = mOpacity;
86 else if(mState == kCollapsing)
95 pCaller->OnEndAnimation();
100 case kExpanding: mBlend.mWeight = (float) progress * mOpacity;
break;
101 case kExpanded: mBlend.mWeight = mOpacity;
break;
102 case kCollapsing: mBlend.mWeight = (float) (1.-progress) * mOpacity;
break;
113 if(mState == kExpanded) {
127 DrawDropShadow(g, r);
136 mBubbleBounds = mRECT;
152 g.
DrawText(mText, mStr.Get(), r, &mBlend);
157 float halfCalloutSize = mCalloutSize/2.f;
160 g.
PathArc(r.
L + mRoundness, r.
T + mRoundness, mRoundness, 270.f, 360.f);
162 if(mArrowDir == kWest)
164 g.
PathArc(r.
R - mRoundness, r.
T + mRoundness, mRoundness, 0.f, 90.f);
165 g.
PathArc(r.
R - mRoundness, r.
B - mRoundness, mRoundness, 90.f, 180.f);
166 g.
PathArc(r.
L + mRoundness, r.
B - mRoundness, mRoundness, 180.f, 270.f);
171 else if(mArrowDir == kEast)
173 g.
PathArc(r.
R - mRoundness, r.
T + mRoundness, mRoundness, 0.f, 90.f);
177 g.
PathArc(r.
R - mRoundness, r.
B - mRoundness, mRoundness, 90.f, 180.f);
178 g.
PathArc(r.
L + mRoundness, r.
B - mRoundness, mRoundness, 180.f, 270.f);
180 else if(mArrowDir == kNorth)
185 g.
PathArc(r.
R - mRoundness, r.
T + mRoundness, mRoundness, 0.f, 90.f);
186 g.
PathArc(r.
R - mRoundness, r.
B - mRoundness, mRoundness, 90.f, 180.f);
187 g.
PathArc(r.
L + mRoundness, r.
B - mRoundness, mRoundness, 180.f, 270.f);
189 else if(mArrowDir == kSouth)
191 g.
PathArc(r.
R - mRoundness, r.
T + mRoundness, mRoundness, 0.f, 90.f);
192 g.
PathArc(r.
R - mRoundness, r.
B - mRoundness, mRoundness, 90.f, 180.f);
196 g.
PathArc(r.
L + mRoundness, r.
B - mRoundness, mRoundness, 180.f, 270.f);
200 g.
PathFill(mFillColor,
true, &mBlend);
209 virtual void MeasureText(
const char* str,
IRECT& contentBounds)
214 void ShowBubble(
IControl* pCaller,
float x,
float y,
const char* str, EDirection dir,
IRECT minimumContentBounds, ITouchID touchID = 0)
216 if(mMaxBounds.
W() == 0)
224 MeasureText(str, contentBounds);
226 if (!minimumContentBounds.
Empty())
228 if(minimumContentBounds.
W() > contentBounds.
W())
230 contentBounds.
R = contentBounds.
L + minimumContentBounds.
W();
233 if(minimumContentBounds.
H() > contentBounds.
H())
235 contentBounds.
B = contentBounds.
T + minimumContentBounds.
H();
239 contentBounds.
HPad(mHorizontalPadding);
240 contentBounds.
Pad(mDropShadowSize);
241 const float halfHeight = contentBounds.
H() / 2.f;
242 const float halfWidth = contentBounds.
W() / 2.f;
244 mBubbleBounds =
IRECT(x, y - halfHeight, x + contentBounds.
W(), y + halfHeight);
247 if(mDirection == EDirection::Horizontal)
249 const float maxR = mMaxBounds.
R - mHorizontalPadding - mDropShadowSize;
252 if(mBubbleBounds.
R > maxR)
254 const float shiftLeft = mBubbleBounds.
R-controlBounds.L;
255 mBubbleBounds.
Translate(-shiftLeft, 0.f);
256 mArrowDir = EArrowDir::kEast;
259 mArrowDir = EArrowDir::kWest;
263 mBubbleBounds.
Translate(-halfWidth, -halfHeight);
266 if(mBubbleBounds.
T < mMaxBounds.
T)
268 mArrowDir = EArrowDir::kNorth;
269 const float shiftDown = mBubbleBounds.
H() + controlBounds.H();
273 mArrowDir = EArrowDir::kSouth;
278 if(mState == kCollapsed)
285 if(pCaller != mCaller)
287 mRECT = mBubbleBounds;
294 bool GetActive()
const 296 return mState > EPopupState::kCollapsed;
299 ITouchID GetTouchID()
const 307 ITouchID mTouchId = 0;
308 EDirection mDirection = EDirection::Horizontal;
312 EArrowDir mArrowDir = EArrowDir::kWest;
314 IBlend mBlend = { EBlend::Default, 0.f };
315 float mRoundness = 5.f;
316 float mDropShadowSize = 10.f;
317 float mCalloutSize = 10.f;
318 float mOpacity = 0.95f;
319 float mStrokeThickness = 2.f;
320 float mHorizontalPadding = 5.f;
321 IColor mFillColor = COLOR_WHITE;
322 IColor mStrokeColor = COLOR_BLACK;
326 END_IGRAPHICS_NAMESPACE
virtual void PathMoveTo(float x, float y)=0
Move the current point in the current path.
virtual void PathClose()=0
Close the path that is being specified.
The lowest level base class of an IGraphics control.
Used to manage a rectangular area, independent of draw class/platform.
virtual void PathArc(float cx, float cy, float r, float a1, float a2, EWinding winding=EWinding::CW)=0
Add an arc to the current path.
Used to manage composite/blend operations, independent of draw class/platform.
void SetMaxBounds(const IRECT &bounds)
Set the bounds that the menu can potentially occupy, if not the full graphics context.
virtual void PathLineTo(float x, float y)=0
Add a line to the current path from the current point to the specified location.
virtual void Hide(bool hide)
Shows or hides the IControl.
void SetFillColor(const IColor &color)
Set the background color for the bubble.
void Translate(float x, float y)
Translate this rectangle.
IControl * SetActionFunction(IActionFunction actionFunc)
Set an Action Function for this control.
virtual void PathStroke(const IPattern &pattern, float thickness, const IStrokeOptions &options=IStrokeOptions(), const IBlend *pBlend=0)=0
Stroke the current current path.
Used to manage color data, independent of draw class/platform.
void HPad(float padding)
Pad this IRECT in the X-axis N.B.
void DrawText(const IText &text, const char *str, const IRECT &bounds, const IBlend *pBlend=0)
Draw some text to the graphics context in a specific rectangle.
Used to manage stroke behaviour for path based drawing back ends.
IControl * SetAnimationEndActionFunction(IActionFunction actionFunc)
Set an Action Function to be called at the end of an animation.
This file contains the base IControl implementation, along with some base classes for specific types ...
void SetAllControlsDirty()
Calls SetDirty() on every control.
float R
Right side of the rectangle (X + W)
void SetRECT(const IRECT &bounds)
Set the rectangular draw area for this control, within the graphics context.
const IRECT & GetRECT() const
Get the rectangular draw area for this control, within the graphics context.
IText is used to manage font and text/text entry style for a piece of text on the UI...
IControl(const IRECT &bounds, int paramIdx=kNoParameter, IActionFunction actionFunc=nullptr)
Constructor.
virtual void PathFill(const IPattern &pattern, const IFillOptions &options=IFillOptions(), const IBlend *pBlend=0)=0
Fill the current current path.
void ResetBounds()
If controls get moved, you may need to call this to avoid the wrong regions getting dirtied...
virtual void DrawFastDropShadow(const IRECT &innerBounds, const IRECT &outerBounds, float xyDrop=5.f, float roundness=0.f, float blur=10.f, IBlend *pBlend=nullptr)
NanoVG only.
The lowest level base class of an IGraphics context.
void SetAnimation(IAnimationFunction func)
Set the animation function.
IRECT GetBounds() const
Returns an IRECT that represents the entire UI bounds This is useful for programatically arranging UI...
EPopupState
An enumerated list, that is used to determine the state of the menu, mainly for animations.
void SetTargetAndDrawRECTs(const IRECT &bounds)
Set BOTH the draw rect and the target area, within the graphics context for this control.
IRECT Union(const IRECT &rhs) const
Create a new IRECT that is a union of this IRECT and rhs.
void Pad(float padding)
Pad this IRECT N.B.
float L
Left side of the rectangle (X)
A special control to draw contextual info as a slider etc is moved If used in the main IControl stack...
void Draw(IGraphics &g) override
Draw the control to the graphics context.
IRECT GetPadded(float padding) const
Get a copy of this IRECT with each value padded by padding N.B.
void SetStrokeColor(const IColor &color)
Set the stroke color for the bubble.
float T
Top of the rectangle (Y)
IBubbleControl(const IText &text=DEFAULT_TEXT.WithAlign(EAlign::Center), const IColor &fillColor=COLOR_WHITE, const IColor &strokeColor=COLOR_BLACK, float roundness=5.f)
Create a new IBubbleControl.
virtual float MeasureText(const IText &text, const char *str, IRECT &bounds) const
Measure the rectangular region that some text will occupy.
virtual void SetDirty(bool triggerAction=true, int valIdx=kNoValIdx)
Mark the control as dirty, i.e.
float B
Bottom of the rectangle (Y + H)