2 * @file MergeFrameCommon.cpp
\r
4 * @brief Implementation file for CMergeFrameCommon
\r
8 #include "MergeFrameCommon.h"
\r
9 #include "OptionsDef.h"
\r
10 #include "OptionsMgr.h"
\r
13 #include "FileTransform.h"
\r
14 #include <../src/mfc/afximpl.h>
\r
16 IMPLEMENT_DYNCREATE(CMergeFrameCommon, CMDIChildWnd)
\r
18 BEGIN_MESSAGE_MAP(CMergeFrameCommon, CMDIChildWnd)
\r
19 //{{AFX_MSG_MAP(CMergeFrameCommon)
\r
20 ON_WM_GETMINMAXINFO()
\r
26 CMergeFrameCommon::CMergeFrameCommon(int nIdenticalIcon, int nDifferentIcon)
\r
27 : m_hIdentical(nIdenticalIcon < 0 ? nullptr : AfxGetApp()->LoadIcon(nIdenticalIcon))
\r
28 , m_hDifferent(nDifferentIcon < 0 ? nullptr : AfxGetApp()->LoadIcon(nDifferentIcon))
\r
29 , m_hCurrent((HICON)-1)
\r
30 , m_bActivated(false)
\r
31 , m_nLastSplitPos{0}
\r
33 ::PostMessage(AfxGetMainWnd()->GetSafeHwnd(), WMU_CHILDFRAMEADDED, 0, reinterpret_cast<LPARAM>(this));
\r
36 CMergeFrameCommon::~CMergeFrameCommon()
\r
38 ::PostMessage(AfxGetMainWnd()->GetSafeHwnd(), WMU_CHILDFRAMEREMOVED, 0, reinterpret_cast<LPARAM>(this));
\r
41 void CMergeFrameCommon::ActivateFrame(int nCmdShow)
\r
45 m_bActivated = true;
\r
47 // get the active child frame, and a flag whether it is maximized
\r
48 BOOL bMaximized = FALSE;
\r
49 CMDIChildWnd * oldActiveFrame = GetMDIFrame()->MDIGetActive(&bMaximized);
\r
50 if (oldActiveFrame == nullptr)
\r
51 // for the first frame, get the restored/maximized state from the registry
\r
52 bMaximized = GetOptionsMgr()->GetBool(OPT_ACTIVE_FRAME_MAX);
\r
54 nCmdShow = SW_SHOWMAXIMIZED;
\r
56 nCmdShow = SW_SHOWNORMAL;
\r
59 CMDIChildWnd::ActivateFrame(nCmdShow);
\r
62 void CMergeFrameCommon::SaveWindowState()
\r
64 // If we are active, save the restored/maximized state
\r
65 // If we are not, do nothing and let the active frame do the job.
\r
66 if (GetParentFrame()->GetActiveFrame() == this)
\r
68 WINDOWPLACEMENT wp = {};
\r
69 wp.length = sizeof(WINDOWPLACEMENT);
\r
70 GetWindowPlacement(&wp);
\r
71 GetOptionsMgr()->SaveOption(OPT_ACTIVE_FRAME_MAX, (wp.showCmd == SW_MAXIMIZE));
\r
75 void CMergeFrameCommon::RemoveBarBorder()
\r
77 afxData.cxBorder2 = 0;
\r
78 afxData.cyBorder2 = 0;
\r
79 for (int i = 0; i < 4; ++i)
\r
81 CControlBar* pBar = GetControlBar(i + AFX_IDW_DOCKBAR_TOP);
\r
82 pBar->SetBarStyle(pBar->GetBarStyle() & ~(CBRS_BORDER_ANY | CBRS_BORDER_3D));
\r
87 * @brief Reflect comparison result in window's icon.
\r
88 * @param nResult [in] Last comparison result which the application returns.
\r
90 void CMergeFrameCommon::SetLastCompareResult(int nResult)
\r
92 HICON hReplace = (nResult == 0) ? m_hIdentical : m_hDifferent;
\r
94 if (m_hCurrent != hReplace)
\r
96 SetIcon(hReplace, TRUE);
\r
98 AfxGetMainWnd()->SetTimer(IDT_UPDATEMAINMENU, 500, nullptr);
\r
100 m_hCurrent = hReplace;
\r
103 theApp.SetLastCompareResult(nResult);
\r
106 void CMergeFrameCommon::ShowIdenticalMessage(const PathContext& paths, bool bIdenticalAll, std::function<int(LPCTSTR, unsigned, unsigned)> fnMessageBox)
\r
109 if (theApp.m_bExitIfNoDiff != MergeCmdLineInfo::ExitQuiet)
\r
111 UINT nFlags = MB_ICONINFORMATION | MB_DONT_DISPLAY_AGAIN;
\r
113 if (theApp.m_bExitIfNoDiff == MergeCmdLineInfo::Exit)
\r
115 // Show the "files are identical" for basic "exit no diff" flag
\r
116 // If user don't want to see the message one uses the quiet version
\r
117 // of the "exit no diff".
\r
118 nFlags &= ~MB_DONT_DISPLAY_AGAIN;
\r
120 if ((paths.GetSize() == 2 && !paths.GetLeft().empty() && !paths.GetRight().empty() &&
\r
121 strutils::compare_nocase(paths.GetLeft(), paths.GetRight()) == 0) ||
\r
122 (paths.GetSize() == 3 && !paths.GetLeft().empty() && !paths.GetMiddle().empty() && !paths.GetRight().empty() &&
\r
123 (strutils::compare_nocase(paths.GetLeft(), paths.GetRight()) == 0 ||
\r
124 strutils::compare_nocase(paths.GetMiddle(), paths.GetRight()) == 0 ||
\r
125 strutils::compare_nocase(paths.GetLeft(), paths.GetMiddle()) == 0)))
\r
127 // compare file to itself, a custom message so user may hide the message in this case only
\r
128 s = _("The same file is opened in both panels.");
\r
129 fnMessageBox(s.c_str(), nFlags, IDS_FILE_TO_ITSELF);
\r
131 else if (bIdenticalAll)
\r
133 s = _("The selected files are identical.");
\r
134 fnMessageBox(s.c_str(), nFlags, IDS_FILESSAME);
\r
140 // Exit application if files are identical.
\r
141 if (theApp.m_bExitIfNoDiff == MergeCmdLineInfo::Exit ||
\r
142 theApp.m_bExitIfNoDiff == MergeCmdLineInfo::ExitQuiet)
\r
144 AfxGetMainWnd()->PostMessage(WM_COMMAND, ID_APP_EXIT);
\r
149 String CMergeFrameCommon::GetTitleString(const PathContext& paths, const String desc[],
\r
150 const PackingInfo *pInfoUnpacker, const PrediffingInfo *pInfoPrediffer, bool hasTrivialDiffs)
\r
152 const int nBuffers = paths.GetSize();
\r
153 String sFileName[3];
\r
155 for (int nBuffer = 0; nBuffer < paths.GetSize(); nBuffer++)
\r
156 sFileName[nBuffer] = !desc[nBuffer].empty() ? desc[nBuffer] : paths::FindFileName(paths[nBuffer]);
\r
157 if (std::count(&sFileName[0], &sFileName[0] + nBuffers, sFileName[0]) == nBuffers)
\r
158 sTitle = sFileName[0] + strutils::format(_T(" x %d"), nBuffers);
\r
160 sTitle = strutils::join(&sFileName[0], &sFileName[0] + nBuffers, _T(" - "));
\r
162 if (pInfoUnpacker && !pInfoUnpacker->GetPluginPipeline().empty())
\r
164 if (pInfoPrediffer && !pInfoPrediffer->GetPluginPipeline().empty())
\r
166 if (hasTrivialDiffs)
\r
168 return (flags.empty() ? _T("") : (_T("(") + flags + _T(") "))) + sTitle;
\r
171 String CMergeFrameCommon::GetTooltipString(const PathContext& paths, const String desc[],
\r
172 const PackingInfo *pInfoUnpacker, const PrediffingInfo *pInfoPrediffer, bool hasTrivialDiffs)
\r
174 const int nBuffers = paths.GetSize();
\r
176 for (int nBuffer = 0; nBuffer < paths.GetSize(); nBuffer++)
\r
178 sTitle += strutils::format(_T("%d: "), nBuffer + 1);
\r
179 if (!desc[nBuffer].empty())
\r
181 sTitle += desc[nBuffer];
\r
182 if (!paths[nBuffer].empty())
\r
183 sTitle += _T(" (") + paths[nBuffer] + _T(")");
\r
187 sTitle += paths[nBuffer];
\r
189 sTitle += _T(" - ");
\r
191 sTitle += _("Left");
\r
192 else if (nBuffer == 1 && paths.GetSize() > 2)
\r
193 sTitle += _("Middle");
\r
195 sTitle += _("Right");
\r
196 sTitle += _T("\n");
\r
198 if (pInfoUnpacker && !pInfoUnpacker->GetPluginPipeline().empty())
\r
199 sTitle += strutils::format(_T("%s: %s\n"), _("Unpacker"), pInfoUnpacker->GetPluginPipeline());
\r
200 if (pInfoPrediffer && !pInfoPrediffer->GetPluginPipeline().empty())
\r
201 sTitle += strutils::format(_T("%s: %s\n"), _("Prediffer"), pInfoPrediffer->GetPluginPipeline());
\r
202 if (hasTrivialDiffs)
\r
203 sTitle += _("Filter applied") + _T("\n");
\r
207 void CMergeFrameCommon::ChangeMergeMenuText(int srcPane, int dstPane, CCmdUI* pCmdUI)
\r
210 switch (pCmdUI->m_nID)
\r
213 text = (srcPane == 0 && dstPane == 1) ?
\r
214 _("Copy to &Middle\tAlt+Right") : _("Copy to &Right\tAlt+Right");
\r
217 text = (srcPane == 2 && dstPane == 1) ?
\r
218 _("Copy to &Middle\tAlt+Left") : _("Copy to L&eft\tAlt+Left");
\r
220 case ID_COPY_FROM_LEFT:
\r
221 text = (srcPane == 1 && dstPane == 2) ?
\r
222 _("Copy from Middle\tAlt+Shift+Right") : _("Copy from Left\tAlt+Shift+Right");
\r
224 case ID_COPY_FROM_RIGHT:
\r
225 text = (srcPane == 1 && dstPane == 0) ?
\r
226 _("Copy from Middle\tAlt+Shift+Left") : _("Copy from Right\tAlt+Shift+Left");
\r
229 text = (srcPane == 0 && dstPane == 1) ?
\r
230 _("Copy to Middle and Advance\tCtrl+Alt+Right") : _("C&opy to Right and Advance\tCtrl+Alt+Right");
\r
233 text = (srcPane == 2 && dstPane == 1) ?
\r
234 _("Copy to Middle and Advance\tCtrl+Alt+Left") : _("Copy &to Left and Advance\tCtrl+Alt+Left");
\r
237 text = (srcPane == 0 && dstPane == 1) ?
\r
238 _("Copy All to Middle") : _("Copy &All to Right");
\r
241 text = (srcPane == 2 && dstPane == 1) ?
\r
242 _("Copy All to Middle") : _("Cop&y All to Left");
\r
246 pCmdUI->SetText(text.c_str());
\r
249 std::pair<int, int> CMergeFrameCommon::MenuIDtoXY(UINT nID, int nActivePane, int nBuffers)
\r
251 if (nActivePane < 0 || nActivePane >= nBuffers)
\r
254 int srcPane = -1, dstPane = -1;
\r
261 dstPane = (nActivePane < nBuffers - 1) ? nActivePane + 1 : nBuffers - 1;
\r
262 srcPane = dstPane - 1;
\r
268 dstPane = (nActivePane > 0) ? nActivePane - 1 : 0;
\r
269 srcPane = dstPane + 1;
\r
271 case ID_COPY_FROM_LEFT:
\r
272 case ID_COPY_LINES_FROM_LEFT:
\r
273 if (nActivePane > 0)
\r
275 dstPane = nActivePane;
\r
276 srcPane = nActivePane - 1;
\r
279 case ID_COPY_FROM_RIGHT:
\r
280 case ID_COPY_LINES_FROM_RIGHT:
\r
281 if (nActivePane < nBuffers - 1)
\r
283 dstPane = nActivePane;
\r
284 srcPane = nActivePane + 1;
\r
287 case ID_COPY_TO_MIDDLE_L:
\r
288 case ID_COPY_LINES_TO_MIDDLE_L:
\r
295 case ID_COPY_TO_RIGHT_L:
\r
296 case ID_COPY_LINES_TO_RIGHT_L:
\r
297 srcPane = 0; dstPane = nBuffers - 1; break;
\r
298 case ID_COPY_FROM_MIDDLE_L:
\r
299 case ID_COPY_LINES_FROM_MIDDLE_L:
\r
306 case ID_COPY_FROM_RIGHT_L:
\r
307 case ID_COPY_LINES_FROM_RIGHT_L:
\r
308 srcPane = nBuffers - 1; dstPane = 0; break;
\r
309 case ID_COPY_TO_LEFT_M:
\r
310 case ID_COPY_LINES_TO_LEFT_M:
\r
317 case ID_COPY_TO_RIGHT_M:
\r
318 case ID_COPY_LINES_TO_RIGHT_M:
\r
322 dstPane = nBuffers - 1;
\r
325 case ID_COPY_FROM_LEFT_M:
\r
326 case ID_COPY_LINES_FROM_LEFT_M:
\r
333 case ID_COPY_FROM_RIGHT_M:
\r
334 case ID_COPY_LINES_FROM_RIGHT_M:
\r
337 srcPane = nBuffers - 1;
\r
341 case ID_COPY_TO_MIDDLE_R:
\r
342 case ID_COPY_LINES_TO_MIDDLE_R:
\r
345 srcPane = nBuffers - 1;
\r
349 case ID_COPY_TO_LEFT_R:
\r
350 case ID_COPY_LINES_TO_LEFT_R:
\r
351 srcPane = nBuffers - 1; dstPane = 0; break;
\r
352 case ID_COPY_FROM_MIDDLE_R:
\r
353 case ID_COPY_LINES_FROM_MIDDLE_R:
\r
357 dstPane = nBuffers - 1;
\r
360 case ID_COPY_FROM_LEFT_R:
\r
361 case ID_COPY_LINES_FROM_LEFT_R:
\r
362 srcPane = 0; dstPane = nBuffers - 1; break;
\r
366 return { srcPane, dstPane };
\r
369 void CMergeFrameCommon::OnGetMinMaxInfo(MINMAXINFO* lpMMI)
\r
371 CMDIChildWnd::OnGetMinMaxInfo(lpMMI);
\r
372 // [Fix for MFC 8.0 MDI Maximizing Child Window bug on Vista]
\r
373 // https://groups.google.com/forum/#!topic/microsoft.public.vc.mfc/iajCdW5DzTM
\r
374 #if _MFC_VER >= 0x0800
\r
375 lpMMI->ptMaxTrackSize.x = max(lpMMI->ptMaxTrackSize.x, lpMMI->ptMaxSize.x);
\r
376 lpMMI->ptMaxTrackSize.y = max(lpMMI->ptMaxTrackSize.y, lpMMI->ptMaxSize.y);
\r
380 void CMergeFrameCommon::OnDestroy()
\r
382 // https://stackoverflow.com/questions/35553955/getting-rid-of-3d-look-of-mdi-frame-window
\r
383 CFrameWnd::OnDestroy();
\r
386 void CMergeFrameCommon::OnMDIActivate(BOOL bActivate, CWnd* pActivateWnd, CWnd* pDeactivateWnd)
\r
388 // call the base class to let standard processing switch to
\r
389 // the top-level menu associated with this window
\r
390 CMDIChildWnd::OnMDIActivate(bActivate, pActivateWnd, pDeactivateWnd);
\r
393 ::PostMessage(AfxGetMainWnd()->GetSafeHwnd(), WMU_CHILDFRAMEACTIVATED, 0, reinterpret_cast<LPARAM>(this));
\r