Files
2025-12-15 04:41:53 -08:00

166 lines
6.8 KiB
C++

#pragma once
#include <XTL.h>
#include "XBApp.h"
#include "XBInput.h"
#include "OnScreenKeyboard.h"
#include "ContextMenu.h"
#include "PaneRenderer.h"
#include "actions.h"
struct ProgState {
bool active; // overlay visible when true
ULONGLONG done; // bytes completed so far
ULONGLONG total; // total bytes (0 if unknown)
char current[256]; // current path/file shown in overlay
DWORD lastPaintMs; // throttle overlay redraw rate
char label[24]; // short title ("Copying...", etc.)
ProgState()
: active(false), done(0), total(0), lastPaintMs(0)
{
current[0] = 0;
label[0] = 0;
}
};
class FileBrowserApp : public CXBApplication {
public:
static FileBrowserApp& Get();
char* GetCurrentIp();
ProgState m_prog;
// Allow centralized action runner to call private helpers/members.
friend class Actions;
// --- CXBApplication lifecycle ------------------------------------------
virtual HRESULT Initialize(); // create font, map drives, compute layout
virtual HRESULT FrameMove(); // input + periodic drive rescan
virtual HRESULT Render(); // draw panes, footer, overlays
// Recompute responsive layout using the current D3D viewport.
void ComputeResponsiveLayout();
// --- Progress HUD API ---------------------------------------------------
// Show the progress overlay and initialize counters/labels.
void BeginProgress(ULONGLONG total, const char* firstLabel, const char* title = "Working...");
// Update progress (bytes + optional label). Throttles Render() internally.
void UpdateProgress(ULONGLONG done, ULONGLONG total, const char* label);
// Hide progress overlay.
void EndProgress();
// Draw the overlay; called from Render() when m_prog.active.
void DrawProgressOverlay();
// --- Status line (footer toast) ----------------------------------------
void SetStatus(const char* fmt, ...); // printf-style
void SetStatusLastErr(const char* prefix); // append GetLastError()
DWORD StatusUntilMs() const; // used by Render() to time out
private:
FileBrowserApp();
FileBrowserApp(const FileBrowserApp&);
FileBrowserApp& operator=(const FileBrowserApp&) { return *this; }
void SetCurrentIp(char* ip);
// --- UI helpers ---------------------------------------------------------
static FLOAT HdrX(FLOAT baseX){ return baseX - 15.0f; } // header left offset
// --- Data refresh / navigation -----------------------------------------
void EnsureListing(Pane& p); // clamp indices and items
void EnterSelection(Pane& p); // drive->dir, ".."->up, dir->descend, .xbe->launch
void UpOne(Pane& p); // go up one or back to drive list
void RefreshPane(Pane& p); // rebuild items, preserve selection/scroll
bool ResolveDestDir(char* outDst, size_t cap);// determine destination dir from other pane
bool ResolveSrcDir(char* srcDst, size_t cap); // determine destination dir from current pane
void SelectItemInPane(Pane& p, const char* name);
// --- Context menu -------------------------------------------------------
void BuildZipSubMenu(); // build the unzip submenu
void BuildConfirmDelSubMenu();
void BuildContextMenu(); // build items based on mode/selection
void OpenMenu(); // position and open popup
void CloseMenu(); // close and return to browse mode
// --- Rename OSD / keyboard ---------------------------------------------
void BeginRename(const char* parentDir, const char* oldName);
void CancelRename();
void AcceptRename(); // validate, sanitize, perform MoveFileA
void DrawRename();
// --- Input routing ------------------------------------------------------
void OnPad(const XBGAMEPAD& pad); // router
void OnPad_Browse(const XBGAMEPAD& pad);
void OnPad_Menu(const XBGAMEPAD& pad);
void OnPad_Rename(const XBGAMEPAD& pad);
// --- Members ------------------------------------------------------------
CXBFont m_font; // UI font (XPR asset)
int m_visible; // number of visible rows per pane
// Edge-detect state for buttons/analog (prevent double triggers).
unsigned char m_prevA, m_prevB, m_prevX, m_prevY;
unsigned char m_prevWhite, m_prevBlack;
DWORD m_prevButtons;
Pane m_pane[2]; // left (0) and right (1) pane data
int m_active; // active pane: 0=left, 1=right
// Up/down auto-repeat (list navigation).
bool m_navUDHeld; // currently repeating
int m_navUDDir; // -1 up, +1 down
DWORD m_navUDNext; // next repeat time (GetTickCount ms)
// Mode and UI components
enum { MODE_BROWSE, MODE_MENU, MODE_RENAME } m_mode;
ContextMenu m_ctx; // popup menu
ContextMenu m_zipSubMenu; // zip submenu
ContextMenu m_confirmDelSubMenu; // delete confirmation submenu
ContextMenu* m_menuStack[8]; // max possible menus
int m_menuDepth;
OnScreenKeyboard m_kb; // rename overlay
PaneRenderer m_renderer; // draws a pane (headers, rows, scrollbar)
// Draw the already-open context menu (used by Render()).
void DrawMenu();
// Status text buffer and expiry tick for footer toast.
char m_status[256];
DWORD m_statusUntilMs;
// Copy current pad state so inputs do not leak between modes.
void AbsorbPadState(const XBGAMEPAD& pad);
// --- Back-to-exit confirm state (press Back twice to exit) ---
bool m_backConfirmArmed; // true after first Back press
DWORD m_backConfirmUntil; // snapshot of status expiry (informational)
unsigned char m_prevBack; // edge detect for Back
// Exit helper (define one of the strategies inside)
void ExitNow();
ULONGLONG m_dvdUsedBytes; // no in-class init here
ULONGLONG m_dvdTotalBytes; // "
bool m_dvdHaveStats;
// -------------------------------------------------------------------------
// Responsive layout state (computed in ComputeResponsiveLayout()).
// These replace the old static k* constants so we can adapt to any
// viewport size/aspect without #defines or hardcoded coordinates.
// -------------------------------------------------------------------------
FLOAT kPaneGap; // gap between the two panes
FLOAT kListX_L; // left pane X
FLOAT kListW; // pane width
FLOAT kHdrY, kHdrH, kHdrW; // header band geometry per pane
FLOAT kListY, kLineH; // list top and per-row height
FLOAT kGutterW; // icon gutter width
FLOAT kPaddingX; // left/right text padding inside pane
FLOAT kScrollBarW; // scrollbar track width
};