diff --git a/src/NppJsonViewer/Define.h b/src/NppJsonViewer/Define.h index 5ee80f1..3834ddb 100644 --- a/src/NppJsonViewer/Define.h +++ b/src/NppJsonViewer/Define.h @@ -1,4 +1,6 @@ #pragma once +#include + #include "PluginInterface.h" // Define the number of plugin commands here @@ -64,6 +66,7 @@ const TCHAR STR_INI_FORMATTING_INDENTCOUNT[] = TEXT("INDENTATION_COUNT"); const TCHAR STR_INI_OTHER_SEC[] = TEXT("Others"); const TCHAR STR_INI_OTHER_FOLLOW_TAB[] = TEXT("FOLLOW_TAB"); +const TCHAR STR_INI_OTHER_TREE_ZOOM[] = TEXT("TREE_ZOOM"); const TCHAR STR_INI_OTHER_AUTO_FORMAT[] = TEXT("AUTO_FORMAT"); const TCHAR STR_INI_OTHER_USE_HIGHLIGHT[] = TEXT("USE_JSON_HIGHLIGHT"); const TCHAR STR_INI_OTHER_IGNORE_COMMENT[] = TEXT("IGNORE_COMMENT"); @@ -117,4 +120,7 @@ struct Setting bool bAutoFormat = false; bool bUseJsonHighlight = true; ParseOptions parseOptions {}; + int nTreeZoom = 100; // Tree view font zoom in percent (80..250) + + std::wstring configPath; // Full path of JSONViewer.ini (not persisted) }; diff --git a/src/NppJsonViewer/JsonViewDlg.cpp b/src/NppJsonViewer/JsonViewDlg.cpp index 4080af0..331d2d4 100644 --- a/src/NppJsonViewer/JsonViewDlg.cpp +++ b/src/NppJsonViewer/JsonViewDlg.cpp @@ -936,6 +936,19 @@ void JsonViewDlg::UpdateUIOnZoom(int zoomPercentage) const SetTreeViewZoom(zoomFactor); } +void JsonViewDlg::PersistZoom(int zoomPercentage) +{ + const auto& zoomRange = m_pTreeViewZoom->GetRange(); + if (zoomPercentage < zoomRange.m_nMinZoom || zoomPercentage > zoomRange.m_nMaxZoom) + return; + + if (m_pSetting->nTreeZoom != zoomPercentage) + { + m_pSetting->nTreeZoom = zoomPercentage; + ProfileSetting(m_pSetting->configPath).SetSettings(*m_pSetting); + } +} + void JsonViewDlg::HandleZoomOnScroll(WPARAM wParam) const { int pos = GetZoomLevel(); // Current zoom level @@ -1101,6 +1114,10 @@ INT_PTR JsonViewDlg::run_dlgProc(UINT message, WPARAM wParam, LPARAM lParam) m_pTreeView->OnInit(getHSelf(), IDC_TREE); m_pTreeViewZoom->OnInit(getHSelf(), IDC_ZOOM_SLIDER, IDC_ZOOM_PERCENT); + // Apply the zoom level restored from JSONViewer.ini + const auto& zoomRange = m_pTreeViewZoom->GetRange(); + UpdateUIOnZoom(std::clamp(m_pSetting->nTreeZoom, zoomRange.m_nMinZoom, zoomRange.m_nMaxZoom)); + PrepareButtons(); // Set default node path as JSON @@ -1182,6 +1199,7 @@ INT_PTR JsonViewDlg::run_dlgProc(UINT message, WPARAM wParam, LPARAM lParam) if (GetKeyState(VK_CONTROL) & 0x8000) { HandleZoomOnScroll(wParam); + PersistZoom(GetZoomLevel()); return TRUE; } return FALSE; @@ -1193,9 +1211,18 @@ INT_PTR JsonViewDlg::run_dlgProc(UINT message, WPARAM wParam, LPARAM lParam) if (reinterpret_cast(lParam) == hSlider) { + // While the thumb is being dragged (TB_THUMBTRACK) the position + // changes continuously, so only persist once the gesture is over. + // WM_HSCROLL carries the notification code in LOWORD(wParam); + // HIWORD is the thumb position itself. + const bool bDragging = (LOWORD(wParam) == TB_THUMBTRACK); + int pos = m_pTreeViewZoom->GetPosition(); UpdateUIOnZoom(pos); + if (!bDragging) + PersistZoom(pos); + return TRUE; } return FALSE; diff --git a/src/NppJsonViewer/JsonViewDlg.h b/src/NppJsonViewer/JsonViewDlg.h index 00cc599..605db34 100644 --- a/src/NppJsonViewer/JsonViewDlg.h +++ b/src/NppJsonViewer/JsonViewDlg.h @@ -95,6 +95,7 @@ class JsonViewDlg void SetTreeViewZoom(double dwZoomFactor) const; void UpdateUIOnZoom(int zoomPercentage) const; void HandleZoomOnScroll(WPARAM wParam) const; + void PersistZoom(int zoomPercentage); void HandleTreeEvents(LPARAM lParam) const; diff --git a/src/NppJsonViewer/NppJsonPlugin.cpp b/src/NppJsonViewer/NppJsonPlugin.cpp index f251481..e7224ff 100644 --- a/src/NppJsonViewer/NppJsonPlugin.cpp +++ b/src/NppJsonViewer/NppJsonPlugin.cpp @@ -169,7 +169,8 @@ void NppJsonPlugin::ConstructSetting() { if (!m_pSetting) { - m_pSetting = std::make_shared(); + m_pSetting = std::make_shared(); + m_pSetting->configPath = m_configPath; ProfileSetting(m_configPath).GetSettings(*m_pSetting); } } diff --git a/src/NppJsonViewer/Profile.cpp b/src/NppJsonViewer/Profile.cpp index 7f13a18..cf6c9c6 100644 --- a/src/NppJsonViewer/Profile.cpp +++ b/src/NppJsonViewer/Profile.cpp @@ -94,6 +94,10 @@ bool ProfileSetting::GetSettings(Setting& info) const if (bRetVal) info.bFollowCurrentTab = static_cast(nVal); + bRetVal = bRetVal && ReadValue(STR_INI_OTHER_SEC, STR_INI_OTHER_TREE_ZOOM, nVal, info.nTreeZoom); + if (bRetVal) + info.nTreeZoom = nVal; + bRetVal = bRetVal && ReadValue(STR_INI_OTHER_SEC, STR_INI_OTHER_AUTO_FORMAT, nVal, info.bAutoFormat); if (bRetVal) info.bAutoFormat = static_cast(nVal); @@ -127,6 +131,7 @@ bool ProfileSetting::SetSettings(const Setting& info) const bRetVal = bRetVal && WriteValue(STR_INI_FORMATTING_SEC, STR_INI_FORMATTING_INDENTCOUNT, info.indent.len); bRetVal = bRetVal && WriteValue(STR_INI_OTHER_SEC, STR_INI_OTHER_FOLLOW_TAB, info.bFollowCurrentTab); + bRetVal = bRetVal && WriteValue(STR_INI_OTHER_SEC, STR_INI_OTHER_TREE_ZOOM, info.nTreeZoom); bRetVal = bRetVal && WriteValue(STR_INI_OTHER_SEC, STR_INI_OTHER_AUTO_FORMAT, info.bAutoFormat); bRetVal = bRetVal && WriteValue(STR_INI_OTHER_SEC, STR_INI_OTHER_USE_HIGHLIGHT, info.bUseJsonHighlight); bRetVal = bRetVal && WriteValue(STR_INI_OTHER_SEC, STR_INI_OTHER_IGNORE_COMMENT, info.parseOptions.bIgnoreComment); diff --git a/tests/UnitTest/ProfileTest.cpp b/tests/UnitTest/ProfileTest.cpp index 10ab846..873d9f6 100644 --- a/tests/UnitTest/ProfileTest.cpp +++ b/tests/UnitTest/ProfileTest.cpp @@ -137,6 +137,7 @@ namespace ProfileSettingTests EXPECT_EQ(setting.bFollowCurrentTab, false); EXPECT_EQ(setting.bAutoFormat, false); EXPECT_EQ(setting.bUseJsonHighlight, true); + EXPECT_EQ(setting.nTreeZoom, 100); EXPECT_EQ(setting.parseOptions.bIgnoreComment, true); EXPECT_EQ(setting.parseOptions.bIgnoreTrailingComma, true); @@ -173,9 +174,32 @@ namespace ProfileSettingTests EXPECT_EQ(actual.bFollowCurrentTab, expected.bFollowCurrentTab); EXPECT_EQ(actual.bAutoFormat, expected.bAutoFormat); EXPECT_EQ(actual.bUseJsonHighlight, expected.bUseJsonHighlight); + EXPECT_EQ(actual.nTreeZoom, expected.nTreeZoom); EXPECT_EQ(actual.parseOptions.bIgnoreComment, expected.parseOptions.bIgnoreComment); EXPECT_EQ(actual.parseOptions.bIgnoreTrailingComma, expected.parseOptions.bIgnoreTrailingComma); EXPECT_EQ(actual.parseOptions.bReplaceUndefined, expected.parseOptions.bReplaceUndefined); } + + TEST_F(ProfileTest, TreeZoom_RoundTrip) + { + // a profile without the TREE_ZOOM key falls back to 100% + { + Setting setting {}; + EXPECT_TRUE(m_pProfile->GetSettings(setting)); + EXPECT_EQ(setting.nTreeZoom, 100); + } + + // every value inside the slider range must survive a write/read cycle + for (int zoom : { 80, 100, 150, 200, 250 }) + { + Setting expected {}; + expected.nTreeZoom = zoom; + ASSERT_TRUE(m_pProfile->SetSettings(expected)) << zoom; + + Setting actual {}; + ASSERT_TRUE(m_pProfile->GetSettings(actual)) << zoom; + EXPECT_EQ(actual.nTreeZoom, zoom); + } + } } // namespace ProfileSettingTests