19#ifdef IGRAPHICS_NANOVG
24using namespace igraphics;
28, mSpecifiedCollapsedBounds(collapsedBounds)
29, mSpecifiedExpandedBounds(expandedBounds)
33 int duration = DEFAULT_ANIMATION_DURATION;
35 if(mState == kSubMenuAppearing)
36 duration = DEFAULT_ANIMATION_DURATION * 2;
38#pragma mark animations
43 pCaller->OnEndAnimation();
47 if(mState == kExpanding)
49 if(mAppearingMenuPanel !=
nullptr)
50 mAppearingMenuPanel->mBlend.mWeight = (
float) progress * mOpacity;
52 else if(mState == kSubMenuAppearing)
54 if(mAppearingMenuPanel !=
nullptr)
55 mAppearingMenuPanel->mBlend.mWeight = (
float) (progress > 0.9) * mOpacity;
57 else if(mState == kCollapsing)
59 for (
auto i = 0; i < mMenuPanels.GetSize(); i++) {
60 mMenuPanels.Get(i)->mBlend.mWeight = (
float) (1.-progress) * mOpacity;
63 else if(mState == kIdling)
65 for (
auto i = 0; i < mMenuPanels.GetSize(); i++) {
66 mMenuPanels.Get(i)->mBlend.mWeight = 0.f;
77IPopupMenuControl::~IPopupMenuControl()
79 mMenuPanels.Empty(
true);
84 assert(mMenu !=
nullptr);
86 for (
auto mr = 0; mr < mMenuPanels.GetSize(); mr++)
88 MenuPanel* pMenuPanel = mMenuPanels.Get(mr);
90 if(pMenuPanel->mShouldDraw)
95 int nItems = pMenuPanel->mMenu.NItems();
96 int nCells = pMenuPanel->mCellBounds.GetSize();
98 int endCell = nCells-1;
103 if(pMenuPanel->mScrollItemOffset > 0)
105 IRECT* pCellRect = pMenuPanel->mCellBounds.Get(0);
106 bool sel = mMouseCellBounds == pCellRect || pCellRect == pMenuPanel->mHighlightedCell;
109 DrawUpArrow(g, *pCellRect, sel, &pMenuPanel->mBlend);
114 if(pMenuPanel->mScrollItemOffset < nItems-nCells)
116 IRECT* pCellRect = pMenuPanel->mCellBounds.Get(nCells-1);
117 bool sel = mMouseCellBounds == pCellRect || pCellRect == pMenuPanel->mHighlightedCell;
126 for(
auto i = startCell; i <= endCell; i++)
128 IRECT* pCellRect = pMenuPanel->mCellBounds.Get(i);
129 IPopupMenu::Item* pMenuItem = pMenuPanel->mMenu.GetItem(startCell + pMenuPanel->mScrollItemOffset + cellOffset++);
134 if(pMenuItem->GetIsSeparator())
138 bool sel = mMouseCellBounds == pCellRect || pCellRect == pMenuPanel->mHighlightedCell;
140 if(pMenuPanel->mClickedCell)
142 if(mState != kFlickering)
149 DrawCellText(g, *pCellRect, pMenuItem, sel, &pMenuPanel->mBlend);
151 if(pMenuItem->GetChecked())
152 DrawTick(g, *pCellRect, pMenuItem, sel, &pMenuPanel->mBlend);
154 if(pMenuItem->GetSubmenu())
161 if(mCallOut && mMenuPanels.GetSize())
164 if (mMenuHasSubmenu && mSubMenuOpened)
175 mMouseCellBounds = mActiveMenuPanel->HitTestCells(x, y);
176 CollapseEverything();
186 mMouseCellBounds = mActiveMenuPanel->HitTestCells(x, y);
193 mMouseCellBounds = mActiveMenuPanel->HitTestCells(x, y);
196 if(mMouseCellBounds ==
nullptr)
198 MenuPanel* pMousedMenuPanel =
nullptr;
200 const int nPanels = mMenuPanels.GetSize();
202 for (
auto p = nPanels-1; p >= 0; p--)
204 MenuPanel* pMenuPanel = mMenuPanels.Get(p);
206 if(pMenuPanel->mShouldDraw && pMenuPanel->mRECT.Contains(x, y))
208 pMousedMenuPanel = pMenuPanel;
213 if(pMousedMenuPanel !=
nullptr)
215 mActiveMenuPanel = pMousedMenuPanel;
216 mMouseCellBounds = mActiveMenuPanel->HitTestCells(x, y);
222 if(mActiveMenuPanel->mScroller)
224 if(mMouseCellBounds == mActiveMenuPanel->mCellBounds.Get(0))
226 mActiveMenuPanel->ScrollUp();
228 else if (mMouseCellBounds == mActiveMenuPanel->mCellBounds.Get((mActiveMenuPanel->mCellBounds.GetSize()-1)))
230 mActiveMenuPanel->ScrollDown();
239 mMouseCellBounds =
nullptr;
261 float trisize = bounds.
H();
262 float halftri = trisize * 0.5f;
263 float ax, ay, bx, by, cx, cy;
265 switch (mCalloutArrowDir) {
267 ax = bounds.
MW() - halftri;
268 ay = bounds.
MH() - halftri;
275 ax = bounds.
MW() + halftri;
276 ay = bounds.
MH() + halftri;
283 ax = bounds.
MW() - halftri;
284 ay = bounds.
MH() + halftri;
291 ax = bounds.
MW() - halftri;
292 ay = bounds.
MH() + halftri;
301 g.
FillTriangle(mPanelBackgroundColor, ax, ay, bx, by, cx, cy, pBlend);
306 float trisize = bounds.
H();
307 float halftri = trisize * 0.5f;
308 float ax, ay, bx, by, cx, cy;
312 ax = bounds.
MW() + halftri;
313 ay = bounds.
MH() + halftri;
321 ax = bounds.
MW() - halftri;
322 ay = bounds.
MH() + halftri;
328 g.
FillTriangle(mPanelBackgroundColor, ax, ay, bx, by, cx, cy, pBlend);
334 g.
FillRoundRect(mPanelBackgroundColor, panel->mTargetRECT, mRoundness, &panel->mBlend);
352 IRECT textRect =
IRECT(tickRect.R + TEXT_HPAD, bounds.T, bounds.R - TEXT_HPAD, bounds.B);
355 mText.mFGColor = mItemMouseoverColor;
358 if(pItem->GetEnabled())
359 mText.mFGColor = mItemColor;
361 mText.mFGColor = mDisabledItemColor;
364 mText.mAlign = EAlign::Near;
365 g.
DrawText(mText, pItem->GetText(), textRect, pBlend);
376 float trisize, halftri, ax, ay, bx, by, cx, cy;
380 IRECT tri =
IRECT(bounds.R + (PAD * 0.5f) - bounds.
H(), bounds.T, bounds.R + (PAD * 0.5f), bounds.B);
381 trisize = (tri.R - tri.L) * 0.5f;
382 halftri = trisize * 0.5f;
383 ax = tri.R - trisize;
384 ay = tri.
MH() + halftri;
392 IRECT tri =
IRECT(bounds.L - (PAD * 0.5f), bounds.T, bounds.L - (PAD * 0.5f) + bounds.
H(), bounds.B);
393 trisize = (tri.R - tri.L) * 0.5f;
394 halftri = trisize * 0.5f;
395 ax = tri.L + trisize;
396 ay = tri.
MH() + halftri;
402 g.
FillTriangle(sel ? mItemMouseoverColor : mItemColor, ax, ay, bx, by, cx, cy, pBlend);
407 IRECT tri =
IRECT(bounds.
MW() - (bounds.
H() * 0.5f), bounds.T, bounds.
MW() + (bounds.
H() * 0.5f), bounds.B);
408 float trisize = (tri.R - tri.L) * 0.6f;
409 float halftri = trisize * 0.5f;
410 float ax = tri.
MW() - halftri;
411 float ay = tri.
MH() + halftri;
412 float bx = ax + trisize;
415 float cy = ay - trisize;
416 g.
FillTriangle(sel ? mItemMouseoverColor : mItemColor, ax, ay, bx, by, cx, cy, pBlend);
421 IRECT tri =
IRECT(bounds.
MW() - (bounds.
H() * 0.5f), bounds.T, bounds.
MW() + (bounds.
H() * 0.5f), bounds.B);
422 float trisize = (tri.R - tri.L) * 0.6f;
423 float halftri = trisize * 0.5f;
424 float ax = tri.
MW() - halftri;
425 float ay = tri.
MH() - halftri;
426 float bx = ax + trisize;
429 float cy = ay + trisize;
430 g.
FillTriangle(sel ? mItemMouseoverColor : mItemColor, ax, ay, bx, by, cx, cy, pBlend);
435 if(pBlend->mWeight > 0.9)
436 g.
FillRect(mSeparatorColor, bounds, &BLEND_25);
443 for (
int i = 0; i< mMenu->NItems(); i++)
445 if (mMenu->GetItem(i)->GetSubmenu())
447 mMenuHasSubmenu =
true;
450 else mMenuHasSubmenu =
false;
453 if(mMaxBounds.
W() == 0)
460IRECT IPopupMenuControl::GetLargestCellRectForMenu(
IPopupMenu& menu,
float x,
float y)
const
464 for (
auto i = 0; i < menu.NItems(); ++i)
471 pGraphics->
MeasureText(mText, pItem->GetText(), textBounds);
472 span = span.
Union(textBounds);
475 span.
HPad(TEXT_HPAD);
476 span.
Pad(TICK_SIZE, 0, ARROW_SIZE, 0);
478 return IRECT(x, y, x + span.
W(), y + span.
H());
481void IPopupMenuControl::GetPanelDimensions(
IPopupMenu&menu,
float& width,
float& height)
const
483 IRECT maxCell = GetLargestCellRectForMenu(menu, 0, 0);
485 int numItems = menu.NItems();
486 int numSeparators = 0;
487 float panelHeight = 0.f;
489 for (
auto i = 0; i < numItems; ++i)
492 if (pItem->GetIsSeparator())
497 float numCells = float(numItems - numSeparators);
498 panelHeight = (numCells * maxCell.
H()) + (numSeparators * mSeparatorSize) + ((numItems - 1) * mCellGap);
501 height = panelHeight;
506 float calloutSpace =0.f;
510 calloutSpace = CALLOUT_SPACE;
513 for(
auto i = 0; i < mActiveMenuPanel->mCellBounds.GetSize(); i++)
515 IRECT* pCellRect = mActiveMenuPanel->mCellBounds.Get(i);
517 IPopupMenu* pSubMenu = pMenuItem->GetSubmenu();
519 if(pCellRect == mMouseCellBounds)
521 if(pSubMenu !=
nullptr)
523 MenuPanel* pMenuPanelForThisMenu =
nullptr;
525 for (
auto mr = 0; mr < mMenuPanels.GetSize(); mr++)
527 MenuPanel* pMenuPanel = mMenuPanels.Get(mr);
529 if(&pMenuPanel->mMenu == pSubMenu)
531 pMenuPanelForThisMenu = pMenuPanel;
532 pMenuPanel->mShouldDraw =
true;
535 pMenuPanel->mShouldDraw =
false;
538 if(pMenuItem->GetEnabled())
539 mActiveMenuPanel->mHighlightedCell = pCellRect;
541 mActiveMenuPanel->mHighlightedCell =
nullptr;
544 if(pMenuPanelForThisMenu ==
nullptr) {
546 float panelWidth = 0.f;
547 float panelHeight = 0.f;
549 GetPanelDimensions(*pSubMenu, panelWidth, panelHeight);
551 float minT = mMaxBounds.T + mDropShadowSize;
552 float maxB = mMaxBounds.B - panelHeight - (mDropShadowSize * 2.f);
553 float maxR = mMaxBounds.R - panelWidth - (mDropShadowSize * 2.f);
554 float minL = mMaxBounds.L + mDropShadowSize;
559 if (mCalloutArrowDir == kSouth)
561 y = pCellRect->T - PAD;
562 if (y > maxB) y = maxB;
563 if ( y <= minT) y = minT;
566 if (mCalloutArrowDir == kNorth)
568 y = (pCellRect->T - (PAD / 2.f) - panelHeight) + (mCellGap * 2.f) + mDropShadowSize;
569 if ( y <= minT) y = minT;
570 if (y > maxB) y = maxB;
573 if (mSubmenuOnRight) x = pCellRect->R + PAD + calloutSpace;
574 else x = pCellRect->L - PAD - calloutSpace - panelWidth - mDropShadowSize;
575 if ( x <= minL ) x = minL;
576 if ( x > maxR ) x = maxR;
578 pMenuPanelForThisMenu = mMenuPanels.Add(
new MenuPanel(*
this, *pSubMenu, x, y, mMenuPanels.Find(mActiveMenuPanel)));
581 for (
auto mr = 0; mr < mMenuPanels.GetSize(); mr++)
583 MenuPanel* pMenuPanel = mMenuPanels.Get(mr);
585 if(pMenuPanel->mShouldDraw)
587 IRECT drawRECT = pMenuPanel->mRECT;
588 IRECT targetRECT = pMenuPanel->mTargetRECT;
590 MenuPanel* pParentMenuPanel = mMenuPanels.Get(pMenuPanel->mParentIdx);
592 while (pParentMenuPanel !=
nullptr)
594 pParentMenuPanel->mShouldDraw =
true;
595 drawRECT = drawRECT.
Union(pParentMenuPanel->mTargetRECT);
596 targetRECT = targetRECT.
Union(pParentMenuPanel->mRECT);
597 pParentMenuPanel = mMenuPanels.Get(pParentMenuPanel->mParentIdx);
598 mSubMenuOpened =
true;
600 if (mSubmenuOnRight) mSubMenuCalloutArrowBounds =
IRECT(pCellRect->R + PAD , pCellRect->
MH() - (calloutSpace / 2.f) , pCellRect->R + PAD + calloutSpace, pCellRect->
MH() + (calloutSpace / 2.f));
601 else mSubMenuCalloutArrowBounds =
IRECT(pCellRect->L - PAD - calloutSpace, pCellRect->
MH() - (calloutSpace / 2.f), pCellRect->L - PAD, pCellRect->
MH() + (calloutSpace / 2.f));
607 if(mAppearingMenuPanel != pMenuPanel)
609 mState = kSubMenuAppearing;
610 mAppearingMenuPanel = pMenuPanelForThisMenu;
621 for (
auto mr = 0; mr < mMenuPanels.GetSize(); mr++)
623 MenuPanel* pMenuPanel = mMenuPanels.Get(mr);
625 if(pMenuPanel->mParentIdx == mMenuPanels.Find(mActiveMenuPanel))
627 mActiveMenuPanel->mHighlightedCell =
nullptr;
628 pMenuPanel->mShouldDraw =
false;
629 mSubMenuOpened =
false;
639void IPopupMenuControl::Expand(
const IRECT& anchorArea)
645 mMenuPanels.Empty(
true);
647 mAnchorArea = anchorArea;
649 float panelWidth = 0.f;
650 float panelHeight = 0.f;
652 GetPanelDimensions(*mMenu, panelWidth, panelHeight);
654 float minT = mMaxBounds.T + mDropShadowSize;
655 float maxB = mMaxBounds.B - panelHeight - (mDropShadowSize * 2.f);
656 float maxR = mMaxBounds.R - panelWidth - (mDropShadowSize * 2.f);
657 float minL = mMaxBounds.L + mDropShadowSize;
662 float calloutSpace =0.f;
665 calloutSpace = CALLOUT_SPACE;
668 if ( anchorArea.
MH() <= mMaxBounds.
MH())
670 y = anchorArea.
MH() - (calloutSpace + mText.mSize);
672 else y = (anchorArea.
MH() - panelHeight) + (calloutSpace + mText.mSize);
674 if ( anchorArea.
MW() <= mMaxBounds.
MW() )
676 x = anchorArea.R + calloutSpace;
677 mCalloutArrowBounds =
IRECT( anchorArea.R, anchorArea.
MH() - (calloutSpace / 2.f), x, anchorArea.
MH() + (calloutSpace / 2.f) );
678 mCalloutArrowDir = kEast;
682 x = anchorArea.L - calloutSpace - panelWidth - mDropShadowSize;
683 mCalloutArrowBounds =
IRECT( anchorArea.L - calloutSpace, anchorArea.
MH() - (calloutSpace / 2.f), anchorArea.L, anchorArea.
MH() + (calloutSpace / 2.f) );
684 mCalloutArrowDir = kWest;
687 if( y <= minT || y > maxB || x <= minL || x > maxR )
689 if ( (y <= minT || x <= minL || x > maxR) && anchorArea.
MH() <= mMaxBounds.
MH() )
691 x = anchorArea.
MW() - (panelWidth / 2.f);
692 y = anchorArea.B + calloutSpace;
693 mCalloutArrowBounds =
IRECT(anchorArea.
MW() - (calloutSpace/2.f), anchorArea.B, anchorArea.
MW() + (calloutSpace/2.f), anchorArea.B + calloutSpace);
694 mCalloutArrowDir = kSouth;
698 if ( anchorArea.
MW() <= mMaxBounds.
MW() )
700 x = anchorArea.R + calloutSpace;
701 mCalloutArrowBounds =
IRECT( anchorArea.R, anchorArea.
MH() - (calloutSpace / 2.f), x, anchorArea.
MH() + (calloutSpace / 2.f) );
702 mCalloutArrowDir = kEast;
706 x = anchorArea.L - calloutSpace - panelWidth - mDropShadowSize;
707 mCalloutArrowBounds =
IRECT( anchorArea.L - calloutSpace, anchorArea.
MH() - (calloutSpace / 2.f), anchorArea.L, anchorArea.
MH() + (calloutSpace / 2.f) );
708 mCalloutArrowDir = kWest;
714 if ( (y > maxB || x <= minL || x > maxR) && anchorArea.
MH() > mMaxBounds.
MH() )
716 x = anchorArea.
MW() - (panelWidth / 2.f);
717 y = anchorArea.T - calloutSpace - panelHeight - mDropShadowSize;
718 mCalloutArrowBounds =
IRECT(anchorArea.
MW() - (calloutSpace/2.f), anchorArea.T - calloutSpace, anchorArea.
MW() + (calloutSpace/2.f), anchorArea.T);
719 mCalloutArrowDir = kNorth;
723 if ( anchorArea.
MW() <= mMaxBounds.
MW() )
725 x = anchorArea.R + calloutSpace;
726 mCalloutArrowBounds =
IRECT( anchorArea.R, anchorArea.
MH() - (calloutSpace / 2.f), x, anchorArea.
MH() + (calloutSpace / 2.f) );
727 mCalloutArrowDir = kEast;
731 x = anchorArea.L - calloutSpace - panelWidth - mDropShadowSize;
732 mCalloutArrowBounds =
IRECT( anchorArea.L - calloutSpace, anchorArea.
MH() - (calloutSpace / 2.f), anchorArea.L, anchorArea.
MH() + (calloutSpace / 2.f) );
733 mCalloutArrowDir = kWest;
739 if ( x <= minL ) x = minL;
740 if ( x > maxR ) x = maxR;
741 if ( y <= minT ) y = minT;
742 if ( y > maxB ) y = maxB;
747 if (anchorArea.B + calloutSpace <= maxB)
749 x = anchorArea.
MW() - (panelWidth / 2.f);
750 y = anchorArea.B + calloutSpace;
751 mCalloutArrowBounds =
IRECT(anchorArea.
MW() - (calloutSpace/2.f), anchorArea.B, anchorArea.
MW() + (calloutSpace/2.f), anchorArea.B + calloutSpace);
752 mCalloutArrowDir = kSouth;
754 if ( x <= minL ) x = minL;
755 if ( x > maxR ) x = maxR;
761 if ( anchorArea.
MW() <= mMaxBounds.
MW() )
763 mSubmenuOnRight =
true;
768 mSubmenuOnRight =
false;
771 x = (anchorArea.
MW() - (panelWidth / 2.f)) + (mMenuShift * shiftfactor);
772 if ( x <= minL ) x = minL;
773 if ( x > maxR ) x = maxR;
775 if (anchorArea.T - mMaxBounds.T <= mMaxBounds.B - anchorArea.B)
777 y = anchorArea.B + calloutSpace;
778 if ( y > maxB ) y = maxB;
779 if ( y <= minT ) y = minT;
780 mCalloutArrowBounds =
IRECT(anchorArea.
MW() - (calloutSpace/2.f), anchorArea.B, anchorArea.
MW() + (calloutSpace/2.f), anchorArea.B + calloutSpace);
781 mCalloutArrowDir = kSouth;
785 y = anchorArea.T - calloutSpace - panelHeight - mDropShadowSize;
786 if ( y <= minT ) y = minT;
787 if ( y > maxB ) y = maxB;
788 mCalloutArrowBounds =
IRECT(anchorArea.
MW() - (calloutSpace/2.f), anchorArea.T - calloutSpace, anchorArea.
MW() + (calloutSpace/2.f), anchorArea.T);
789 mCalloutArrowDir = kNorth;
793 mActiveMenuPanel = mAppearingMenuPanel = mMenuPanels.Add(
new MenuPanel(*
this, *mMenu, x, y, -1));
796 SetRECT(mActiveMenuPanel->mRECT);
801void IPopupMenuControl::CollapseEverything()
803 IPopupMenu* pClickedMenu = &mActiveMenuPanel->mMenu;
805 pClickedMenu->SetChosenItemIdx(-1);
807 for (
auto i = 0; i < mActiveMenuPanel->mCellBounds.GetSize(); i++)
809 IRECT* pR = mActiveMenuPanel->mCellBounds.Get(i);
811 if (mMouseCellBounds == pR)
813 int itemChosen = mActiveMenuPanel->mScrollItemOffset + i;
816 if (pItem->GetIsChoosable())
818 pClickedMenu->SetChosenItemIdx(itemChosen);
819 mActiveMenuPanel->mClickedCell = pR;
824 if (pClickedMenu->GetFunction())
825 pClickedMenu->ExecFunction();
829 mSubMenuOpened =
false;
830 mActiveMenuPanel =
nullptr;
832 mState = kFlickering;
837void IPopupMenuControl::OnEndAnimation()
841 if(mState == kExpanding)
843 for (
auto i = 0; i < mMenuPanels.GetSize(); i++) {
844 mMenuPanels.Get(i)->mBlend.mWeight = mOpacity;
849 else if (mState == kFlickering)
851 mState = kCollapsing;
855 else if (mState == kSubMenuAppearing)
857 for (
auto i = 0; i < mMenuPanels.GetSize(); i++) {
858 mMenuPanels.Get(i)->mBlend.mWeight = mOpacity;
863 else if(mState == kCollapsing)
865 mTargetRECT = mSpecifiedCollapsedBounds;
867 for (
auto i = 0; i < mMenuPanels.GetSize(); i++) {
868 mMenuPanels.Get(i)->mBlend.mWeight = 0.;
872 mMouseCellBounds =
nullptr;
873 mAnchorArea =
IRECT();
878 else if(mState == kIdling)
882 mMenuPanels.Empty(
true);
883 mRECT = mSpecifiedCollapsedBounds;
887 IControl::OnEndAnimation();
892, mParentIdx(parentIdx)
894 mSingleCellBounds = control.GetLargestCellRectForMenu(menu, x, y);
896 float left = x + control.PAD;
897 float top = y + control.PAD;
900 auto GetIncrements = [&](
IPopupMenu::Item* pMenuItem,
float& incX,
float& incY)
904 if (pMenuItem->GetIsSeparator())
905 incY = control.mSeparatorSize;
910 for (
auto i = 0; i < menu.NItems(); ++i)
914 float toAddX, toAddY;
915 bool newColumn =
false;
917 GetIncrements(pMenuItem, toAddX, toAddY);
919 if(control.mMaxColumnItems > 0 && i > 1)
920 newColumn = !(i % control.mMaxColumnItems);
922 if((top + toAddY + control.PAD) > control.mMaxBounds.B || newColumn)
924 if(control.mScrollIfTooBig)
926 const float maxTop = control.mMaxBounds.T + control.PAD + control.mDropShadowSize;
927 const float maxBottom = control.mMaxBounds.B - control.PAD;
928 const float maxH = (maxBottom - maxTop);
929 mScrollMaxRows =
static_cast<int>(maxH / (CellHeight() + control.mCellGap));
932 mCellBounds.Empty(
true);
933 GetIncrements(menu.GetItem(0), toAddX, toAddY);
935 if(menu.NItems() < mScrollMaxRows)
937 top = (y + control.PAD + CellHeight()) - (menu.NItems() * CellHeight());
939 for (
auto r = 0; r < menu.NItems(); r++)
941 GetIncrements(menu.GetItem(r), toAddX, toAddY);
942 bottom = top + toAddY;
943 right = left + toAddX;
944 mCellBounds.Add(
new IRECT(left, top, right, bottom));
945 top = bottom + control.mCellGap;
946 bottom = top + toAddY;
954 for (
auto r = 0; r < mScrollMaxRows; r++)
956 GetIncrements(menu.GetItem(r), toAddX, toAddY);
957 bottom = top + toAddY;
958 right = left + toAddX;
959 mCellBounds.Add(
new IRECT(left, top, right, bottom));
960 top = bottom + control.mCellGap;
961 bottom = top + toAddY;
968 left += mSingleCellBounds.W() + control.mCellGap;
969 top = mSingleCellBounds.T + control.PAD;
973 right = left + toAddX;
974 bottom = top + toAddY;
976 mCellBounds.Add(
new IRECT(left, top, right, bottom));
977 top = bottom + control.mCellGap;
982 if(mCellBounds.GetSize())
984 span = *mCellBounds.Get(0);
986 for(
auto i = 1; i < mCellBounds.GetSize(); i++)
988 span = span.
Union(*mCellBounds.Get(i));
992 if (control.mSpecifiedExpandedBounds.
W())
994 mTargetRECT = control.mSpecifiedExpandedBounds.
GetPadded(control.PAD);
995 mRECT = control.mSpecifiedExpandedBounds.
GetPadded(control.mDropShadowSize + control.PAD);
999 mTargetRECT = span.
GetPadded(control.PAD);
1000 mRECT = span.
GetPadded(control.mDropShadowSize + control.PAD);
1004IPopupMenuControl::MenuPanel::~MenuPanel()
1006 mCellBounds.
Empty(
true);
1009IRECT* IPopupMenuControl::MenuPanel::HitTestCells(
float x,
float y)
const
1011 for(
auto i = 0; i < mCellBounds.GetSize(); i++)
1013 IRECT* pR = mCellBounds.Get(i);
1014 if(pR->
Contains(x, y) && mMenu.GetItem(i)->GetEnabled())
The lowest level base class of an IGraphics control.
virtual void OnMouseDown(float x, float y, const IMouseMod &mod)
Implement this method to respond to a mouse down event on this control.
virtual void Hide(bool hide)
Shows or hides the IControl.
void SetTargetRECT(const IRECT &bounds)
Set the rectangular mouse tracking target area, within the graphics context for this control.
double GetAnimationProgress() const
Get the progress in a control's animation, in the range 0-1.
void SetRECT(const IRECT &bounds)
Set the rectangular draw area for this control, within the graphics context.
virtual void SetDirty(bool triggerAction=true, int valIdx=kNoValIdx)
Mark the control as dirty, i.e.
IControl * SetActionFunction(IActionFunction actionFunc)
Set an Action Function for this control.
void SetAnimation(IAnimationFunction func)
Set the animation function.
The lowest level base class of an IGraphics context.
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.
void SetControlValueAfterPopupMenu(IPopupMenu *pMenu)
Called by PopupMenuControl in order to update a control with a new value after returning from the non...
virtual void FillRect(const IColor &color, const IRECT &bounds, const IBlend *pBlend=0)
Fill a rectangular region of the graphics context with a color.
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.
virtual void UpdateTooltips()=0
Call this if you modify control tool tips at runtime.
virtual void FillRoundRect(const IColor &color, const IRECT &bounds, float cornerRadius=5.f, const IBlend *pBlend=0)
Fill a rounded rectangle with a color.
virtual void FillTriangle(const IColor &color, float x1, float y1, float x2, float y2, float x3, float y3, const IBlend *pBlend=0)
Fill a triangle with a color.
IRECT GetBounds() const
Returns an IRECT that represents the entire UI bounds This is useful for programatically arranging UI...
virtual float MeasureText(const IText &text, const char *str, IRECT &bounds) const
Measure the rectangular region that some text will occupy.
Used to manage composite/blend operations, independent of draw class/platform.
Used to manage mouse modifiers i.e.
Used to manage a rectangular area, independent of draw class/platform.
void Pad(float padding)
Pad this IRECT N.B.
IRECT GetCentredInside(const IRECT &sr) const
Get a rectangle the size of sr but with the same center point as this rectangle.
void HPad(float padding)
Pad this IRECT in the X-axis N.B.
IRECT Union(const IRECT &rhs) const
Create a new IRECT that is a union of this IRECT and rhs.
bool Contains(const IRECT &rhs) const
Returns true if this IRECT completely contains rhs.
IRECT GetPadded(float padding) const
Get a copy of this IRECT with each value padded by padding N.B.
IRECT GetHPadded(float padding) const
Get a copy of this IRECT padded in the X-axis N.B.
IText is used to manage font and text/text entry style for a piece of text on the UI,...