Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 4cabcc9

Browse filesBrowse files
authored
[Feature]: Zoom tree view with ctrl+ mouse wheel and slider (#207)
* Add zoom feature for treeview on ctrl+mouse scroll * Add zoom feature using slider * Const functions * Implement reset on double click on the zoomer value * Rename variable * FIx x86 compilation * Fix ui fluctuations #closes #89 #closes #192 #fixes #89 #fixes #192
1 parent 3f37522 commit 4cabcc9
Copy full SHA for 4cabcc9

File tree

Expand file treeCollapse file tree

8 files changed

+246
-2
lines changed
Filter options
Expand file treeCollapse file tree

8 files changed

+246
-2
lines changed

‎src/NppJsonViewer/JsonViewDlg.cpp

Copy file name to clipboardExpand all lines: src/NppJsonViewer/JsonViewDlg.cpp
+95Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ JsonViewDlg::JsonViewDlg(HINSTANCE hInstance, const NppData& nppData, const bool
1919
, m_nDlgId(nCmdId)
2020
, m_pEditor(std::make_unique<ScintillaEditor>(nppData))
2121
, m_pTreeView(std::make_unique<TreeViewCtrl>())
22+
, m_pTreeViewZoom(std::make_unique<SliderCtrl>())
2223
, m_pSetting(pSetting)
2324
, m_pCurrFileName(std::make_unique<wchar_t[]>(FILENAME_LEN_IN_TITLE))
2425
{
@@ -895,6 +896,74 @@ void JsonViewDlg::EnableControls(const std::vector<DWORD>& ids, bool enable)
895896
EnableWindow(GetDlgItem(getHSelf(), id), enable ? TRUE : FALSE);
896897
}
897898

899+
auto JsonViewDlg::GetZoomLevel() const -> int
900+
{
901+
return m_pTreeViewZoom->GetPosition();
902+
}
903+
904+
void JsonViewDlg::SetZoomLevel(int pos) const
905+
{
906+
m_pTreeViewZoom->SetPosition(pos);
907+
}
908+
909+
void JsonViewDlg::SetTreeViewZoom(double dwZoomFactor) const
910+
{
911+
HWND hTreeView = GetDlgItem(getHSelf(), IDC_TREE);
912+
static HFONT hCurrentFont = reinterpret_cast<HFONT>(SendMessage(hTreeView, WM_GETFONT, 0, 0));
913+
914+
LOGFONT logFont {};
915+
GetObject(hCurrentFont, sizeof(LOGFONT), &logFont);
916+
logFont.lfHeight = static_cast<LONG>(logFont.lfHeight * dwZoomFactor);
917+
918+
static HFONT hTreeFont = nullptr;
919+
if (hTreeFont)
920+
{
921+
DeleteObject(hTreeFont);
922+
}
923+
hTreeFont = CreateFontIndirect(&logFont);
924+
925+
SendMessage(hTreeView, WM_SETFONT, reinterpret_cast<WPARAM>(hTreeFont), TRUE);
926+
InvalidateRect(hTreeView, nullptr, TRUE);
927+
}
928+
929+
void JsonViewDlg::UpdateUIOnZoom(int zoomPercentage) const
930+
{
931+
// Update zoom level on slider
932+
SetZoomLevel(zoomPercentage);
933+
934+
// Update the Tree view
935+
double zoomFactor = zoomPercentage / 100.0;
936+
SetTreeViewZoom(zoomFactor);
937+
}
938+
939+
void JsonViewDlg::HandleZoomOnScroll(WPARAM wParam) const
940+
{
941+
int pos = GetZoomLevel(); // Current zoom level
942+
int delta = GET_WHEEL_DELTA_WPARAM(wParam);
943+
944+
const auto& zoomRange = m_pTreeViewZoom->GetRange();
945+
const bool isZoomIn = delta > 0;
946+
bool bRefreshUI = true;
947+
948+
if (isZoomIn && pos < zoomRange.m_nMaxZoom)
949+
{
950+
pos += 10; // Zoom in
951+
}
952+
else if (!isZoomIn && pos > zoomRange.m_nMinZoom)
953+
{
954+
pos -= 10; // Zoom out
955+
}
956+
else
957+
{
958+
bRefreshUI = false;
959+
}
960+
961+
if (bRefreshUI)
962+
{
963+
UpdateUIOnZoom(pos);
964+
}
965+
}
966+
898967
void JsonViewDlg::HandleTreeEvents(LPARAM lParam) const
899968
{
900969
LPNMHDR lpnmh = reinterpret_cast<LPNMHDR>(lParam);
@@ -1030,6 +1099,7 @@ INT_PTR JsonViewDlg::run_dlgProc(UINT message, WPARAM wParam, LPARAM lParam)
10301099
::SetWindowLongPtr(getHSelf(), GWLP_USERDATA, reinterpret_cast<LONG_PTR>(this));
10311100

10321101
m_pTreeView->OnInit(getHSelf(), IDC_TREE);
1102+
m_pTreeViewZoom->OnInit(getHSelf(), IDC_ZOOM_SLIDER, IDC_ZOOM_PERCENT);
10331103

10341104
PrepareButtons();
10351105

@@ -1107,6 +1177,31 @@ INT_PTR JsonViewDlg::run_dlgProc(UINT message, WPARAM wParam, LPARAM lParam)
11071177
return TRUE;
11081178
}
11091179

1180+
case WM_MOUSEWHEEL:
1181+
{
1182+
if (GetKeyState(VK_CONTROL) & 0x8000)
1183+
{
1184+
HandleZoomOnScroll(wParam);
1185+
return TRUE;
1186+
}
1187+
return FALSE;
1188+
}
1189+
1190+
case WM_HSCROLL:
1191+
{
1192+
HWND hSlider = GetDlgItem(getHSelf(), IDC_ZOOM_SLIDER);
1193+
1194+
if (reinterpret_cast<HWND>(lParam) == hSlider)
1195+
{
1196+
int pos = m_pTreeViewZoom->GetPosition();
1197+
UpdateUIOnZoom(pos);
1198+
1199+
return TRUE;
1200+
}
1201+
return FALSE;
1202+
}
1203+
1204+
11101205
default:
11111206
return DockingDlgInterface::run_dlgProc(message, wParam, lParam);
11121207
}

‎src/NppJsonViewer/JsonViewDlg.h

Copy file name to clipboardExpand all lines: src/NppJsonViewer/JsonViewDlg.h
+8Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "PluginInterface.h"
1010
#include "resource.h"
1111
#include "TreeViewCtrl.h"
12+
#include "SliderCtrl.h"
1213
#include "ScintillaEditor.h"
1314
#include "JsonHandler.h"
1415
#include "JsonNode.h"
@@ -89,6 +90,12 @@ class JsonViewDlg
8990
void ShowControls(const std::vector<DWORD>& ids, bool show);
9091
void EnableControls(const std::vector<DWORD>& ids, bool enable);
9192

93+
auto GetZoomLevel() const -> int;
94+
void SetZoomLevel(int pos) const;
95+
void SetTreeViewZoom(double dwZoomFactor) const;
96+
void UpdateUIOnZoom(int zoomPercentage) const;
97+
void HandleZoomOnScroll(WPARAM wParam) const;
98+
9299
void HandleTreeEvents(LPARAM lParam) const;
93100

94101
auto GetFormatSetting() const -> std::tuple<LE, LF, char, unsigned>;
@@ -118,5 +125,6 @@ class JsonViewDlg
118125
std::unique_ptr<wchar_t[]> m_pCurrFileName;
119126
std::unique_ptr<ScintillaEditor> m_pEditor = nullptr;
120127
std::unique_ptr<TreeViewCtrl> m_pTreeView = nullptr;
128+
std::unique_ptr<SliderCtrl> m_pTreeViewZoom = nullptr;
121129
std::shared_ptr<Setting> m_pSetting = nullptr;
122130
};

