Merge pull request #8900 from unknownbrackets/ui-text-wrap

Wrap text in many places where it makes sense
This commit is contained in:
Henrik Rydgård authored and GitHub committed 2016-08-09 00:16:13 +02:00
commit 0924dbfdee
11 files changed
+296 -153

No files matched your search

+74 -29
View File
@@ -46,7 +46,6 @@ GameScreen::~GameScreen() {
void GameScreen::CreateViews() {
GameInfo *info = g_gameInfoCache->GetInfo(NULL, gamePath_, GAMEINFO_WANTBG | GAMEINFO_WANTSIZE);
g_gameInfoCache->WaitUntilDone(info);
I18NCategory *di = GetI18NCategory("Dialog");
I18NCategory *ga = GetI18NCategory("Game");
@@ -67,18 +66,31 @@ void GameScreen::CreateViews() {
leftColumn->Add(new Choice(di->T("Back"), "", false, new AnchorLayoutParams(150, WRAP_CONTENT, 10, NONE, NONE, 10)))->OnClick.Handle(this, &GameScreen::OnSwitchBack);
if (info) {
texvGameIcon_ = leftColumn->Add(new Thin3DTextureView(0, IS_DEFAULT, new AnchorLayoutParams(144 * 2, 80 * 2, 10, 10, NONE, NONE)));
tvTitle_ = leftColumn->Add(new TextView(info->GetTitle(), ALIGN_LEFT, false, new AnchorLayoutParams(10, 200, NONE, NONE)));
LinearLayout *infoLayout = new LinearLayout(ORIENT_VERTICAL, new AnchorLayoutParams(10, 200, NONE, NONE));
leftColumn->Add(infoLayout);
tvTitle_ = infoLayout->Add(new TextView(info->GetTitle(), ALIGN_LEFT | FLAG_WRAP_TEXT, false, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT)));
tvTitle_->SetShadow(true);
infoLayout->Add(new Spacer(12));
// This one doesn't need to be updated.
leftColumn->Add(new TextView(gamePath_, ALIGN_LEFT, true, new AnchorLayoutParams(10, 250, NONE, NONE)))->SetShadow(true);
tvGameSize_ = leftColumn->Add(new TextView("...", ALIGN_LEFT, true, new AnchorLayoutParams(10, 290, NONE, NONE)));
infoLayout->Add(new TextView(gamePath_, ALIGN_LEFT | FLAG_WRAP_TEXT, true, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT)))->SetShadow(true);
tvGameSize_ = infoLayout->Add(new TextView("...", ALIGN_LEFT, true, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT)));
tvGameSize_->SetShadow(true);
tvSaveDataSize_ = leftColumn->Add(new TextView("...", ALIGN_LEFT, true, new AnchorLayoutParams(10, 320, NONE, NONE)));
tvSaveDataSize_ = infoLayout->Add(new TextView("...", ALIGN_LEFT, true, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT)));
tvSaveDataSize_->SetShadow(true);
tvInstallDataSize_ = leftColumn->Add(new TextView("", ALIGN_LEFT, true, new AnchorLayoutParams(10, 350, NONE, NONE)));
tvInstallDataSize_ = infoLayout->Add(new TextView("", ALIGN_LEFT, true, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT)));
tvInstallDataSize_->SetShadow(true);
tvRegion_ = leftColumn->Add(new TextView("", ALIGN_LEFT, true, new AnchorLayoutParams(10, 380, NONE, NONE)));
tvInstallDataSize_->SetVisibility(V_GONE);
tvRegion_ = infoLayout->Add(new TextView("", ALIGN_LEFT, true, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT)));
tvRegion_->SetShadow(true);
} else {
texvGameIcon_ = nullptr;
tvTitle_ = nullptr;
tvGameSize_ = nullptr;
tvSaveDataSize_ = nullptr;
tvInstallDataSize_ = nullptr;
tvRegion_ = nullptr;
}
ViewGroup *rightColumn = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(300, FILL_PARENT, actionMenuMargins));
@@ -87,39 +99,54 @@ void GameScreen::CreateViews() {
LinearLayout *rightColumnItems = new LinearLayout(ORIENT_VERTICAL);
rightColumnItems->SetSpacing(0.0f);
rightColumn->Add(rightColumnItems);
Choice *play = new Choice(ga->T("Play"));
rightColumnItems->Add(play)->OnClick.Handle(this, &GameScreen::OnPlay);
if (info && !info->id.empty())
{
if (info->hasConfig)
{
rightColumnItems->Add(new Choice(ga->T("Game Settings")))->OnClick.Handle(this, &GameScreen::OnGameSettings);
rightColumnItems->Add(new Choice(ga->T("Delete Game Config")))->OnClick.Handle(this, &GameScreen::OnDeleteConfig);
}
else
{
rightColumnItems->Add(new Choice(ga->T("Create Game Config")))->OnClick.Handle(this, &GameScreen::OnCreateConfig);
}
rightColumnItems->Add(new Choice(ga->T("Play")))->OnClick.Handle(this, &GameScreen::OnPlay);
if (info) {
btnGameSettings_ = rightColumnItems->Add(new Choice(ga->T("Game Settings")));
btnGameSettings_->OnClick.Handle(this, &GameScreen::OnGameSettings);
btnDeleteGameConfig_ = rightColumnItems->Add(new Choice(ga->T("Delete Game Config")));
btnDeleteGameConfig_->OnClick.Handle(this, &GameScreen::OnDeleteConfig);
btnCreateGameConfig_ = rightColumnItems->Add(new Choice(ga->T("Create Game Config")));
btnCreateGameConfig_->OnClick.Handle(this, &GameScreen::OnCreateConfig);
btnGameSettings_->SetVisibility(V_GONE);
btnDeleteGameConfig_->SetVisibility(V_GONE);
btnCreateGameConfig_->SetVisibility(V_GONE);
btnDeleteSaveData_ = new Choice(ga->T("Delete Save Data"));
rightColumnItems->Add(btnDeleteSaveData_)->OnClick.Handle(this, &GameScreen::OnDeleteSaveData);
btnDeleteSaveData_->SetVisibility(V_GONE);
} else {
btnGameSettings_ = nullptr;
btnCreateGameConfig_ = nullptr;
btnDeleteGameConfig_ = nullptr;
btnDeleteSaveData_ = nullptr;
}
std::vector<std::string> saveDirs = info->GetSaveDataDirectories();
if (saveDirs.size()) {
rightColumnItems->Add(new Choice(ga->T("Delete Save Data")))->OnClick.Handle(this, &GameScreen::OnDeleteSaveData);
}
rightColumnItems->Add(new Choice(ga->T("Delete Game")))->OnClick.Handle(this, &GameScreen::OnDeleteGame);
rightColumnItems->Add(AddOtherChoice(new Choice(ga->T("Delete Game"))))->OnClick.Handle(this, &GameScreen::OnDeleteGame);
if (host->CanCreateShortcut()) {
rightColumnItems->Add(new Choice(ga->T("Create Shortcut")))->OnClick.Handle(this, &GameScreen::OnCreateShortcut);
rightColumnItems->Add(AddOtherChoice(new Choice(ga->T("Create Shortcut"))))->OnClick.Handle(this, &GameScreen::OnCreateShortcut);
}
if (isRecentGame(gamePath_)) {
rightColumnItems->Add(new Choice(ga->T("Remove From Recent")))->OnClick.Handle(this, &GameScreen::OnRemoveFromRecent);
rightColumnItems->Add(AddOtherChoice(new Choice(ga->T("Remove From Recent"))))->OnClick.Handle(this, &GameScreen::OnRemoveFromRecent);
}
#ifdef _WIN32
rightColumnItems->Add(new Choice(ga->T("Show In Folder")))->OnClick.Handle(this, &GameScreen::OnShowInFolder);
rightColumnItems->Add(AddOtherChoice(new Choice(ga->T("Show In Folder"))))->OnClick.Handle(this, &GameScreen::OnShowInFolder);
#endif
if (g_Config.bEnableCheats) {
rightColumnItems->Add(new Choice(pa->T("Cheats")))->OnClick.Handle(this, &GameScreen::OnCwCheat);
rightColumnItems->Add(AddOtherChoice(new Choice(pa->T("Cheats"))))->OnClick.Handle(this, &GameScreen::OnCwCheat);
}
}
UI::Choice *GameScreen::AddOtherChoice(UI::Choice *choice) {
otherChoices_.push_back(choice);
// While loading.
choice->SetVisibility(UI::V_GONE);
return choice;
}
UI::EventReturn GameScreen::OnCreateConfig(UI::EventParams &e)
{
GameInfo *info = g_gameInfoCache->GetInfo(NULL, gamePath_,0);
@@ -187,6 +214,7 @@ void GameScreen::update(InputState &input) {
if (info->installDataSize > 0) {
sprintf(temp, "%s: %1.2f %s", ga->T("InstallData"), (float) (info->installDataSize) / 1024.f / 1024.f, ga->T("MB"));
tvInstallDataSize_->SetText(temp);
tvInstallDataSize_->SetVisibility(UI::V_VISIBLE);
}
}
@@ -200,6 +228,23 @@ void GameScreen::update(InputState &input) {
};
tvRegion_->SetText(ga->T(regionNames[info->region]));
}
if (!info->id.empty()) {
btnGameSettings_->SetVisibility(info->hasConfig ? UI::V_VISIBLE : UI::V_GONE);
btnDeleteGameConfig_->SetVisibility(info->hasConfig ? UI::V_VISIBLE : UI::V_GONE);
btnCreateGameConfig_->SetVisibility(info->hasConfig ? UI::V_GONE : UI::V_VISIBLE);
std::vector<std::string> saveDirs = info->GetSaveDataDirectories();
if (saveDirs.size()) {
btnDeleteSaveData_->SetVisibility(UI::V_VISIBLE);
}
}
if (!info->IsPending()) {
// At this point, the above buttons won't become visible. We can show these now.
for (UI::Choice *choice : otherChoices_) {
choice->SetVisibility(UI::V_VISIBLE);
}
}
}
UI::EventReturn GameScreen::OnShowInFolder(UI::EventParams &e) {
+8
View File
@@ -44,6 +44,8 @@ protected:
bool isRecentGame(const std::string &gamePath);
private:
UI::Choice *AddOtherChoice(UI::Choice *choice);
// Event handlers
UI::EventReturn OnPlay(UI::EventParams &e);
UI::EventReturn OnGameSettings(UI::EventParams &e);
@@ -64,4 +66,10 @@ private:
UI::TextView *tvSaveDataSize_;
UI::TextView *tvInstallDataSize_;
UI::TextView *tvRegion_;
UI::Choice *btnGameSettings_;
UI::Choice *btnCreateGameConfig_;
UI::Choice *btnDeleteGameConfig_;
UI::Choice *btnDeleteSaveData_;
std::vector<UI::Choice *> otherChoices_;
};
+6 -7
View File
@@ -284,7 +284,7 @@ void GameButton::Draw(UIContext &dc) {
title_ = ReplaceAll(title_, "\n", " ");
}
dc.MeasureText(dc.GetFontStyle(), title_.c_str(), &tw, &th, 0);
dc.MeasureText(dc.GetFontStyle(), 1.0f, 1.0f, title_.c_str(), &tw, &th, 0);
int availableWidth = bounds_.w - 150;
float sineWidth = std::max(0.0f, (tw - availableWidth)) / 2.0f;
@@ -367,7 +367,7 @@ void DirButton::Draw(UIContext &dc) {
}
float tw, th;
dc.MeasureText(dc.GetFontStyle(), text.c_str(), &tw, &th, 0);
dc.MeasureText(dc.GetFontStyle(), 1.0f, 1.0f, text.c_str(), &tw, &th, 0);
bool compact = bounds_.w < 180;
@@ -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 | FLAG_WRAP_TEXT, 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));
+2 -2
View File
@@ -16,7 +16,7 @@ void OnScreenMessagesView::Draw(UIContext &dc) {
// Get height
float w, h;
dc.MeasureText(dc.theme->uiFont, "Wg", &w, &h);
dc.MeasureText(dc.theme->uiFont, 1.0f, 1.0f, "Wg", &w, &h);
float y = 10.0f;
// Then draw them all.
@@ -27,7 +27,7 @@ void OnScreenMessagesView::Draw(UIContext &dc) {
if (alpha < 0.0) alpha = 0.0f;
// Messages that are wider than the screen are left-aligned instead of centered.
float tw, th;
dc.MeasureText(dc.theme->uiFont, iter->text.c_str(), &tw, &th);
dc.MeasureText(dc.theme->uiFont, 1.0f, 1.0f, iter->text.c_str(), &tw, &th);
float x = bounds_.centerX();
int align = ALIGN_TOP | ALIGN_HCENTER;
if (tw > bounds_.w) {
+20 -12
View File
@@ -51,20 +51,28 @@ std::string GetFileDateAsString(std::string filename) {
return "";
}
static std::string TrimString(const std::string &str) {
size_t pos = str.find_last_not_of(" \r\n\t");
if (pos != str.npos) {
return str.substr(0, pos + 1);
}
return str;
}
class SavedataPopupScreen : public PopupScreen {
public:
SavedataPopupScreen(std::string savePath, std::string title) : PopupScreen(title), savePath_(savePath) {
SavedataPopupScreen(std::string savePath, std::string title) : PopupScreen(TrimString(title)), savePath_(savePath) {
}
void CreatePopupContents(UI::ViewGroup *parent) override {
using namespace UI;
GameInfo *ginfo = g_gameInfoCache->GetInfo(screenManager()->getThin3DContext(), savePath_, GAMEINFO_WANTBG | GAMEINFO_WANTSIZE);
LinearLayout *root = new LinearLayout(ORIENT_VERTICAL);
parent->Add(root);
LinearLayout *content = new LinearLayout(ORIENT_VERTICAL);
parent->Add(content);
if (!ginfo)
return;
LinearLayout *toprow = new LinearLayout(ORIENT_HORIZONTAL, new LayoutParams(FILL_PARENT, WRAP_CONTENT));
root->Add(toprow);
content->Add(toprow);
I18NCategory *sa = GetI18NCategory("Savedata");
if (ginfo->fileType == FILETYPE_PSP_SAVEDATA_DIRECTORY) {
@@ -74,15 +82,15 @@ public:
if (ginfo->iconTexture) {
toprow->Add(new Thin3DTextureView(ginfo->iconTexture, IS_FIXED, new LinearLayoutParams(Margins(10, 5))));
}
LinearLayout *topright = new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(1.0));
LinearLayout *topright = new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(WRAP_CONTENT, WRAP_CONTENT, 1.0f));
topright->SetSpacing(1.0f);
topright->Add(new TextView(savedata_title, 0, false));
topright->Add(new TextView(savedata_title, ALIGN_LEFT | FLAG_WRAP_TEXT, false));
topright->Add(new TextView(StringFromFormat("%d kB", ginfo->gameSize / 1024), 0, true));
topright->Add(new TextView(GetFileDateAsString(savePath_ + "/PARAM.SFO"), 0, true));
toprow->Add(topright);
root->Add(new Spacer(3.0));
root->Add(new TextView(savedata_detail, 0, true, new LinearLayoutParams(Margins(10, 0))));
root->Add(new Spacer(3.0));
content->Add(new Spacer(3.0));
content->Add(new TextView(ReplaceAll(savedata_detail, "\r", ""), ALIGN_LEFT | FLAG_WRAP_TEXT, true, new LinearLayoutParams(Margins(10, 0))));
content->Add(new Spacer(3.0));
} else {
std::string image_path = ReplaceAll(savePath_, ".ppst", ".jpg");
if (File::Exists(image_path)) {
@@ -91,14 +99,14 @@ public:
} else {
toprow->Add(new TextView(sa->T("No screenshot"), new LinearLayoutParams(Margins(10, 5))));
}
root->Add(new TextView(GetFileDateAsString(savePath_), 0, true, new LinearLayoutParams(Margins(10, 5))));
content->Add(new TextView(GetFileDateAsString(savePath_), 0, true, new LinearLayoutParams(Margins(10, 5))));
}
I18NCategory *di = GetI18NCategory("Dialog");
LinearLayout *buttons = new LinearLayout(ORIENT_HORIZONTAL);
buttons->Add(new Button(di->T("Back"), new LinearLayoutParams(1.0)))->OnClick.Handle<UIScreen>(this, &UIScreen::OnBack);
buttons->Add(new Button(di->T("Delete"), new LinearLayoutParams(1.0)))->OnClick.Handle(this, &SavedataPopupScreen::OnDeleteButtonClick);
root->Add(buttons);
content->Add(buttons);
}
protected:
@@ -243,7 +251,7 @@ void SavedataButton::Draw(UIContext &dc) {
subtitle_ = CleanSaveString(savedata_title) + StringFromFormat(" (%d kB)", ginfo->gameSize / 1024);
}
dc.MeasureText(dc.GetFontStyle(), title_.c_str(), &tw, &th, 0);
dc.MeasureText(dc.GetFontStyle(), 1.0f, 1.0f, title_.c_str(), &tw, &th, 0);
int availableWidth = bounds_.w - 150;
float sineWidth = std::max(0.0f, (tw - availableWidth)) / 2.0f;
+8 -13
View File
@@ -127,36 +127,31 @@ void UIContext::SetFontStyle(const UI::FontStyle &fontStyle) {
}
}
void UIContext::MeasureText(const UI::FontStyle &style, const char *str, float *x, float *y, int align) const {
MeasureTextCount(style, str, (int)strlen(str), x, y, align);
void UIContext::MeasureText(const UI::FontStyle &style, float scaleX, float scaleY, const char *str, float *x, float *y, int align) const {
MeasureTextCount(style, scaleX, scaleY, str, (int)strlen(str), x, y, align);
}
void UIContext::MeasureTextCount(const UI::FontStyle &style, const char *str, int count, float *x, float *y, int align) const {
void UIContext::MeasureTextCount(const UI::FontStyle &style, float scaleX, float scaleY, const char *str, int count, float *x, float *y, int align) const {
if (!textDrawer_ || (align & FLAG_DYNAMIC_ASCII)) {
float sizeFactor = (float)style.sizePts / 24.0f;
Draw()->SetFontScale(fontScaleX_ * sizeFactor, fontScaleY_ * sizeFactor);
Draw()->SetFontScale(scaleX * sizeFactor, scaleY * sizeFactor);
Draw()->MeasureTextCount(style.atlasFont, str, count, x, y);
} else {
textDrawer_->SetFont(style.fontName.c_str(), style.sizePts, style.flags);
textDrawer_->SetFontScale(fontScaleX_, fontScaleY_);
textDrawer_->SetFontScale(scaleX, scaleY);
textDrawer_->MeasureString(str, count, x, y);
textDrawer_->SetFont(fontStyle_->fontName.c_str(), fontStyle_->sizePts, fontStyle_->flags);
}
}
void UIContext::MeasureTextRect(const UI::FontStyle &style, const char *str, int count, const Bounds &bounds, float *x, float *y, int align) const {
if ((align & FLAG_WRAP_TEXT) == 0) {
MeasureTextCount(style, str, count, x, y, align);
return;
}
void UIContext::MeasureTextRect(const UI::FontStyle &style, float scaleX, float scaleY, const char *str, int count, const Bounds &bounds, float *x, float *y, int align) const {
if (!textDrawer_ || (align & FLAG_DYNAMIC_ASCII)) {
float sizeFactor = (float)style.sizePts / 24.0f;
Draw()->SetFontScale(fontScaleX_ * sizeFactor, fontScaleY_ * sizeFactor);
Draw()->SetFontScale(scaleX * sizeFactor, scaleY * sizeFactor);
Draw()->MeasureTextRect(style.atlasFont, str, count, bounds, x, y, align);
} else {
textDrawer_->SetFont(style.fontName.c_str(), style.sizePts, style.flags);
textDrawer_->SetFontScale(fontScaleX_, fontScaleY_);
textDrawer_->SetFontScale(scaleX, scaleY);
textDrawer_->MeasureStringRect(str, count, bounds, x, y, align);
textDrawer_->SetFont(fontStyle_->fontName.c_str(), fontStyle_->sizePts, fontStyle_->flags);
}
+3 -3
View File
@@ -59,9 +59,9 @@ public:
void SetFontStyle(const UI::FontStyle &style);
const UI::FontStyle &GetFontStyle() { return *fontStyle_; }
void SetFontScale(float scaleX, float scaleY);
void MeasureTextCount(const UI::FontStyle &style, const char *str, int count, float *x, float *y, int align = 0) const;
void MeasureText(const UI::FontStyle &style, const char *str, float *x, float *y, int align = 0) const;
void MeasureTextRect(const UI::FontStyle &style, const char *str, int count, const Bounds &bounds, float *x, float *y, int align = 0) const;
void MeasureTextCount(const UI::FontStyle &style, float scaleX, float scaleY, const char *str, int count, float *x, float *y, int align = 0) const;
void MeasureText(const UI::FontStyle &style, float scaleX, float scaleY, const char *str, float *x, float *y, int align = 0) const;
void MeasureTextRect(const UI::FontStyle &style, float scaleX, float scaleY, const char *str, int count, const Bounds &bounds, float *x, float *y, int align = 0) const;
void DrawText(const char *str, float x, float y, uint32_t color, int align = 0);
void DrawTextShadow(const char *str, float x, float y, uint32_t color, int align = 0);
void DrawTextRect(const char *str, const Bounds &bounds, uint32_t color, int align = 0);
+17 -9
View File
@@ -313,6 +313,14 @@ UI::EventReturn ListPopupScreen::OnListChoice(UI::EventParams &e) {
namespace UI {
std::string ChopTitle(const std::string &title) {
size_t pos = title.find('\n');
if (pos != title.npos) {
return title.substr(0, pos);
}
return title;
}
UI::EventReturn PopupMultiChoice::HandleClick(UI::EventParams &e) {
restoreFocus_ = HasFocus();
@@ -323,7 +331,7 @@ UI::EventReturn PopupMultiChoice::HandleClick(UI::EventParams &e) {
choices.push_back(category ? category->T(choices_[i]) : choices_[i]);
}
ListPopupScreen *popupScreen = new ListPopupScreen(text_, choices, *value_ - minVal_,
ListPopupScreen *popupScreen = new ListPopupScreen(ChopTitle(text_), choices, *value_ - minVal_,
std::bind(&PopupMultiChoice::ChoiceCallback, this, placeholder::_1));
popupScreen->SetHiddenChoices(hidden_);
screenManager_->push(popupScreen);
@@ -369,7 +377,7 @@ void PopupMultiChoice::Draw(UIContext &dc) {
dc.SetFontStyle(dc.theme->uiFont);
float ignore;
dc.MeasureText(dc.theme->uiFont, valueText_.c_str(), &textPadding_.right, &ignore, ALIGN_RIGHT | ALIGN_VCENTER);
dc.MeasureText(dc.theme->uiFont, 1.0f, 1.0f, valueText_.c_str(), &textPadding_.right, &ignore, ALIGN_RIGHT | ALIGN_VCENTER);
textPadding_.right += paddingX;
Choice::Draw(dc);
@@ -403,7 +411,7 @@ PopupSliderChoiceFloat::PopupSliderChoiceFloat(float *value, float minValue, flo
EventReturn PopupSliderChoice::HandleClick(EventParams &e) {
restoreFocus_ = HasFocus();
SliderPopupScreen *popupScreen = new SliderPopupScreen(value_, minValue_, maxValue_, text_, step_, units_);
SliderPopupScreen *popupScreen = new SliderPopupScreen(value_, minValue_, maxValue_, ChopTitle(text_), step_, units_);
popupScreen->OnChange.Handle(this, &PopupSliderChoice::HandleChange);
screenManager_->push(popupScreen);
return EVENT_DONE;
@@ -435,7 +443,7 @@ void PopupSliderChoice::Draw(UIContext &dc) {
}
float ignore;
dc.MeasureText(dc.theme->uiFont, temp, &textPadding_.right, &ignore, ALIGN_RIGHT | ALIGN_VCENTER);
dc.MeasureText(dc.theme->uiFont, 1.0f, 1.0f, temp, &textPadding_.right, &ignore, ALIGN_RIGHT | ALIGN_VCENTER);
textPadding_.right += paddingX;
Choice::Draw(dc);
@@ -445,7 +453,7 @@ void PopupSliderChoice::Draw(UIContext &dc) {
EventReturn PopupSliderChoiceFloat::HandleClick(EventParams &e) {
restoreFocus_ = HasFocus();
SliderFloatPopupScreen *popupScreen = new SliderFloatPopupScreen(value_, minValue_, maxValue_, text_, step_, units_);
SliderFloatPopupScreen *popupScreen = new SliderFloatPopupScreen(value_, minValue_, maxValue_, ChopTitle(text_), step_, units_);
popupScreen->OnChange.Handle(this, &PopupSliderChoiceFloat::HandleChange);
screenManager_->push(popupScreen);
return EVENT_DONE;
@@ -477,7 +485,7 @@ void PopupSliderChoiceFloat::Draw(UIContext &dc) {
}
float ignore;
dc.MeasureText(dc.theme->uiFont, temp, &textPadding_.right, &ignore, ALIGN_RIGHT | ALIGN_VCENTER);
dc.MeasureText(dc.theme->uiFont, 1.0f, 1.0f, temp, &textPadding_.right, &ignore, ALIGN_RIGHT | ALIGN_VCENTER);
textPadding_.right += paddingX;
Choice::Draw(dc);
@@ -652,7 +660,7 @@ PopupTextInputChoice::PopupTextInputChoice(std::string *value, const std::string
EventReturn PopupTextInputChoice::HandleClick(EventParams &e) {
restoreFocus_ = HasFocus();
TextEditPopupScreen *popupScreen = new TextEditPopupScreen(value_, placeHolder_, text_, maxLen_);
TextEditPopupScreen *popupScreen = new TextEditPopupScreen(value_, placeHolder_, ChopTitle(text_), maxLen_);
popupScreen->OnChange.Handle(this, &PopupTextInputChoice::HandleChange);
screenManager_->push(popupScreen);
return EVENT_DONE;
@@ -667,7 +675,7 @@ void PopupTextInputChoice::Draw(UIContext &dc) {
dc.SetFontStyle(dc.theme->uiFont);
float ignore;
dc.MeasureText(dc.theme->uiFont, value_->c_str(), &textPadding_.right, &ignore, ALIGN_RIGHT | ALIGN_VCENTER);
dc.MeasureText(dc.theme->uiFont, 1.0f, 1.0f, value_->c_str(), &textPadding_.right, &ignore, ALIGN_RIGHT | ALIGN_VCENTER);
textPadding_.right += paddingX;
Choice::Draw(dc);
@@ -726,7 +734,7 @@ void ChoiceWithValueDisplay::Draw(UIContext &dc) {
}
float ignore;
dc.MeasureText(dc.theme->uiFont, valueText.str().c_str(), &textPadding_.right, &ignore, ALIGN_RIGHT | ALIGN_VCENTER);
dc.MeasureText(dc.theme->uiFont, 1.0f, 1.0f, valueText.str().c_str(), &textPadding_.right, &ignore, ALIGN_RIGHT | ALIGN_VCENTER);
textPadding_.right += paddingX;
Choice::Draw(dc);
+105 -37
View File
@@ -24,7 +24,7 @@ static recursive_mutex mutex_;
const float ITEM_HEIGHT = 64.f;
const float MIN_TEXT_SCALE = 0.8f;
const float MAX_ITEM_SIZE = 65535.0f;
struct DispatchQueueItem {
Event *e;
@@ -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<EventReturn(EventParams&)> 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<View *> &list) {
if (bounds_.Contains(x, y)) {
list.push_back(this);
@@ -390,14 +413,13 @@ void Item::GetContentDimensions(const UIContext &dc, float &w, float &h) const {
void ClickableItem::GetContentDimensions(const UIContext &dc, float &w, float &h) const {
w = 0.0f;
h = 0.0f;
h = ITEM_HEIGHT;
}
ClickableItem::ClickableItem(LayoutParams *layoutParams) : Clickable(layoutParams) {
if (!layoutParams) {
if (layoutParams_->width == WRAP_CONTENT)
layoutParams_->width = FILL_PARENT;
layoutParams_->height = ITEM_HEIGHT;
}
}
@@ -414,16 +436,35 @@ void ClickableItem::Draw(UIContext &dc) {
dc.FillRect(style.background, bounds_);
}
void Choice::GetContentDimensions(const UIContext &dc, float &w, float &h) const {
void Choice::GetContentDimensionsBySpec(const UIContext &dc, MeasureSpec horiz, MeasureSpec vert, float &w, float &h) const {
if (atlasImage_ != -1) {
const AtlasImage &img = dc.Draw()->GetAtlas()->images[atlasImage_];
w = img.w;
h = img.h;
} else {
dc.MeasureText(dc.theme->uiFont, text_.c_str(), &w, &h);
const int paddingX = 12;
float availWidth = horiz.size - paddingX * 2 - textPadding_.horiz();
if (availWidth < 0.0f) {
// Let it have as much space as it needs.
availWidth = MAX_ITEM_SIZE;
}
float scale = CalculateTextScale(dc, availWidth);
Bounds availBounds(0, 0, availWidth, vert.size);
dc.MeasureTextRect(dc.theme->uiFont, scale, scale, text_.c_str(), (int)text_.size(), availBounds, &w, &h, FLAG_WRAP_TEXT);
}
w += 24;
h += 16;
h = std::max(h, ITEM_HEIGHT);
}
float Choice::CalculateTextScale(const UIContext &dc, float availWidth) const {
float actualWidth, actualHeight;
Bounds availBounds(0, 0, availWidth, bounds_.h);
dc.MeasureTextRect(dc.theme->uiFont, 1.0f, 1.0f, text_.c_str(), (int)text_.size(), availBounds, &actualWidth, &actualHeight);
if (actualWidth > availWidth) {
return std::max(MIN_TEXT_SCALE, availWidth / actualWidth);
}
return 1.0f;
}
void Choice::HighlightChanged(bool highlighted){
@@ -459,23 +500,18 @@ void Choice::Draw(UIContext &dc) {
const int paddingX = 12;
const float availWidth = bounds_.w - paddingX * 2 - textPadding_.horiz();
float scale = 1.0f;
float actualWidth, actualHeight;
dc.MeasureText(dc.theme->uiFont, text_.c_str(), &actualWidth, &actualHeight, ALIGN_VCENTER);
if (actualWidth > availWidth) {
scale = std::max(MIN_TEXT_SCALE, availWidth / actualWidth);
}
float scale = CalculateTextScale(dc, availWidth);
dc.SetFontScale(scale, scale);
if (centered_) {
dc.DrawText(text_.c_str(), bounds_.centerX(), bounds_.centerY(), style.fgColor, ALIGN_CENTER);
dc.DrawTextRect(text_.c_str(), bounds_, style.fgColor, ALIGN_CENTER | FLAG_WRAP_TEXT);
} else {
if (iconImage_ != -1) {
dc.Draw()->DrawImage(iconImage_, bounds_.x2() - 32 - paddingX, bounds_.centerY(), 0.5f, style.fgColor, ALIGN_CENTER);
}
dc.DrawText(text_.c_str(), bounds_.x + paddingX + textPadding_.left, bounds_.centerY(), style.fgColor, ALIGN_VCENTER);
Bounds textBounds(bounds_.x + paddingX + textPadding_.left, bounds_.y, availWidth, bounds_.h);
dc.DrawTextRect(text_.c_str(), textBounds, style.fgColor, ALIGN_VCENTER | FLAG_WRAP_TEXT);
}
dc.SetFontScale(1.0f, 1.0f);
}
@@ -518,7 +554,7 @@ void PopupHeader::Draw(UIContext &dc) {
float tw, th;
dc.SetFontStyle(dc.theme->uiFont);
dc.MeasureText(dc.GetFontStyle(), text_.c_str(), &tw, &th, 0);
dc.MeasureText(dc.GetFontStyle(), 1.0f, 1.0f, text_.c_str(), &tw, &th, 0);
float sineWidth = std::max(0.0f, (tw - availableWidth)) / 2.0f;
@@ -565,27 +601,54 @@ void CheckBox::Draw(UIContext &dc) {
const int paddingX = 12;
// Padding right of the checkbox image too.
const float availWidth = bounds_.w - paddingX * 2 - imageW - paddingX;
float scale = 1.0f;
float actualWidth, actualHeight;
dc.MeasureText(dc.theme->uiFont, text_.c_str(), &actualWidth, &actualHeight, ALIGN_VCENTER);
if (actualWidth > availWidth) {
scale = std::max(MIN_TEXT_SCALE, availWidth / actualWidth);
}
float scale = CalculateTextScale(dc, availWidth);
dc.SetFontScale(scale, scale);
dc.DrawText(text_.c_str(), bounds_.x + paddingX, bounds_.centerY(), style.fgColor, ALIGN_VCENTER);
Bounds textBounds(bounds_.x + paddingX, bounds_.y, availWidth, bounds_.h);
dc.DrawTextRect(text_.c_str(), textBounds, style.fgColor, ALIGN_VCENTER | FLAG_WRAP_TEXT);
dc.Draw()->DrawImage(image, bounds_.x2() - paddingX, bounds_.centerY(), 1.0f, style.fgColor, ALIGN_RIGHT | ALIGN_VCENTER);
dc.SetFontScale(1.0f, 1.0f);
}
float CheckBox::CalculateTextScale(const UIContext &dc, float availWidth) const {
float actualWidth, actualHeight;
Bounds availBounds(0, 0, availWidth, bounds_.h);
dc.MeasureTextRect(dc.theme->uiFont, 1.0f, 1.0f, text_.c_str(), (int)text_.size(), availBounds, &actualWidth, &actualHeight, ALIGN_VCENTER);
if (actualWidth > availWidth) {
return std::max(MIN_TEXT_SCALE, availWidth / actualWidth);
}
return 1.0f;
}
void CheckBox::GetContentDimensions(const UIContext &dc, float &w, float &h) const {
int image = *toggle_ ? dc.theme->checkOn : dc.theme->checkOff;
float imageW, imageH;
dc.Draw()->MeasureImage(image, &imageW, &imageH);
const int paddingX = 12;
// Padding right of the checkbox image too.
float availWidth = bounds_.w - paddingX * 2 - imageW - paddingX;
if (availWidth < 0.0f) {
// Let it have as much space as it needs.
availWidth = MAX_ITEM_SIZE;
}
float scale = CalculateTextScale(dc, availWidth);
float actualWidth, actualHeight;
Bounds availBounds(0, 0, availWidth, bounds_.h);
dc.MeasureTextRect(dc.theme->uiFont, scale, scale, text_.c_str(), (int)text_.size(), availBounds, &actualWidth, &actualHeight, ALIGN_VCENTER | FLAG_WRAP_TEXT);
w = bounds_.w;
h = std::max(actualHeight, ITEM_HEIGHT);
}
void Button::GetContentDimensions(const UIContext &dc, float &w, float &h) const {
if (imageID_ != -1) {
const AtlasImage *img = &dc.Draw()->GetAtlas()->images[imageID_];
w = img->w;
h = img->h;
} else {
dc.MeasureText(dc.theme->uiFont, text_.c_str(), &w, &h);
dc.MeasureText(dc.theme->uiFont, 1.0f, 1.0f, text_.c_str(), &w, &h);
}
// Add some internal padding to not look totally ugly
w += 16;
@@ -602,7 +665,7 @@ void Button::Draw(UIContext &dc) {
// dc.Draw()->DrawImage4Grid(style.image, bounds_.x, bounds_.y, bounds_.x2(), bounds_.y2(), style.bgColor);
dc.FillRect(style.background, bounds_);
float tw, th;
dc.MeasureText(dc.theme->uiFont, text_.c_str(), &tw, &th);
dc.MeasureText(dc.theme->uiFont, 1.0f, 1.0f, text_.c_str(), &tw, &th);
if (tw > bounds_.w || imageID_ != -1) {
dc.PushScissor(bounds_);
}
@@ -657,17 +720,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);
dc.MeasureTextRect(small_ ? dc.theme->uiFontSmall : dc.theme->uiFont, text_.c_str(), (int)text_.length(), bounds, &w, &h, textAlign_);
if (bounds.w < 0) {
// If there's no size, let's grow as big as we want.
bounds.w = horiz.size == 0 ? MAX_ITEM_SIZE : horiz.size;
}
if (bounds.h < 0) {
bounds.h = vert.size == 0 ? MAX_ITEM_SIZE : vert.size;
}
ApplyBoundsBySpec(bounds, horiz, vert);
dc.MeasureTextRect(small_ ? dc.theme->uiFontSmall : dc.theme->uiFont, 1.0f, 1.0f, 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.
@@ -721,7 +789,7 @@ void TextEdit::Draw(UIContext &dc) {
if (HasFocus()) {
// Hack to find the caret position. Might want to find a better way...
dc.MeasureTextCount(dc.theme->uiFont, text_.c_str(), caret_, &w, &h, ALIGN_VCENTER | ALIGN_LEFT);
dc.MeasureTextCount(dc.theme->uiFont, 1.0f, 1.0f, text_.c_str(), caret_, &w, &h, ALIGN_VCENTER | ALIGN_LEFT);
float caretX = w;
caretX += textX;
@@ -735,7 +803,7 @@ void TextEdit::Draw(UIContext &dc) {
}
void TextEdit::GetContentDimensions(const UIContext &dc, float &w, float &h) const {
dc.MeasureText(dc.theme->uiFont, text_.size() ? text_.c_str() : "Wj", &w, &h);
dc.MeasureText(dc.theme->uiFont, 1.0f, 1.0f, text_.size() ? text_.c_str() : "Wj", &w, &h);
w += 2;
h += 2;
}
@@ -904,7 +972,7 @@ void TextEdit::InsertAtCaret(const char *text) {
}
void ProgressBar::GetContentDimensions(const UIContext &dc, float &w, float &h) const {
dc.MeasureText(dc.theme->uiFont, " 100% ", &w, &h);
dc.MeasureText(dc.theme->uiFont, 1.0f, 1.0f, " 100% ", &w, &h);
}
void ProgressBar::Draw(UIContext &dc) {
+11 -6
View File
@@ -273,10 +273,10 @@ struct Margins {
Margins(int8_t horiz, int8_t vert) : top(vert), bottom(vert), left(horiz), right(horiz) {}
Margins(int8_t l, int8_t t, int8_t r, int8_t b) : top(t), bottom(b), left(l), right(r) {}
int horiz() {
int horiz() const {
return left + right;
}
int vert() {
int vert() const {
return top + bottom;
}
@@ -292,10 +292,10 @@ struct Padding {
Padding(float horiz, float vert) : top(vert), bottom(vert), left(horiz), right(horiz) {}
Padding(float l, float t, float r, float b) : top(t), bottom(b), left(l), right(r) {}
float horiz() {
float horiz() const {
return left + right;
}
float vert() {
float vert() const {
return top + bottom;
}
@@ -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; }
@@ -608,7 +609,7 @@ public:
: ClickableItem(layoutParams), atlasImage_(image), iconImage_(-1), centered_(false), highlighted_(false), selected_(false) {}
virtual void HighlightChanged(bool highlighted);
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;
virtual void SetCentered(bool c) {
centered_ = c;
@@ -620,6 +621,7 @@ public:
protected:
// hackery
virtual bool IsSticky() const { return false; }
virtual float CalculateTextScale(const UIContext &dc, float availWidth) const;
std::string text_;
std::string smallText_;
@@ -708,11 +710,14 @@ public:
}
void Draw(UIContext &dc) override;
void GetContentDimensions(const UIContext &dc, float &w, float &h) const override;
EventReturn OnClicked(EventParams &e);
//allow external agents to toggle the checkbox
void Toggle();
private:
float CalculateTextScale(const UIContext &dc, float availWidth) const;
bool *toggle_;
std::string text_;
std::string smallText_;
@@ -742,7 +747,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; }
+42 -35
View File
@@ -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<LinearLayoutParams>();
const LinearLayoutParams *linLayoutParams = view->GetLayoutParams()->As<LinearLayoutParams>();
Margins margins = defaultMargins_;
@@ -422,22 +422,23 @@ void LinearLayout::Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec v
if (orientation_ == ORIENT_HORIZONTAL) {
MeasureSpec v = vert;
if (v.type == UNSPECIFIED && measuredHeight_ != 0.0)
if (v.type == UNSPECIFIED && measuredHeight_ != 0.0f)
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.0f)
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;
@@ -457,7 +458,6 @@ void LinearLayout::Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec v
// and distribute among the weighted ones.
if (orientation_ == ORIENT_HORIZONTAL) {
MeasureBySpec(layoutParams_->width, weightZeroSum, horiz, &measuredWidth_);
MeasureBySpec(layoutParams_->height, maxOther, vert, &measuredHeight_);
// If we've got stretch, allow growing to fill the parent.
float allowedWidth = measuredWidth_;
@@ -469,33 +469,36 @@ 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<LinearLayoutParams>();
const LinearLayoutParams *linLayoutParams = view->GetLayoutParams()->As<LinearLayoutParams>();
if (linLayoutParams && linLayoutParams->weight > 0.0f) {
Margins margins = defaultMargins_;
if (linLayoutParams->HasMargins())
margins = linLayoutParams->margins;
MeasureSpec v = vert;
if (v.type == UNSPECIFIED && measuredHeight_ != 0.0)
if (v.type == UNSPECIFIED && measuredHeight_ != 0.0f)
v = MeasureSpec(AT_MOST, measuredHeight_);
MeasureSpec h(AT_MOST, unit * linLayoutParams->weight - margins.horiz());
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();
maxOther = std::max(maxOther, view->GetMeasuredHeight() + margins.vert());
}
}
if (horiz.type == AT_MOST && measuredWidth_ < horiz.size) {
measuredWidth_ += usedWidth;
}
// Measure here in case maxOther moved (can happen due to word wrap.)
MeasureBySpec(layoutParams_->height, maxOther, vert, &measuredHeight_);
} else {
MeasureBySpec(layoutParams_->height, weightZeroSum, vert, &measuredHeight_);
MeasureBySpec(layoutParams_->width, maxOther, horiz, &measuredWidth_);
// If we've got stretch, allow growing to fill the parent.
float allowedHeight = measuredHeight_;
@@ -507,30 +510,34 @@ 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<LinearLayoutParams>();
const LinearLayoutParams *linLayoutParams = view->GetLayoutParams()->As<LinearLayoutParams>();
if (linLayoutParams && linLayoutParams->weight > 0.0f) {
Margins margins = defaultMargins_;
if (linLayoutParams->HasMargins())
margins = linLayoutParams->margins;
MeasureSpec h = horiz;
if (h.type == UNSPECIFIED && measuredWidth_ != 0.0)
if (h.type == UNSPECIFIED && measuredWidth_ != 0.0f)
h = MeasureSpec(AT_MOST, measuredWidth_);
MeasureSpec v(AT_MOST, unit * linLayoutParams->weight - margins.vert());
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();
maxOther = std::max(maxOther, view->GetMeasuredWidth() + margins.horiz());
}
}
if (vert.type == AT_MOST && measuredHeight_ < vert.size) {
measuredHeight_ += usedHeight;
}
// Measure here in case maxOther moved (can happen due to word wrap.)
MeasureBySpec(layoutParams_->width, maxOther, horiz, &measuredWidth_);
}
}
@@ -627,15 +634,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(UNSPECIFIED));
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 +973,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 +1113,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 +1169,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 +1180,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);