Skip to content

Commit a22a6b3

Browse files
authored
Add Location Pane (#5)
1 parent b8cc49a commit a22a6b3

13 files changed

+875
-249
lines changed

src/WinWebDiff/WinWebDiff.cpp

+37-2
Original file line numberDiff line numberDiff line change
@@ -124,14 +124,28 @@ struct CmdLineInfo
124124
int nUrls;
125125
};
126126

127+
static HRESULT OnWebDiffEvent(const WebDiffEvent& e);
128+
129+
struct CallbackImpl: public IWebDiffEventHandler
130+
{
131+
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject) override { return E_NOTIMPL; }
132+
ULONG STDMETHODCALLTYPE AddRef(void) override { return ++m_nRef; }
133+
ULONG STDMETHODCALLTYPE Release(void) override { if (--m_nRef == 0) { delete this; return 0; } return m_nRef; }
134+
HRESULT STDMETHODCALLTYPE Invoke(const WebDiffEvent& event) { return OnWebDiffEvent(event); }
135+
int m_nRef = 0;
136+
};
137+
127138
HINSTANCE m_hInstance;
128139
HINSTANCE hInstDLL;
129140
HWND m_hWnd;
141+
HWND m_hwndWebToolWindow;
130142
WCHAR m_szTitle[256] = L"WinWebDiff";
131143
WCHAR m_szWindowClass[256] = L"WINWEBDIFF";
132144
IWebDiffWindow* m_pWebDiffWindow = nullptr;
145+
IWebToolWindow *m_pWebToolWindow = nullptr;
133146
std::list<TempFile> m_tempFiles;
134147
std::list<TempFolder> m_tempFolders;
148+
CallbackImpl m_callback;
135149

136150
ATOM MyRegisterClass(HINSTANCE hInstance);
137151
BOOL InitInstance(HINSTANCE, int);
@@ -185,7 +199,7 @@ int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
185199
MSG msg;
186200
while (GetMessage(&msg, nullptr, 0, 0))
187201
{
188-
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
202+
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg) && m_hwndWebToolWindow == 0 || !IsDialogMessage(m_hwndWebToolWindow, &msg))
189203
{
190204
TranslateMessage(&msg);
191205
DispatchMessage(&msg);
@@ -372,6 +386,14 @@ void UpdateMenuState(HWND hWnd)
372386
CheckMenuItem(hMenu, IDM_SYNC_CLICK, m_pWebDiffWindow->GetSyncEventFlag(IWebDiffWindow::EVENT_CLICK) ? MF_CHECKED : MF_UNCHECKED);
373387
CheckMenuItem(hMenu, IDM_SYNC_INPUT, m_pWebDiffWindow->GetSyncEventFlag(IWebDiffWindow::EVENT_INPUT) ? MF_CHECKED : MF_UNCHECKED);
374388
CheckMenuItem(hMenu, IDM_SYNC_GOBACKFORWARD, m_pWebDiffWindow->GetSyncEventFlag(IWebDiffWindow::EVENT_GOBACKFORWARD) ? MF_CHECKED : MF_UNCHECKED);
389+
m_pWebToolWindow->Sync();
390+
}
391+
392+
HRESULT OnWebDiffEvent(const WebDiffEvent& e)
393+
{
394+
if (WebDiffEvent::CompareScreenshotsSelected <= e.type && e.type <= WebDiffEvent::CompareResourceTreesSelected)
395+
PostMessage(m_hWnd, WM_COMMAND, IDM_COMPARE_SCREENSHOTS + e.type - WebDiffEvent::CompareScreenshotsSelected, 0);
396+
return S_OK;
375397
}
376398

