Docs refresh: add user manual & architecture review; update README with accurate details
This commit is contained in:
+96
-12
@@ -218,6 +218,8 @@ struct PopupState {
|
||||
int rowH = 30;
|
||||
int pad = 3;
|
||||
int wheelAccum = 0;
|
||||
bool canDelete = false;
|
||||
int hotX = -1;
|
||||
};
|
||||
static PopupState g_pop;
|
||||
|
||||
@@ -659,16 +661,79 @@ static int PopupRowFromY(int y) {
|
||||
return abs;
|
||||
}
|
||||
|
||||
static Rect PopupDeleteRect(const RECT& rc, int visIdx) {
|
||||
int n = (int)g_pop.items.size();
|
||||
bool hasBar = n > g_pop.visRows;
|
||||
int barW = std::max(3, (int)(4 * g_dpiScale));
|
||||
int rowW = rc.right - 2 * g_pop.pad - (hasBar ? barW + g_pop.pad : 0);
|
||||
int xW = g_pop.rowH;
|
||||
return Rect(g_pop.pad + rowW - xW, g_pop.pad + visIdx * g_pop.rowH, xW, g_pop.rowH - 2);
|
||||
}
|
||||
|
||||
static void PopupRefreshHotFromCursor(HWND h) {
|
||||
POINT pt; GetCursorPos(&pt); ScreenToClient(h, &pt);
|
||||
int row = PopupRowFromY(pt.y);
|
||||
int hx = -1;
|
||||
if (g_pop.canDelete && row >= 0) {
|
||||
RECT rc; GetClientRect(h, &rc);
|
||||
if (PopupDeleteRect(rc, row - g_pop.scroll).Contains(pt.x, pt.y)) hx = row;
|
||||
}
|
||||
g_pop.hot = row; g_pop.hotX = hx;
|
||||
}
|
||||
|
||||
static void PopupDeleteRow(HWND h, int row) {
|
||||
if (row < 0 || row >= (int)g_history.size()) return;
|
||||
std::wstring path = g_history[row].path;
|
||||
bool ok = DeleteFileW(path.c_str()) != FALSE;
|
||||
|
||||
if (ok && path == g_sessionPath) {
|
||||
g_sessionPath.clear();
|
||||
g_lastLoadedText = GetEditText(g_pop.owner);
|
||||
}
|
||||
|
||||
g_history = LoadHistoryIndex();
|
||||
g_pop.items.clear();
|
||||
g_pop.items.reserve(g_history.size());
|
||||
for (const auto& e : g_history) g_pop.items.push_back(e.label);
|
||||
|
||||
SetStatus(g_pop.owner, ok ? L"Deleted" : L"Delete failed");
|
||||
|
||||
int n = (int)g_pop.items.size();
|
||||
if (n == 0) { DestroyWindow(h); return; }
|
||||
|
||||
if (n < g_pop.visRows) {
|
||||
g_pop.visRows = n;
|
||||
int newH = n * g_pop.rowH + 2 * g_pop.pad;
|
||||
RECT wr; GetWindowRect(h, &wr);
|
||||
SetWindowPos(h, nullptr, wr.left, wr.bottom - newH,
|
||||
wr.right - wr.left, newH, SWP_NOZORDER | SWP_NOACTIVATE);
|
||||
}
|
||||
int maxScroll = std::max(0, n - g_pop.visRows);
|
||||
g_pop.scroll = std::min(g_pop.scroll, maxScroll);
|
||||
|
||||
PopupRefreshHotFromCursor(h);
|
||||
InvalidateRect(h, nullptr, FALSE);
|
||||
}
|
||||
|
||||
LRESULT CALLBACK PopupProc(HWND h, UINT m, WPARAM w, LPARAM l) {
|
||||
switch (m) {
|
||||
case WM_MOUSEMOVE: {
|
||||
int row = PopupRowFromY(GET_Y_LPARAM(l));
|
||||
if (row != g_pop.hot) { g_pop.hot = row; InvalidateRect(h, nullptr, FALSE); }
|
||||
int hx = -1;
|
||||
if (g_pop.canDelete && row >= 0) {
|
||||
RECT rc; GetClientRect(h, &rc);
|
||||
if (PopupDeleteRect(rc, row - g_pop.scroll).Contains(GET_X_LPARAM(l), GET_Y_LPARAM(l)))
|
||||
hx = row;
|
||||
}
|
||||
if (row != g_pop.hot || hx != g_pop.hotX) {
|
||||
g_pop.hot = row; g_pop.hotX = hx;
|
||||
InvalidateRect(h, nullptr, FALSE);
|
||||
}
|
||||
TRACKMOUSEEVENT t{ sizeof(t), TME_LEAVE, h, 0 }; TrackMouseEvent(&t);
|
||||
return 0;
|
||||
}
|
||||
case WM_MOUSELEAVE:
|
||||
g_pop.hot = -1; InvalidateRect(h, nullptr, FALSE);
|
||||
g_pop.hot = -1; g_pop.hotX = -1; InvalidateRect(h, nullptr, FALSE);
|
||||
return 0;
|
||||
case WM_MOUSEWHEEL: {
|
||||
int maxScroll = (int)g_pop.items.size() - g_pop.visRows;
|
||||
@@ -679,17 +744,25 @@ LRESULT CALLBACK PopupProc(HWND h, UINT m, WPARAM w, LPARAM l) {
|
||||
g_pop.wheelAccum -= steps * WHEEL_DELTA;
|
||||
g_pop.scroll -= steps * 3;
|
||||
g_pop.scroll = std::max(0, std::min(g_pop.scroll, maxScroll));
|
||||
POINT pt; GetCursorPos(&pt); ScreenToClient(h, &pt);
|
||||
g_pop.hot = PopupRowFromY(pt.y);
|
||||
PopupRefreshHotFromCursor(h);
|
||||
InvalidateRect(h, nullptr, FALSE);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
case WM_KEYDOWN:
|
||||
if (w == VK_ESCAPE) DestroyWindow(h);
|
||||
else if (w == VK_DELETE && g_pop.canDelete && g_pop.hot >= 0)
|
||||
PopupDeleteRow(h, g_pop.hot);
|
||||
return 0;
|
||||
case WM_LBUTTONUP: {
|
||||
int row = PopupRowFromY(GET_Y_LPARAM(l));
|
||||
if (g_pop.canDelete && row >= 0) {
|
||||
RECT rc; GetClientRect(h, &rc);
|
||||
if (PopupDeleteRect(rc, row - g_pop.scroll).Contains(GET_X_LPARAM(l), GET_Y_LPARAM(l))) {
|
||||
PopupDeleteRow(h, row);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (row >= 0)
|
||||
PostMessageW(g_pop.owner, WM_APP_SELECT, (WPARAM)g_pop.ctrlId, (LPARAM)row);
|
||||
DestroyWindow(h);
|
||||
@@ -712,21 +785,31 @@ LRESULT CALLBACK PopupProc(HWND h, UINT m, WPARAM w, LPARAM l) {
|
||||
Rect all(0, 0, rc.right, rc.bottom);
|
||||
FillRound(g, T_CARD, all, 10);
|
||||
StrokeRound(g, T_FAINT, all, 10, 1.0f);
|
||||
|
||||
int n = (int)g_pop.items.size();
|
||||
bool hasBar = n > g_pop.visRows;
|
||||
int barW = std::max(3, (int)(4 * g_dpiScale));
|
||||
int rowW = rc.right - 2 * g_pop.pad - (hasBar ? barW + g_pop.pad : 0);
|
||||
int last = std::min(n, g_pop.scroll + g_pop.visRows);
|
||||
|
||||
int n = (int)g_pop.items.size();
|
||||
bool hasBar = n > g_pop.visRows;
|
||||
int barW = std::max(3, (int)(4 * g_dpiScale));
|
||||
int rowW = rc.right - 2 * g_pop.pad - (hasBar ? barW + g_pop.pad : 0);
|
||||
int reserve = g_pop.canDelete ? g_pop.rowH : 0;
|
||||
int last = std::min(n, g_pop.scroll + g_pop.visRows);
|
||||
for (int i = g_pop.scroll; i < last; ++i) {
|
||||
int vis = i - g_pop.scroll;
|
||||
Rect row(g_pop.pad, g_pop.pad + vis * g_pop.rowH, rowW, g_pop.rowH - 2);
|
||||
if (i == g_pop.hot) FillRound(g, T_CARD_HI, row, 7);
|
||||
RectF tb((REAL)row.X + 9, (REAL)row.Y, (REAL)row.Width - 12, (REAL)row.Height);
|
||||
RectF tb((REAL)row.X + 9, (REAL)row.Y, (REAL)(row.Width - 12 - reserve), (REAL)row.Height);
|
||||
DrawTextC(g, g_pop.items[i].c_str(), *g_gpUI,
|
||||
(i == g_pop.sel) ? T_ACCENT : T_TEXT,
|
||||
tb, StringAlignmentNear, StringAlignmentCenter);
|
||||
if (g_pop.canDelete && i == g_pop.hot) {
|
||||
Rect xr = PopupDeleteRect(rc, vis);
|
||||
if (i == g_pop.hotX) FillRound(g, T_CARD_LO, xr, 6);
|
||||
Color xc = (i == g_pop.hotX) ? T_DANGER : T_FAINT;
|
||||
Pen xpen(xc, 1.8f);
|
||||
int xpad = std::max(6, (int)(8 * g_dpiScale));
|
||||
g.DrawLine(&xpen, xr.X + xpad, xr.Y + xpad,
|
||||
xr.X + xr.Width - xpad, xr.Y + xr.Height - xpad);
|
||||
g.DrawLine(&xpen, xr.X + xr.Width - xpad, xr.Y + xpad,
|
||||
xr.X + xpad, xr.Y + xr.Height - xpad);
|
||||
}
|
||||
}
|
||||
if (hasBar) {
|
||||
int trackH = rc.bottom - 2 * g_pop.pad;
|
||||
@@ -785,6 +868,7 @@ void ShowSelectPopup(HWND owner, int ctrlId, const std::vector<std::wstring>& it
|
||||
g_pop.sel = sel;
|
||||
g_pop.owner = owner;
|
||||
g_pop.ctrlId = ctrlId;
|
||||
g_pop.canDelete = (ctrlId == ID_SEL_HISTORY);
|
||||
g_pop.visRows = visRows;
|
||||
g_pop.rowH = rowH;
|
||||
g_pop.pad = pad;
|
||||
|
||||
Reference in New Issue
Block a user