Full-node GUI wallet for DragonX cryptocurrency. Built with Dear ImGui, SDL3, and OpenGL3/DX11. Features: - Send/receive shielded and transparent transactions - Autoshield with merged transaction display - Built-in CPU mining (xmrig) - Peer management and network monitoring - Wallet encryption with PIN lock - QR code generation for receive addresses - Transaction history with pagination - Console for direct RPC commands - Cross-platform (Linux, Windows)
352 lines
11 KiB
C++
352 lines
11 KiB
C++
// DragonX Wallet - ImGui Edition
|
|
// Copyright 2024-2026 The Hush Developers
|
|
// Released under the GPLv3
|
|
|
|
#pragma once
|
|
|
|
#include "imgui.h"
|
|
|
|
namespace dragonx {
|
|
namespace ui {
|
|
namespace material {
|
|
|
|
// ============================================================================
|
|
// Material Design 8dp Grid System
|
|
// ============================================================================
|
|
// All spacing in Material Design is based on an 8dp grid.
|
|
// https://m2.material.io/design/layout/spacing-methods.html
|
|
|
|
constexpr float kGridUnit = 8.0f; // Base unit in dp (device-independent pixels)
|
|
|
|
// ============================================================================
|
|
// Spacing Scale
|
|
// ============================================================================
|
|
// Use these values for all margins, padding, and gaps
|
|
|
|
namespace spacing {
|
|
|
|
constexpr float Xxs = 2.0f; // 0.25x - Very tight spacing
|
|
constexpr float Xs = 4.0f; // 0.5x - Extra small
|
|
constexpr float Sm = 8.0f; // 1x - Small (default minimum)
|
|
constexpr float Md = 16.0f; // 2x - Medium (default standard)
|
|
constexpr float Lg = 24.0f; // 3x - Large
|
|
constexpr float Xl = 32.0f; // 4x - Extra large
|
|
constexpr float Xxl = 40.0f; // 5x - Double extra large
|
|
constexpr float Xxxl = 48.0f; // 6x - Triple extra large
|
|
|
|
// Multiplier helpers
|
|
constexpr float Grid(float multiplier) { return kGridUnit * multiplier; }
|
|
|
|
} // namespace spacing
|
|
|
|
// ============================================================================
|
|
// Component Dimensions
|
|
// ============================================================================
|
|
// Standard sizes for Material Design components
|
|
|
|
namespace size {
|
|
|
|
// Buttons
|
|
constexpr float ButtonHeight = 36.0f;
|
|
constexpr float ButtonMinWidth = 64.0f;
|
|
constexpr float ButtonPaddingH = 16.0f;
|
|
constexpr float ButtonPaddingV = 8.0f;
|
|
constexpr float ButtonIconGap = 8.0f; // Gap between icon and label
|
|
constexpr float ButtonCornerRadius = 4.0f;
|
|
|
|
// FAB (Floating Action Button)
|
|
constexpr float FabSize = 56.0f;
|
|
constexpr float FabMiniSize = 40.0f;
|
|
constexpr float FabExtendedHeight = 48.0f;
|
|
constexpr float FabExtendedPadding = 16.0f;
|
|
constexpr float FabCornerRadius = 16.0f; // Half of mini size for circle
|
|
|
|
// Icons
|
|
constexpr float IconSize = 24.0f;
|
|
constexpr float IconSizeSm = 18.0f;
|
|
constexpr float IconSizeLg = 36.0f;
|
|
constexpr float IconButtonSize = 48.0f; // Touch target for icon buttons
|
|
|
|
// App Bar / Toolbar
|
|
constexpr float AppBarHeight = 56.0f; // Mobile
|
|
constexpr float AppBarHeightLarge = 64.0f; // Desktop
|
|
constexpr float AppBarPadding = 16.0f;
|
|
|
|
// Navigation
|
|
constexpr float NavDrawerWidth = 256.0f;
|
|
constexpr float NavRailWidth = 72.0f;
|
|
constexpr float NavItemHeight = 48.0f;
|
|
constexpr float NavItemPadding = 12.0f;
|
|
constexpr float NavSectionPadding = 8.0f;
|
|
|
|
// Cards
|
|
constexpr float CardCornerRadius = 4.0f;
|
|
constexpr float CardPadding = 16.0f;
|
|
constexpr float CardElevation = 1.0f; // Default elevation in dp
|
|
|
|
// Dialogs
|
|
constexpr float DialogMinWidth = 280.0f;
|
|
constexpr float DialogMaxWidth = 560.0f;
|
|
constexpr float DialogPadding = 24.0f;
|
|
constexpr float DialogTitlePadding = 20.0f;
|
|
constexpr float DialogActionGap = 8.0f;
|
|
constexpr float DialogCornerRadius = 4.0f;
|
|
|
|
// Lists
|
|
constexpr float ListItemHeight = 48.0f; // Single line
|
|
constexpr float ListItemHeightTwoLine = 64.0f;
|
|
constexpr float ListItemHeightThreeLine = 88.0f;
|
|
constexpr float ListItemPaddingH = 16.0f;
|
|
constexpr float ListAvatarSize = 40.0f;
|
|
constexpr float ListIconMargin = 32.0f;
|
|
|
|
// Text Fields
|
|
constexpr float TextFieldHeight = 56.0f;
|
|
constexpr float TextFieldPadding = 16.0f;
|
|
constexpr float TextFieldDenseHeight = 40.0f;
|
|
constexpr float TextFieldCornerRadius = 4.0f;
|
|
|
|
// Chips
|
|
constexpr float ChipHeight = 32.0f;
|
|
constexpr float ChipPaddingH = 12.0f;
|
|
constexpr float ChipCornerRadius = 16.0f;
|
|
|
|
// Tabs
|
|
constexpr float TabHeight = 48.0f;
|
|
constexpr float TabMinWidth = 90.0f;
|
|
constexpr float TabMaxWidth = 360.0f;
|
|
constexpr float TabPaddingH = 16.0f;
|
|
constexpr float TabIndicatorHeight = 2.0f;
|
|
|
|
// Snackbar
|
|
constexpr float SnackbarMinWidth = 288.0f;
|
|
constexpr float SnackbarMaxWidth = 568.0f;
|
|
constexpr float SnackbarHeight = 48.0f;
|
|
constexpr float SnackbarPadding = 8.0f;
|
|
constexpr float SnackbarMargin = 8.0f;
|
|
|
|
// Dividers
|
|
constexpr float DividerThickness = 1.0f;
|
|
constexpr float DividerInset = 16.0f; // For inset dividers
|
|
|
|
} // namespace size
|
|
|
|
// ============================================================================
|
|
// Responsive Breakpoints
|
|
// ============================================================================
|
|
// Based on Material Design responsive layout grid
|
|
|
|
namespace breakpoint {
|
|
|
|
constexpr float Xs = 0.0f; // Extra small: 0-599dp
|
|
constexpr float Sm = 600.0f; // Small: 600-904dp
|
|
constexpr float Md = 905.0f; // Medium: 905-1239dp
|
|
constexpr float Lg = 1240.0f; // Large: 1240-1439dp
|
|
constexpr float Xl = 1440.0f; // Extra large: 1440dp+
|
|
|
|
// Returns the current breakpoint category
|
|
enum class Category { Xs, Sm, Md, Lg, Xl };
|
|
|
|
inline Category GetCategory(float windowWidth) {
|
|
if (windowWidth >= Xl) return Category::Xl;
|
|
if (windowWidth >= Lg) return Category::Lg;
|
|
if (windowWidth >= Md) return Category::Md;
|
|
if (windowWidth >= Sm) return Category::Sm;
|
|
return Category::Xs;
|
|
}
|
|
|
|
// Margin values for each breakpoint
|
|
inline float GetMargin(Category cat) {
|
|
switch (cat) {
|
|
case Category::Xs: return 16.0f;
|
|
case Category::Sm: return 32.0f;
|
|
case Category::Md: return 32.0f; // Or fluid centering
|
|
case Category::Lg: return 200.0f;
|
|
case Category::Xl: return 200.0f; // Or fluid centering
|
|
}
|
|
return 16.0f;
|
|
}
|
|
|
|
// Column count for each breakpoint
|
|
inline int GetColumns(Category cat) {
|
|
switch (cat) {
|
|
case Category::Xs: return 4;
|
|
case Category::Sm: return 8;
|
|
default: return 12;
|
|
}
|
|
}
|
|
|
|
// Recommended navigation style
|
|
enum class NavStyle { BottomNav, NavRail, NavDrawer };
|
|
|
|
inline NavStyle GetNavStyle(Category cat) {
|
|
switch (cat) {
|
|
case Category::Xs: return NavStyle::BottomNav;
|
|
case Category::Sm:
|
|
case Category::Md: return NavStyle::NavRail;
|
|
default: return NavStyle::NavDrawer;
|
|
}
|
|
}
|
|
|
|
} // namespace breakpoint
|
|
|
|
// ============================================================================
|
|
// Layout Helpers
|
|
// ============================================================================
|
|
|
|
/**
|
|
* @brief Get current window's breakpoint category
|
|
*/
|
|
inline breakpoint::Category GetCurrentBreakpoint() {
|
|
ImVec2 windowSize = ImGui::GetWindowSize();
|
|
return breakpoint::GetCategory(windowSize.x);
|
|
}
|
|
|
|
/**
|
|
* @brief Get recommended margin for current window
|
|
*/
|
|
inline float GetCurrentMargin() {
|
|
return breakpoint::GetMargin(GetCurrentBreakpoint());
|
|
}
|
|
|
|
/**
|
|
* @brief Add horizontal spacing (uses 8dp grid)
|
|
* @param units Number of 8dp units (default 1)
|
|
*/
|
|
inline void HSpace(float units = 1.0f) {
|
|
ImGui::SameLine(0, kGridUnit * units);
|
|
}
|
|
|
|
/**
|
|
* @brief Add vertical spacing (uses 8dp grid)
|
|
* @param units Number of 8dp units (default 1)
|
|
*/
|
|
inline void VSpace(float units = 1.0f) {
|
|
ImGui::Dummy(ImVec2(0, kGridUnit * units));
|
|
}
|
|
|
|
/**
|
|
* @brief Begin a padded region
|
|
* @param padding Padding in pixels (use spacing:: constants)
|
|
*/
|
|
inline void BeginPadding(float padding) {
|
|
ImGui::BeginGroup();
|
|
ImGui::Dummy(ImVec2(0, padding));
|
|
ImGui::Indent(padding);
|
|
}
|
|
|
|
/**
|
|
* @brief End a padded region
|
|
* @param padding Same padding used in BeginPadding
|
|
*/
|
|
inline void EndPadding(float padding) {
|
|
ImGui::Unindent(padding);
|
|
ImGui::Dummy(ImVec2(0, padding));
|
|
ImGui::EndGroup();
|
|
}
|
|
|
|
/**
|
|
* @brief Center the next item horizontally within available width
|
|
* @param itemWidth Width of the item to center
|
|
*/
|
|
inline void CenterHorizontally(float itemWidth) {
|
|
float availWidth = ImGui::GetContentRegionAvail().x;
|
|
float offset = (availWidth - itemWidth) * 0.5f;
|
|
if (offset > 0) {
|
|
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + offset);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Calculate column width for responsive grid
|
|
* @param numColumns Number of columns to span
|
|
* @param gutterWidth Gap between columns (default 16dp)
|
|
*/
|
|
inline float GetColumnWidth(int numColumns = 1, float gutterWidth = spacing::Md) {
|
|
float availWidth = ImGui::GetContentRegionAvail().x;
|
|
auto cat = GetCurrentBreakpoint();
|
|
int totalColumns = breakpoint::GetColumns(cat);
|
|
|
|
float totalGutter = gutterWidth * (totalColumns - 1);
|
|
float columnWidth = (availWidth - totalGutter) / totalColumns;
|
|
|
|
return columnWidth * numColumns + gutterWidth * (numColumns - 1);
|
|
}
|
|
|
|
// ============================================================================
|
|
// Card Layout Helper
|
|
// ============================================================================
|
|
|
|
struct CardLayout {
|
|
float width;
|
|
float minHeight;
|
|
float padding;
|
|
float cornerRadius;
|
|
int elevation;
|
|
|
|
CardLayout()
|
|
: width(0) // 0 = auto width
|
|
, minHeight(0)
|
|
, padding(size::CardPadding)
|
|
, cornerRadius(size::CardCornerRadius)
|
|
, elevation(1)
|
|
{}
|
|
|
|
CardLayout& Width(float w) { width = w; return *this; }
|
|
CardLayout& MinHeight(float h) { minHeight = h; return *this; }
|
|
CardLayout& Padding(float p) { padding = p; return *this; }
|
|
CardLayout& CornerRadius(float r) { cornerRadius = r; return *this; }
|
|
CardLayout& Elevation(int e) { elevation = e; return *this; }
|
|
};
|
|
|
|
// ============================================================================
|
|
// Navigation Drawer Item
|
|
// ============================================================================
|
|
|
|
struct NavItem {
|
|
const char* label;
|
|
const char* icon; // Icon font glyph or nullptr
|
|
bool selected;
|
|
bool enabled;
|
|
|
|
NavItem(const char* lbl, const char* ico = nullptr)
|
|
: label(lbl), icon(ico), selected(false), enabled(true)
|
|
{}
|
|
|
|
NavItem& Selected(bool s) { selected = s; return *this; }
|
|
NavItem& Enabled(bool e) { enabled = e; return *this; }
|
|
};
|
|
|
|
// ============================================================================
|
|
// Alignment Helpers
|
|
// ============================================================================
|
|
|
|
/**
|
|
* @brief Align item to right edge of available space
|
|
* @param itemWidth Width of the item
|
|
*/
|
|
inline void AlignRight(float itemWidth) {
|
|
float availWidth = ImGui::GetContentRegionAvail().x;
|
|
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + availWidth - itemWidth);
|
|
}
|
|
|
|
/**
|
|
* @brief Push items to start from right side (call before group of items)
|
|
*/
|
|
inline void BeginRightAlign() {
|
|
ImGui::BeginGroup();
|
|
}
|
|
|
|
/**
|
|
* @brief End right-aligned group and position it
|
|
*/
|
|
inline void EndRightAlign() {
|
|
ImGui::EndGroup();
|
|
float groupWidth = ImGui::GetItemRectSize().x;
|
|
AlignRight(groupWidth);
|
|
}
|
|
|
|
} // namespace material
|
|
} // namespace ui
|
|
} // namespace dragonx
|