refactor(ui): delete dead button code (buttons.h + ApplyTactile)
UI-standardization audit found two dead, contradictory "how to draw a button" surfaces with zero call sites: - src/ui/material/components/buttons.h (353 lines: TextButton/Outlined/Contained/ Button(spec)/IconButton/FAB) — included by 3 mining files but never used. - ApplyTactile (draw_helpers.h) — a retrofit-tactile-onto-plain-button wrapper, never called. Remove the file, the 3 dead includes, and ApplyTactile. TactileButton/StyledButton remain the canonical button helpers. No behavior change. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,352 +0,0 @@
|
|||||||
// DragonX Wallet - ImGui Edition
|
|
||||||
// Copyright 2024-2026 The Hush Developers
|
|
||||||
// Released under the GPLv3
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "../colors.h"
|
|
||||||
#include "../typography.h"
|
|
||||||
#include "../layout.h"
|
|
||||||
#include "../tooltip_style.h"
|
|
||||||
#include "imgui.h"
|
|
||||||
#include "imgui_internal.h"
|
|
||||||
|
|
||||||
namespace dragonx {
|
|
||||||
namespace ui {
|
|
||||||
namespace material {
|
|
||||||
|
|
||||||
// ============================================================================
|
|
||||||
// Material Design Button Components
|
|
||||||
// ============================================================================
|
|
||||||
// Based on https://m2.material.io/components/buttons
|
|
||||||
//
|
|
||||||
// Three button variants:
|
|
||||||
// - Text Button: Low emphasis, no container
|
|
||||||
// - Outlined Button: Medium emphasis, border only
|
|
||||||
// - Contained Button: High emphasis, filled background
|
|
||||||
|
|
||||||
enum class ButtonStyle {
|
|
||||||
Text, // Low emphasis - text only
|
|
||||||
Outlined, // Medium emphasis - border
|
|
||||||
Contained // High emphasis - filled (default)
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Button configuration
|
|
||||||
*/
|
|
||||||
struct ButtonSpec {
|
|
||||||
ButtonStyle style = ButtonStyle::Contained;
|
|
||||||
bool enabled = true;
|
|
||||||
bool fullWidth = false;
|
|
||||||
const char* icon = nullptr; // Leading icon (text glyph)
|
|
||||||
ImU32 color = 0; // 0 = use primary color
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Render a Material Design button
|
|
||||||
*
|
|
||||||
* @param label Button text (will be uppercased per Material spec)
|
|
||||||
* @param spec Button configuration
|
|
||||||
* @return true if clicked
|
|
||||||
*/
|
|
||||||
bool Button(const char* label, const ButtonSpec& spec = ButtonSpec());
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Render a text-only button (low emphasis)
|
|
||||||
*/
|
|
||||||
inline bool TextButton(const char* label, bool enabled = true) {
|
|
||||||
ButtonSpec spec;
|
|
||||||
spec.style = ButtonStyle::Text;
|
|
||||||
spec.enabled = enabled;
|
|
||||||
return Button(label, spec);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Render an outlined button (medium emphasis)
|
|
||||||
*/
|
|
||||||
inline bool OutlinedButton(const char* label, bool enabled = true) {
|
|
||||||
ButtonSpec spec;
|
|
||||||
spec.style = ButtonStyle::Outlined;
|
|
||||||
spec.enabled = enabled;
|
|
||||||
return Button(label, spec);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Render a contained/filled button (high emphasis)
|
|
||||||
*/
|
|
||||||
inline bool ContainedButton(const char* label, bool enabled = true) {
|
|
||||||
ButtonSpec spec;
|
|
||||||
spec.style = ButtonStyle::Contained;
|
|
||||||
spec.enabled = enabled;
|
|
||||||
return Button(label, spec);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Render an icon button (circular touch target)
|
|
||||||
*
|
|
||||||
* @param icon Icon glyph/character
|
|
||||||
* @param tooltip Hover tooltip text
|
|
||||||
* @param enabled Whether button is enabled
|
|
||||||
* @return true if clicked
|
|
||||||
*/
|
|
||||||
bool IconButton(const char* icon, const char* tooltip = nullptr, bool enabled = true);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Render a Floating Action Button (FAB)
|
|
||||||
*
|
|
||||||
* @param icon Icon glyph
|
|
||||||
* @param label Optional label for extended FAB
|
|
||||||
* @param mini Use mini size (40dp instead of 56dp)
|
|
||||||
* @return true if clicked
|
|
||||||
*/
|
|
||||||
bool FAB(const char* icon, const char* label = nullptr, bool mini = false);
|
|
||||||
|
|
||||||
// ============================================================================
|
|
||||||
// Implementation
|
|
||||||
// ============================================================================
|
|
||||||
|
|
||||||
inline bool Button(const char* label, const ButtonSpec& spec) {
|
|
||||||
ImGuiWindow* window = ImGui::GetCurrentWindow();
|
|
||||||
if (window->SkipItems)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
ImGuiContext& g = *GImGui;
|
|
||||||
const ImGuiStyle& style = g.Style;
|
|
||||||
const ImGuiID id = window->GetID(label);
|
|
||||||
|
|
||||||
// Convert label to uppercase for Material Design
|
|
||||||
char upperLabel[256];
|
|
||||||
{
|
|
||||||
const char* src = label;
|
|
||||||
char* dst = upperLabel;
|
|
||||||
char* end = upperLabel + sizeof(upperLabel) - 1;
|
|
||||||
while (*src && dst < end) {
|
|
||||||
*dst++ = (char)toupper((unsigned char)*src++);
|
|
||||||
}
|
|
||||||
*dst = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get button font
|
|
||||||
ImFont* buttonFont = Typography::instance().button();
|
|
||||||
ImGui::PushFont(buttonFont);
|
|
||||||
|
|
||||||
// Calculate button size
|
|
||||||
ImVec2 labelSize = ImGui::CalcTextSize(upperLabel);
|
|
||||||
float iconWidth = spec.icon ? (size::IconSize + size::ButtonIconGap) : 0.0f;
|
|
||||||
|
|
||||||
ImVec2 buttonSize;
|
|
||||||
buttonSize.x = spec.fullWidth ? ImGui::GetContentRegionAvail().x
|
|
||||||
: ImMax(labelSize.x + iconWidth + size::ButtonPaddingH * 2, size::ButtonMinWidth);
|
|
||||||
buttonSize.y = size::ButtonHeight;
|
|
||||||
|
|
||||||
// Get position
|
|
||||||
ImVec2 pos = window->DC.CursorPos;
|
|
||||||
ImRect bb(pos, ImVec2(pos.x + buttonSize.x, pos.y + buttonSize.y));
|
|
||||||
|
|
||||||
ImGui::ItemSize(buttonSize, style.FramePadding.y);
|
|
||||||
if (!ImGui::ItemAdd(bb, id)) {
|
|
||||||
ImGui::PopFont();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle interaction
|
|
||||||
bool hovered, held;
|
|
||||||
bool pressed = ImGui::ButtonBehavior(bb, id, &hovered, &held, 0);
|
|
||||||
|
|
||||||
if (!spec.enabled) {
|
|
||||||
hovered = held = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hovered) ImGui::SetMouseCursor(ImGuiMouseCursor_Hand);
|
|
||||||
|
|
||||||
// Get colors
|
|
||||||
ImU32 primaryColor = spec.color ? spec.color : Primary();
|
|
||||||
ImU32 textColor;
|
|
||||||
ImU32 bgColor;
|
|
||||||
ImU32 borderColor = 0;
|
|
||||||
|
|
||||||
switch (spec.style) {
|
|
||||||
case ButtonStyle::Text:
|
|
||||||
bgColor = 0; // No background
|
|
||||||
textColor = spec.enabled ? primaryColor : OnSurfaceDisabled();
|
|
||||||
if (hovered) bgColor = BlendOverlay(Surface(), StateHover(), 1.0f);
|
|
||||||
if (held) bgColor = BlendOverlay(Surface(), StatePressed(), 1.0f);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ButtonStyle::Outlined:
|
|
||||||
bgColor = 0; // No background
|
|
||||||
textColor = spec.enabled ? primaryColor : OnSurfaceDisabled();
|
|
||||||
borderColor = spec.enabled ? primaryColor : OnSurfaceDisabled();
|
|
||||||
if (hovered) bgColor = BlendOverlay(Surface(), StateHover(), 1.0f);
|
|
||||||
if (held) bgColor = BlendOverlay(Surface(), StatePressed(), 1.0f);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ButtonStyle::Contained:
|
|
||||||
default:
|
|
||||||
if (spec.enabled) {
|
|
||||||
bgColor = primaryColor;
|
|
||||||
textColor = OnPrimary();
|
|
||||||
if (hovered) bgColor = BlendOverlay(primaryColor, StateHover(), 1.0f);
|
|
||||||
if (held) bgColor = BlendOverlay(primaryColor, StatePressed(), 1.0f);
|
|
||||||
} else {
|
|
||||||
bgColor = WithAlphaF(OnSurface(), 0.12f);
|
|
||||||
textColor = OnSurfaceDisabled();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Render
|
|
||||||
ImDrawList* drawList = window->DrawList;
|
|
||||||
|
|
||||||
// Background
|
|
||||||
if (bgColor) {
|
|
||||||
drawList->AddRectFilled(bb.Min, bb.Max, bgColor, size::ButtonCornerRadius);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Border (for outlined)
|
|
||||||
if (borderColor) {
|
|
||||||
drawList->AddRect(bb.Min, bb.Max, borderColor, size::ButtonCornerRadius, 0, 1.0f);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Icon
|
|
||||||
float contentX = bb.Min.x + size::ButtonPaddingH;
|
|
||||||
float contentY = bb.Min.y + (buttonSize.y - labelSize.y) * 0.5f;
|
|
||||||
|
|
||||||
if (spec.icon) {
|
|
||||||
ImFont* iconFont = Type().iconMed();
|
|
||||||
ImVec2 iconSize = iconFont->CalcTextSizeA(iconFont->LegacySize, FLT_MAX, 0, spec.icon);
|
|
||||||
ImVec2 iconPos(contentX, bb.Min.y + (buttonSize.y - iconSize.y) * 0.5f);
|
|
||||||
drawList->AddText(iconFont, iconFont->LegacySize, iconPos, textColor, spec.icon);
|
|
||||||
contentX += iconSize.x + size::ButtonIconGap;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Label
|
|
||||||
drawList->AddText(ImVec2(contentX, contentY), textColor, upperLabel);
|
|
||||||
|
|
||||||
ImGui::PopFont();
|
|
||||||
|
|
||||||
return pressed && spec.enabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool IconButton(const char* icon, const char* tooltip, bool enabled) {
|
|
||||||
ImGuiWindow* window = ImGui::GetCurrentWindow();
|
|
||||||
if (window->SkipItems)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
ImGuiContext& g = *GImGui;
|
|
||||||
const ImGuiID id = window->GetID(icon);
|
|
||||||
|
|
||||||
ImVec2 pos = window->DC.CursorPos;
|
|
||||||
ImVec2 size(size::IconButtonSize, size::IconButtonSize);
|
|
||||||
ImRect bb(pos, ImVec2(pos.x + size.x, pos.y + size.y));
|
|
||||||
|
|
||||||
ImGui::ItemSize(size);
|
|
||||||
if (!ImGui::ItemAdd(bb, id))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
bool hovered, held;
|
|
||||||
bool pressed = ImGui::ButtonBehavior(bb, id, &hovered, &held, 0);
|
|
||||||
|
|
||||||
if (!enabled) {
|
|
||||||
hovered = held = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hovered) ImGui::SetMouseCursor(ImGuiMouseCursor_Hand);
|
|
||||||
|
|
||||||
// Render ripple/hover circle
|
|
||||||
ImDrawList* drawList = window->DrawList;
|
|
||||||
ImVec2 center = bb.GetCenter();
|
|
||||||
float radius = size::IconButtonSize * 0.5f;
|
|
||||||
|
|
||||||
if (hovered || held) {
|
|
||||||
ImU32 overlayColor = held ? StatePressed() : StateHover();
|
|
||||||
drawList->AddCircleFilled(center, radius, overlayColor);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Render icon (use icon font)
|
|
||||||
ImFont* iconFont = Type().iconMed();
|
|
||||||
ImU32 iconColor = enabled ? OnSurface() : OnSurfaceDisabled();
|
|
||||||
ImVec2 iconSize = iconFont->CalcTextSizeA(iconFont->LegacySize, FLT_MAX, 0, icon);
|
|
||||||
ImVec2 iconPos(center.x - iconSize.x * 0.5f, center.y - iconSize.y * 0.5f);
|
|
||||||
drawList->AddText(iconFont, iconFont->LegacySize, iconPos, iconColor, icon);
|
|
||||||
|
|
||||||
// Tooltip
|
|
||||||
if (tooltip && hovered) {
|
|
||||||
material::Tooltip("%s", tooltip);
|
|
||||||
}
|
|
||||||
|
|
||||||
return pressed && enabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool FAB(const char* icon, const char* label, bool mini) {
|
|
||||||
ImGuiWindow* window = ImGui::GetCurrentWindow();
|
|
||||||
if (window->SkipItems)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
ImGuiContext& g = *GImGui;
|
|
||||||
const ImGuiID id = window->GetID(icon);
|
|
||||||
|
|
||||||
bool extended = (label != nullptr);
|
|
||||||
float fabSize = mini ? size::FabMiniSize : size::FabSize;
|
|
||||||
|
|
||||||
ImVec2 buttonSize;
|
|
||||||
if (extended) {
|
|
||||||
ImVec2 labelSize = ImGui::CalcTextSize(label);
|
|
||||||
buttonSize.x = size::FabExtendedPadding * 2 + size::IconSize + spacing::Sm + labelSize.x;
|
|
||||||
buttonSize.y = size::FabExtendedHeight;
|
|
||||||
} else {
|
|
||||||
buttonSize.x = fabSize;
|
|
||||||
buttonSize.y = fabSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
ImVec2 pos = window->DC.CursorPos;
|
|
||||||
ImRect bb(pos, ImVec2(pos.x + buttonSize.x, pos.y + buttonSize.y));
|
|
||||||
|
|
||||||
ImGui::ItemSize(buttonSize);
|
|
||||||
if (!ImGui::ItemAdd(bb, id))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
bool hovered, held;
|
|
||||||
bool pressed = ImGui::ButtonBehavior(bb, id, &hovered, &held, 0);
|
|
||||||
|
|
||||||
if (hovered) ImGui::SetMouseCursor(ImGuiMouseCursor_Hand);
|
|
||||||
|
|
||||||
// Colors
|
|
||||||
ImU32 bgColor = Secondary();
|
|
||||||
ImU32 textColor = OnSecondary();
|
|
||||||
|
|
||||||
if (hovered) bgColor = BlendOverlay(bgColor, StateHover(), 1.0f);
|
|
||||||
if (held) bgColor = BlendOverlay(bgColor, StatePressed(), 1.0f);
|
|
||||||
|
|
||||||
// Render
|
|
||||||
ImDrawList* drawList = window->DrawList;
|
|
||||||
float radius = extended ? size::FabCornerRadius : (fabSize * 0.5f);
|
|
||||||
drawList->AddRectFilled(bb.Min, bb.Max, bgColor, radius);
|
|
||||||
|
|
||||||
// Icon
|
|
||||||
ImVec2 center = bb.GetCenter();
|
|
||||||
ImFont* iconFont = Type().iconMed();
|
|
||||||
if (extended) {
|
|
||||||
ImVec2 iconSize = iconFont->CalcTextSizeA(iconFont->LegacySize, FLT_MAX, 0, icon);
|
|
||||||
float iconX = bb.Min.x + size::FabExtendedPadding;
|
|
||||||
float iconY = center.y - iconSize.y * 0.5f;
|
|
||||||
drawList->AddText(iconFont, iconFont->LegacySize, ImVec2(iconX, iconY), textColor, icon);
|
|
||||||
|
|
||||||
// Label
|
|
||||||
Typography::instance().pushFont(TypeStyle::Button);
|
|
||||||
float labelX = iconX + iconSize.x + spacing::Sm;
|
|
||||||
float labelY = center.y - ImGui::GetFontSize() * 0.5f;
|
|
||||||
drawList->AddText(ImVec2(labelX, labelY), textColor, label);
|
|
||||||
Typography::instance().popFont();
|
|
||||||
} else {
|
|
||||||
ImVec2 iconSize = iconFont->CalcTextSizeA(iconFont->LegacySize, FLT_MAX, 0, icon);
|
|
||||||
ImVec2 iconPos(center.x - iconSize.x * 0.5f, center.y - iconSize.y * 0.5f);
|
|
||||||
drawList->AddText(iconFont, iconFont->LegacySize, iconPos, textColor, icon);
|
|
||||||
}
|
|
||||||
|
|
||||||
return pressed;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace material
|
|
||||||
} // namespace ui
|
|
||||||
} // namespace dragonx
|
|
||||||
@@ -260,18 +260,6 @@ inline void DrawButtonGlassOverlay(ImDrawList* dl, const ImVec2& bMin,
|
|||||||
DrawTactileOverlay(dl, bMin, bMax, rounding, active);
|
DrawTactileOverlay(dl, bMin, bMax, rounding, active);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convenience: call right after any ImGui::Button() / SmallButton() call
|
|
||||||
// to add tactile depth. Uses the last item rect automatically.
|
|
||||||
inline void ApplyTactile(ImDrawList* dl = nullptr)
|
|
||||||
{
|
|
||||||
if (!dl) dl = ImGui::GetWindowDrawList();
|
|
||||||
ImVec2 bMin = ImGui::GetItemRectMin();
|
|
||||||
ImVec2 bMax = ImGui::GetItemRectMax();
|
|
||||||
float rounding = ImGui::GetStyle().FrameRounding;
|
|
||||||
bool active = ImGui::IsItemActive();
|
|
||||||
DrawTactileOverlay(dl, bMin, bMax, rounding, active);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ── Button font tier helper ─────────────────────────────────────────────
|
// ── Button font tier helper ─────────────────────────────────────────────
|
||||||
// Resolves an int tier (0=sm, 1=md/default, 2=lg) to the matching ImFont*.
|
// Resolves an int tier (0=sm, 1=md/default, 2=lg) to the matching ImFont*.
|
||||||
// Passing -1 or any out-of-range value returns the default button font.
|
// Passing -1 or any out-of-range value returns the default button font.
|
||||||
|
|||||||
@@ -16,7 +16,6 @@
|
|||||||
#include "../material/type.h"
|
#include "../material/type.h"
|
||||||
#include "../material/draw_helpers.h"
|
#include "../material/draw_helpers.h"
|
||||||
#include "../material/colors.h"
|
#include "../material/colors.h"
|
||||||
#include "../material/components/buttons.h"
|
|
||||||
#include "../layout.h"
|
#include "../layout.h"
|
||||||
#include "../notifications.h"
|
#include "../notifications.h"
|
||||||
#include "../../embedded/IconsMaterialDesign.h"
|
#include "../../embedded/IconsMaterialDesign.h"
|
||||||
|
|||||||
@@ -16,7 +16,6 @@
|
|||||||
#include "../material/type.h"
|
#include "../material/type.h"
|
||||||
#include "../material/draw_helpers.h"
|
#include "../material/draw_helpers.h"
|
||||||
#include "../material/colors.h"
|
#include "../material/colors.h"
|
||||||
#include "../material/components/buttons.h"
|
|
||||||
#include "../layout.h"
|
#include "../layout.h"
|
||||||
#include "../notifications.h"
|
#include "../notifications.h"
|
||||||
#include "../../embedded/IconsMaterialDesign.h"
|
#include "../../embedded/IconsMaterialDesign.h"
|
||||||
|
|||||||
@@ -22,7 +22,6 @@
|
|||||||
#include "../material/type.h"
|
#include "../material/type.h"
|
||||||
#include "../material/draw_helpers.h"
|
#include "../material/draw_helpers.h"
|
||||||
#include "../material/colors.h"
|
#include "../material/colors.h"
|
||||||
#include "../material/components/buttons.h"
|
|
||||||
#include "../effects/low_spec.h"
|
#include "../effects/low_spec.h"
|
||||||
#include "../layout.h"
|
#include "../layout.h"
|
||||||
#include "../notifications.h"
|
#include "../notifications.h"
|
||||||
|
|||||||
Reference in New Issue
Block a user