Skip to content

Commit bd72554

Browse files
committed
Explore navigation on click
1 parent c406080 commit bd72554

13 files changed

+286
-42
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: 58 additions & 12 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

@@ -171,14 +173,8 @@ bool JsonViewDlg::CheckForTokenUndefined(eMethod method, std::string selectedTex
171173
if (m_pSetting->parseOptions.bReplaceUndefined)
172174
{
173175
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-
});
176+
StringHelper::ToLower(text);
177+
182178
if (text == "undefined")
183179
{
184180
try
@@ -390,10 +386,11 @@ auto JsonViewDlg::PopulateTreeUsingSax(HTREEITEM tree_root, const std::string& j
390386
{
391387
std::optional<std::wstring> retVal = std::nullopt;
392388

393-
RapidJsonHandler handler(this, tree_root);
389+
auto pTS = std::make_shared<TrackingStream>(jsonText);
390+
RapidJsonHandler handler(this, tree_root, pTS);
394391
rapidjson::StringBuffer sb;
395392

396-
Result res = JsonHandler(m_pSetting->parseOptions).ParseJson<flgBaseReader>(jsonText, sb, handler);
393+
Result res = JsonHandler(m_pSetting->parseOptions).ParseJson<flgBaseReader>(jsonText, sb, handler, pTS);
397394
if (!res.success)
398395
{
399396
if (CheckForTokenUndefined(JsonViewDlg::eMethod::ParseJson, jsonText, res, tree_root))
@@ -429,6 +426,13 @@ HTREEITEM JsonViewDlg::InsertToTree(HTREEITEM parent, const std::string& text)
429426
return m_hTreeView->InsertNode(wText, NULL, parent);
430427
}
431428

429+
HTREEITEM JsonViewDlg::InsertToTree(HTREEITEM parent, const std::string& text, const Position& pos)
430+
{
431+
auto wText = StringHelper::ToWstring(text, CP_UTF8);
432+
auto lparam = new Position(pos);
433+
return m_hTreeView->InsertNode(wText, reinterpret_cast<LPARAM>(lparam), parent);
434+
}
435+
432436
void JsonViewDlg::AppendNodeCount(HTREEITEM node, unsigned elementCount, bool bArray)
433437
{
434438
if (!node)
@@ -450,6 +454,16 @@ void JsonViewDlg::UpdateNodePath(HTREEITEM htiNode)
450454
CUtility::SetEditCtrlText(::GetDlgItem(_hSelf, IDC_EDT_NODEPATH), nodePath);
451455
}
452456

457+
void JsonViewDlg::GoToLine(size_t nLineToGo)
458+
{
459+
m_pEditor->GoToLine(0, nLineToGo);
460+
}
461+
462+
void JsonViewDlg::GoToPosition(size_t nLineToGo, size_t nPos)
463+
{
464+
m_pEditor->GoToPosition(0, nLineToGo, nPos);
465+
}
466+
453467
void JsonViewDlg::SearchInTree()
454468
{
455469
std::wstring itemToSearch = CUtility::GetEditCtrlText(::GetDlgItem(_hSelf, IDC_EDT_SEARCH));
@@ -869,6 +883,20 @@ void JsonViewDlg::HandleTreeEvents(LPARAM lParam)
869883
if (!lpnmh || lpnmh->idFrom != IDC_TREE)
870884
return; // Not click inside JsonTree
871885

886+
auto GetNodePosition = [this](HTREEITEM hItem)
887+
{
888+
Position* pPosition = nullptr;
889+
if (hItem != nullptr)
890+
{
891+
LPARAM nodePos = m_hTreeView->GetNodePos(hItem);
892+
if (nodePos != -1)
893+
{
894+
pPosition = reinterpret_cast<Position*>(nodePos);
895+
}
896+
}
897+
return pPosition;
898+
};
899+
872900
switch (lpnmh->code)
873901
{
874902
case TVN_SELCHANGED:
@@ -878,6 +906,24 @@ void JsonViewDlg::HandleTreeEvents(LPARAM lParam)
878906
if (hItem && (pnmtv->action == TVC_BYMOUSE || pnmtv->action == TVC_BYKEYBOARD))
879907
{
880908
UpdateNodePath(hItem);
909+
910+
auto pPosition = GetNodePosition(hItem);
911+
if (pPosition != nullptr)
912+
{
913+
GoToLine(pPosition->nLine - 1); // line index start with 0 in editor, hence --
914+
}
915+
}
916+
}
917+
break;
918+
919+
case NM_DBLCLK:
920+
{
921+
HTREEITEM hItem = m_hTreeView->GetSelection();
922+
923+
auto pPosition = GetNodePosition(hItem);
924+
if (pPosition != nullptr)
925+
{
926+
GoToPosition(pPosition->nLine - 1, pPosition->nColumn); // line index start with 0 in editor, hence --
881927
}
882928
}
883929
break;

src/NppJsonViewer/JsonViewDlg.h

Lines changed: 4 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,6 +45,7 @@ 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:
@@ -54,6 +56,8 @@ class JsonViewDlg : public DockingDlgInterface
5456
void ValidateJson();
5557

5658
void UpdateNodePath(HTREEITEM htiNode);
59+
void GoToLine(size_t nLineToGo);
60+
void GoToPosition(size_t nLineToGo, size_t nPos);
5761

5862
void SearchInTree();
5963

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)

src/NppJsonViewer/RapidJsonHandler.h

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
#include <rapidjson/reader.h>
99

1010
#include "JsonNode.h"
11-
11+
#include "TrackingStream.h"
1212

1313
class JsonViewDlg;
1414

@@ -19,17 +19,20 @@ struct TreeNode
1919
int counter {};
2020
};
2121

22+
2223
class RapidJsonHandler : public rapidjson::BaseReaderHandler<rapidjson::UTF8<>, RapidJsonHandler>
2324
{
24-
std::string m_strLastKey;
25+
JsonKey m_jsonLastKey {};
2526
std::stack<TreeNode*> m_NodeStack;
2627

27-
JsonViewDlg* m_dlg = nullptr;
28-
HTREEITEM m_treeRoot = nullptr;
28+
TrackingStreamSharedPtr m_pTS;
29+
JsonViewDlg* m_dlg = nullptr;
30+
HTREEITEM m_treeRoot = nullptr;
2931

3032
public:
31-
RapidJsonHandler(JsonViewDlg* dlg, HTREEITEM treeRoot)
32-
: m_dlg(dlg)
33+
RapidJsonHandler(JsonViewDlg* dlg, HTREEITEM treeRoot, TrackingStreamSharedPtr pTS = nullptr)
34+
: m_pTS(pTS ? pTS->GetShared() : nullptr)
35+
, m_dlg(dlg)
3336
, m_treeRoot(treeRoot)
3437
{
3538
}

src/NppJsonViewer/ScintillaEditor.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,3 +98,15 @@ void ScintillaEditor::RefreshSelectionPos()
9898
if (m_nEndPos < m_nStartPos)
9999
std::swap(m_nStartPos, m_nEndPos);
100100
}
101+
102+
void ScintillaEditor::GoToLine(size_t nStartLine, size_t nLineToGo) const
103+
{
104+
::SendMessage(m_hScintilla, SCI_GOTOLINE, nStartLine + nLineToGo, 0);
105+
}
106+
107+
void ScintillaEditor::GoToPosition(size_t nStartLine, size_t nLineToGo, size_t nColumnIndex) const
108+
{
109+
size_t lineStartPos = SendMessage(m_hScintilla, SCI_POSITIONFROMLINE, nStartLine + nLineToGo, 0);
110+
size_t targetPos = lineStartPos + nColumnIndex;
111+
::SendMessage(m_hScintilla, SCI_GOTOPOS, targetPos, 0);
112+
}

0 commit comments

Comments
 (0)