OSDN Git Service

Merge branch 'rel_0.3.x'
[tortoisegit/TortoiseGitJp.git] / ext / ResizableLib / ResizableLayout.h
1 /////////////////////////////////////////////////////////////////////////////\r
2 //\r
3 // This file is part of ResizableLib\r
4 // http://sourceforge.net/projects/resizablelib\r
5 //\r
6 // Copyright (C) 2000-2004 by Paolo Messina\r
7 // http://www.geocities.com/ppescher - mailto:ppescher@hotmail.com\r
8 //\r
9 // The contents of this file are subject to the Artistic License (the "License").\r
10 // You may not use this file except in compliance with the License. \r
11 // You may obtain a copy of the License at:\r
12 // http://www.opensource.org/licenses/artistic-license.html\r
13 //\r
14 // If you find this code useful, credits would be nice!\r
15 //\r
16 /////////////////////////////////////////////////////////////////////////////\r
17 \r
18 /*!\r
19  *  @file\r
20  *  @brief Interface for the CResizableLayout class.\r
21  */\r
22 \r
23 #if !defined(AFX_RESIZABLELAYOUT_H__INCLUDED_)\r
24 #define AFX_RESIZABLELAYOUT_H__INCLUDED_\r
25 \r
26 #include <afxtempl.h>\r
27 #include "ResizableMsgSupport.h"\r
28 \r
29 #if _MSC_VER > 1000\r
30 #pragma once\r
31 #endif // _MSC_VER > 1000\r
32 \r
33 /*! @addtogroup CoreComponents\r
34  *  @{\r
35  */\r
36 \r
37 //! @brief Special type for layout alignment\r
38 /*!\r
39  *  Implements anchor points as a percentage of the parent window client area.\r
40  *  Control corners are always kept at a fixed distance from their anchor points,\r
41  *  thus allowing a control to resize proportionally as the parent window is resized.\r
42  */\r
43 typedef struct tagANCHOR\r
44 {\r
45         int cx; //!< horizontal component, in percent\r
46         int cy; //!< vertical component, in percent\r
47 \r
48         tagANCHOR() {}\r
49 \r
50         tagANCHOR(int x, int y)\r
51         {\r
52                 cx = x;\r
53                 cy = y;\r
54         }\r
55 \r
56 } ANCHOR, *PANCHOR, *LPANCHOR;\r
57 \r
58 /*! @defgroup ConstAnchors Alignment Constants\r
59  *  Define common layout alignment constants for anchor points.\r
60  *  @{\r
61  */\r
62         //! Anchor to the top-left corner\r
63         const ANCHOR TOP_LEFT(0, 0);\r
64         //! Anchor to the top edge and center horizontally\r
65         const ANCHOR TOP_CENTER(50, 0);\r
66         //! Anchor to the top-right corner\r
67         const ANCHOR TOP_RIGHT(100, 0);\r
68         //! Anchor to the left edge and center vertically\r
69         const ANCHOR MIDDLE_LEFT(0, 50);\r
70         //! Anchor to the center\r
71         const ANCHOR MIDDLE_CENTER(50, 50);\r
72         //! Anchor to the right edge and center vertically\r
73         const ANCHOR MIDDLE_RIGHT(100, 50);\r
74         //! Anchor to the bottom-left corner\r
75         const ANCHOR BOTTOM_LEFT(0, 100);\r
76         //! Anchor to the bottom edge and center horizontally\r
77         const ANCHOR BOTTOM_CENTER(50, 100);\r
78         //! Anchor to the bottom-right corner\r
79         const ANCHOR BOTTOM_RIGHT(100, 100);\r
80 // @}\r
81 \r
82 //! @brief Holds a control layout settings\r
83 /*!\r
84  *  Layout settings specify how a control must be moved and resized with respect to\r
85  *  the parent window and how it reacts to dynamic changes to its size when painting\r
86  *  its client area, with special care for flickering.\r
87  */\r
88 typedef struct tagLAYOUTINFO\r
89 {\r
90         //! Handle of the window the layout of which is being defined\r
91         HWND hWnd;\r
92         //! Identification number assigned to the callback slot\r
93         UINT_PTR nCallbackID;\r
94 \r
95         //! Window class name to identify standard controls\r
96         TCHAR sWndClass[MAX_PATH];\r
97 \r
98         //! Anchor point for the top-left corner\r
99         ANCHOR anchorTopLeft;\r
100         //! Fixed distance for the top-left corner\r
101         SIZE marginTopLeft;\r
102         \r
103         //! Anchor point for the bottom-right corner\r
104         ANCHOR anchorBottomRight;\r
105         //! Fixed distance for the bottom-right corner\r
106         SIZE marginBottomRight;\r
107 \r
108         //! Flag that enables support for custom windows\r
109         BOOL bMsgSupport;\r
110         //! Redraw settings for anti-flickering and proper painting\r
111         RESIZEPROPERTIES properties;\r
112 \r
113         tagLAYOUTINFO() : hWnd(NULL), nCallbackID(0), bMsgSupport(FALSE)\r
114         {\r
115                 sWndClass[0] = 0;\r
116         }\r
117 \r
118         tagLAYOUTINFO(HWND hwnd, ANCHOR tl_type, SIZE tl_margin, \r
119                 ANCHOR br_type, SIZE br_margin)\r
120                 :\r
121                 hWnd(hwnd), nCallbackID(0), bMsgSupport(FALSE),\r
122                 anchorTopLeft(tl_type), marginTopLeft(tl_margin),\r
123                 anchorBottomRight(br_type), marginBottomRight(br_margin)\r
124         {\r
125                 sWndClass[0] = 0;\r
126         }\r
127 \r
128 } LAYOUTINFO, *PLAYOUTINFO, *LPLAYOUTINFO;\r
129 \r
130 //! @brief Layout manager implementation\r
131 /*!\r
132  *  Derive from this class to implement resizable windows, adding the ability\r
133  *  to dinamically resize and reposition child controls.\r
134  *      Special care is taken to ensure a smooth animation during the resize\r
135  *  operations performed by the users, without annoying flickering effects.\r
136  */\r
137 class CResizableLayout\r
138 {\r
139 private:\r
140         //@{\r
141         //! @brief Collection of layout settings for each control\r
142         CMap<HWND, HWND, POSITION, POSITION> m_mapLayout;\r
143         CList<LAYOUTINFO, LAYOUTINFO&> m_listLayout;\r
144         CList<LAYOUTINFO, LAYOUTINFO&> m_listLayoutCB;\r
145         //@}\r
146 \r
147         //@{\r
148         //! @brief Used for clipping implementation\r
149         HRGN m_hOldClipRgn;\r
150         int m_nOldClipRgn;\r
151         //@}\r
152 \r
153         //@{\r
154         //! @brief Used for advanced anti-flickering\r
155         RECT m_rectClientBefore;\r
156         BOOL m_bNoRecursion;\r
157         //@}\r
158 \r
159         //! @brief Apply clipping settings for the specified control\r
160         void ClipChildWindow(const LAYOUTINFO &layout, CRgn* pRegion) const;\r
161 \r
162         //! @brief Helper function to calculate new layout\r
163         void CalcNewChildPosition(const LAYOUTINFO &layout,\r
164                 const CRect &rectParent, CRect &rectChild, UINT& uFlags) const;\r
165 \r
166 protected:\r
167         //! @brief Override to initialize resize properties (clipping, refresh)\r
168         virtual void InitResizeProperties(LAYOUTINFO& layout) const;\r
169 \r
170         //! @brief Override to specify clipping for unsupported windows\r
171         virtual BOOL LikesClipping(const LAYOUTINFO &layout) const;\r
172 \r
173         //! @brief Override to specify refresh for unsupported windows\r
174         virtual BOOL NeedsRefresh(const LAYOUTINFO &layout,\r
175                 const CRect &rectOld, const CRect &rectNew) const;\r
176 \r
177         //! @brief Clip controls in the layout out of the specified device context\r
178         BOOL ClipChildren(CDC* pDC, BOOL bUndo);\r
179 \r
180         //! @brief Get the layout clipping region\r
181         void GetClippingRegion(CRgn* pRegion) const;\r
182         \r
183         //! @brief Override for scrollable or expanding parent windows\r
184         virtual void GetTotalClientRect(LPRECT lpRect) const;\r
185 \r
186         //@{\r
187         //! @brief Add anchor points for the specified control to the layout\r
188         void AddAnchor(HWND hWnd, ANCHOR anchorTopLeft, ANCHOR anchorBottomRight);\r
189 \r
190         void AddAnchor(HWND hWnd, ANCHOR anchorTopLeft)\r
191         {\r
192                 AddAnchor(hWnd, anchorTopLeft, anchorTopLeft);\r
193         }\r
194 \r
195         void AddAnchor(UINT nID, ANCHOR anchorTopLeft, ANCHOR anchorBottomRight)\r
196         {\r
197                 AddAnchor(::GetDlgItem(GetResizableWnd()->GetSafeHwnd(), nID),\r
198                         anchorTopLeft, anchorBottomRight);\r
199         }\r
200 \r
201         void AddAnchor(UINT nID, ANCHOR anchorTopLeft)\r
202         {\r
203                 AddAnchor(::GetDlgItem(GetResizableWnd()->GetSafeHwnd(), nID),\r
204                         anchorTopLeft, anchorTopLeft);\r
205         }\r
206         //@}\r
207 \r
208         //! @brief Add a callback slot to the layout for dynamic controls or anchor points\r
209         UINT_PTR AddAnchorCallback();\r
210 \r
211         //@{\r
212         //! @brief Get position and size of a control in the layout from the parent's client area\r
213         BOOL GetAnchorPosition(HWND hWnd, const CRect &rectParent,\r
214                 CRect &rectChild, UINT* lpFlags = NULL) const\r
215         {\r
216                 POSITION pos;\r
217                 if (!m_mapLayout.Lookup(hWnd, pos))\r
218                         return FALSE;\r
219 \r
220                 UINT uTmpFlags;\r
221                 CalcNewChildPosition(m_listLayout.GetAt(pos), rectParent, rectChild,\r
222                         (lpFlags != NULL) ? (*lpFlags) : uTmpFlags);\r
223                 return TRUE;\r
224         }\r
225 \r
226         BOOL GetAnchorPosition(UINT nID, const CRect &rectParent,\r
227                 CRect &rectChild, UINT* lpFlags = NULL) const\r
228         {\r
229                 return GetAnchorPosition(::GetDlgItem(GetResizableWnd()->GetSafeHwnd(), nID),\r
230                         rectParent, rectChild, lpFlags);\r
231         }\r
232         //@}\r
233 \r
234         //@{\r
235         //! @brief Get margins surrounding a control in the layout with the given size\r
236         BOOL GetAnchorMargins(HWND hWnd, const CSize &sizeChild, CRect &rectMargins) const;\r
237 \r
238         BOOL GetAnchorMargins(UINT nID, const CSize &sizeChild, CRect &rectMargins) const\r
239         {\r
240                 return GetAnchorMargins(::GetDlgItem(GetResizableWnd()->GetSafeHwnd(), nID),\r
241                         sizeChild, rectMargins);\r
242         }\r
243         //@}\r
244 \r
245         //@{\r
246         //! @brief Remove a control from the layout\r
247         BOOL RemoveAnchor(HWND hWnd)\r
248         {\r
249                 POSITION pos;\r
250                 if (!m_mapLayout.Lookup(hWnd, pos))\r
251                         return FALSE;\r
252 \r
253                 m_listLayout.RemoveAt(pos);\r
254                 return m_mapLayout.RemoveKey(hWnd);\r
255         }\r
256 \r
257         BOOL RemoveAnchor(UINT nID)\r
258         {\r
259                 return RemoveAnchor(::GetDlgItem(GetResizableWnd()->GetSafeHwnd(), nID));\r
260         }\r
261         //@}\r
262 \r
263         //! @brief Reset the layout content\r
264         void RemoveAllAnchors()\r
265         {\r
266                 m_mapLayout.RemoveAll();\r
267                 m_listLayout.RemoveAll();\r
268                 m_listLayoutCB.RemoveAll();\r
269         }\r
270 \r
271         //! @brief Reposition and size all the controls in the layout\r
272         void ArrangeLayout() const;\r
273 \r
274         //! @brief Override to provide dynamic control's layout info\r
275         virtual BOOL ArrangeLayoutCallback(LAYOUTINFO& layout) const;\r
276 \r
277         //! @brief Override to provide the parent window\r
278         virtual CWnd* GetResizableWnd() const = 0;\r
279 \r
280         //! @brief Enhance anti-flickering\r
281         void HandleNcCalcSize(BOOL bAfterDefault, LPNCCALCSIZE_PARAMS lpncsp, LRESULT& lResult);\r
282         \r
283         //! @brief Enable resizable style for top level parent windows\r
284         void MakeResizable(LPCREATESTRUCT lpCreateStruct);\r
285 \r
286 public:\r
287         CResizableLayout()\r
288         {\r
289                 m_bNoRecursion = FALSE;\r
290                 m_hOldClipRgn = ::CreateRectRgn(0,0,0,0);\r
291                 m_nOldClipRgn = 0;\r
292         }\r
293 \r
294         virtual ~CResizableLayout()\r
295         {\r
296                 // just for safety\r
297                 RemoveAllAnchors();\r
298 \r
299                 DeleteObject(m_hOldClipRgn); \r
300         }\r
301 };\r
302 \r
303 // @}\r
304 #endif // !defined(AFX_RESIZABLELAYOUT_H__INCLUDED_)\r