‎src/NppJsonViewer/NPPJSONViewer.vcxproj

Copy file name to clipboardExpand all lines: src/NppJsonViewer/NPPJSONViewer.vcxproj
+2Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,7 @@
197197
<ClCompile Include="ScintillaEditor.cpp" />
198198
<ClCompile Include="SettingsDlg.cpp" />
199199
<ClCompile Include="ShortcutCommand.cpp" />
200+
<ClCompile Include="SliderCtrl.cpp" />
200201
<ClCompile Include="TreeViewCtrl.cpp" />
201202
</ItemGroup>
202203
<ItemGroup>
@@ -221,6 +222,7 @@
221222
<ClInclude Include="ScintillaEditor.h" />
222223
<ClInclude Include="SettingsDlg.h" />
223224
<ClInclude Include="ShortcutCommand.h" />
225+
<ClInclude Include="SliderCtrl.h" />
224226
<ClInclude Include="StopWatch.h" />
225227
<ClCompile Include="TreeHandler.h" />
226228
<ClInclude Include="TrackingStream.h" />

‎src/NppJsonViewer/NPPJSONViewer.vcxproj.filters

Copy file name to clipboardExpand all lines: src/NppJsonViewer/NPPJSONViewer.vcxproj.filters
+6Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,9 @@
6060
<ClCompile Include="TreeHandler.h">
6161
<Filter>Header Files</Filter>
6262
</ClCompile>
63+
<ClCompile Include="SliderCtrl.cpp">
64+
<Filter>Source Files</Filter>
65+
</ClCompile>
6366
</ItemGroup>
6467
<ItemGroup>
6568
<ClInclude Include="resource.h">
@@ -134,6 +137,9 @@
134137
<ClInclude Include="TrackingStream.h">
135138
<Filter>Header Files</Filter>
136139
</ClInclude>
140+
<ClInclude Include="SliderCtrl.h">
141+
<Filter>Header Files</Filter>
142+
</ClInclude>
137143
</ItemGroup>
138144
<ItemGroup>
139145
<ResourceCompile Include="resource.rc">