377399
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
@@ -380,13 +402,20 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
380402
{
381403
case WM_CREATE:
382404
m_pWebDiffWindow = WinWebDiff_CreateWindow(hInstDLL, hWnd);
405+
m_pWebToolWindow = WinWebDiff_CreateToolWindow(hInstDLL, hWnd, m_pWebDiffWindow);
406+
m_hwndWebToolWindow = m_pWebToolWindow->GetHWND();
407+
m_callback.AddRef();
408+
m_pWebDiffWindow->AddEventListener(&m_callback);
383409
UpdateMenuState(hWnd);
384410
break;
385411
case WM_SIZE:
386412
{
387-
RECT rc;
413+
RECT rc, rcToolWindow;
388414
GetClientRect(hWnd, &rc);
415+
GetClientRect(m_hwndWebToolWindow, &rcToolWindow);
416+
rc.right -= rcToolWindow.right;
389417
m_pWebDiffWindow->SetWindowRect(rc);
418+
MoveWindow(m_hwndWebToolWindow, rc.right, 0, rcToolWindow.right, rc.bottom, TRUE);
390419
break;
391420
}
392421
case WM_COMMAND:
@@ -447,26 +476,32 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
447476
break;
448477
case IDM_VIEW_SIZE_FIT_TO_WINDOW:
449478
m_pWebDiffWindow->SetFitToWindow(true);
479+
m_pWebToolWindow->Sync();
450480
break;
451481
case IDM_VIEW_SIZE_320x512:
452482
m_pWebDiffWindow->SetFitToWindow(false);
453483
m_pWebDiffWindow->SetSize({ 320, 512 });
484+
m_pWebToolWindow->Sync();
454485
break;
455486
case IDM_VIEW_SIZE_375x600:
456487
m_pWebDiffWindow->SetFitToWindow(false);
457488
m_pWebDiffWindow->SetSize({ 375, 600 });
489+
m_pWebToolWindow->Sync();
458490
break;
459491
case IDM_VIEW_SIZE_1024x640:
460492
m_pWebDiffWindow->SetFitToWindow(false);
461493
m_pWebDiffWindow->SetSize({ 1024, 640 });
494+
m_pWebToolWindow->Sync();
462495
break;
463496
case IDM_VIEW_SIZE_1280x800:
464497
m_pWebDiffWindow->SetFitToWindow(false);
465498
m_pWebDiffWindow->SetSize({ 1280, 800 });
499+
m_pWebToolWindow->Sync();
466500
break;
467501
case IDM_VIEW_SIZE_1440x900:
468502
m_pWebDiffWindow->SetFitToWindow(false);
469503
m_pWebDiffWindow->SetSize({ 1440, 900});
504+
m_pWebToolWindow->Sync();
470505
break;
471506
case IDM_VIEW_SPLITHORIZONTALLY:
472507
m_pWebDiffWindow->SetHorizontalSplit(!m_pWebDiffWindow->GetHorizontalSplit());

src/WinWebDiff/WinWebDiff.rc

0 Bytes
Binary file not shown.

src/WinWebDiffLib/DiffLocation.hpp

+227
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,227 @@
1+
#include <vector>
2+
#include <map>
3+
#include <string>
4+
#include <rapidjson/document.h>
5+
6+
using WDocument = rapidjson::GenericDocument<rapidjson::UTF16<>>;
7+
using WValue = rapidjson::GenericValue<rapidjson::UTF16<>>;
8+
9+
class DiffLocation
10+
{
11+
public:
12+
struct Rect
13+
{
14+
float left;
15+
float top;
16+
float width;
17+
float height;
18+
};
19+
struct ContainerRect : public Rect
20+
{
21+
int id;
22+
int containerId;
23+
float scrollLeft;
24+
float scrollTop;
25+
float scrollWidth;
26+
float scrollHeight;
27+
float clientWidth;
28+
float clientHeight;
29+
};
30+
struct DiffRect : public Rect
31+
{
32+
int id;
33+
int containerId;
34+
};
35+
36+
void read(const WDocument& doc)
37+
{
38+
std::wstring window = doc[L"window"].GetString();
39+
std::vector<ContainerRect> containerRects;
40+
std::vector<DiffRect> diffRects;
41+
for (const auto& value : doc[L"diffRects"].GetArray())
42+
{
43+
DiffRect rect;
44+
rect.id = value[L"id"].GetInt();
45+
rect.containerId = value[L"containerId"].GetInt();
46+
rect.left = value[L"left"].GetFloat();
47+
rect.top = value[L"top"].GetFloat();
48+
rect.width = value[L"width"].GetFloat();
49+
rect.height = value[L"height"].GetFloat();
50+
diffRects.push_back(rect);
51+
}
52+
for (const auto& value : doc[L"containerRects"].GetArray())
53+
{
54+
ContainerRect rect;
55+
rect.id = value[L"id"].GetInt();
56+
rect.containerId = value[L"containerId"].GetInt();
57+
rect.left = value[L"left"].GetFloat();
58+
rect.top = value[L"top"].GetFloat();
59+
rect.width = value[L"width"].GetFloat();
60+
rect.height = value[L"height"].GetFloat();
61+
rect.scrollLeft = value[L"scrollLeft"].GetFloat();
62+
rect.scrollTop = value[L"scrollTop"].GetFloat();
63+
rect.scrollWidth = value[L"scrollWidth"].GetFloat();
64+
rect.scrollHeight = value[L"scrollHeight"].GetFloat();
65+
rect.clientWidth = value[L"clientWidth"].GetFloat();
66+
rect.clientHeight = value[L"clientHeight"].GetFloat();
67+
containerRects.push_back(rect);
68+
}
69+
for (auto it = doc[L"frameRects"].MemberBegin(); it != doc[L"frameRects"].MemberEnd(); ++it)
70+
{
71+
Rect rect;
72+
rect.left = it->value[L"left"].GetFloat();
73+
rect.top = it->value[L"top"].GetFloat();
74+
rect.width = it->value[L"width"].GetFloat();
75+
rect.height = it->value[L"height"].GetFloat();
76+
m_frameRects.insert_or_assign(it->name.GetString(), rect);
77+
}
78+
m_diffRects.insert_or_assign(window, diffRects);
79+
m_containerRects.insert_or_assign(window, containerRects);
80+
if (window == L"")
81+
{
82+
m_scrollX = doc[L"scrollX"].GetFloat();
83+
m_scrollY = doc[L"scrollY"].GetFloat();
84+
m_clientWidth = doc[L"clientWidth"].GetFloat();
85+
m_clientHeight = doc[L"clientHeight"].GetFloat();
86+
}
87+
}
88+
89+
void clear()
90+
{
91+
m_diffRects.clear();
92+
m_containerRects.clear();
93+
m_scrollX = 0.0f;
94+
m_scrollY = 0.0f;
95+
m_clientWidth = 0.0f;
96+
m_clientHeight = 0.0f;
97+
}
98+
99+
void calcGlobalPosition(Rect& rect, std::wstring window)
100+
{
101+
while (!window.empty())
102+
{
103+
rect.left += m_frameRects[window].left;
104+
rect.top += m_frameRects[window].top;
105+
size_t lastOpeningBracketPos = window.find_last_of('[');
106+
if (lastOpeningBracketPos != std::string::npos) {
107+
window = window.substr(0, lastOpeningBracketPos);
108+
}
109+
}
110+
}
111+
112+
std::vector<DiffRect> getDiffRectArray()
113+
{
114+
std::vector<DiffRect> diffRectsSerialized;
115+
for (const auto& pair: m_diffRects)
116+
{
117+
const auto& window = pair.first;
118+
for (const auto& diffRect : pair.second)
119+
{
120+
DiffRect rect;
121+
rect.id = diffRect.id;
122+
rect.containerId = diffRect.containerId;
123+
rect.left = diffRect.left;
124+
rect.top = diffRect.top;
125+
rect.width = diffRect.width;
126+
rect.height = diffRect.height;
127+
for (int containerId = diffRect.containerId; containerId != -1; )
128+
{
129+
const ContainerRect& containerRect = m_containerRects[window][containerId];
130+
if (containerRect.id == 0 && (containerRect.width == 0 || containerRect.height == 0))
131+
break;
132+
clip(rect, containerRect);
133+
containerId = containerRect.containerId;
134+
}
135+
rect.left += m_scrollX;
136+
rect.top += m_scrollY;
137+
if (!window.empty())
138+
{
139+
calcGlobalPosition(rect, window);
140+
Rect rcFrame = m_frameRects[window];
141+
rcFrame.left += m_scrollX;
142+
rcFrame.top += m_scrollY;
143+
clip(rect, rcFrame);
144+
}
145+
diffRectsSerialized.push_back(rect);
146+
}
147+
}
148+
return diffRectsSerialized;
149+
}
150+
151+
std::vector<ContainerRect> getContainerRectArray()
152+
{
153+
std::vector<ContainerRect> containerRectsSerialized;
154+
for (const auto& pair: m_containerRects)
155+
{
156+
const auto& window = pair.first;
157+
for (const auto& containerRect : pair.second)
158+
{
159+
ContainerRect rect;
160+
rect.id = containerRect.id;
161+
rect.containerId = containerRect.containerId;
162+
rect.left = containerRect.left + m_scrollX;
163+
rect.top = containerRect.top + m_scrollY;
164+
rect.width = containerRect.width;
165+
rect.height = containerRect.height;
166+
rect.scrollLeft = containerRect.scrollLeft;
167+
rect.scrollTop = containerRect.scrollTop;
168+
rect.scrollWidth = containerRect.scrollWidth;
169+
rect.scrollHeight = containerRect.scrollHeight;
170+
rect.clientWidth = containerRect.clientWidth;
171+
rect.clientHeight = containerRect.clientHeight;
172+
if (!window.empty())
173+
{
174+
calcGlobalPosition(rect, window);
175+
Rect rcFrame = m_frameRects[window];
176+
rcFrame.left += m_scrollX;
177+
rcFrame.top += m_scrollY;
178+
clip(rect, rcFrame);
179+
}
180+
containerRectsSerialized.push_back(rect);
181+
}
182+
}
183+
return containerRectsSerialized;
184+
}
185+
186+
Rect getVisibleAreaRect()
187+
{
188+
return { m_scrollX, m_scrollY, m_clientWidth, m_clientHeight };
189+
}
190+
191+
private:
192+
bool clip(Rect& rect, const Rect& containerRect)
193+
{
194+
if (rect.left + rect.width < containerRect.left ||
195+
rect.top + rect.height < containerRect.top ||
196+
rect.left > containerRect.left + containerRect.width ||
197+
rect.top > containerRect.top + containerRect.height)
198+
{
199+
rect.left = rect.top = -99999.9f;
200+
rect.width = rect.height = 0.0f;
201+
return true;
202+
}
203+
if (rect.left < containerRect.left) {
204+
rect.width -= containerRect.left - rect.left;
205+
rect.left = containerRect.left;
206+
}
207+
if (rect.top < containerRect.top) {
208+
rect.height -= containerRect.top - rect.top;
209+
rect.top = containerRect.top;
210+
}
211+
if (rect.left + rect.width > containerRect.left + containerRect.width) {
212+
rect.width = containerRect.left + containerRect.width - rect.left;
213+
}
214+
if (rect.top + rect.height > containerRect.top + containerRect.height) {
215+
rect.height = containerRect.top + containerRect.height - rect.top;
216+
}
217+
return false;
218+
}
219+
220+
std::map<std::wstring, std::vector<DiffRect>> m_diffRects;
221+
std::map<std::wstring, std::vector<ContainerRect>> m_containerRects;
222+
std::map<std::wstring, Rect> m_frameRects;
223+
float m_scrollX = 0.0f;
224+
float m_scrollY = 0.0f;
225+
float m_clientWidth = 0.0f;
226+
float m_clientHeight = 0.0f;
227+
};

src/WinWebDiffLib/Resource.h

+38-6
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,52 @@
99
#define IDD_DIALOGBAR 103
1010
#define IDC_DIFFMAP 112
1111
#define IDR_SCRIPT 130
12-
#define IDC_MENU 1021
13-
#define IDC_ZOOM 1022
14-
#define IDC_WIDTH 1023
15-
#define IDC_HEIGHT 1024
12+
#define IDR_POPUP_WEBPAGE_COMPARE 131
13+
#define IDR_POPUP_WEBPAGE_SYNC_EVENTS 132
14+
#define IDC_COMPARE 1021
15+
#define IDC_ZOOM_LABEL 1022
16+
#define IDC_ZOOM 1023
17+
#define IDC_WIDTH 1024
18+
#define IDC_BY 1025
19+
#define IDC_HEIGHT 1026
20+
#define IDC_FITTOWINDOW 1027
21+
#define IDC_USERAGENT 1028
22+
#define IDC_SHOWDIFFERENCES 1029
23+
#define IDC_SYNC_EVENTS 1030
24+
#define ID_WEB_COMPARE_SCREENSHOTS 1633
25+
#define ID_WEB_COMPARE_FULLSIZE_SCREENSHOTS 1634
26+
#define ID_WEB_COMPARE_HTMLS 1635
27+
#define ID_WEB_COMPARE_TEXTS 1636
28+
#define ID_WEB_COMPARE_RESOURCETREES 1637
29+
#define ID_WEB_SYNC_ENABLED 1638
30+
#define ID_WEB_SYNC_SCROLL 1639
31+
#define ID_WEB_SYNC_CLICK 1640
32+
#define ID_WEB_SYNC_INPUT 1641
33+
#define ID_WEB_SYNC_GOBACKFORWARD 1642
34+
#define IDS_COMPARE 2000
35+
#define IDS_ZOOM 2001
36+
#define IDS_SYNC_EVENTS 2002
37+
#define IDS_SHOWDIFFERENCES 2003
38+
#define IDS_WEB_COMPARE_SCREENSHOTS 2004
39+
#define IDS_WEB_COMPARE_FULLSIZE_SCREENSHOTS 2005
40+
#define IDS_WEB_COMPARE_HTMLS 2006
41+
#define IDS_WEB_COMPARE_TEXTS 2007
42+
#define IDS_WEB_COMPARE_RESOURCETREES 2008
43+
#define IDS_WEB_SYNC_ENABLED 2009
44+
#define IDS_WEB_SYNC_SCROLL 2010
45+
#define IDS_WEB_SYNC_CLICK 2011
46+
#define IDS_WEB_SYNC_INPUT 2012
47+
#define IDS_WEB_SYNC_GOBACKFORWARD 2013
1648
#define IDC_STATIC -1
1749

1850
// Next default values for new objects
1951
//
2052
#ifdef APSTUDIO_INVOKED
2153
#ifndef APSTUDIO_READONLY_SYMBOLS
2254
#define _APS_NO_MFC 1
23-
#define _APS_NEXT_RESOURCE_VALUE 131
55+
#define _APS_NEXT_RESOURCE_VALUE 133
2456
#define _APS_NEXT_COMMAND_VALUE 32771
25-
#define _APS_NEXT_CONTROL_VALUE 1003
57+
#define _APS_NEXT_CONTROL_VALUE 1031
2658
#define _APS_NEXT_SYMED_VALUE 110
2759
#endif
2860
#endif

0 commit comments

Comments
 (0)