diff --git a/src/NppJsonViewer/JsonViewDlg.cpp b/src/NppJsonViewer/JsonViewDlg.cpp index d0a66b6..4080af0 100644 --- a/src/NppJsonViewer/JsonViewDlg.cpp +++ b/src/NppJsonViewer/JsonViewDlg.cpp @@ -19,6 +19,7 @@ JsonViewDlg::JsonViewDlg(HINSTANCE hInstance, const NppData& nppData, const bool , m_nDlgId(nCmdId) , m_pEditor(std::make_unique(nppData)) , m_pTreeView(std::make_unique()) + , m_pTreeViewZoom(std::make_unique()) , m_pSetting(pSetting) , m_pCurrFileName(std::make_unique(FILENAME_LEN_IN_TITLE)) { @@ -895,6 +896,74 @@ void JsonViewDlg::EnableControls(const std::vector& ids, bool enable) EnableWindow(GetDlgItem(getHSelf(), id), enable ? TRUE : FALSE); } +auto JsonViewDlg::GetZoomLevel() const -> int +{ + return m_pTreeViewZoom->GetPosition(); +} + +void JsonViewDlg::SetZoomLevel(int pos) const +{ + m_pTreeViewZoom->SetPosition(pos); +} + +void JsonViewDlg::SetTreeViewZoom(double dwZoomFactor) const +{ + HWND hTreeView = GetDlgItem(getHSelf(), IDC_TREE); + static HFONT hCurrentFont = reinterpret_cast(SendMessage(hTreeView, WM_GETFONT, 0, 0)); + + LOGFONT logFont {}; + GetObject(hCurrentFont, sizeof(LOGFONT), &logFont); + logFont.lfHeight = static_cast(logFont.lfHeight * dwZoomFactor); + + static HFONT hTreeFont = nullptr; + if (hTreeFont) + { + DeleteObject(hTreeFont); + } + hTreeFont = CreateFontIndirect(&logFont); + + SendMessage(hTreeView, WM_SETFONT, reinterpret_cast(hTreeFont), TRUE); + InvalidateRect(hTreeView, nullptr, TRUE); +} + +void JsonViewDlg::UpdateUIOnZoom(int zoomPercentage) const +{ + // Update zoom level on slider + SetZoomLevel(zoomPercentage); + + // Update the Tree view + double zoomFactor = zoomPercentage / 100.0; + SetTreeViewZoom(zoomFactor); +} + +void JsonViewDlg::HandleZoomOnScroll(WPARAM wParam) const +{ + int pos = GetZoomLevel(); // Current zoom level + int delta = GET_WHEEL_DELTA_WPARAM(wParam); + + const auto& zoomRange = m_pTreeViewZoom->GetRange(); + const bool isZoomIn = delta > 0; + bool bRefreshUI = true; + + if (isZoomIn && pos < zoomRange.m_nMaxZoom) + { + pos += 10; // Zoom in + } + else if (!isZoomIn && pos > zoomRange.m_nMinZoom) + { + pos -= 10; // Zoom out + } + else + { + bRefreshUI = false; + } + + if (bRefreshUI) + { + UpdateUIOnZoom(pos); + } +} + void JsonViewDlg::HandleTreeEvents(LPARAM lParam) const { LPNMHDR lpnmh = reinterpret_cast(lParam); @@ -1030,6 +1099,7 @@ INT_PTR JsonViewDlg::run_dlgProc(UINT message, WPARAM wParam, LPARAM lParam) ::SetWindowLongPtr(getHSelf(), GWLP_USERDATA, reinterpret_cast(this)); m_pTreeView->OnInit(getHSelf(), IDC_TREE); + m_pTreeViewZoom->OnInit(getHSelf(), IDC_ZOOM_SLIDER, IDC_ZOOM_PERCENT); PrepareButtons(); @@ -1107,6 +1177,31 @@ INT_PTR JsonViewDlg::run_dlgProc(UINT message, WPARAM wParam, LPARAM lParam) return TRUE; } + case WM_MOUSEWHEEL: + { + if (GetKeyState(VK_CONTROL) & 0x8000) + { + HandleZoomOnScroll(wParam); + return TRUE; + } + return FALSE; + } + + case WM_HSCROLL: + { + HWND hSlider = GetDlgItem(getHSelf(), IDC_ZOOM_SLIDER); + + if (reinterpret_cast(lParam) == hSlider) + { + int pos = m_pTreeViewZoom->GetPosition(); + UpdateUIOnZoom(pos); + + return TRUE; + } + return FALSE; + } + + default: return DockingDlgInterface::run_dlgProc(message, wParam, lParam); } diff --git a/src/NppJsonViewer/JsonViewDlg.h b/src/NppJsonViewer/JsonViewDlg.h index 3fb2a32..2599520 100644 --- a/src/NppJsonViewer/JsonViewDlg.h +++ b/src/NppJsonViewer/JsonViewDlg.h @@ -9,6 +9,7 @@ #include "PluginInterface.h" #include "resource.h" #include "TreeViewCtrl.h" +#include "SliderCtrl.h" #include "ScintillaEditor.h" #include "JsonHandler.h" #include "JsonNode.h" @@ -89,6 +90,12 @@ class JsonViewDlg void ShowControls(const std::vector& ids, bool show); void EnableControls(const std::vector& ids, bool enable); + auto GetZoomLevel() const -> int; + void SetZoomLevel(int pos) const; + void SetTreeViewZoom(double dwZoomFactor) const; + void UpdateUIOnZoom(int zoomPercentage) const; + void HandleZoomOnScroll(WPARAM wParam) const; + void HandleTreeEvents(LPARAM lParam) const; auto GetFormatSetting() const -> std::tuple; @@ -118,5 +125,6 @@ class JsonViewDlg std::unique_ptr m_pCurrFileName; std::unique_ptr m_pEditor = nullptr; std::unique_ptr m_pTreeView = nullptr; + std::unique_ptr m_pTreeViewZoom = nullptr; std::shared_ptr m_pSetting = nullptr; }; diff --git a/src/NppJsonViewer/NPPJSONViewer.vcxproj b/src/NppJsonViewer/NPPJSONViewer.vcxproj index 5e23da4..ee23ea4 100644 --- a/src/NppJsonViewer/NPPJSONViewer.vcxproj +++ b/src/NppJsonViewer/NPPJSONViewer.vcxproj @@ -197,6 +197,7 @@ + @@ -221,6 +222,7 @@ + diff --git a/src/NppJsonViewer/NPPJSONViewer.vcxproj.filters b/src/NppJsonViewer/NPPJSONViewer.vcxproj.filters index e3a4ea1..b94df99 100644 --- a/src/NppJsonViewer/NPPJSONViewer.vcxproj.filters +++ b/src/NppJsonViewer/NPPJSONViewer.vcxproj.filters @@ -60,6 +60,9 @@ Header Files + + Source Files + @@ -134,6 +137,9 @@ Header Files + + Header Files + diff --git a/src/NppJsonViewer/SliderCtrl.cpp b/src/NppJsonViewer/SliderCtrl.cpp new file mode 100644 index 0000000..e041f7e --- /dev/null +++ b/src/NppJsonViewer/SliderCtrl.cpp @@ -0,0 +1,76 @@ +#include "SliderCtrl.h" + +#include + +SliderCtrl::SliderCtrl(const SliderRange& sliderRange) + : m_sliderRange(sliderRange) +{ +} + +SliderCtrl::~SliderCtrl() +{ + // Restore the original window procedure on cleanup + SetWindowLongPtr(m_hSelf, GWLP_WNDPROC, reinterpret_cast(m_oldSliderProc)); +} + +void SliderCtrl::OnInit(HWND hParent, int sliderID, int sliderInfoID) +{ + m_hParent = hParent; + m_hSelf = GetDlgItem(m_hParent, sliderID); + m_hSelfInfo = GetDlgItem(m_hParent, sliderInfoID); + + // Set slider range and initial position + SendMessage(m_hSelf, TBM_SETRANGE, TRUE, MAKELPARAM(m_sliderRange.m_nMinZoom, m_sliderRange.m_nMaxZoom)); + SendMessage(m_hSelf, TBM_SETPOS, TRUE, m_sliderRange.m_nDefault); + SendMessage(m_hSelf, TBM_SETPAGESIZE, 0, m_sliderRange.m_nSteps); + + UpdateInfo(m_sliderRange.m_nDefault); + + // Subclass the slider control to handle double-click events + m_oldSliderProc = reinterpret_cast(SetWindowLongPtr(m_hSelfInfo, GWLP_WNDPROC, reinterpret_cast(runWinProc))); + + // Save this instance for access in the static window procedure + SetWindowLongPtr(m_hSelfInfo, GWLP_USERDATA, reinterpret_cast(this)); +} + +auto SliderCtrl::GetPosition() const -> int +{ + int pos = static_cast(SendMessage(m_hSelf, TBM_GETPOS, 0, 0)); + return pos; +} + +void SliderCtrl::SetPosition(int pos) const +{ + // Set slider position + SendMessage(m_hSelf, TBM_SETPOS, TRUE, pos); + + // Set slider position in text value + UpdateInfo(pos); +} + +void SliderCtrl::UpdateInfo(int zoomPercentage) const +{ + std::wstring sliderInfoText = std::to_wstring(zoomPercentage) + L"%"; + SetWindowText(m_hSelfInfo, sliderInfoText.c_str()); +} + +LRESULT SliderCtrl::runWinProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + SliderCtrl* pThis = reinterpret_cast(GetWindowLongPtr(hWnd, GWLP_USERDATA)); + + if (pThis) + { + if (message == WM_LBUTTONDBLCLK) + { + // Reset slider to 100% on double-click + // Also notify its parent to adjust tree view as well + pThis->SetPosition(100); + SendMessage(pThis->m_hParent, WM_HSCROLL, NULL, reinterpret_cast(pThis->m_hSelf)); + } + + // Call the original window procedure for other messages + return CallWindowProc(pThis->m_oldSliderProc, hWnd, message, wParam, lParam); + } + + return FALSE; +} diff --git a/src/NppJsonViewer/SliderCtrl.h b/src/NppJsonViewer/SliderCtrl.h new file mode 100644 index 0000000..e8e3c74 --- /dev/null +++ b/src/NppJsonViewer/SliderCtrl.h @@ -0,0 +1,53 @@ +#pragma once + + +#include +#include + +struct SliderRange +{ + int m_nDefault = 100; + int m_nMinZoom = 80; + int m_nMaxZoom = 250; + int m_nSteps = 10; +}; // namespace SliderRange + +class SliderCtrl +{ + HWND m_hParent = nullptr; + HWND m_hSelf = nullptr; + HWND m_hSelfInfo = nullptr; + HWND m_hTreeView = nullptr; + WNDPROC m_oldSliderProc = nullptr; + const SliderRange m_sliderRange {}; + +public: + explicit SliderCtrl(const SliderRange& sliderRange = {}); + + ~SliderCtrl(); + + void OnInit(HWND hParent, int sliderID, int sliderInfoID); + + HWND GetSliderHandle() const + { + return m_hSelf; + } + + HWND GetSliderInfoHandle() const + { + return m_hSelfInfo; + } + + auto GetRange() const -> const SliderRange& + { + return m_sliderRange; + } + + auto GetPosition() const -> int; + void SetPosition(int pos) const; + void UpdateInfo(int zoomPercentage) const; + +private: + // Static window procedure for the slider + static LRESULT CALLBACK runWinProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); +}; diff --git a/src/NppJsonViewer/resource.h b/src/NppJsonViewer/resource.h index 23a0b03..13d1e52 100644 --- a/src/NppJsonViewer/resource.h +++ b/src/NppJsonViewer/resource.h @@ -42,6 +42,8 @@ #define IDC_CHK_IGNORE_COMMENT 1031 #define IDC_CHK_JSON_HIGHLIGHT 1032 #define IDC_CHK_REPLACE_UNDEFINED 1033 +#define IDC_ZOOM_SLIDER 1034 +#define IDC_ZOOM_PERCENT 1035 #define IDM_COPY_TREEITEM 40001 #define IDM_COPY_NODENAME 40002 #define IDM_COPY_NODEVALUE 40003 @@ -55,7 +57,7 @@ #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 110 #define _APS_NEXT_COMMAND_VALUE 40007 -#define _APS_NEXT_CONTROL_VALUE 1034 +#define _APS_NEXT_CONTROL_VALUE 1036 #define _APS_NEXT_SYMED_VALUE 101 #endif #endif diff --git a/src/NppJsonViewer/resource.rc b/src/NppJsonViewer/resource.rc index 9064ec1..0222e52 100644 --- a/src/NppJsonViewer/resource.rc +++ b/src/NppJsonViewer/resource.rc @@ -88,7 +88,9 @@ BEGIN CONTROL "",IDC_DIVIDER,"Static",SS_ETCHEDVERT,56,1,2,16 EDITTEXT IDC_EDT_SEARCH,60,2,99,12,ES_AUTOHSCROLL PUSHBUTTON "",IDC_BTN_SEARCH,160,2,16,12,BS_ICON - 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 + CONTROL "",IDC_ZOOM_SLIDER,"msctls_trackbar32",TBS_AUTOTICKS | TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,2,16,58,12 + RTEXT "100%",IDC_ZOOM_PERCENT,60,16,22,12,SS_NOTIFY | NOT WS_GROUP,WS_EX_RIGHT + 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 EDITTEXT IDC_EDT_NODEPATH,2,296,173,12,ES_AUTOHSCROLL | ES_READONLY END