‎src/NppJsonViewer/SliderCtrl.cpp

Copy file name to clipboard
+76Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
#include "SliderCtrl.h"
2+
3+
#include <string>
4+
5+
SliderCtrl::SliderCtrl(const SliderRange& sliderRange)
6+
: m_sliderRange(sliderRange)
7+
{
8+
}
9+
10+
SliderCtrl::~SliderCtrl()
11+
{
12+
// Restore the original window procedure on cleanup
13+
SetWindowLongPtr(m_hSelf, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(m_oldSliderProc));
14+
}
15+
16+
void SliderCtrl::OnInit(HWND hParent, int sliderID, int sliderInfoID)
17+
{
18+
m_hParent = hParent;
19+
m_hSelf = GetDlgItem(m_hParent, sliderID);
20+
m_hSelfInfo = GetDlgItem(m_hParent, sliderInfoID);
21+
22+
// Set slider range and initial position
23+
SendMessage(m_hSelf, TBM_SETRANGE, TRUE, MAKELPARAM(m_sliderRange.m_nMinZoom, m_sliderRange.m_nMaxZoom));
24+
SendMessage(m_hSelf, TBM_SETPOS, TRUE, m_sliderRange.m_nDefault);
25+
SendMessage(m_hSelf, TBM_SETPAGESIZE, 0, m_sliderRange.m_nSteps);
26+
27+
UpdateInfo(m_sliderRange.m_nDefault);
28+
29+
// Subclass the slider control to handle double-click events
30+
m_oldSliderProc = reinterpret_cast<WNDPROC>(SetWindowLongPtr(m_hSelfInfo, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(runWinProc)));
31+
32+
// Save this instance for access in the static window procedure
33+
SetWindowLongPtr(m_hSelfInfo, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(this));
34+
}
35+
36+
auto SliderCtrl::GetPosition() const -> int
37+
{
38+
int pos = static_cast<int>(SendMessage(m_hSelf, TBM_GETPOS, 0, 0));
39+
return pos;
40+
}
41+
42+
void SliderCtrl::SetPosition(int pos) const
43+
{
44+
// Set slider position
45+
SendMessage(m_hSelf, TBM_SETPOS, TRUE, pos);
46+
47+
// Set slider position in text value
48+
UpdateInfo(pos);
49+
}
50+
51+
void SliderCtrl::UpdateInfo(int zoomPercentage) const
52+
{
53+
std::wstring sliderInfoText = std::to_wstring(zoomPercentage) + L"%";
54+
SetWindowText(m_hSelfInfo, sliderInfoText.c_str());
55+
}
56+
57+
LRESULT SliderCtrl::runWinProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
58+
{
59+
SliderCtrl* pThis = reinterpret_cast<SliderCtrl*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
60+
61+
if (pThis)
62+
{
63+
if (message == WM_LBUTTONDBLCLK)
64+
{
65+
// Reset slider to 100% on double-click
66+
// Also notify its parent to adjust tree view as well
67+
pThis->SetPosition(100);
68+
SendMessage(pThis->m_hParent, WM_HSCROLL, NULL, reinterpret_cast<LPARAM>(pThis->m_hSelf));
69+
}
70+
71+
// Call the original window procedure for other messages
72+
return CallWindowProc(pThis->m_oldSliderProc, hWnd, message, wParam, lParam);
73+
}
74+
75+
return FALSE;
76+
}

‎src/NppJsonViewer/SliderCtrl.h

