11static const int kGap = 6;
15int GuiPopover::maxHeight(
int screenHeight,
const Insets& insets)
17 return screenHeight - insets.top - insets.bottom - 2 * kGap;
20GuiPopover::Position GuiPopover::place(
const Anchor& a,
int w,
int h,
int screenW,
int screenH,
const Insets& insets)
22 const int top = insets.top + kGap;
23 const int bottom = screenH - insets.bottom - kGap;
27 p.x = (screenW - w) / 2;
28 p.y = (screenH - h) / 2;
30 else if(a.edge == Anchor::BESIDE)
34 const int rightX = a.x + a.w + kGap, leftX = a.x - kGap - w;
35 const int rightRoom = screenW - insets.side - rightX, leftRoom = leftX - insets.side + w;
38 else if(leftX >= insets.side)
41 p.x = (rightRoom >= leftRoom) ? rightX : insets.side;
42 p.y = std::max(top, std::min(a.y + a.h / 2 - h / 2, bottom - h));
48 const int below = a.y + a.h + kGap, above = a.y - h - kGap;
49 if(below + h <= bottom)
54 p.y = std::max(top, std::min(below, bottom - h));
55 if(a.edge == Anchor::LEFT_MARGIN)
57 else if(a.edge == Anchor::RIGHT_MARGIN)
58 p.x = screenW - insets.side - w;
60 p.x = (a.x + a.w / 2 > screenW / 2) ? a.x + a.w - w : a.x;
62 p.x = std::max(insets.side, std::min(p.x, screenW - insets.side - w));
68 const int len = 8, base = 16, edge = 18;
69 Tail t = {
false, TAIL::UP, 0, 0, 0, 0 };
72 const int ax = a.x + a.w / 2, ay = a.y + a.h / 2;
75 t = {
true, TAIL::UP, std::max(at.x + edge, std::min(ax - base / 2, at.x + panelW - edge - base)), at.y - len + 1, base, len };
77 else if(at.y + panelH <= a.y)
79 t = {
true, TAIL::DOWN, std::max(at.x + edge, std::min(ax - base / 2, at.x + panelW - edge - base)), at.y + panelH - 1, base, len };
83 t = {
true, TAIL::LEFT, at.x - len + 1, std::max(at.y + edge, std::min(ay - base / 2, at.y + panelH - edge - base)), len, base };
85 else if(at.x + panelW <= ax)
87 t = {
true, TAIL::RIGHT, at.x + panelW - 1, std::max(at.y + edge, std::min(ay - base / 2, at.y + panelH - edge - base)), len, base };
95 GuiPopover(anchorAt, keepClear, platform->getVideo()->getScreenWidth(), platform->getVideo()->getScreenHeight())
100 anchor(anchorAt), insets(keepClear), screenW(screenWidth), screenH(screenHeight), cancel(nullptr), click(nullptr), panel(nullptr), dismissed(false), by(-1)
104 placedTail = {
false, TAIL::UP, 0, 0, 0, 0 };
107 click =
ui.trigger();
114void GuiPopover::dismiss()
123 if(dismissed || !c ||
getState() == STATE::DISABLED)
131 bool leave = cancel->isClicked(c);
132 if(!leave && chan >= 0 && click->isClicked(c))
135 leave = pad.
validPointer && (!panel || !panel->isInside(pad.cursor_x, pad.cursor_y));
144void GuiPopover::setPanel(GuiCard& card)
149void GuiPopover::setPanel(GuiCard& card,
PixelColor tailColor)
155 const int panelW = card.getWidth(), panelH = card.getHeight();
156 placed = place(anchor, panelW, panelH, screenW, screenH, insets);
158 GuiLayout& at =
ui.column().size(screenW, screenH).addGap((
float)placed.y).add(
ui.row().size(screenW, panelH).addGap((
float)placed.x).add(card));
162 placedTail =
tailAt(anchor, placed, panelW, panelH);
166 GuiShape& arrow =
ui.own<GuiShape>(placedTail.w, placedTail.h);
167 arrow.
setArrow(kinds[(
int)placedTail.direction], tailColor, tailColor);
168 GuiLayout& tailPlaced =
ui.column().size(screenW, screenH).addGap((
float)placedTail.y).add(
ui.row().size(screenW, placedTail.h).addGap((
float)placedTail.x).add(arrow));
Umbrella header for the platform-agnostic libgui core.
STATE getState()
Gets the element's current state.
GuiElement * parentElement
Parent element.
virtual void update(InputController *c)
Called constantly to allow the element to respond to the current input data.
void setPosition(int x, int y)
Sets the element's position.
virtual void setAlignment(ALIGN_H hor, ALIGN_V vert)
Sets the element's alignment respective to its parent element.
GuiLayout & add(GuiElement *e, const GuiItem &item=GuiItem())
Adds a child. Children are laid out in the order they are added.
GuiLayout & setFixedSize(int w, int h)
Fixes the container's size (0 on an axis = fit the content)
GuiPopover(const Anchor &anchor=Anchor(), const Insets &insets=Insets())
A popover as large as the screen the platform reports, opening beside anchor (centered with none) and...
static Tail tailAt(const Anchor &anchor, const Position &at, int panelW, int panelH)
Puts the built panel (a card owned by ui, fixed or fit to its content: it is laid out here to measure...
UiScope ui
Owns the panel and everything else the popover is made of; build the panel with it.
void setArrow(SHAPE dir, PixelColor rest, PixelColor lit)
Makes this a small arrow: a filled triangle pointing the way of dir (a SHAPE::TRIANGLE_*),...
Input-condition matcher attached to a GuiElement (via setSimpleTrigger() etc.) and evaluated against ...
void setSecondaryTrigger(int ch=-1)
SHAPE
Basic shape kinds a paint can be applied to.
@ TRIANGLE_UP
A triangle pointing up, left or right, apex on the middle of one side and base along the opposite sid...
@ TRIANGLE_DOWN
(scroll arrows, the tail of a popover).
The control a popover opens beside, in canvas pixels.
bool valid
false for a popover with no anchor: it is centered
What a popover keeps clear at the screen's edges: the bars at the top and bottom, and the margin at b...
Where the panel's top-left corner goes.
The little tail on the panel: x,y is its top-left corner, w,h its size, direction the way it points (...
static GuiTheme & current()
The theme the rest of the library reads. The first call fills it in with GuiThemeInit().
8-bit-per-channel RGBA color used by the video interfaces.