feat(market): portfolio editor — taller icon grid + custom color picker
- Reorder the Appearance column so Color sits above the icon grid, and let the icon grid fill the remaining height of the left column (via GetContentRegionAvail().y). Fixes the large empty space that sat below the color row and gives the icon picker much more room. - Add a custom-color circle after the preset swatches: it shows the current color when it isn't a preset (else a "+"), and clicking it opens a ColorPicker3 popup. The picked RGB packs straight into the group's color. New i18n key portfolio_custom_color. Full-node + Lite build clean; ctest 1/1; hygiene clean. Rendering change — needs a screenshot check. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -102,6 +102,7 @@ static unsigned int s_pf_color = 0; // selected accent (packed IM_COL32; 0 = de
|
|||||||
static char s_pf_search[64] = {0}; // address-list filter text
|
static char s_pf_search[64] = {0}; // address-list filter text
|
||||||
static int s_pf_type_filter = 0; // 0 = all, 1 = shielded, 2 = transparent
|
static int s_pf_type_filter = 0; // 0 = all, 1 = shielded, 2 = transparent
|
||||||
static bool s_pf_funded_only = false;
|
static bool s_pf_funded_only = false;
|
||||||
|
static float s_pf_custom_rgb[3] = {0.31f, 0.62f, 1.0f}; // working RGB for the custom color picker
|
||||||
|
|
||||||
// Preset accent palette for portfolio groups (0 slot = "default / no color").
|
// Preset accent palette for portfolio groups (0 slot = "default / no color").
|
||||||
static const ImU32 kPfPalette[] = {
|
static const ImU32 kPfPalette[] = {
|
||||||
@@ -256,11 +257,74 @@ static void RenderPortfolioEditor(App* app)
|
|||||||
ImGui::InputText("##pfLabel", s_pf_label, sizeof(s_pf_label));
|
ImGui::InputText("##pfLabel", s_pf_label, sizeof(s_pf_label));
|
||||||
ImGui::Dummy(ImVec2(0, Layout::spacingSm()));
|
ImGui::Dummy(ImVec2(0, Layout::spacingSm()));
|
||||||
|
|
||||||
// Icon picker
|
// Color picker: preset swatches + a custom-color circle that opens a picker popup.
|
||||||
|
{
|
||||||
|
float sw = 22.0f * dp;
|
||||||
|
ImGui::TextUnformatted(TR("portfolio_color"));
|
||||||
|
ImDrawList* cdl = ImGui::GetWindowDrawList();
|
||||||
|
int nColors = (int)(sizeof(kPfPalette) / sizeof(kPfPalette[0]));
|
||||||
|
for (int c = 0; c <= nColors; c++) { // slot 0 = default / no color
|
||||||
|
if (c != 0) ImGui::SameLine(0, 5.0f * dp);
|
||||||
|
ImVec2 mn = ImGui::GetCursorScreenPos();
|
||||||
|
ImVec2 cc(mn.x + sw * 0.5f, mn.y + sw * 0.5f);
|
||||||
|
bool isDefault = (c == 0);
|
||||||
|
bool sel = isDefault ? (s_pf_color == 0u) : (s_pf_color == kPfPalette[c - 1]);
|
||||||
|
bool hov = ImGui::IsMouseHoveringRect(mn, ImVec2(mn.x + sw, mn.y + sw));
|
||||||
|
if (isDefault) cdl->AddCircle(cc, sw * 0.40f, OnSurfaceMedium(), 0, 1.5f * dp);
|
||||||
|
else cdl->AddCircleFilled(cc, sw * 0.40f, kPfPalette[c - 1]);
|
||||||
|
if (sel) cdl->AddCircle(cc, sw * 0.50f, OnSurface(), 0, 2.0f * dp);
|
||||||
|
else if (hov) cdl->AddCircle(cc, sw * 0.50f, WithAlpha(OnSurface(), 120), 0, 1.5f * dp);
|
||||||
|
ImGui::PushID(2000 + c);
|
||||||
|
ImGui::InvisibleButton("##pfcol", ImVec2(sw, sw));
|
||||||
|
if (ImGui::IsItemClicked()) s_pf_color = isDefault ? 0u : kPfPalette[c - 1];
|
||||||
|
ImGui::PopID();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Custom-color circle: shows the current color when it isn't a preset, else a "+";
|
||||||
|
// click opens a color-picker popup.
|
||||||
|
bool isCustom = (s_pf_color != 0u);
|
||||||
|
for (int c = 0; c < nColors; c++)
|
||||||
|
if (s_pf_color == kPfPalette[c]) isCustom = false;
|
||||||
|
ImGui::SameLine(0, 5.0f * dp);
|
||||||
|
ImVec2 mn = ImGui::GetCursorScreenPos();
|
||||||
|
ImVec2 cc(mn.x + sw * 0.5f, mn.y + sw * 0.5f);
|
||||||
|
bool hov = ImGui::IsMouseHoveringRect(mn, ImVec2(mn.x + sw, mn.y + sw));
|
||||||
|
if (isCustom) {
|
||||||
|
cdl->AddCircleFilled(cc, sw * 0.40f, (ImU32)s_pf_color);
|
||||||
|
} else {
|
||||||
|
cdl->AddCircle(cc, sw * 0.40f, OnSurfaceMedium(), 0, 1.5f * dp);
|
||||||
|
float pr = sw * 0.18f;
|
||||||
|
cdl->AddLine(ImVec2(cc.x - pr, cc.y), ImVec2(cc.x + pr, cc.y), OnSurfaceMedium(), 1.5f * dp);
|
||||||
|
cdl->AddLine(ImVec2(cc.x, cc.y - pr), ImVec2(cc.x, cc.y + pr), OnSurfaceMedium(), 1.5f * dp);
|
||||||
|
}
|
||||||
|
if (isCustom) cdl->AddCircle(cc, sw * 0.50f, OnSurface(), 0, 2.0f * dp);
|
||||||
|
else if (hov) cdl->AddCircle(cc, sw * 0.50f, WithAlpha(OnSurface(), 120), 0, 1.5f * dp);
|
||||||
|
ImGui::InvisibleButton("##pfcustomcol", ImVec2(sw, sw));
|
||||||
|
if (ImGui::IsItemClicked()) {
|
||||||
|
ImU32 base = s_pf_color ? (ImU32)s_pf_color : IM_COL32(0x4F, 0x9D, 0xFF, 0xFF);
|
||||||
|
s_pf_custom_rgb[0] = ((base >> IM_COL32_R_SHIFT) & 0xFF) / 255.0f;
|
||||||
|
s_pf_custom_rgb[1] = ((base >> IM_COL32_G_SHIFT) & 0xFF) / 255.0f;
|
||||||
|
s_pf_custom_rgb[2] = ((base >> IM_COL32_B_SHIFT) & 0xFF) / 255.0f;
|
||||||
|
ImGui::OpenPopup("##pfCustomColor");
|
||||||
|
}
|
||||||
|
if (hov) material::Tooltip("%s", TR("portfolio_custom_color"));
|
||||||
|
if (ImGui::BeginPopup("##pfCustomColor")) {
|
||||||
|
ImGui::ColorPicker3("##pfpick", s_pf_custom_rgb,
|
||||||
|
ImGuiColorEditFlags_NoSidePreview | ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_NoLabel);
|
||||||
|
s_pf_color = IM_COL32((int)(s_pf_custom_rgb[0] * 255.0f + 0.5f),
|
||||||
|
(int)(s_pf_custom_rgb[1] * 255.0f + 0.5f),
|
||||||
|
(int)(s_pf_custom_rgb[2] * 255.0f + 0.5f), 255);
|
||||||
|
ImGui::EndPopup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui::Dummy(ImVec2(0, Layout::spacingSm()));
|
||||||
|
|
||||||
|
// Icon picker — fills the remaining height of the left column.
|
||||||
{
|
{
|
||||||
float cell = 28.0f * dp, cellGap = 4.0f * dp;
|
float cell = 28.0f * dp, cellGap = 4.0f * dp;
|
||||||
ImGui::TextUnformatted(TR("portfolio_icon"));
|
ImGui::TextUnformatted(TR("portfolio_icon"));
|
||||||
ImGui::BeginChild("##pfIconGrid", ImVec2(0, cell * 3.0f + cellGap * 2.0f + Layout::spacingSm() * 2.0f), true);
|
float iconGridH = std::max(cell * 2.0f + cellGap, ImGui::GetContentRegionAvail().y);
|
||||||
|
ImGui::BeginChild("##pfIconGrid", ImVec2(0, iconGridH), true);
|
||||||
ImDrawList* gdl = ImGui::GetWindowDrawList();
|
ImDrawList* gdl = ImGui::GetWindowDrawList();
|
||||||
float availW = ImGui::GetContentRegionAvail().x;
|
float availW = ImGui::GetContentRegionAvail().x;
|
||||||
int cols = std::max(1, (int)((availW + cellGap) / (cell + cellGap)));
|
int cols = std::max(1, (int)((availW + cellGap) / (cell + cellGap)));
|
||||||
@@ -299,31 +363,6 @@ static void RenderPortfolioEditor(App* app)
|
|||||||
}
|
}
|
||||||
ImGui::EndChild();
|
ImGui::EndChild();
|
||||||
}
|
}
|
||||||
ImGui::Dummy(ImVec2(0, Layout::spacingSm()));
|
|
||||||
|
|
||||||
// Color picker
|
|
||||||
{
|
|
||||||
float sw = 22.0f * dp;
|
|
||||||
ImGui::TextUnformatted(TR("portfolio_color"));
|
|
||||||
ImDrawList* cdl = ImGui::GetWindowDrawList();
|
|
||||||
int nColors = (int)(sizeof(kPfPalette) / sizeof(kPfPalette[0]));
|
|
||||||
for (int c = 0; c <= nColors; c++) { // slot 0 = default / no color
|
|
||||||
if (c != 0) ImGui::SameLine(0, 5.0f * dp);
|
|
||||||
ImVec2 mn = ImGui::GetCursorScreenPos();
|
|
||||||
ImVec2 cc(mn.x + sw * 0.5f, mn.y + sw * 0.5f);
|
|
||||||
bool isDefault = (c == 0);
|
|
||||||
bool sel = isDefault ? (s_pf_color == 0u) : (s_pf_color == kPfPalette[c - 1]);
|
|
||||||
bool hov = ImGui::IsMouseHoveringRect(mn, ImVec2(mn.x + sw, mn.y + sw));
|
|
||||||
if (isDefault) cdl->AddCircle(cc, sw * 0.40f, OnSurfaceMedium(), 0, 1.5f * dp);
|
|
||||||
else cdl->AddCircleFilled(cc, sw * 0.40f, kPfPalette[c - 1]);
|
|
||||||
if (sel) cdl->AddCircle(cc, sw * 0.50f, OnSurface(), 0, 2.0f * dp);
|
|
||||||
else if (hov) cdl->AddCircle(cc, sw * 0.50f, WithAlpha(OnSurface(), 120), 0, 1.5f * dp);
|
|
||||||
ImGui::PushID(2000 + c);
|
|
||||||
ImGui::InvisibleButton("##pfcol", ImVec2(sw, sw));
|
|
||||||
if (ImGui::IsItemClicked()) s_pf_color = isDefault ? 0u : kPfPalette[c - 1];
|
|
||||||
ImGui::PopID();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
ImGui::EndChild();
|
ImGui::EndChild();
|
||||||
|
|
||||||
|
|||||||
@@ -1123,6 +1123,7 @@ void I18n::loadBuiltinEnglish()
|
|||||||
strings_["portfolio_icon"] = "Icon";
|
strings_["portfolio_icon"] = "Icon";
|
||||||
strings_["portfolio_color"] = "Color";
|
strings_["portfolio_color"] = "Color";
|
||||||
strings_["portfolio_no_icon"] = "None";
|
strings_["portfolio_no_icon"] = "None";
|
||||||
|
strings_["portfolio_custom_color"] = "Custom color\xE2\x80\xA6";
|
||||||
strings_["portfolio_appearance"] = "APPEARANCE";
|
strings_["portfolio_appearance"] = "APPEARANCE";
|
||||||
strings_["portfolio_addresses_hdr"] = "ADDRESSES";
|
strings_["portfolio_addresses_hdr"] = "ADDRESSES";
|
||||||
strings_["portfolio_search"] = "Search addresses\xE2\x80\xA6";
|
strings_["portfolio_search"] = "Search addresses\xE2\x80\xA6";
|
||||||
|
|||||||
Reference in New Issue
Block a user