Copy file name to clipboard
+53Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
#pragma once
2+
3+
4+
#include <Windows.h>
5+
#include <CommCtrl.h>
6+
7+
struct SliderRange
8+
{
9+
int m_nDefault = 100;
10+
int m_nMinZoom = 80;
11+
int m_nMaxZoom = 250;
12+
int m_nSteps = 10;
13+
}; // namespace SliderRange
14+
15+
class SliderCtrl
16+
{
17+
HWND m_hParent = nullptr;
18+
HWND m_hSelf = nullptr;
19+
HWND m_hSelfInfo = nullptr;
20+
HWND m_hTreeView = nullptr;
21+
WNDPROC m_oldSliderProc = nullptr;
22+
const SliderRange m_sliderRange {};
23+
24+
public:
25+
explicit SliderCtrl(const SliderRange& sliderRange = {});
26+
27+
~SliderCtrl();
28+
29+
void OnInit(HWND hParent, int sliderID, int sliderInfoID);
30+
31+
HWND GetSliderHandle() const
32+
{
33+
return m_hSelf;
34+
}
35+
36+
HWND GetSliderInfoHandle() const
37+
{
38+
return m_hSelfInfo;
39+
}
40+
41+
auto GetRange() const -> const SliderRange&
42+
{
43+
return m_sliderRange;
44+
}
45+
46+
auto GetPosition() const -> int;
47+
void SetPosition(int pos) const;
48+
void UpdateInfo(int zoomPercentage) const;
49+
50+
private:
51+
// Static window procedure for the slider
52+
static LRESULT CALLBACK runWinProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
53+
};

‎src/NppJsonViewer/resource.h

Copy file name to clipboardExpand all lines: src/NppJsonViewer/resource.h
+3-1Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@
4242
#define IDC_CHK_IGNORE_COMMENT 1031
4343
#define IDC_CHK_JSON_HIGHLIGHT 1032
4444
#define IDC_CHK_REPLACE_UNDEFINED 1033
45+
#define IDC_ZOOM_SLIDER 1034
46+
#define IDC_ZOOM_PERCENT 1035
4547
#define IDM_COPY_TREEITEM 40001
4648
#define IDM_COPY_NODENAME 40002
4749
#define IDM_COPY_NODEVALUE 40003
@@ -55,7 +57,7 @@
5557
#ifndef APSTUDIO_READONLY_SYMBOLS
5658
#define _APS_NEXT_RESOURCE_VALUE 110
5759
#define _APS_NEXT_COMMAND_VALUE 40007
58-
#define _APS_NEXT_CONTROL_VALUE 1034
60+
#define _APS_NEXT_CONTROL_VALUE 1036
5961
#define _APS_NEXT_SYMED_VALUE 101
6062
#endif
6163
#endif

‎src/NppJsonViewer/resource.rc

Copy file name to clipboardExpand all lines: src/NppJsonViewer/resource.rc
+3-1Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,9 @@ BEGIN
8888
CONTROL "",IDC_DIVIDER,"Static",SS_ETCHEDVERT,56,1,2,16
8989
EDITTEXT IDC_EDT_SEARCH,60,2,99,12,ES_AUTOHSCROLL
9090
PUSHBUTTON "",IDC_BTN_SEARCH,160,2,16,12,BS_ICON
91-
CONTROL "",IDC_TREE,"SysTreeView32",TVS_HASBUTTONS | TVS_HASLINES | TVS_DISABLEDRAGDROP | TVS_SHOWSELALWAYS | TVS_FULLROWSELECT | WS_HSCROLL | WS_TABSTOP,2,18,173,274,WS_EX_CLIENTEDGE
91+
CONTROL "",IDC_ZOOM_SLIDER,"msctls_trackbar32",TBS_AUTOTICKS | TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,2,16,58,12
92+
RTEXT "100%",IDC_ZOOM_PERCENT,60,16,22,12,SS_NOTIFY | NOT WS_GROUP,WS_EX_RIGHT
93+
CONTROL "",IDC_TREE,"SysTreeView32",TVS_HASBUTTONS | TVS_HASLINES | TVS_DISABLEDRAGDROP | TVS_SHOWSELALWAYS | TVS_FULLROWSELECT | WS_HSCROLL | WS_TABSTOP,2,30,173,264,WS_EX_CLIENTEDGE
9294
EDITTEXT IDC_EDT_NODEPATH,2,296,173,12,ES_AUTOHSCROLL | ES_READONLY
9395
END
9496

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.