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 __super::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 = { sizeof(WINDOWPLACEMENT) };
\r
69 GetWindowPlacement(&wp);
\r
70 GetOptionsMgr()->SaveOption(OPT_ACTIVE_FRAME_MAX, (wp.showCmd == SW_MAXIMIZE));
\r
74 void CMergeFrameCommon::RemoveBarBorder()
\r
76 afxData.cxBorder2 = 0;
\r
77 afxData.cyBorder2 = 0;
\r
78 for (int i = 0; i < 4; ++i)
\r
80 CControlBar* pBar = GetControlBar(i + AFX_IDW_DOCKBAR_TOP);
\r
81 pBar->SetBarStyle(pBar->GetBarStyle() & ~(CBRS_BORDER_ANY | CBRS_BORDER_3D));
\r
86 * @brief Reflect comparison result in window's icon.
\r
87 * @param nResult [in] Last comparison result which the application returns.
\r
89 void CMergeFrameCommon::SetLastCompareResult(int nResult)
\r
91 HICON hReplace = (nResult == 0) ? m_hIdentical : m_hDifferent;
\r
93 if (m_hCurrent != hReplace)
\r
95 SetIcon(hReplace, TRUE);
\r
97 AfxGetMainWnd()->SetTimer(IDT_UPDATEMAINMENU, 500, nullptr);
\r
99 m_hCurrent = hReplace;
\r
102 theApp.SetLastCompareResult(nResult);
\r
105 void CMergeFrameCommon::ShowIdenticalMessage(const PathContext& paths, bool bIdenticalAll, std::function<int(const tchar_t*, unsigned, unsigned)> fnMessageBox)
\r
108 if (theApp.m_bExitIfNoDiff != MergeCmdLineInfo::ExitQuiet)
\r
110 UINT nFlags = MB_ICONINFORMATION | MB_DONT_DISPLAY_AGAIN;
\r
112 if (theApp.m_bExitIfNoDiff == MergeCmdLineInfo::Exit)
\r
114 // Show the "files are identical" for basic "exit no diff" flag
\r
115 // If user don't want to see the message one uses the quiet version
\r
116 // of the "exit no diff".
\r
117 nFlags &= ~MB_DONT_DISPLAY_AGAIN;
\r
119 if ((paths.GetSize() == 2 && !paths.GetLeft().empty() && !paths.GetRight().empty() &&
\r
120 strutils::compare_nocase(paths.GetLeft(), paths.GetRight()) == 0) ||
\r
121 (paths.GetSize() == 3 && !paths.GetLeft().empty() && !paths.GetMiddle().empty() && !paths.GetRight().empty() &&
\r
122 (strutils::compare_nocase(paths.GetLeft(), paths.GetRight()) == 0 ||
\r
123 strutils::compare_nocase(paths.GetMiddle(), paths.GetRight()) == 0 ||
\r
124 strutils::compare_nocase(paths.GetLeft(), paths.GetMiddle()) == 0)))
\r
126 // compare file to itself, a custom message so user may hide the message in this case only
\r
127 s = _("The same file is opened in both panels.");
\r
128 fnMessageBox(s.c_str(), nFlags, IDS_FILE_TO_ITSELF);
\r
130 else if (bIdenticalAll)
\r
132 s = _("The selected files are identical.");
\r
133 fnMessageBox(s.c_str(), nFlags, IDS_FILESSAME);
\r
139 // Exit application if files are identical.
\r
140 if (theApp.m_bExitIfNoDiff == MergeCmdLineInfo::Exit ||
\r
141 theApp.m_bExitIfNoDiff == MergeCmdLineInfo::ExitQuiet)
\r
143 AfxGetMainWnd()->PostMessage(WM_COMMAND, ID_APP_EXIT);
\r
148 String CMergeFrameCommon::GetTitleString(const PathContext& paths, const String desc[],
\r
149 const PackingInfo *pInfoUnpacker, const PrediffingInfo *pInfoPrediffer, bool hasTrivialDiffs)
\r
151 const int nBuffers = paths.GetSize();
\r
152 String sFileName[3];
\r
154 for (int nBuffer = 0; nBuffer < paths.GetSize(); nBuffer++)
\r
155 sFileName[nBuffer] = !desc[nBuffer].empty() ? desc[nBuffer] : paths::FindFileName(paths[nBuffer]);
\r
156 if (std::count(&sFileName[0], &sFileName[0] + nBuffers, sFileName[0]) == nBuffers)
\r
157 sTitle = sFileName[0] + strutils::format(_T(" x %d"), nBuffers);
\r
159 sTitle = strutils::join(&sFileName[0], &sFileName[0] + nBuffers, _T(" - "));
\r
161 if (pInfoUnpacker && !pInfoUnpacker->GetPluginPipeline().empty())
\r
163 if (pInfoPrediffer && !pInfoPrediffer->GetPluginPipeline().empty())
\r
165 if (hasTrivialDiffs)
\r
167 return (flags.empty() ? _T("") : (_T("(") + flags + _T(") "))) + sTitle;
\r
170 String CMergeFrameCommon::GetTooltipString(const PathContext& paths, const String desc[],
\r
171 const PackingInfo *pInfoUnpacker, const PrediffingInfo *pInfoPrediffer, bool hasTrivialDiffs)
\r
173 const int nBuffers = paths.GetSize();
\r
175 for (int nBuffer = 0; nBuffer < paths.GetSize(); nBuffer++)
\r
177 sTitle += strutils::format(_T("%d: "), nBuffer + 1);
\r
178 if (!desc[nBuffer].empty())
\r
180 sTitle += desc[nBuffer];
\r
181 if (!paths[nBuffer].empty())
\r
182 sTitle += _T(" (") + paths[nBuffer] + _T(")");
\r
186 sTitle += paths[nBuffer];
\r
188 sTitle += _T(" - ");
\r
190 sTitle += _("Left");
\r
191 else if (nBuffer == 1 && paths.GetSize() > 2)
\r
192 sTitle += _("Middle");
\r
194 sTitle += _("Right");
\r
195 sTitle += _T("\n");
\r
197 if (pInfoUnpacker && !pInfoUnpacker->GetPluginPipeline().empty())
\r
198 sTitle += strutils::format(_T("%s: %s\n"), _("Unpacker"), pInfoUnpacker->GetPluginPipeline());
\r
199 if (pInfoPrediffer && !pInfoPrediffer->GetPluginPipeline().empty())
\r
200 sTitle += strutils::format(_T("%s: %s\n"), _("Prediffer"), pInfoPrediffer->GetPluginPipeline());
\r
201 if (hasTrivialDiffs)
\r
202 sTitle += _("Filter applied") + _T("\n");
\r
206 void CMergeFrameCommon::ChangeMergeMenuText(int srcPane, int dstPane, CCmdUI* pCmdUI)
\r
209 switch (pCmdUI->m_nID)
\r
212 text = (srcPane == 0 && dstPane == 1) ?
\r
213 _("Copy to &Middle\tAlt+Right") : _("Copy to &Right\tAlt+Right");
\r
216 text = (srcPane == 2 && dstPane == 1) ?
\r
217 _("Copy to &Middle\tAlt+Left") : _("Copy to L&eft\tAlt+Left");
\r
219 case ID_COPY_FROM_LEFT:
\r
220 text = (srcPane == 1 && dstPane == 2) ?
\r
221 _("Copy from Middle\tAlt+Shift+Right") : _("Copy from Left\tAlt+Shift+Right");
\r
223 case ID_COPY_FROM_RIGHT:
\r
224 text = (srcPane == 1 && dstPane == 0) ?
\r
225 _("Copy from Middle\tAlt+Shift+Left") : _("Copy from Right\tAlt+Shift+Left");
\r
228 text = (srcPane == 0 && dstPane == 1) ?
\r
229 _("Copy to Middle and Advance\tCtrl+Alt+Right") : _("C&opy to Right and Advance\tCtrl+Alt+Right");
\r
232 text = (srcPane == 2 && dstPane == 1) ?
\r
233 _("Copy to Middle and Advance\tCtrl+Alt+Left") : _("Copy &to Left and Advance\tCtrl+Alt+Left");
\r
236 text = (srcPane == 0 && dstPane == 1) ?
\r
237 _("Copy All to Middle") : _("Copy &All to Right");
\r
240 text = (srcPane == 2 && dstPane == 1) ?
\r
241 _("Copy All to Middle") : _("Cop&y All to Left");
\r
245 pCmdUI->SetText(text.c_str());
\r
248 std::pair<int, int> CMergeFrameCommon::MenuIDtoXY(UINT nID, int nActivePane, int nBuffers)
\r
250 if (nActivePane < 0 || nActivePane >= nBuffers)
\r
253 int srcPane = -1, dstPane = -1;
\r
260 dstPane = (nActivePane < nBuffers - 1) ? nActivePane + 1 : nBuffers - 1;
\r
261 srcPane = dstPane - 1;
\r
267 dstPane = (nActivePane > 0) ? nActivePane - 1 : 0;
\r
268 srcPane = dstPane + 1;
\r
270 case ID_COPY_FROM_LEFT:
\r
271 case ID_COPY_LINES_FROM_LEFT:
\r
272 if (nActivePane > 0)
\r
274 dstPane = nActivePane;
\r
275 srcPane = nActivePane - 1;
\r
278 case ID_COPY_FROM_RIGHT:
\r
279 case ID_COPY_LINES_FROM_RIGHT:
\r
280 if (nActivePane < nBuffers - 1)
\r
282 dstPane = nActivePane;
\r
283 srcPane = nActivePane + 1;
\r
286 case ID_COPY_TO_MIDDLE_L:
\r
287 case ID_COPY_LINES_TO_MIDDLE_L:
\r
294 case ID_COPY_TO_RIGHT_L:
\r
295 case ID_COPY_LINES_TO_RIGHT_L:
\r
296 srcPane = 0; dstPane = nBuffers - 1; break;
\r
297 case ID_COPY_FROM_MIDDLE_L:
\r
298 case ID_COPY_LINES_FROM_MIDDLE_L:
\r
305 case ID_COPY_FROM_RIGHT_L:
\r
306 case ID_COPY_LINES_FROM_RIGHT_L:
\r
307 srcPane = nBuffers - 1; dstPane = 0; break;
\r
308 case ID_COPY_TO_LEFT_M:
\r
309 case ID_COPY_LINES_TO_LEFT_M:
\r
316 case ID_COPY_TO_RIGHT_M:
\r
317 case ID_COPY_LINES_TO_RIGHT_M:
\r
321 dstPane = nBuffers - 1;
\r
324 case ID_COPY_FROM_LEFT_M:
\r
325 case ID_COPY_LINES_FROM_LEFT_M:
\r
332 case ID_COPY_FROM_RIGHT_M:
\r
333 case ID_COPY_LINES_FROM_RIGHT_M:
\r
336 srcPane = nBuffers - 1;
\r
340 case ID_COPY_TO_MIDDLE_R:
\r
341 case ID_COPY_LINES_TO_MIDDLE_R:
\r
344 srcPane = nBuffers - 1;
\r
348 case ID_COPY_TO_LEFT_R:
\r
349 case ID_COPY_LINES_TO_LEFT_R:
\r
350 srcPane = nBuffers - 1; dstPane = 0; break;
\r
351 case ID_COPY_FROM_MIDDLE_R:
\r
352 case ID_COPY_LINES_FROM_MIDDLE_R:
\r
356 dstPane = nBuffers - 1;
\r
359 case ID_COPY_FROM_LEFT_R:
\r
360 case ID_COPY_LINES_FROM_LEFT_R:
\r
361 srcPane = 0; dstPane = nBuffers - 1; break;
\r
365 return { srcPane, dstPane };
\r
368 void CMergeFrameCommon::OnGetMinMaxInfo(MINMAXINFO* lpMMI)
\r
370 __super::OnGetMinMaxInfo(lpMMI);
\r
371 // [Fix for MFC 8.0 MDI Maximizing Child Window bug on Vista]
\r
372 // https://groups.google.com/forum/#!topic/microsoft.public.vc.mfc/iajCdW5DzTM
\r
373 lpMMI->ptMaxTrackSize.x = max(lpMMI->ptMaxTrackSize.x, lpMMI->ptMaxSize.x);
\r
374 lpMMI->ptMaxTrackSize.y = max(lpMMI->ptMaxTrackSize.y, lpMMI->ptMaxSize.y);
\r
377 void CMergeFrameCommon::OnDestroy()
\r
379 // https://stackoverflow.com/questions/35553955/getting-rid-of-3d-look-of-mdi-frame-window
\r
380 CFrameWnd::OnDestroy();
\r
383 void CMergeFrameCommon::OnMDIActivate(BOOL bActivate, CWnd* pActivateWnd, CWnd* pDeactivateWnd)
\r
385 // call the base class to let standard processing switch to
\r
386 // the top-level menu associated with this window
\r
387 __super::OnMDIActivate(bActivate, pActivateWnd, pDeactivateWnd);
\r
390 ::PostMessage(AfxGetMainWnd()->GetSafeHwnd(), WMU_CHILDFRAMEACTIVATED, 0, reinterpret_cast<LPARAM>(this));
\r