From cf7ccddf1e936ec1eeaf34160ec6bfd9c85ece74 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 10 Jun 2013 22:05:58 +0200 Subject: [PATCH] Add horizontal orientation to TabHolder. Don't draw things outside current scissor rect. --- math/geom2d.h | 5 +++++ ui/ui_context.cpp | 8 ++++++++ ui/ui_context.h | 1 + ui/view.cpp | 6 +++++- ui/view.h | 7 ++++++- ui/viewgroup.cpp | 10 +++++++--- ui/viewgroup.h | 4 ++-- 7 files changed, 34 insertions(+), 7 deletions(-) diff --git a/math/geom2d.h b/math/geom2d.h index d72dd0ae29..a2faca80b1 100644 --- a/math/geom2d.h +++ b/math/geom2d.h @@ -30,6 +30,11 @@ struct Bounds { bool Contains(float px, float py) const { return (px >= x && py >= y && px < x + w && py < y + h); } + + bool Intersects(const Bounds &other) const { + return !(x > other.x2() || x2() < other.x || y > other.y2() || y2() < other.y); + } + float x2() const { return x + w; } float y2() const { return y + h; } float centerX() const { return x + w * 0.5f; } diff --git a/ui/ui_context.cpp b/ui/ui_context.cpp index 8751109c21..34d5edb732 100644 --- a/ui/ui_context.cpp +++ b/ui/ui_context.cpp @@ -77,6 +77,14 @@ void UIContext::PopScissor() { ActivateTopScissor(); } +Bounds UIContext::GetScissorBounds() { + if (!scissorStack_.empty()) + return scissorStack_.back(); + else + return Bounds(0, 0, dp_xres, dp_yres); +} + + void UIContext::ActivateTopScissor() { if (scissorStack_.size()) { const Bounds &bounds = scissorStack_.back(); diff --git a/ui/ui_context.h b/ui/ui_context.h index ed9e17aa40..146d92f106 100644 --- a/ui/ui_context.h +++ b/ui/ui_context.h @@ -43,6 +43,7 @@ public: // TODO: Support transformed bounds using stencil void PushScissor(const Bounds &bounds); void PopScissor(); + Bounds GetScissorBounds(); void ActivateTopScissor(); diff --git a/ui/view.cpp b/ui/view.cpp index 87df3a150e..476345108c 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -42,7 +42,7 @@ void MeasureBySpec(Size sz, float contentWidth, MeasureSpec spec, float *measure *measured = spec.size; } else if (sz == FILL_PARENT) { if (spec.type == UNSPECIFIED) - *measured = 0.0; // We have no value to set + *measured = contentWidth; // We have no value to set else *measured = spec.size; } else if (spec.type == EXACTLY || (spec.type == AT_MOST && *measured > spec.size)) { @@ -180,6 +180,10 @@ void ClickableItem::Draw(UIContext &dc) { dc.FillRect(style.background, bounds_); } +void Choice::GetContentDimensions(const UIContext &dc, float &w, float &h) const { + dc.Draw()->MeasureText(dc.theme->uiFont, text_.c_str(), &w, &h); +} + void Choice::Draw(UIContext &dc) { ClickableItem::Draw(dc); diff --git a/ui/view.h b/ui/view.h index 093c518718..9771654901 100644 --- a/ui/view.h +++ b/ui/view.h @@ -133,6 +133,10 @@ enum Orientation { ORIENT_VERTICAL, }; +inline Orientation Opposite(Orientation o) { + if (o == ORIENT_HORIZONTAL) return ORIENT_VERTICAL; else return ORIENT_HORIZONTAL; +} + enum MeasureSpecType { UNSPECIFIED, EXACTLY, @@ -167,7 +171,7 @@ class View; struct EventParams { View *v; uint32_t a, b, x, y; - const char *c; + std::string s; }; struct HandlerRegistration { @@ -416,6 +420,7 @@ public: Choice(const std::string &text, const std::string &smallText = "", LayoutParams *layoutParams = 0) : ClickableItem(layoutParams), text_(text), smallText_(smallText) {} + virtual void GetContentDimensions(const UIContext &dc, float &w, float &h) const; virtual void Draw(UIContext &dc); private: diff --git a/ui/viewgroup.cpp b/ui/viewgroup.cpp index e02cf1cc53..a928c5f7ad 100644 --- a/ui/viewgroup.cpp +++ b/ui/viewgroup.cpp @@ -47,8 +47,11 @@ void ViewGroup::Touch(const TouchInput &input) { void ViewGroup::Draw(UIContext &dc) { for (auto iter = views_.begin(); iter != views_.end(); ++iter) { // TODO: If there is a transformation active, transform input coordinates accordingly. - if ((*iter)->GetVisibility() == V_VISIBLE) - (*iter)->Draw(dc); + if ((*iter)->GetVisibility() == V_VISIBLE) { + // Check if bounds are in current scissor rectangle. + if (dc.GetScissorBounds().Intersects((*iter)->GetBounds())) + (*iter)->Draw(dc); + } } } @@ -530,6 +533,7 @@ void GridLayout::Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec ver // Okay, got the width we are supposed to adjust to. Now we can calculate the number of columns. int numColumns = (measuredWidth_ - settings_.spacing) / (settings_.columnWidth + settings_.spacing); + if (!numColumns) numColumns = 1; int numRows = (int)(views_.size() + (numColumns - 1)) / numColumns; float estimatedHeight = settings_.rowHeight * numRows; @@ -620,7 +624,7 @@ void GridLayout::Layout() { views_[i]->Layout(); x += itemBounds.w; - if (x >= bounds_.w) { + if (x + itemBounds.w >= bounds_.w) { x = 0; y += itemBounds.h + settings_.spacing; } else { diff --git a/ui/viewgroup.h b/ui/viewgroup.h index 27c40ecda5..d70d7bf4dd 100644 --- a/ui/viewgroup.h +++ b/ui/viewgroup.h @@ -197,9 +197,9 @@ public: class TabHolder : public LinearLayout { public: TabHolder(Orientation orientation, float stripSize, LayoutParams *layoutParams = 0) - : LinearLayout(ORIENT_HORIZONTAL, layoutParams), + : LinearLayout(Opposite(orientation), layoutParams), orientation_(orientation), stripSize_(stripSize), currentTab_(0) { - tabStrip_ = new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(stripSize, WRAP_CONTENT)); + tabStrip_ = new LinearLayout(orientation, new LinearLayoutParams(stripSize, WRAP_CONTENT)); Add(tabStrip_); }