Skip to content

Commit ed7909c

Browse files
authored
[Big rock]: Feature - navigate on click/double click (#200)
* Explore navigation on click * Re draw tree view on compress/format/sort validate etc. * Fix memory leak
1 parent c406080 commit ed7909c

13 files changed

+322
-50
lines changed

src/NppJsonViewer/JsonHandler.h

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <rapidjson/error/en.h>
1111

1212
#include "Define.h"
13+
#include "TrackingStream.h"
1314

1415
namespace rj = rapidjson;
1516

@@ -42,7 +43,7 @@ class JsonHandler
4243
auto ValidateJson(const std::string& jsonText) -> const Result;
4344

4445
template <unsigned format, typename Handler>
45-
auto ParseJson(const std::string& jsonText, rj::StringBuffer& sb, Handler& handler) -> const Result;
46+
auto ParseJson(const std::string& jsonText, rj::StringBuffer& sb, Handler& handler, TrackingStreamSharedPtr pTS = nullptr) -> const Result;
4647

4748
private:
4849
void SortJsonObject(rj::Value& jsonObject, rj::Document::AllocatorType& allocator) const;
@@ -51,13 +52,18 @@ class JsonHandler
5152
};
5253

5354
template <unsigned flgBase, typename Handler>
54-
inline auto JsonHandler::ParseJson(const std::string& jsonText, rj::StringBuffer& sb, Handler& handler) -> const Result
55+
inline auto JsonHandler::ParseJson(const std::string& jsonText, rj::StringBuffer& sb, Handler& handler, TrackingStreamSharedPtr pTS) -> const Result
5556
{
5657
Result retVal {};
5758

58-
bool success = false;
59-
rj::Reader reader;
60-
rj::StringStream ss(jsonText.c_str());
59+
bool success = false;
60+
rj::Reader reader;
61+
62+
std::shared_ptr<rj::StringStream> pSS = nullptr;
63+
if (!pTS)
64+
{
65+
pSS = std::make_shared<rj::StringStream>(jsonText.c_str());
66+
}
6167

6268
// TODO: Find some better way
6369
constexpr auto flgBase_comment = flgBase | rj::kParseCommentsFlag;
@@ -66,22 +72,22 @@ inline auto JsonHandler::ParseJson(const std::string& jsonText, rj::StringBuffer
6672

6773
if (m_parseOptions.bIgnoreComment && m_parseOptions.bIgnoreTrailingComma)
6874
{
69-
success = reader.Parse<flgBase_Both>(ss, handler) && sb.GetString();
75+
success = pTS ? reader.Parse<flgBase_Both>(*pTS, handler) && sb.GetString() : reader.Parse<flgBase_Both>(*pSS, handler) && sb.GetString();
7076
}
7177

7278
else if (!m_parseOptions.bIgnoreComment && m_parseOptions.bIgnoreTrailingComma)
7379
{
74-
success = reader.Parse<flgBase_comma>(ss, handler) && sb.GetString();
80+
success = pTS ? reader.Parse<flgBase_comma>(*pTS, handler) && sb.GetString() : reader.Parse<flgBase_comma>(*pSS, handler) && sb.GetString();
7581
}
7682

7783
else if (m_parseOptions.bIgnoreComment && !m_parseOptions.bIgnoreTrailingComma)
7884
{
79-
success = reader.Parse<flgBase_comment>(ss, handler) && sb.GetString();
85+
success = pTS ? reader.Parse<flgBase_comment>(*pTS, handler) && sb.GetString() : reader.Parse<flgBase_comment>(*pSS, handler) && sb.GetString();
8086
}
8187

8288
else if (!m_parseOptions.bIgnoreComment && !m_parseOptions.bIgnoreTrailingComma)
8389
{
84-
success = reader.Parse<flgBase>(ss, handler) && sb.GetString();
90+
success = pTS ? reader.Parse<flgBase>(*pTS, handler) && sb.GetString() : reader.Parse<flgBase>(*pSS, handler) && sb.GetString();
8591
}
8692

8793
if (success)

src/NppJsonViewer/JsonNode.h

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,32 @@ enum class JsonNodeType : short
1111
OBJECT,
1212
};
1313

14+
struct Position
15+
{
16+
size_t nLine {};
17+
size_t nColumn {};
18+
19+
void clear()
20+
{
21+
nLine = nColumn = 0;
22+
}
23+
};
24+
25+
struct JsonKey
26+
{
27+
Position pos {};
28+
std::string strKey;
29+
30+
void clear()
31+
{
32+
pos.clear();
33+
strKey.clear();
34+
}
35+
};
36+
1437
struct JsonNode
1538
{
16-
std::string key;
39+
JsonKey key;
1740
std::string value;
1841
JsonNodeType type = JsonNodeType::UNKNOWN;
1942
};

src/NppJsonViewer/JsonViewDlg.cpp

Lines changed: 63 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
1+
#include <format>
2+
#include <regex>
3+
14
#include "JsonViewDlg.h"
25
#include "Define.h"
36
#include "Utility.h"
47
#include "StringHelper.h"
58
#include "RapidJsonHandler.h"
69
#include "ScintillaEditor.h"
710
#include "Profile.h"
8-
#include <format>
9-
#include <regex>
11+
1012

1113
constexpr int FILENAME_LEN_IN_TITLE = 16;
1214

@@ -100,6 +102,8 @@ void JsonViewDlg::FormatJson()
100102

101103
ReportError(res);
102104
}
105+
106+
ReDrawJsonTree();
103107
}
104108

