OSDN Git Service

Various refactorings involving NULL, ASSERT, TRUE and FALSE (6)
[winmerge-jp/winmerge-jp.git] / Src / EditorFilepathBar.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 //    WinMerge:  an interactive diff/merge utility
3 //    Copyright (C) 1997-2000  Thingamahoochie Software
4 //    Author: Dean Grimm
5 //
6 //    This program is free software; you can redistribute it and/or modify
7 //    it under the terms of the GNU General Public License as published by
8 //    the Free Software Foundation; either version 2 of the License, or
9 //    (at your option) any later version.
10 //
11 //    This program is distributed in the hope that it will be useful,
12 //    but WITHOUT ANY WARRANTY; without even the implied warranty of
13 //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 //    GNU General Public License for more details.
15 //
16 //    You should have received a copy of the GNU General Public License
17 //    along with this program; if not, write to the Free Software
18 //    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 //
20 /////////////////////////////////////////////////////////////////////////////
21 /** 
22  * @file  EditorFilepathBar.cpp
23  *
24  * @brief Implementation file for CEditorFilepathBar class
25  */
26
27 #include "stdafx.h"
28 #include "EditorFilepathBar.h"
29
30 #ifdef _DEBUG
31 #define new DEBUG_NEW
32 #endif
33
34
35 BEGIN_MESSAGE_MAP(CEditorFilePathBar, CDialogBar)
36         ON_NOTIFY_EX (TTN_NEEDTEXT, 0, OnToolTipNotify)
37         ON_CONTROL_RANGE (EN_SETFOCUS, IDC_STATIC_TITLE_PANE0, IDC_STATIC_TITLE_PANE2, OnSetFocusEdit)
38 END_MESSAGE_MAP()
39
40
41 /**
42  * @brief Constructor.
43  */
44 CEditorFilePathBar::CEditorFilePathBar()
45 : m_nPanes(2)
46 {
47 }
48
49 /**
50  * @brief Destructor.
51  */
52 CEditorFilePathBar::~CEditorFilePathBar()
53 {
54 }
55
56 /**
57  * @brief Create the window.
58  * This function subclasses the edit controls.
59  * @param [in] pParentWnd Parent window for edit controls.
60  * @return TRUE if succeeded, FALSE otherwise.
61  */
62 BOOL CEditorFilePathBar::Create(CWnd* pParentWnd)
63 {
64         if (! CDialogBar::Create(pParentWnd, CEditorFilePathBar::IDD, 
65                         CBRS_TOP | CBRS_TOOLTIPS | CBRS_FLYBY, CEditorFilePathBar::IDD))
66                 return FALSE;
67
68         NONCLIENTMETRICS ncm = { sizeof NONCLIENTMETRICS };
69         if (SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof NONCLIENTMETRICS, &ncm, 0))
70                 m_font.CreateFontIndirect(&ncm.lfStatusFont);
71
72         // subclass the two custom edit boxes
73         for (int pane = 0; pane < countof(m_Edit); pane++)
74         {
75                 m_Edit[pane].SubClassEdit(IDC_STATIC_TITLE_PANE0 + pane, this);
76                 m_Edit[pane].SetFont(&m_font);
77                 m_Edit[pane].SetMargins(4, 4);
78         }
79         return TRUE;
80 };
81
82 CSize CEditorFilePathBar::CalcFixedLayout(BOOL bStretch, BOOL bHorz)
83 {
84         TEXTMETRIC tm;
85         CClientDC dc(this);
86         CFont *pOldFont = dc.SelectObject(&m_font);
87         dc.GetTextMetrics(&tm);
88         dc.SelectObject(pOldFont);
89         return CSize(SHRT_MAX, tm.tmHeight + 6);
90 }
91
92 void CEditorFilePathBar::SetPaneCount(int nPanes)
93 {
94         m_nPanes = nPanes;
95 }
96
97 /** 
98  * @brief Resize both controls to an equal size.
99  */
100 void CEditorFilePathBar::Resize()
101 {
102         if (m_hWnd == nullptr)
103                 return;
104
105         WINDOWPLACEMENT infoBar;
106         GetWindowPlacement(&infoBar);
107
108         int widths[3];
109         for (int pane = 0; pane < m_nPanes; pane++)
110                 widths[pane] = (infoBar.rcNormalPosition.right / m_nPanes);
111         Resize(widths);
112 }
113
114 /** 
115  * @brief Set callback function on EN_SETFOCUS notification
116  */
117 void CEditorFilePathBar::SetOnSetFocusCallback(const std::function<void(int)> callbackfunc)
118 {
119         m_callbackfunc = callbackfunc;
120 }
121
122 /** 
123  * @brief Set widths.
124  * This function resizes both controls to given size. The width is usually
125  * same as the splitter view width.
126  * @param [in] leftWidth Left-side control width.
127  * @param [in] rightWidth Right-side control width.
128  */
129 void CEditorFilePathBar::Resize(int widths[])
130 {
131         if (m_hWnd == nullptr)
132                 return;
133
134         // resize left filename
135         CRect rc;
136         int x = 0;
137         GetClientRect(&rc);
138         for (int pane = 0; pane < m_nPanes; pane++)
139         {
140                 CRect rcOld;
141                 m_Edit[pane].GetClientRect(&rcOld);
142                 rc.left = x;
143                 rc.right = x + widths[pane] + (pane == 0 ? 5 : 7);
144                 x = rc.right;
145                 if (rcOld.Width() != rc.Width())
146                 {
147                         m_Edit[pane].MoveWindow(&rc);
148                         m_Edit[pane].RefreshDisplayText();
149                 }
150         }
151 }
152
153 /**
154  * @brief Called when tooltip is about to be shown.
155  * In this function we set the tooltip text shown.
156  */
157 BOOL CEditorFilePathBar::OnToolTipNotify(UINT id, NMHDR * pTTTStruct, LRESULT * pResult)
158 {
159         if (m_hWnd == nullptr)
160                 return FALSE;
161
162         TOOLTIPTEXT *pTTT = (TOOLTIPTEXT *)pTTTStruct;
163         if (pTTT->uFlags & TTF_IDISHWND)
164         {
165                 // idFrom is actually the HWND of the CEdit 
166                 int nID = ::GetDlgCtrlID((HWND)pTTTStruct->idFrom);
167                 if(nID == IDC_STATIC_TITLE_PANE0 || nID == IDC_STATIC_TITLE_PANE1 || nID == IDC_STATIC_TITLE_PANE2)
168                 {
169                         // compute max width : 97% of application width or 80% or full screen width
170                         CRect rect;
171                         GetWindowRect(rect);
172                         int maxWidth = (int)(rect.Width() * .97);
173                         CRect rectScreen; 
174                         SystemParametersInfo(SPI_GETWORKAREA, 0, rectScreen, 0);
175                         if (rectScreen.Width() * .8 > maxWidth)
176                                 maxWidth = (int)(rectScreen.Width() * .8);
177
178                         // use the tooltip font
179                         HANDLE hFont = (HANDLE) ::SendMessage(pTTTStruct->hwndFrom, WM_GETFONT, 0, 0);
180                         CClientDC tempDC(this);
181                         HANDLE hOldFont = ::SelectObject(tempDC.GetSafeHdc(),hFont);
182
183                         // fill in the returned structure
184                         CFilepathEdit * pItem = static_cast<CFilepathEdit*>(GetDlgItem(nID));
185                         pTTT->lpszText = const_cast<TCHAR *>(pItem->GetUpdatedTipText(&tempDC, maxWidth).c_str());
186
187                         // set old font back
188                         if (hOldFont)
189                                 ::SelectObject(tempDC.GetSafeHdc(),hOldFont);
190
191                         // we must set TTM_SETMAXTIPWIDTH to use \n in tooltips
192                         // just to do the first time, but how to access the tooltip during init ?
193                         ::SendMessage(pTTTStruct->hwndFrom, TTM_SETMAXTIPWIDTH, 0, 5000);
194
195                         return TRUE;
196                 }
197         }
198         return FALSE;
199 }
200
201 void CEditorFilePathBar::OnSetFocusEdit(UINT id)
202 {
203         if (m_callbackfunc)
204                 m_callbackfunc(id - IDC_STATIC_TITLE_PANE0);
205 }
206
207 /** 
208  * @brief Get the path for one side
209  *
210  * @param [in] pane Index (0-based) of pane to update.
211  */
212 String CEditorFilePathBar::GetText(int pane) const
213 {
214         ASSERT (pane >= 0 && pane < countof(m_Edit));
215
216         // Check for `nullptr` since window may be closing..
217         if (m_hWnd == nullptr)
218                 return _T("");
219
220         CString str;
221         m_Edit[pane].GetWindowText(str);
222         return String(str);
223 }
224
225 /** 
226  * @brief Set the path for one side
227  *
228  * @param [in] pane Index (0-based) of pane to update.
229  * @param [in] lpszString New text for pane.
230  */
231 void CEditorFilePathBar::SetText(int pane, const String& sString)
232 {
233         ASSERT (pane >= 0 && pane < countof(m_Edit));
234
235         // Check for `nullptr` since window may be closing..
236         if (m_hWnd == nullptr)
237                 return;
238
239         m_Edit[pane].SetOriginalText(sString);
240 }
241
242 /** 
243  * @brief Set the active status for one status (change the appearance)
244  *
245  * @param [in] pane Index (0-based) of pane to update.
246  * @param [in] bActive If `true` activates pane, `false` deactivates.
247  */
248 void CEditorFilePathBar::SetActive(int pane, bool bActive)
249 {
250         ASSERT (pane >= 0 && pane < countof(m_Edit));
251
252         // Check for `nullptr` since window may be closing..
253         if (m_hWnd == nullptr)
254                 return;
255
256         m_Edit[pane].SetActive(bActive);
257 }