Skip to content

Commit 89df0bf

Browse files
committed
feat: merge draggable EXIF info panel support (#179) and bump version to v6.1.0.11
2 parents 7ff6f2a + 0f2c4fb commit 89df0bf

4 files changed

Lines changed: 71 additions & 4 deletions

File tree

QuickView/EditState.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,10 @@ struct AppConfig {
196196

197197
bool ShowBorderIndicator = true;
198198

199+
// --- Info Panel Position ---
200+
float InfoPanelX = 16.0f;
201+
float InfoPanelY = 32.0f;
202+
199203
// --- Control ---
200204
bool EnableCrossFade = true; // Enable cross-fade animation when changing images
201205
int ZoomModeIn = 0; // 0=Auto, 1=Linear, 2=Nearest, 3=High Quality Cubic
@@ -375,6 +379,8 @@ struct ViewState {
375379
bool CompareActive = false;
376380
int ExifOrientation = 1; // EXIF Orientation (1-8, 1=Normal)
377381
bool IsPendingFullscreenExitDrag = false; // [Requirement] Exit fullscreen on drag
382+
bool IsDraggingInfoPanel = false;
383+
POINT InfoPanelDragAnchor = { 0, 0 };
378384

379385
void Reset() {
380386
Zoom = 1.0f;
@@ -396,6 +402,8 @@ struct ViewState {
396402
CompareActive = false;
397403
ExifOrientation = 1;
398404
IsPendingFullscreenExitDrag = false;
405+
IsDraggingInfoPanel = false;
406+
InfoPanelDragAnchor = { 0, 0 };
399407
}
400408
};
401409

@@ -475,6 +483,9 @@ struct RuntimeConfig {
475483
std::wstring SoftProofProfilePath; // Currently active proofing ICC path
476484
bool ShowGamutWarningOverlay = false;
477485

486+
float InfoPanelX = 16.0f;
487+
float InfoPanelY = 32.0f;
488+
478489
// Overlay (Tracing) Mode
479490
OverlayState OverlayModeState = OverlayState::Normal;
480491
BYTE OverlayAlpha = 128; // Current opacity (0-255), default ~50%
@@ -510,6 +521,8 @@ struct RuntimeConfig {
510521
NavTraverse = cfg.NavTraverse;
511522
SortOrder = cfg.SortOrder;
512523
SortDescending = cfg.SortDescending;
524+
InfoPanelX = cfg.InfoPanelX;
525+
InfoPanelY = cfg.InfoPanelY;
513526
}
514527
};
515528

QuickView/UIRenderer.cpp

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,13 @@ HitTestResult UIRenderer::HitTest(float x, float y) {
271271
}
272272
}
273273

274+
// Draggable Panel Body
275+
if (x >= m_lastInfoPanelRect.left && x <= m_lastInfoPanelRect.right &&
276+
y >= m_lastInfoPanelRect.top && y <= m_lastInfoPanelRect.bottom) {
277+
result.type = UIHitResult::InfoPanelDrag;
278+
return result;
279+
}
280+
274281
// Not on any clickable element, reset hover
275282
m_hoverRowIndex = -1;
276283

@@ -2615,7 +2622,9 @@ void UIRenderer::DrawCompactInfo(ID2D1DeviceContext* dc) {
26152622
float textW = MeasureTextWidth(info);
26162623
// [[maybe_unused]] float totalW = textW + 56.0f * s;
26172624

2618-
D2D1_RECT_F rect = D2D1::RectF(16.0f * s, 8.0f * s, 16.0f * s + textW, 32.0f * s);
2625+
float startX = g_runtime.InfoPanelX * s;
2626+
float startY = g_runtime.InfoPanelY * s;
2627+
D2D1_RECT_F rect = D2D1::RectF(startX, startY, startX + textW, startY + 24.0f * s);
26192628
// [Visual Consistency] Follow UI theme instead of image luma
26202629
const AdaptiveUiPalette palette = BuildAdaptivePalette(IsLightThemeActive() ? 1.0f : 0.0f, &m_compactInfoAdaptiveBlend);
26212630

@@ -2635,6 +2644,9 @@ void UIRenderer::DrawCompactInfo(ID2D1DeviceContext* dc) {
26352644
// Close Button [x]
26362645
m_panelCloseRect = D2D1::RectF(m_panelToggleRect.right + 4.0f * s, rect.top, m_panelToggleRect.right + 28.0f * s, rect.bottom);
26372646
DrawTextWithFourWayShadow(dc, L"[x]", 3, m_panelFormat.Get(), m_panelCloseRect, brushRed.Get(), brushShadow.Get(), 1.1f * s);
2647+
2648+
// Save bounds for hit testing (include buttons)
2649+
m_lastInfoPanelRect = D2D1::RectF(rect.left, rect.top, m_panelCloseRect.right, m_panelCloseRect.bottom);
26382650
}
26392651

26402652
float UIRenderer::EstimateCanvasLuminance() const {
@@ -2835,13 +2847,14 @@ void UIRenderer::DrawInfoPanel(ID2D1DeviceContext* dc) {
28352847
}
28362848
width = (std::clamp)(width, 220.0f * s, 300.0f * s);
28372849
float height = 26.0f * s + (float)m_infoGrid.size() * GRID_ROW_HEIGHT * s + 14.0f * s;
2838-
float startX = 16.0f * s;
2839-
float startY = 32.0f * s;
2850+
float startX = g_runtime.InfoPanelX * s;
2851+
float startY = g_runtime.InfoPanelY * s;
28402852

28412853
if (g_currentMetadata.HasGPS) height += 50.0f * s;
28422854
if (g_runtime.InfoPanelExpanded && !g_currentMetadata.HistL.empty()) height += 100.0f * s;
28432855

28442856
D2D1_RECT_F panelRect = D2D1::RectF(startX, startY, startX + width, startY + height);
2857+
m_lastInfoPanelRect = panelRect;
28452858

28462859
// [Geek Glass] Panel Background Render
28472860
QuickView::UI::GeekGlass::GeekGlassConfig glassConfig;

QuickView/UIRenderer.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,8 @@ enum class UIHitResult {
6464
GPSLink, // Click to open in Maps
6565
InfoRow, // Click to copy row content
6666
HudToggleLite, // Click to toggle HUD Lite mode
67-
HudToggleExpand // Click to toggle HUD Expand mode
67+
HudToggleExpand,// Click to toggle HUD Expand mode
68+
InfoPanelDrag // Drag to move Info Panel
6869
};
6970

7071
// Window Controls Hit Test Result
@@ -140,6 +141,8 @@ class UIRenderer {
140141
// ===== Hit Testing (For Click Detection) =====
141142
HitTestResult HitTest(float x, float y);
142143

144+
float GetUIScale() const { return m_uiScale; }
145+
143146
// ===== Accessors for Hit Rects =====
144147
D2D1_RECT_F GetPanelToggleRect() const { return m_panelToggleRect; }
145148
D2D1_RECT_F GetPanelCloseRect() const { return m_panelCloseRect; }
@@ -263,6 +266,7 @@ class UIRenderer {
263266
std::vector<D2D1_RECT_F> m_compareRowRects; // Track individual row rects in Compare HUD
264267
D2D1_RECT_F m_hudToggleLiteRect = {}; // Track HUD lite mode icon area
265268
D2D1_RECT_F m_hudToggleExpandRect = {}; // Track HUD expand mode icon area
269+
D2D1_RECT_F m_lastInfoPanelRect = {}; // Cached bounds of the Info Panel
266270

267271
// Grid Layout Constants
268272
static constexpr float GRID_ICON_WIDTH = 16.0f;

QuickView/main.cpp

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8078,6 +8078,28 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
80788078
// Mouse Interaction
80798079
case WM_MOUSEMOVE: {
80808080
g_currentCursor = LoadCursor(nullptr, IDC_ARROW);
8081+
if (g_viewState.IsDraggingInfoPanel) {
8082+
POINT pt = { (short)LOWORD(lParam), (short)HIWORD(lParam) };
8083+
int dx = pt.x - g_viewState.InfoPanelDragAnchor.x;
8084+
int dy = pt.y - g_viewState.InfoPanelDragAnchor.y;
8085+
8086+
if (dx != 0 || dy != 0) {
8087+
float s = g_uiRenderer ? g_uiRenderer->GetUIScale() : 1.0f;
8088+
g_runtime.InfoPanelX += dx / s;
8089+
g_runtime.InfoPanelY += dy / s;
8090+
8091+
// Keep it visible on screen (approx boundaries)
8092+
RECT rc; GetClientRect(hwnd, &rc);
8093+
float maxW = rc.right / s;
8094+
float maxH = rc.bottom / s;
8095+
g_runtime.InfoPanelX = std::max(0.0f, std::min(g_runtime.InfoPanelX, maxW - 50.0f));
8096+
g_runtime.InfoPanelY = std::max(0.0f, std::min(g_runtime.InfoPanelY, maxH - 50.0f));
8097+
8098+
g_viewState.InfoPanelDragAnchor = pt;
8099+
RequestRepaint(PaintLayer::Static);
8100+
}
8101+
return 0; // Handled
8102+
}
80818103
if (g_viewState.IsDragging) {
80828104
g_currentCursor = LoadCursor(nullptr, IDC_SIZEALL);
80838105
} else if (g_config.EdgeNavClick && !g_gallery.IsVisible() && !g_settingsOverlay.IsVisible() && !g_helpOverlay.IsVisible() && !g_dialog.IsVisible) {
@@ -8925,6 +8947,12 @@ SKIP_EDGE_NAV:;
89258947
auto hit = g_uiRenderer->HitTest((float)pt.x, (float)pt.y);
89268948

89278949
switch (hit.type) {
8950+
case UIHitResult::InfoPanelDrag:
8951+
g_viewState.IsDraggingInfoPanel = true;
8952+
g_viewState.InfoPanelDragAnchor = pt;
8953+
SetCapture(hwnd);
8954+
return 0;
8955+
89288956
case UIHitResult::PanelToggle:
89298957
g_runtime.InfoPanelExpanded = !g_runtime.InfoPanelExpanded;
89308958
if (g_runtime.InfoPanelExpanded && g_currentMetadata.HistR.empty() && !g_imagePath.empty()) {
@@ -9148,6 +9176,15 @@ SKIP_EDGE_NAV:;
91489176
return 0;
91499177
}
91509178

9179+
if (g_viewState.IsDraggingInfoPanel) {
9180+
g_viewState.IsDraggingInfoPanel = false;
9181+
ReleaseCapture();
9182+
g_config.InfoPanelX = g_runtime.InfoPanelX;
9183+
g_config.InfoPanelY = g_runtime.InfoPanelY;
9184+
SaveConfig();
9185+
return 0;
9186+
}
9187+
91519188
if (g_viewState.IsPendingFullscreenExitDrag) {
91529189
g_viewState.IsPendingFullscreenExitDrag = false;
91539190
ReleaseCapture();

0 commit comments

Comments
 (0)