refactor(ui): extract shared ProgressBar / CopyableTextOverlay / DrawPill helpers
UI-standardization audit: three draw patterns were copy-pasted across tabs and dialogs. Promote each to a material:: helper and adopt at every verbatim site. Output is pixel-identical (same colors/geometry threaded through as params). - material::DrawProgressBar / ProgressBar — replaces 3 byte-identical rounded fill bars in the daemon/xmrig/bootstrap download dialogs. - material::CopyableTextOverlay — the click-to-copy affordance (hit button + hand cursor + tooltip + hover underline + clipboard) shared by the peers best-block hash and the 3 mining stats (difficulty/block/address). Returns "copied this frame" so callers keep their own toast (no ui-layer dependency). - material::DrawPill / PillSize — rounded bg + optional border + inset text badge, shared by the explorer status pill, the market Z/T chip, and the network official/custom tag. Divergent one-offs left in place (transactions status pills use schema rounding around pre-positioned multi-line text; the mining filter-pill is a button bg). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -162,18 +162,7 @@ private:
|
||||
ImGui::Spacing();
|
||||
|
||||
// Progress bar
|
||||
float barH = 8.0f * dp;
|
||||
float barW = ImGui::GetContentRegionAvail().x;
|
||||
ImVec2 barMin = ImGui::GetCursorScreenPos();
|
||||
ImVec2 barMax(barMin.x + barW, barMin.y + barH);
|
||||
ImDrawList* dl = ImGui::GetWindowDrawList();
|
||||
dl->AddRectFilled(barMin, barMax, IM_COL32(255, 255, 255, 30), 4.0f * dp);
|
||||
float fillW = barW * (prog.percent / 100.0f);
|
||||
if (fillW > 0) {
|
||||
dl->AddRectFilled(barMin, ImVec2(barMin.x + fillW, barMax.y),
|
||||
Primary(), 4.0f * dp);
|
||||
}
|
||||
ImGui::Dummy(ImVec2(0, barH));
|
||||
material::ProgressBar(ImGui::GetContentRegionAvail().x, 8.0f * dp, prog.percent / 100.0f);
|
||||
ImGui::Spacing();
|
||||
|
||||
// Percent + status text
|
||||
|
||||
@@ -189,16 +189,7 @@ private:
|
||||
: TR("daemon_update_installing");
|
||||
Type().text(TypeStyle::Subtitle2, title);
|
||||
ImGui::Spacing();
|
||||
const float barH = 8.0f * dp;
|
||||
const float barW = fullW();
|
||||
const ImVec2 bMin = ImGui::GetCursorScreenPos();
|
||||
const ImVec2 bMax(bMin.x + barW, bMin.y + barH);
|
||||
ImDrawList* dl = ImGui::GetWindowDrawList();
|
||||
dl->AddRectFilled(bMin, bMax, IM_COL32(255, 255, 255, 30), 4.0f * dp);
|
||||
const float fillW = barW * (p.percent / 100.0f);
|
||||
if (fillW > 0)
|
||||
dl->AddRectFilled(bMin, ImVec2(bMin.x + fillW, bMax.y), Primary(), 4.0f * dp);
|
||||
ImGui::Dummy(ImVec2(0, barH));
|
||||
material::ProgressBar(fullW(), 8.0f * dp, p.percent / 100.0f);
|
||||
ImGui::Spacing();
|
||||
ImGui::Text("%s", p.status_text.c_str());
|
||||
ImGui::Spacing();
|
||||
|
||||
@@ -600,17 +600,11 @@ static void renderChainStats(App* app, float availWidth) {
|
||||
|
||||
float maxTextW = cardW * 0.34f;
|
||||
statusText = truncateHashToFit(statusText, capFont, maxTextW);
|
||||
ImVec2 textSz = capFont->CalcTextSizeA(capFont->LegacySize, 1000.0f, 0.0f, statusText.c_str());
|
||||
float pillPadX = Layout::spacingSm();
|
||||
float pillH = capFont->LegacySize + Layout::spacingXs() * 2.0f;
|
||||
float pillW = textSz.x + pillPadX * 2.0f;
|
||||
ImVec2 pillMin(cardMin.x + cardW - pad - pillW, cardMin.y + pad * 0.5f);
|
||||
ImVec2 pillMax(pillMin.x + pillW, pillMin.y + pillH);
|
||||
|
||||
dl->AddRectFilled(pillMin, pillMax, WithAlpha(pillCol, 32), pillH * 0.5f);
|
||||
dl->AddRect(pillMin, pillMax, WithAlpha(pillCol, 110), pillH * 0.5f, 0, 1.0f * dp);
|
||||
dl->AddText(capFont, capFont->LegacySize,
|
||||
ImVec2(pillMin.x + pillPadX, pillMin.y + Layout::spacingXs()), pillCol, statusText.c_str());
|
||||
ImVec2 pillPad(Layout::spacingSm(), Layout::spacingXs());
|
||||
ImVec2 pillSz = material::PillSize(statusText.c_str(), capFont, pillPad);
|
||||
ImVec2 pillMin(cardMin.x + cardW - pad - pillSz.x, cardMin.y + pad * 0.5f);
|
||||
material::DrawPill(dl, pillMin, statusText.c_str(), capFont, pillCol,
|
||||
WithAlpha(pillCol, 32), WithAlpha(pillCol, 110), pillPad);
|
||||
};
|
||||
|
||||
auto drawChainTip = [&](const ImVec2& cardMin, float cardW) {
|
||||
|
||||
@@ -654,10 +654,9 @@ static void pfDrawAddressSection(App* app)
|
||||
bool isZ = (a.type == "shielded");
|
||||
const char* chip = isZ ? "Z" : "T";
|
||||
ImU32 chipCol = isZ ? Success() : Warning();
|
||||
float chipW = capF->CalcTextSizeA(capF->LegacySize, FLT_MAX, 0, chip).x + 8.0f * dp;
|
||||
ldl->AddRectFilled(ImVec2(rx, rcy - capF->LegacySize * 0.5f - 2.0f),
|
||||
ImVec2(rx + chipW, rcy + capF->LegacySize * 0.5f + 2.0f), WithAlpha(chipCol, 40), 4.0f * dp);
|
||||
ldl->AddText(capF, capF->LegacySize, ImVec2(rx + 4.0f * dp, rcy - capF->LegacySize * 0.5f), chipCol, chip);
|
||||
ImVec2 chipPos(rx, rcy - capF->LegacySize * 0.5f - 2.0f);
|
||||
float chipW = material::DrawPill(ldl, chipPos, chip, capF, chipCol,
|
||||
WithAlpha(chipCol, 40), 0, ImVec2(4.0f * dp, 2.0f), 4.0f * dp).x;
|
||||
rx += chipW + Layout::spacingSm();
|
||||
std::string aicon = app->getAddressIcon(a.address);
|
||||
if (!aicon.empty()) {
|
||||
|
||||
@@ -283,17 +283,9 @@ void RenderMiningEarnings(App* app, const WalletState& state, const MiningInfo&
|
||||
snprintf(buf, sizeof(buf), "%.4f", mining.difficulty);
|
||||
dl->AddText(capFont, capFont->LegacySize, ImVec2(col1X + valOffX, cy), OnSurface(), buf);
|
||||
ImVec2 diffSz = capFont->CalcTextSizeA(capFont->LegacySize, 10000, 0, buf);
|
||||
ImGui::SetCursorScreenPos(ImVec2(col1X + valOffX, cy));
|
||||
ImGui::InvisibleButton("##DiffCopy", ImVec2(diffSz.x + Layout::spacingMd(), capFont->LegacySize + 4 * dp));
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetMouseCursor(ImGuiMouseCursor_Hand);
|
||||
material::Tooltip("%s", TR("mining_click_copy_difficulty"));
|
||||
dl->AddLine(ImVec2(col1X + valOffX, cy + capFont->LegacySize + 1 * dp),
|
||||
ImVec2(col1X + valOffX + diffSz.x, cy + capFont->LegacySize + 1 * dp),
|
||||
WithAlpha(OnSurface(), 60), 1.0f * dp);
|
||||
}
|
||||
if (ImGui::IsItemClicked()) {
|
||||
ImGui::SetClipboardText(buf);
|
||||
if (material::CopyableTextOverlay("##DiffCopy", ImVec2(col1X + valOffX, cy), diffSz,
|
||||
capFont->LegacySize, buf, TR("mining_click_copy_difficulty"),
|
||||
ImVec2(Layout::spacingMd(), 4 * dp))) {
|
||||
Notifications::instance().info(TR("mining_difficulty_copied"));
|
||||
}
|
||||
}
|
||||
@@ -304,17 +296,9 @@ void RenderMiningEarnings(App* app, const WalletState& state, const MiningInfo&
|
||||
snprintf(buf, sizeof(buf), "%d", mining.blocks);
|
||||
dl->AddText(capFont, capFont->LegacySize, ImVec2(col2X + valOffX, cy), OnSurface(), buf);
|
||||
ImVec2 blkSz = capFont->CalcTextSizeA(capFont->LegacySize, 10000, 0, buf);
|
||||
ImGui::SetCursorScreenPos(ImVec2(col2X + valOffX, cy));
|
||||
ImGui::InvisibleButton("##BlockCopy", ImVec2(blkSz.x + Layout::spacingMd(), capFont->LegacySize + 4 * dp));
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetMouseCursor(ImGuiMouseCursor_Hand);
|
||||
material::Tooltip("%s", TR("mining_click_copy_block"));
|
||||
dl->AddLine(ImVec2(col2X + valOffX, cy + capFont->LegacySize + 1 * dp),
|
||||
ImVec2(col2X + valOffX + blkSz.x, cy + capFont->LegacySize + 1 * dp),
|
||||
WithAlpha(OnSurface(), 60), 1.0f * dp);
|
||||
}
|
||||
if (ImGui::IsItemClicked()) {
|
||||
ImGui::SetClipboardText(buf);
|
||||
if (material::CopyableTextOverlay("##BlockCopy", ImVec2(col2X + valOffX, cy), blkSz,
|
||||
capFont->LegacySize, buf, TR("mining_click_copy_block"),
|
||||
ImVec2(Layout::spacingMd(), 4 * dp))) {
|
||||
Notifications::instance().info(TR("mining_block_copied"));
|
||||
}
|
||||
}
|
||||
@@ -342,17 +326,10 @@ void RenderMiningEarnings(App* app, const WalletState& state, const MiningInfo&
|
||||
dl->AddText(capFont, capFont->LegacySize, ImVec2(col3X + valOffX, cy), OnSurface(), truncAddr.c_str());
|
||||
|
||||
ImVec2 addrTextSz = capFont->CalcTextSizeA(capFont->LegacySize, 10000, 0, truncAddr.c_str());
|
||||
ImGui::SetCursorScreenPos(ImVec2(col3X + valOffX, cy));
|
||||
ImGui::InvisibleButton("##MiningAddrCopy", ImVec2(addrTextSz.x + Layout::spacingMd(), capFont->LegacySize + 4 * dp));
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetMouseCursor(ImGuiMouseCursor_Hand);
|
||||
material::Tooltip("%s", TR("mining_click_copy_address"));
|
||||
dl->AddLine(ImVec2(col3X + valOffX, cy + capFont->LegacySize + 1 * dp),
|
||||
ImVec2(col3X + valOffX + addrTextSz.x, cy + capFont->LegacySize + 1 * dp),
|
||||
WithAlpha(OnSurface(), 60), 1.0f * dp);
|
||||
}
|
||||
if (ImGui::IsItemClicked()) {
|
||||
ImGui::SetClipboardText(mining_address.c_str());
|
||||
if (material::CopyableTextOverlay("##MiningAddrCopy", ImVec2(col3X + valOffX, cy), addrTextSz,
|
||||
capFont->LegacySize, mining_address.c_str(),
|
||||
TR("mining_click_copy_address"),
|
||||
ImVec2(Layout::spacingMd(), 4 * dp))) {
|
||||
Notifications::instance().info(TR("mining_address_copied"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -285,9 +285,8 @@ void RenderLiteNetworkTab(App* app)
|
||||
ImVec2 tagSz = cap->CalcTextSizeA(cap->LegacySize, FLT_MAX, 0, tag);
|
||||
float tagX = rx - tagSz.x;
|
||||
float tagY = cardMin.y + 9.0f * dp;
|
||||
dl->AddRectFilled(ImVec2(tagX - 6 * dp, tagY - 1 * dp), ImVec2(rx + 6 * dp, tagY + tagSz.y + 1 * dp),
|
||||
tagBg, 4.0f * dp);
|
||||
dl->AddText(cap, cap->LegacySize, ImVec2(tagX, tagY), tagFg, tag);
|
||||
material::DrawPill(dl, ImVec2(tagX - 6 * dp, tagY - 1 * dp), tag, cap, tagFg, tagBg, 0,
|
||||
ImVec2(6 * dp, 1 * dp), 4.0f * dp);
|
||||
if (selected) {
|
||||
const char* inUse = TR("lite_net_in_use");
|
||||
ImVec2 uSz = cap->CalcTextSizeA(cap->LegacySize, FLT_MAX, 0, inUse);
|
||||
|
||||
@@ -314,17 +314,10 @@ void RenderPeersTab(App* app)
|
||||
// Click to copy full hash
|
||||
ImVec2 hashSz = sub1->CalcTextSizeA(sub1->LegacySize, FLT_MAX, 0, truncHash.c_str());
|
||||
ImVec2 savedCursor = ImGui::GetCursorScreenPos();
|
||||
ImGui::SetCursorScreenPos(ImVec2(cx, valY));
|
||||
ImGui::InvisibleButton("##BestBlockCopy", ImVec2(hashSz.x + Layout::spacingSm(), sub1->LegacySize + 2 * dp));
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetMouseCursor(ImGuiMouseCursor_Hand);
|
||||
material::Tooltip("%s %s", TR("peers_click_copy"), hash.c_str());
|
||||
dl->AddLine(ImVec2(cx, valY + sub1->LegacySize + 1 * dp),
|
||||
ImVec2(cx + hashSz.x, valY + sub1->LegacySize + 1 * dp),
|
||||
WithAlpha(OnSurface(), 60), 1.0f * dp);
|
||||
}
|
||||
if (ImGui::IsItemClicked()) {
|
||||
ImGui::SetClipboardText(hash.c_str());
|
||||
std::string copyTip = std::string(TR("peers_click_copy")) + " " + hash;
|
||||
if (material::CopyableTextOverlay("##BestBlockCopy", ImVec2(cx, valY), hashSz,
|
||||
sub1->LegacySize, hash.c_str(), copyTip.c_str(),
|
||||
ImVec2(Layout::spacingSm(), 2 * dp))) {
|
||||
ui::Notifications::instance().info(TR("peers_hash_copied"));
|
||||
}
|
||||
ImGui::SetCursorScreenPos(savedCursor);
|
||||
|
||||
@@ -182,16 +182,7 @@ private:
|
||||
: TR("xmrig_installing");
|
||||
Type().text(TypeStyle::Subtitle2, title);
|
||||
ImGui::Spacing();
|
||||
const float barH = 8.0f * dp;
|
||||
const float barW = fullW();
|
||||
const ImVec2 bMin = ImGui::GetCursorScreenPos();
|
||||
const ImVec2 bMax(bMin.x + barW, bMin.y + barH);
|
||||
ImDrawList* dl = ImGui::GetWindowDrawList();
|
||||
dl->AddRectFilled(bMin, bMax, IM_COL32(255, 255, 255, 30), 4.0f * dp);
|
||||
const float fillW = barW * (p.percent / 100.0f);
|
||||
if (fillW > 0)
|
||||
dl->AddRectFilled(bMin, ImVec2(bMin.x + fillW, bMax.y), Primary(), 4.0f * dp);
|
||||
ImGui::Dummy(ImVec2(0, barH));
|
||||
material::ProgressBar(fullW(), 8.0f * dp, p.percent / 100.0f);
|
||||
ImGui::Spacing();
|
||||
ImGui::Text("%s", p.status_text.c_str());
|
||||
ImGui::Spacing();
|
||||
|
||||
Reference in New Issue
Block a user