105109
void JsonViewDlg::CompressJson()
@@ -130,6 +134,8 @@ void JsonViewDlg::CompressJson()
130134

131135
ReportError(res);
132136
}
137+
138+
ReDrawJsonTree();
133139
}
134140

135141
void JsonViewDlg::SortJsonByKey()
@@ -162,6 +168,8 @@ void JsonViewDlg::SortJsonByKey()
162168

163169
ReportError(res);
164170
}
171+
172+
ReDrawJsonTree();
165173
}
166174

167175
bool JsonViewDlg::CheckForTokenUndefined(eMethod method, std::string selectedText, Result& res, HTREEITEM tree_root)
@@ -171,14 +179,8 @@ bool JsonViewDlg::CheckForTokenUndefined(eMethod method, std::string selectedTex
171179
if (m_pSetting->parseOptions.bReplaceUndefined)
172180
{
173181
auto text = selectedText.substr(res.error_pos, 9);
174-
std::transform(
175-
text.begin(),
176-
text.end(),
177-
text.begin(),
178-
[](unsigned char c)
179-
{
180-
return (unsigned char)std::tolower(c);
181-
});
182+
StringHelper::ToLower(text);
183+
182184
if (text == "undefined")
183185
{
184186
try
@@ -217,7 +219,7 @@ bool JsonViewDlg::CheckForTokenUndefined(eMethod method, std::string selectedTex
217219
else
218220
{
219221
m_pEditor->ReplaceSelection(text);
220-
m_pEditor->MakeSelection(m_pEditor->GetSelectionStart(), static_cast<int>(text.length()));
222+
m_pEditor->MakeSelection(m_pEditor->GetSelectionStart(), text.length());
221223
m_pEditor->RefreshSelectionPos();
222224
}
223225
}
@@ -326,6 +328,8 @@ void JsonViewDlg::ValidateJson()
326328

327329
ReportError(res);
328330
}
331+
332+
DrawJsonTree();
329333
}
330334

331335
void JsonViewDlg::DrawJsonTree()
@@ -379,6 +383,16 @@ void JsonViewDlg::DrawJsonTree()
379383
EnableControls(ctrls, true);
380384
}
381385

