diff --git a/UI/MainScreen.cpp b/UI/MainScreen.cpp index ec68e3f410..30001e539c 100644 --- a/UI/MainScreen.cpp +++ b/UI/MainScreen.cpp @@ -484,15 +484,14 @@ void GameBrowser::Refresh() { LinearLayout *topBar = new LinearLayout(ORIENT_HORIZONTAL, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT)); if (allowBrowsing_) { topBar->Add(new Spacer(2.0f)); - Margins pathMargins(5, 0); - topBar->Add(new TextView(path_.GetFriendlyPath().c_str(), ALIGN_VCENTER, true, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT, 1.0f))); + topBar->Add(new TextView(path_.GetFriendlyPath().c_str(), ALIGN_VCENTER, true, new LinearLayoutParams(FILL_PARENT, 64.0f, 1.0f))); #if defined(_WIN32) || defined(USING_QT_UI) - topBar->Add(new Choice(mm->T("Browse", "Browse...")))->OnClick.Handle(this, &GameBrowser::HomeClick); + topBar->Add(new Choice(mm->T("Browse", "Browse..."), new LayoutParams(WRAP_CONTENT, 64.0f)))->OnClick.Handle(this, &GameBrowser::HomeClick); #else - topBar->Add(new Choice(mm->T("Home")))->OnClick.Handle(this, &GameBrowser::HomeClick); + topBar->Add(new Choice(mm->T("Home"), new LayoutParams(WRAP_CONTENT, 64.0f)))->OnClick.Handle(this, &GameBrowser::HomeClick); #endif } else { - topBar->Add(new Spacer(new LinearLayoutParams(1.0f))); + topBar->Add(new Spacer(new LinearLayoutParams(FILL_PARENT, 64.0f, 1.0f))); } ChoiceStrip *layoutChoice = topBar->Add(new ChoiceStrip(ORIENT_HORIZONTAL)); diff --git a/ext/native/ui/view.cpp b/ext/native/ui/view.cpp index 88bdab3619..6f09ad0b22 100644 --- a/ext/native/ui/view.cpp +++ b/ext/native/ui/view.cpp @@ -102,9 +102,10 @@ void MeasureBySpec(Size sz, float contentWidth, MeasureSpec spec, float *measure *measured = contentWidth < spec.size ? contentWidth : spec.size; else if (spec.type == EXACTLY) *measured = spec.size; - } else if (sz == FILL_PARENT) { + } else if (sz == FILL_PARENT) { + // UNSPECIFIED may have a minimum size of the parent. Let's use it to fill. if (spec.type == UNSPECIFIED) - *measured = contentWidth; // We have no value to set + *measured = std::max(spec.size, contentWidth); else *measured = spec.size; } else if (spec.type == EXACTLY || (spec.type == AT_MOST && *measured > spec.size)) { @@ -112,6 +113,24 @@ void MeasureBySpec(Size sz, float contentWidth, MeasureSpec spec, float *measure } } +void ApplyBoundBySpec(float &bound, MeasureSpec spec) { + switch (spec.type) { + case AT_MOST: + bound = bound < spec.size ? bound : spec.size; + break; + case EXACTLY: + bound = spec.size; + break; + case UNSPECIFIED: + break; + } +} + +void ApplyBoundsBySpec(Bounds &bounds, MeasureSpec horiz, MeasureSpec vert) { + ApplyBoundBySpec(bounds.w, horiz); + ApplyBoundBySpec(bounds.h, vert); +} + void Event::Add(std::function func) { HandlerRegistration reg; reg.func = func; @@ -142,7 +161,7 @@ View::~View() { void View::Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec vert) { float contentW = 0.0f, contentH = 0.0f; - GetContentDimensions(dc, contentW, contentH); + GetContentDimensionsBySpec(dc, horiz, vert, contentW, contentH); MeasureBySpec(layoutParams_->width, contentW, horiz, &measuredWidth_); MeasureBySpec(layoutParams_->height, contentH, vert, &measuredHeight_); } @@ -154,6 +173,10 @@ void View::GetContentDimensions(const UIContext &dc, float &w, float &h) const { h = 10.0f; } +void View::GetContentDimensionsBySpec(const UIContext &dc, MeasureSpec horiz, MeasureSpec vert, float &w, float &h) const { + GetContentDimensions(dc, w, h); +} + void View::Query(float x, float y, std::vector &list) { if (bounds_.Contains(x, y)) { list.push_back(this); @@ -657,17 +680,22 @@ void Thin3DTextureView::Draw(UIContext &dc) { } } -void TextView::GetContentDimensions(const UIContext &dc, float &w, float &h) const { - // We don't have the bounding w/h yet, so stick with hardset layout params. +void TextView::GetContentDimensionsBySpec(const UIContext &dc, MeasureSpec horiz, MeasureSpec vert, float &w, float &h) const { Bounds bounds(0, 0, layoutParams_->width, layoutParams_->height); + if (bounds.w < 0) { + // If there's no size, let's grow as big as we want. + bounds.w = horiz.size == 0 ? 1000.f : horiz.size; + } + if (bounds.h < 0) { + bounds.h = vert.size == 0 ? 1000.f : vert.size; + } + ApplyBoundsBySpec(bounds, horiz, vert); dc.MeasureTextRect(small_ ? dc.theme->uiFontSmall : dc.theme->uiFont, text_.c_str(), (int)text_.length(), bounds, &w, &h, textAlign_); } void TextView::Draw(UIContext &dc) { - float w, h; - GetContentDimensions(dc, w, h); bool clip = false; - if (w > bounds_.w || h > bounds_.h) + if (measuredWidth_ > bounds_.w || measuredHeight_ > bounds_.h) clip = true; if (bounds_.w < 0 || bounds_.h < 0 || !clip_) { // We have a layout but, but try not to screw up rendering. diff --git a/ext/native/ui/view.h b/ext/native/ui/view.h index 370b5b0483..69a7a908c6 100644 --- a/ext/native/ui/view.h +++ b/ext/native/ui/view.h @@ -388,6 +388,7 @@ public: // Override this for easy standard behaviour. No need to override Measure. virtual void GetContentDimensions(const UIContext &dc, float &w, float &h) const; + virtual void GetContentDimensionsBySpec(const UIContext &dc, MeasureSpec horiz, MeasureSpec vert, float &w, float &h) const; // Called when the layout is done. void SetBounds(Bounds bounds) { bounds_ = bounds; } @@ -742,7 +743,7 @@ public: TextView(const std::string &text, int textAlign, bool small, LayoutParams *layoutParams = 0) : InertView(layoutParams), text_(text), textAlign_(textAlign), textColor_(0xFFFFFFFF), small_(small), shadow_(false), focusable_(false), clip_(true) {} - void GetContentDimensions(const UIContext &dc, float &w, float &h) const override; + void GetContentDimensionsBySpec(const UIContext &dc, MeasureSpec horiz, MeasureSpec vert, float &w, float &h) const override; void Draw(UIContext &dc) override; void SetText(const std::string &text) { text_ = text; } diff --git a/ext/native/ui/viewgroup.cpp b/ext/native/ui/viewgroup.cpp index 94f093d297..6e4e0e73e6 100644 --- a/ext/native/ui/viewgroup.cpp +++ b/ext/native/ui/viewgroup.cpp @@ -405,12 +405,12 @@ void LinearLayout::Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec v int numVisible = 0; - for (size_t i = 0; i < views_.size(); i++) { - if (views_[i]->GetVisibility() == V_GONE) + for (View *view : views_) { + if (view->GetVisibility() == V_GONE) continue; numVisible++; - const LinearLayoutParams *linLayoutParams = views_[i]->GetLayoutParams()->As(); + const LinearLayoutParams *linLayoutParams = view->GetLayoutParams()->As(); Margins margins = defaultMargins_; @@ -424,20 +424,21 @@ void LinearLayout::Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec v MeasureSpec v = vert; if (v.type == UNSPECIFIED && measuredHeight_ != 0.0) v = MeasureSpec(AT_MOST, measuredHeight_); - views_[i]->Measure(dc, MeasureSpec(UNSPECIFIED, measuredWidth_), v - (float)margins.vert()); + view->Measure(dc, MeasureSpec(UNSPECIFIED, measuredWidth_), v - (float)margins.vert()); } else if (orientation_ == ORIENT_VERTICAL) { MeasureSpec h = horiz; - if (h.type == UNSPECIFIED && measuredWidth_ != 0) h = MeasureSpec(AT_MOST, measuredWidth_); - views_[i]->Measure(dc, h - (float)margins.horiz(), MeasureSpec(UNSPECIFIED, measuredHeight_)); + if (h.type == UNSPECIFIED && measuredWidth_ != 0) + h = MeasureSpec(AT_MOST, measuredWidth_); + view->Measure(dc, h - (float)margins.horiz(), MeasureSpec(UNSPECIFIED, measuredHeight_)); } float amount; if (orientation_ == ORIENT_HORIZONTAL) { - amount = views_[i]->GetMeasuredWidth() + margins.horiz(); - maxOther = std::max(maxOther, views_[i]->GetMeasuredHeight() + margins.vert()); + amount = view->GetMeasuredWidth() + margins.horiz(); + maxOther = std::max(maxOther, view->GetMeasuredHeight() + margins.vert()); } else { - amount = views_[i]->GetMeasuredHeight() + margins.vert(); - maxOther = std::max(maxOther, views_[i]->GetMeasuredWidth() + margins.horiz()); + amount = view->GetMeasuredHeight() + margins.vert(); + maxOther = std::max(maxOther, view->GetMeasuredWidth() + margins.horiz()); } sum += amount; @@ -469,10 +470,10 @@ void LinearLayout::Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec v float usedWidth = 0.0f; // Redistribute the stretchy ones! and remeasure the children! - for (size_t i = 0; i < views_.size(); i++) { - if (views_[i]->GetVisibility() == V_GONE) + for (View *view : views_) { + if (view->GetVisibility() == V_GONE) continue; - const LinearLayoutParams *linLayoutParams = views_[i]->GetLayoutParams()->As(); + const LinearLayoutParams *linLayoutParams = view->GetLayoutParams()->As(); if (linLayoutParams && linLayoutParams->weight > 0.0f) { Margins margins = defaultMargins_; @@ -485,8 +486,8 @@ void LinearLayout::Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec v if (horiz.type == EXACTLY) { h.type = EXACTLY; } - views_[i]->Measure(dc, h, v - (float)margins.vert()); - usedWidth += views_[i]->GetMeasuredWidth(); + view->Measure(dc, h, v - (float)margins.vert()); + usedWidth += view->GetMeasuredWidth(); } } @@ -507,10 +508,10 @@ void LinearLayout::Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec v float usedHeight = 0.0f; // Redistribute the stretchy ones! and remeasure the children! - for (size_t i = 0; i < views_.size(); i++) { - if (views_[i]->GetVisibility() == V_GONE) + for (View *view : views_) { + if (view->GetVisibility() == V_GONE) continue; - const LinearLayoutParams *linLayoutParams = views_[i]->GetLayoutParams()->As(); + const LinearLayoutParams *linLayoutParams = view->GetLayoutParams()->As(); if (linLayoutParams && linLayoutParams->weight > 0.0f) { Margins margins = defaultMargins_; @@ -523,8 +524,8 @@ void LinearLayout::Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec v if (vert.type == EXACTLY) { v.type = EXACTLY; } - views_[i]->Measure(dc, h - (float)margins.horiz(), v); - usedHeight += views_[i]->GetMeasuredHeight(); + view->Measure(dc, h - (float)margins.horiz(), v); + usedHeight += view->GetMeasuredHeight(); } } @@ -627,15 +628,15 @@ void ScrollView::Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec ver } // The scroll view itself simply obeys its parent - but also tries to fit the child if possible. - MeasureBySpec(layoutParams_->width, 0.0f, horiz, &measuredWidth_); - MeasureBySpec(layoutParams_->height, 0.0f, vert, &measuredHeight_); + MeasureBySpec(layoutParams_->width, horiz.size, horiz, &measuredWidth_); + MeasureBySpec(layoutParams_->height, vert.size, vert, &measuredHeight_); if (views_.size()) { if (orientation_ == ORIENT_HORIZONTAL) { - views_[0]->Measure(dc, MeasureSpec(UNSPECIFIED), MeasureSpec(AT_MOST, measuredHeight_ - margins.vert())); + views_[0]->Measure(dc, MeasureSpec(UNSPECIFIED, measuredWidth_), MeasureSpec(AT_MOST, measuredHeight_ - margins.vert())); MeasureBySpec(layoutParams_->height, views_[0]->GetMeasuredHeight(), vert, &measuredHeight_); } else { - views_[0]->Measure(dc, MeasureSpec(AT_MOST, measuredWidth_ - margins.horiz()), MeasureSpec(UNSPECIFIED)); + views_[0]->Measure(dc, MeasureSpec(AT_MOST, measuredWidth_ - margins.horiz()), MeasureSpec(UNSPECIFIED, measuredHeight_)); MeasureBySpec(layoutParams_->width, views_[0]->GetMeasuredWidth(), horiz, &measuredWidth_); } if (orientation_ == ORIENT_VERTICAL && vert.type != EXACTLY) { @@ -966,8 +967,8 @@ void AnchorLayout::Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec v Size width = WRAP_CONTENT; Size height = WRAP_CONTENT; - MeasureSpec specW(UNSPECIFIED, 0.0f); - MeasureSpec specH(UNSPECIFIED, 0.0f); + MeasureSpec specW(UNSPECIFIED, measuredWidth_); + MeasureSpec specH(UNSPECIFIED, measuredHeight_); if (!overflow_) { if (horiz.type != UNSPECIFIED) { @@ -1106,9 +1107,9 @@ TabHolder::TabHolder(Orientation orientation, float stripSize, LayoutParams *lay currentTab_(0) { SetSpacing(0.0f); if (orientation == ORIENT_HORIZONTAL) { - tabStrip_ = new ChoiceStrip(orientation, new LayoutParams(FILL_PARENT, WRAP_CONTENT)); + tabStrip_ = new ChoiceStrip(orientation, new LayoutParams(WRAP_CONTENT, WRAP_CONTENT)); tabStrip_->SetTopTabs(true); - tabScroll_ = new ScrollView(orientation, new LayoutParams(FILL_PARENT, FILL_PARENT)); + tabScroll_ = new ScrollView(orientation, new LayoutParams(FILL_PARENT, WRAP_CONTENT)); tabScroll_->Add(tabStrip_); Add(tabScroll_); } else { @@ -1162,7 +1163,7 @@ ChoiceStrip::ChoiceStrip(Orientation orientation, LayoutParams *layoutParams) void ChoiceStrip::AddChoice(const std::string &title) { StickyChoice *c = new StickyChoice(title, "", orientation_ == ORIENT_HORIZONTAL ? - 0 : + nullptr : new LinearLayoutParams(FILL_PARENT, ITEM_HEIGHT)); c->OnClick.Handle(this, &ChoiceStrip::OnChoiceClick); Add(c); @@ -1173,7 +1174,7 @@ void ChoiceStrip::AddChoice(const std::string &title) { void ChoiceStrip::AddChoice(ImageID buttonImage) { StickyChoice *c = new StickyChoice(buttonImage, orientation_ == ORIENT_HORIZONTAL ? - 0 : + nullptr : new LinearLayoutParams(FILL_PARENT, ITEM_HEIGHT)); c->OnClick.Handle(this, &ChoiceStrip::OnChoiceClick); Add(c);