OSDN Git Service

7c079c62c486571571c70ef05c8df9d572804a23
[winmerge-jp/winmerge-jp.git] / Src / MergeFrameCommon.cpp
1 /** \r
2  * @file  MergeFrameCommon.cpp\r
3  *\r
4  * @brief Implementation file for CMergeFrameCommon\r
5  *\r
6  */\r
7 #include "StdAfx.h"\r
8 #include "MergeFrameCommon.h"\r
9 #include "OptionsDef.h"\r
10 #include "OptionsMgr.h"\r
11 #include "paths.h"\r
12 #include "Merge.h"\r
13 #include "FileTransform.h"\r
14 #include <../src/mfc/afximpl.h>\r
15 \r
16 IMPLEMENT_DYNCREATE(CMergeFrameCommon, CMDIChildWnd)\r
17 \r
18 BEGIN_MESSAGE_MAP(CMergeFrameCommon, CMDIChildWnd)\r
19         //{{AFX_MSG_MAP(CMergeFrameCommon)\r
20         ON_WM_GETMINMAXINFO()\r
21         ON_WM_DESTROY()\r
22         ON_WM_MDIACTIVATE()\r
23         //}}AFX_MSG_MAP\r
24 END_MESSAGE_MAP()\r
25 \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
32 {\r
33         ::PostMessage(AfxGetMainWnd()->GetSafeHwnd(), WMU_CHILDFRAMEADDED, 0, reinterpret_cast<LPARAM>(this));\r
34 }\r
35 \r
36 CMergeFrameCommon::~CMergeFrameCommon()\r
37 {\r
38         ::PostMessage(AfxGetMainWnd()->GetSafeHwnd(), WMU_CHILDFRAMEREMOVED, 0, reinterpret_cast<LPARAM>(this));\r
39 }\r
40 \r
41 void CMergeFrameCommon::ActivateFrame(int nCmdShow)\r
42 {\r
43         if (!m_bActivated) \r
44         {\r
45                 m_bActivated = true;\r
46 \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
53                 if (bMaximized)\r
54                         nCmdShow = SW_SHOWMAXIMIZED;\r
55                 else\r
56                         nCmdShow = SW_SHOWNORMAL;\r
57         }\r
58 \r
59         CMDIChildWnd::ActivateFrame(nCmdShow);\r
60 }\r
61 \r
62 void CMergeFrameCommon::SaveWindowState()\r
63 {\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
67         {\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
72         }\r
73 }\r
74 \r
75 void CMergeFrameCommon::RemoveBarBorder()\r
76 {\r
77         afxData.cxBorder2 = 0;\r
78         afxData.cyBorder2 = 0;\r
79         for (int i = 0; i < 4; ++i)\r
80         {\r
81                 CControlBar* pBar = GetControlBar(i + AFX_IDW_DOCKBAR_TOP);\r
82                 pBar->SetBarStyle(pBar->GetBarStyle() & ~(CBRS_BORDER_ANY | CBRS_BORDER_3D));\r
83         }\r
84 }\r
85 \r
86 /**\r
87  * @brief Reflect comparison result in window's icon.\r
88  * @param nResult [in] Last comparison result which the application returns.\r
89  */\r
90 void CMergeFrameCommon::SetLastCompareResult(int nResult)\r
91 {\r
92         HICON hReplace = (nResult == 0) ? m_hIdentical : m_hDifferent;\r
93 \r
94         if (m_hCurrent != hReplace)\r
95         {\r
96                 SetIcon(hReplace, TRUE);\r
97 \r
98                 AfxGetMainWnd()->SetTimer(IDT_UPDATEMAINMENU, 500, nullptr);\r
99 \r
100                 m_hCurrent = hReplace;\r
101         }\r
102 \r
103         theApp.SetLastCompareResult(nResult);\r
104 }\r
105 \r
106 void CMergeFrameCommon::ShowIdenticalMessage(const PathContext& paths, bool bIdenticalAll, std::function<int(LPCTSTR, unsigned, unsigned)> fnMessageBox)\r
107 {\r
108         String s;\r
109         if (theApp.m_bExitIfNoDiff != MergeCmdLineInfo::ExitQuiet)\r
110         {\r
111                 UINT nFlags = MB_ICONINFORMATION | MB_DONT_DISPLAY_AGAIN;\r
112 \r
113                 if (theApp.m_bExitIfNoDiff == MergeCmdLineInfo::Exit)\r
114                 {\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
119                 }\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
126                 {\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
130                 }\r
131                 else if (bIdenticalAll)\r
132                 {\r
133                         s = _("The selected files are identical.");\r
134                         fnMessageBox(s.c_str(), nFlags, IDS_FILESSAME);\r
135                 }\r
136         }\r
137 \r
138         if (bIdenticalAll)\r
139         {\r
140                 // Exit application if files are identical.\r
141                 if (theApp.m_bExitIfNoDiff == MergeCmdLineInfo::Exit ||\r
142                         theApp.m_bExitIfNoDiff == MergeCmdLineInfo::ExitQuiet)\r
143                 {\r
144                         AfxGetMainWnd()->PostMessage(WM_COMMAND, ID_APP_EXIT);\r
145                 }\r
146         }\r
147 }\r
148 \r
149 String CMergeFrameCommon::GetTitleString(const PathContext& paths, const String desc[],\r
150         const PackingInfo *pInfoUnpacker, const PrediffingInfo *pInfoPrediffer, bool hasTrivialDiffs)\r
151 {\r
152         const int nBuffers = paths.GetSize();\r
153         String sFileName[3];\r
154         String sTitle;\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
159         else\r
160                 sTitle = strutils::join(&sFileName[0], &sFileName[0] + nBuffers, _T(" - "));\r
161         String flags;\r
162         if (pInfoUnpacker && !pInfoUnpacker->GetPluginPipeline().empty())\r
163                 flags += _T("U");\r
164         if (pInfoPrediffer && !pInfoPrediffer->GetPluginPipeline().empty())\r
165                 flags += _T("P");\r
166         if (hasTrivialDiffs)\r
167                 flags += _T("F");\r
168         return (flags.empty() ? _T("") : (_T("(") + flags + _T(") "))) + sTitle;\r
169 }\r
170 \r
171 String CMergeFrameCommon::GetTooltipString(const PathContext& paths, const String desc[],\r
172         const PackingInfo *pInfoUnpacker, const PrediffingInfo *pInfoPrediffer, bool hasTrivialDiffs)\r
173 {\r
174         const int nBuffers = paths.GetSize();\r
175         String sTitle;\r
176         for (int nBuffer = 0; nBuffer < paths.GetSize(); nBuffer++)\r
177         {\r
178                 sTitle += strutils::format(_T("%d: "), nBuffer + 1);\r
179                 if (!desc[nBuffer].empty())\r
180                 {\r
181                         sTitle += desc[nBuffer];\r
182                         if (!paths[nBuffer].empty()) \r
183                                 sTitle += _T(" (") + paths[nBuffer] + _T(")");\r
184                 }\r
185                 else\r
186                 {\r
187                         sTitle += paths[nBuffer];\r
188                 }\r
189                 sTitle += _T(" - ");\r
190                 if (nBuffer == 0)\r
191                         sTitle += _("Left");\r
192                 else if (nBuffer == 1 && paths.GetSize() > 2)\r
193                         sTitle += _("Middle");\r
194                 else\r
195                         sTitle += _("Right");\r
196                 sTitle += _T("\n");\r
197         }\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
204         return sTitle;\r
205 }\r
206 \r
207 void CMergeFrameCommon::ChangeMergeMenuText(int srcPane, int dstPane, CCmdUI* pCmdUI)\r
208 {\r
209         String text;\r
210         switch (pCmdUI->m_nID)\r
211         {\r
212         case ID_L2R:\r
213                 text = (srcPane == 0 && dstPane == 1) ?\r
214                         _("Copy to &Middle\tAlt+Right") : _("Copy to &Right\tAlt+Right");\r
215                 break;\r
216         case ID_R2L:\r
217                 text = (srcPane == 2 && dstPane == 1) ?\r
218                         _("Copy to &Middle\tAlt+Left") : _("Copy to L&eft\tAlt+Left");\r
219                 break;\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
223                 break;\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
227                 break;\r
228         case ID_L2RNEXT:\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
231                 break;\r
232         case ID_R2LNEXT:\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
235                 break;\r
236         case ID_ALL_RIGHT:\r
237                 text = (srcPane == 0 && dstPane == 1) ?\r
238                         _("Copy All to Middle") : _("Copy &All to Right");\r
239                 break;\r
240         case ID_ALL_LEFT:\r
241                 text = (srcPane == 2 && dstPane == 1) ?\r
242                         _("Copy All to Middle") : _("Cop&y All to Left");\r
243                 break;\r
244         }\r
245         if (!text.empty())\r
246                 pCmdUI->SetText(text.c_str());\r
247 }\r
248 \r
249 std::pair<int, int> CMergeFrameCommon::MenuIDtoXY(UINT nID, int nActivePane, int nBuffers)\r
250 {\r
251         if (nActivePane < 0 || nActivePane >= nBuffers)\r
252                 return { -1, -1 };\r
253 \r
254         int srcPane = -1, dstPane = -1;\r
255         switch (nID)\r
256         {\r
257         case ID_L2R:\r
258         case ID_L2RNEXT:\r
259         case ID_ALL_RIGHT:\r
260         case ID_LINES_L2R:\r
261                 dstPane = (nActivePane < nBuffers - 1) ? nActivePane + 1 : nBuffers - 1;\r
262                 srcPane = dstPane - 1;\r
263                 break;\r
264         case ID_R2L:\r
265         case ID_R2LNEXT:\r
266         case ID_ALL_LEFT:\r
267         case ID_LINES_R2L:\r
268                 dstPane = (nActivePane > 0) ? nActivePane - 1 : 0;\r
269                 srcPane = dstPane + 1;\r
270                 break;\r
271         case ID_COPY_FROM_LEFT:\r
272         case ID_COPY_LINES_FROM_LEFT:\r
273                 if (nActivePane > 0)\r
274                 {\r
275                         dstPane = nActivePane;\r
276                         srcPane = nActivePane - 1;\r
277                 }\r
278                 break;\r
279         case ID_COPY_FROM_RIGHT:\r
280         case ID_COPY_LINES_FROM_RIGHT:\r
281                 if (nActivePane < nBuffers - 1)\r
282                 {\r
283                         dstPane = nActivePane;\r
284                         srcPane = nActivePane + 1;\r
285                 }\r
286                 break;\r
287         case ID_COPY_TO_MIDDLE_L:\r
288         case ID_COPY_LINES_TO_MIDDLE_L:\r
289                 if (nBuffers > 2)\r
290                 {\r
291                         srcPane = 0;\r
292                         dstPane = 1;\r
293                 }\r
294                 break;\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
300                 if (nBuffers > 2)\r
301                 {\r
302                         srcPane = 1;\r
303                         dstPane = 0;\r
304                 }\r
305                 break;\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
311                 if (nBuffers > 2)\r
312                 {\r
313                         srcPane = 1;\r
314                         dstPane = 0;\r
315                 }\r
316                 break;\r
317         case ID_COPY_TO_RIGHT_M:\r
318         case ID_COPY_LINES_TO_RIGHT_M:\r
319                 if (nBuffers > 2)\r
320                 {\r
321                         srcPane = 1;\r
322                         dstPane = nBuffers - 1;\r
323                 }\r
324                 break;\r
325         case ID_COPY_FROM_LEFT_M:\r
326         case ID_COPY_LINES_FROM_LEFT_M:\r
327                 if (nBuffers > 2)\r
328                 {\r
329                         srcPane = 0;\r
330                         dstPane = 1;\r
331                 }\r
332                 break;\r
333         case ID_COPY_FROM_RIGHT_M:\r
334         case ID_COPY_LINES_FROM_RIGHT_M:\r
335                 if (nBuffers > 2)\r
336                 {\r
337                         srcPane = nBuffers - 1;\r
338                         dstPane = 1;\r
339                 }\r
340                 break;\r
341         case ID_COPY_TO_MIDDLE_R:\r
342         case ID_COPY_LINES_TO_MIDDLE_R:\r
343                 if (nBuffers > 2)\r
344                 {\r
345                         srcPane = nBuffers - 1;\r
346                         dstPane = 1;\r
347                 }\r
348                 break;\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
354                 if (nBuffers > 2)\r
355                 {\r
356                         srcPane = 1;\r
357                         dstPane = nBuffers - 1;\r
358                 }\r
359                 break;\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
363         default:\r
364                 return { -1, -1 };\r
365         }\r
366         return { srcPane, dstPane };\r
367 }\r
368 \r
369 void CMergeFrameCommon::OnGetMinMaxInfo(MINMAXINFO* lpMMI)\r
370 {\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
377 #endif\r
378 }\r
379 \r
380 void CMergeFrameCommon::OnDestroy()\r
381 {\r
382         // https://stackoverflow.com/questions/35553955/getting-rid-of-3d-look-of-mdi-frame-window\r
383         CFrameWnd::OnDestroy();\r
384 }\r
385 \r
386 void CMergeFrameCommon::OnMDIActivate(BOOL bActivate, CWnd* pActivateWnd, CWnd* pDeactivateWnd)\r
387 {\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
391 \r
392         if (bActivate)\r
393                 ::PostMessage(AfxGetMainWnd()->GetSafeHwnd(), WMU_CHILDFRAMEACTIVATED, 0, reinterpret_cast<LPARAM>(this));\r
394 }\r