386+
void JsonViewDlg::ReDrawJsonTree(bool bForce)
387+
{
388+
const bool bIsVisible = isCreated() && isVisible();
389+
const bool bReDraw = bForce || bIsVisible;
390+
if (bReDraw)
391+
{
392+
DrawJsonTree();
393+
}
394+
}
395+
382396
void JsonViewDlg::HighlightAsJson(bool bForcefully) const
383397
{
384398
bool setJsonLang = bForcefully || m_pSetting->bUseJsonHighlight;
@@ -390,10 +404,11 @@ auto JsonViewDlg::PopulateTreeUsingSax(HTREEITEM tree_root, const std::string& j
390404
{
391405
std::optional<std::wstring> retVal = std::nullopt;
392406

393-
RapidJsonHandler handler(this, tree_root);
407+
auto pTS = std::make_shared<TrackingStream>(jsonText);
408+
RapidJsonHandler handler(this, tree_root, pTS);
394409
rapidjson::StringBuffer sb;
395410

396-
Result res = JsonHandler(m_pSetting->parseOptions).ParseJson<flgBaseReader>(jsonText, sb, handler);
411+
Result res = JsonHandler(m_pSetting->parseOptions).ParseJson<flgBaseReader>(jsonText, sb, handler, pTS);
397412
if (!res.success)
398413
{
399414
if (CheckForTokenUndefined(JsonViewDlg::eMethod::ParseJson, jsonText, res, tree_root))
@@ -429,6 +444,13 @@ HTREEITEM JsonViewDlg::InsertToTree(HTREEITEM parent, const std::string& text)
429444
return m_hTreeView->InsertNode(wText, NULL, parent);
430445
}
431446

447+
HTREEITEM JsonViewDlg::InsertToTree(HTREEITEM parent, const std::string& text, const Position& pos)
448+
{
449+
auto wText = StringHelper::ToWstring(text, CP_UTF8);
450+
auto lparam = new Position(pos);
451+
return m_hTreeView->InsertNode(wText, reinterpret_cast<LPARAM>(lparam), parent);
452+
}
453+
432454
void JsonViewDlg::AppendNodeCount(HTREEITEM node, unsigned elementCount, bool bArray)
433455
{
434456
if (!node)
@@ -450,6 +472,16 @@ void JsonViewDlg::UpdateNodePath(HTREEITEM htiNode)
450472
CUtility::SetEditCtrlText(::GetDlgItem(_hSelf, IDC_EDT_NODEPATH), nodePath);
451473
}
452474

475+
void JsonViewDlg::GoToLine(size_t nLineToGo)
476+
{
477+
m_pEditor->GoToLine(nLineToGo);
478+
}
479+
480+
void JsonViewDlg::GoToPosition(size_t nLineToGo, size_t nPos)
481+
{
482+
m_pEditor->GoToPosition(nLineToGo, nPos);
483+
}
484+
453485
void JsonViewDlg::SearchInTree()
454486
{
455487
std::wstring itemToSearch = CUtility::GetEditCtrlText(::GetDlgItem(_hSelf, IDC_EDT_SEARCH));
@@ -878,6 +910,24 @@ void JsonViewDlg::HandleTreeEvents(LPARAM lParam)
878910
if (hItem && (pnmtv->action == TVC_BYMOUSE || pnmtv->action == TVC_BYKEYBOARD))
879911
{
880912
UpdateNodePath(hItem);
913+
914+
auto pPosition = m_hTreeView->GetNodePosition(hItem);
915+
if (pPosition != nullptr)
916+
{
917+
GoToLine(pPosition->nLine);
918+
}
919+
}
920+
}
921+
break;
922+
923+
case NM_DBLCLK:
924+
{
925+
HTREEITEM hItem = m_hTreeView->GetSelection();
926+
927+
auto pPosition = m_hTreeView->GetNodePosition(hItem);
928+
if (pPosition != nullptr)
929+
{
930+
GoToPosition(pPosition->nLine, pPosition->nColumn);
881931
}
882932
}
883933
break;

src/NppJsonViewer/JsonViewDlg.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "TreeViewCtrl.h"
1212
#include "ScintillaEditor.h"
1313
#include "JsonHandler.h"
14+
#include "JsonNode.h"
1415

1516

1617
class JsonViewDlg : public DockingDlgInterface
@@ -44,16 +45,20 @@ class JsonViewDlg : public DockingDlgInterface
4445
void UpdateTitle();
4546

4647
HTREEITEM InsertToTree(HTREEITEM parent, const std::string& text);
48+
HTREEITEM InsertToTree(HTREEITEM parent, const std::string& text, const Position& pos);
4749
void AppendNodeCount(HTREEITEM node, unsigned elementCount, bool bArray);
4850

4951
private:
5052
void DrawJsonTree();
53+
void ReDrawJsonTree(bool bForce = false);
5154
void HighlightAsJson(bool bForcefully = false) const;
5255
auto PopulateTreeUsingSax(HTREEITEM tree_root, const std::string& jsonText) -> std::optional<std::wstring>;
5356

5457
void ValidateJson();
5558

5659
void UpdateNodePath(HTREEITEM htiNode);
60+
void GoToLine(size_t nLineToGo);
61+
void GoToPosition(size_t nLineToGo, size_t nPos);
5762

5863
void SearchInTree();
5964

src/NppJsonViewer/NPPJSONViewer.vcxproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,7 @@
222222
<ClInclude Include="SettingsDlg.h" />
223223
<ClInclude Include="ShortcutCommand.h" />
224224
<ClInclude Include="StopWatch.h" />
225+
<ClInclude Include="TrackingStream.h" />
225226
<ClInclude Include="TreeViewCtrl.h" />
226227
</ItemGroup>
227228
<ItemGroup>

src/NppJsonViewer/NPPJSONViewer.vcxproj.filters

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,9 @@
128128
<ClInclude Include="..\..\external\npp\Window.h">
129129
<Filter>ThirdParty\npp</Filter>
130130
</ClInclude>
131+
<ClInclude Include="TrackingStream.h">
132+
<Filter>Header Files</Filter>
133+
</ClInclude>
131134
</ItemGroup>
132135
<ItemGroup>
133136
<ResourceCompile Include="resource.rc">

src/NppJsonViewer/RapidJsonHandler.cpp

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,9 @@ bool RapidJsonHandler::String(const Ch* str, unsigned /*length*/, bool /*copy*/)
8181

8282
bool RapidJsonHandler::Key(const Ch* str, unsigned /*length*/, bool /*copy*/)
8383
{
84-
m_strLastKey = str;
84+
m_jsonLastKey.strKey = str;
85+
m_jsonLastKey.pos.nLine = m_pTS->getLine();
86+
m_jsonLastKey.pos.nColumn = m_pTS->getColumn();
8587
return true;
8688
}
8789

@@ -101,13 +103,13 @@ bool RapidJsonHandler::StartObject()
101103
parent = m_NodeStack.top();
102104
}
103105

104-
if (!m_strLastKey.empty() || parent->node.type == JsonNodeType::ARRAY)
106+
if (!m_jsonLastKey.strKey.empty() || parent->node.type == JsonNodeType::ARRAY)
105107
{
106108
HTREEITEM newNode = nullptr;
107109
if (parent->node.type != JsonNodeType::ARRAY)
108110
{
109-
newNode = m_dlg->InsertToTree(parent->subRoot, m_strLastKey);
110-
m_strLastKey.clear();
111+
newNode = m_dlg->InsertToTree(parent->subRoot, m_jsonLastKey.strKey, m_jsonLastKey.pos);
112+
m_jsonLastKey.clear();
111113
}
112114
else
113115
{
@@ -150,13 +152,13 @@ bool RapidJsonHandler::StartArray()
150152
parent = m_NodeStack.top();
151153
}
152154

153-
if (!m_strLastKey.empty() || parent->node.type == JsonNodeType::ARRAY)
155+
if (!m_jsonLastKey.strKey.empty() || parent->node.type == JsonNodeType::ARRAY)
154156
{
155157
HTREEITEM newNode;
156158
if (parent->node.type != JsonNodeType::ARRAY)
157159
{
158-
newNode = m_dlg->InsertToTree(parent->subRoot, m_strLastKey);
159-
m_strLastKey.clear();
160+
newNode = m_dlg->InsertToTree(parent->subRoot, m_jsonLastKey.strKey, m_jsonLastKey.pos);
161+
m_jsonLastKey.clear();
160162
}
161163
else
162164
{
@@ -188,22 +190,22 @@ void RapidJsonHandler::InsertToTree(TreeNode* node, const char* const str, bool
188190

189191
if (node->node.type != JsonNodeType::ARRAY)
190192
{
191-
node->node.key = m_strLastKey;
193+
node->node.key = m_jsonLastKey;
192194
node->node.value = str;
193-
m_strLastKey.clear();
195+
m_jsonLastKey.clear();
194196
}
195197
else
196198
{
197-
node->node.key = "[" + std::to_string(node->counter) + "]";
198-
node->node.value = str;
199+
node->node.key.strKey = "[" + std::to_string(node->counter) + "]";
200+
node->node.value = str;
199201
node->counter++;
200202
}
201203

202204
// Insert item to tree
203205
if (bQuote)
204-
m_dlg->InsertToTree(node->subRoot, node->node.key + " : \"" + node->node.value + "\"");
206+
m_dlg->InsertToTree(node->subRoot, node->node.key.strKey + " : \"" + node->node.value + "\"", node->node.key.pos);
205207
else
206-
m_dlg->InsertToTree(node->subRoot, node->node.key + " : " + node->node.value);
208+
m_dlg->InsertToTree(node->subRoot, node->node.key.strKey + " : " + node->node.value, node->node.key.pos);
207209
}
208210

209211
void RapidJsonHandler::AppendNodeCount(unsigned elementCount, bool bArray)

0 commit comments

Comments
 (0)