]> git.saurik.com Git - wxWidgets.git/blob - contrib/src/foldbar/foldpanelbar.cpp
Workaround for memory bug when using wxRegConfig and calling
[wxWidgets.git] / contrib / src / foldbar / foldpanelbar.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: foldpanelbar.cpp
3 // Purpose:
4 // Author: Jorgen Bodde
5 // Modified by:
6 // Created: 22/06/2004
7 // RCS-ID: $Id$
8 // Copyright: (c) Jorgen Bodde
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // For compilers that support precompilation, includes "wx/wx.h".
13 #include "wx/wxprec.h"
14
15 #ifdef __BORLANDC__
16 #pragma hdrstop
17 #endif
18
19 #include "wx/foldbar/foldpanelbar.h"
20 #include "icon_collapsed.xpm"
21 #include "icon_expanded.xpm"
22 #include "icon_theresmore.xpm"
23
24 //----------------------------------------------------------------------------
25 // wxFoldPanelBar
26 //----------------------------------------------------------------------------
27
28 IMPLEMENT_CLASS( wxFoldPanelBar, wxPanel )
29
30 BEGIN_EVENT_TABLE(wxFoldPanelBar,wxPanel)
31 EVT_SIZE(wxFoldPanelBar::OnSizePanel)
32 //EVT_PAINT(wxFoldPanelBar::OnPaint)
33 EVT_CAPTIONBAR(wxID_ANY, wxFoldPanelBar::OnPressCaption)
34 END_EVENT_TABLE()
35
36 wxFoldPanelBar::wxFoldPanelBar()
37 {
38
39 }
40
41 wxFoldPanelBar::wxFoldPanelBar( wxWindow *parent, wxWindowID id, const wxPoint &position,
42 const wxSize& size, long style, long extraStyle)
43 : _foldPanel(0)
44 , _bottomPanel(0)
45 , _controlCreated(false)
46 {
47 Create( parent, id, position, size, style, extraStyle);
48 }
49
50 void wxFoldPanelBar::Create( wxWindow *parent, wxWindowID id, const wxPoint &position,
51 const wxSize& size, long style, long extraStyle )
52 {
53
54 _extraStyle = extraStyle;
55
56 // create the panel (duh!). This causes a size event, which we are going
57 // to skip when we are not initialised
58
59 wxPanel::Create(parent, id, position, size, style);
60
61 // the fold panel area
62
63 _foldPanel = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxNO_BORDER|wxTAB_TRAVERSAL);
64
65 // the extra area for some icons / context menu etc
66
67 #if 0
68 _bottomPanel = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(wxDefaultCoord,22), wxNO_BORDER|wxTAB_TRAVERSAL);
69 _bottomPanel->SetBackgroundColour(*wxWHITE);
70 #endif
71
72 // create the fold icons to be used in the captions
73
74 _images = new wxImageList(16, 16);
75
76 wxBitmap *bmp = new wxBitmap(icon_expanded);
77 _images->Add(*bmp);
78 delete bmp;
79
80 bmp = new wxBitmap(icon_collapsed);
81 _images->Add(*bmp);
82 delete bmp;
83
84 _moreBmp = new wxBitmap(icon_theresmore);
85
86 // do this as last, to check if create is already called
87
88 _controlCreated = true;
89 }
90
91 wxFoldPanelBar::~wxFoldPanelBar()
92 {
93 delete _images;
94 delete _moreBmp;
95 }
96
97 wxFoldPanel wxFoldPanelBar::AddFoldPanel(const wxString &caption, bool collapsedInitially, const wxCaptionBarStyle &style)
98 {
99 wxASSERT(_controlCreated);
100
101 // create a fold panel item, which is first only the caption.
102 // the user can now add a panel area which will be folded in
103 // when pressed.
104
105 wxFoldPanelItem *item = new wxFoldPanelItem(_foldPanel, caption, _images, collapsedInitially, style);
106
107 // look at the last added one and reposition this one
108 int y = 0;
109 if(_panels.GetCount() > 0)
110 y = _panels.Last()->GetY() + _panels.Last()->GetPanelHeight();
111
112 item->Reposition(y);
113 _panels.Add(item);
114
115 //return wxFoldPanel(item);
116 return wxFoldPanel(item);
117 }
118
119 int wxFoldPanelBar::AddFoldPanelWindow(const wxFoldPanel &panel, wxWindow *window, int flags, int ySpacing, int leftSpacing,
120 int rightSpacing)
121 {
122 wxCHECK(panel.IsOk(), -1);
123 panel.GetItem()->AddWindow(window, flags, ySpacing, leftSpacing, rightSpacing);
124
125 // TODO: Take old and new height, and if difference, reposition all the lower panels
126 // this is because the user can add new wxWindow controls somewhere in between
127 // when other panels are already present.
128
129 return 0;
130 }
131
132 int wxFoldPanelBar::AddFoldPanelSeperator(const wxFoldPanel &panel, const wxColour &color, int ySpacing, int leftSpacing,
133 int rightSpacing)
134 {
135 wxCHECK(panel.IsOk(), -1);
136 panel.GetItem()->AddSeparator(color, ySpacing, leftSpacing, rightSpacing);
137
138 return 0;
139 }
140
141 void wxFoldPanelBar::OnSizePanel(wxSizeEvent &event)
142 {
143 // skip all stuff when we are not initialised yet
144
145 if(!_controlCreated)
146 {
147 event.Skip();
148 return;
149 }
150
151 // now size the fold panel area and the
152 // lower bar in such a way that the bar is always
153 // visible
154
155 wxRect foldrect = GetRect();
156
157 // fold panel itself. If too little space,
158 // don't show it
159
160 #if 0
161 if(foldrect.GetHeight() < 23)
162 foldrect.SetHeight(0);
163 else
164 foldrect.SetHeight(foldrect.GetHeight() - 22);
165 #endif
166
167 foldrect.SetX(0);
168 foldrect.SetY(0);
169 _foldPanel->SetSize(foldrect);
170
171 if(_extraStyle & wxFPB_COLLAPSE_TO_BOTTOM)
172 {
173 wxRect rect = RepositionCollapsedToBottom();
174 if(rect.GetHeight() > 0)
175 RefreshRect(rect);
176 }
177
178 // TODO: A smart way to check wether the old - new width of the
179 // panel changed, if so no need to resize the fold panel items
180
181 RedisplayFoldPanelItems();
182
183 // tool panel for icons and other stuff
184
185 #if 0
186 wxRect bottomrect = GetRect();
187 if(bottomrect.GetHeight() < 22)
188 bottomrect.SetY(0);
189 else
190 bottomrect.SetY(bottomrect.GetHeight() - 22);
191
192 bottomrect.SetHeight(22);
193 bottomrect.SetX(0);
194 _bottomPanel->SetSize(bottomrect);
195
196 // TODO: redraw the bitmap properly
197 // use the captionbar algorithm for that
198
199 _bottomPanel->Refresh();
200 #endif
201 }
202
203 void wxFoldPanelBar::OnPaint(wxPaintEvent &event)
204 {
205 if(!_controlCreated)
206 return;
207 #if 0
208 // paint the bottom panel only, where the
209 // arrow is shown when there is more to show the user
210 // just as informative icon
211
212 wxPaintDC dc(_bottomPanel);
213
214 wxSize size = _bottomPanel->GetSize();
215 int offset = (size.GetHeight() - _moreBmp->GetHeight()) / 2;
216
217 dc.DrawBitmap(*_moreBmp, size.GetWidth() - _moreBmp->GetWidth() - 2, offset, true);
218 #endif
219
220 event.Skip();
221 }
222
223 void wxFoldPanelBar::OnPressCaption(wxCaptionBarEvent &event)
224 {
225 // act upon the folding or expanding status of the bar
226 // to expand or collapse the panel(s)
227
228 if(event.GetFoldStatus())
229 Collapse(wxFoldPanel((wxFoldPanelItem *)event.GetTag()));
230 else
231 Expand(wxFoldPanel((wxFoldPanelItem *)event.GetTag()));
232 }
233
234 void wxFoldPanelBar::RefreshPanelsFrom(wxFoldPanelItem *item)
235 {
236 wxASSERT(item);
237
238 int i = _panels.Index(item);
239 if(i != wxNOT_FOUND)
240 RefreshPanelsFrom(i);
241 }
242
243 void wxFoldPanelBar::RefreshPanelsFrom(size_t i)
244 {
245 Freeze();
246
247 // if collapse to bottom is on, the panels that are not expanded
248 // should be drawn at the bottom. All panels that are expanded
249 // are drawn on top. The last expanded panel gets all the extra space
250
251 if(_extraStyle & wxFPB_COLLAPSE_TO_BOTTOM)
252 {
253 int offset = 0;
254
255 for(size_t j = 0; j < _panels.GetCount(); j++)
256 {
257 if(_panels.Item(j)->IsExpanded())
258 offset += _panels.Item(j)->Reposition(offset);
259 }
260
261 // put all non collapsed panels at the bottom where there is space, else
262 // put them right behind the expanded ones
263
264 RepositionCollapsedToBottom();
265 }
266 else
267 {
268 int y = _panels.Item(i)->GetY() + _panels.Item(i)->GetPanelHeight();
269 for(i++; i < _panels.GetCount(); i++)
270 y += _panels.Item(i)->Reposition(y);
271 }
272 Thaw();
273 }
274
275 void wxFoldPanelBar::RedisplayFoldPanelItems()
276 {
277 // resize them all. No need to reposition
278
279 wxFoldPanelItem *item;
280 for(size_t i = 0; i < _panels.GetCount(); i++)
281 {
282 item = _panels.Item(i);
283 wxASSERT(item);
284
285 item->ResizePanel();
286 }
287 }
288
289 wxRect wxFoldPanelBar::RepositionCollapsedToBottom()
290 {
291 wxRect value(0,0,0,0);
292
293 // determine wether the number of panels left
294 // times the size of their captions is enough
295 // to be placed in the left over space
296
297 int expanded = 0, collapsed = 0, offset;
298 GetPanelsHeight(collapsed, expanded);
299
300 // if no room stick them behind the normal ones, else
301 // at the bottom
302
303 if((GetSize().GetHeight() - expanded - collapsed) < 0)
304 offset = expanded;
305 else
306 {
307 // value is the region which is left unpainted
308 // I will send it back as 'slack' so it does not need to
309 // be recalulated.
310
311 value.SetX(0);
312 value.SetY(expanded);
313 value.SetHeight(GetSize().GetHeight() - expanded);
314 value.SetWidth(GetSize().GetWidth());
315
316 offset = GetSize().GetHeight() - collapsed;
317 }
318
319
320 // go reposition
321
322 for(size_t i = 0; i < _panels.GetCount(); i++)
323 {
324 if(!_panels.Item(i)->IsExpanded())
325 offset += _panels.Item(i)->Reposition(offset);
326 }
327
328 return value;
329 }
330
331 int wxFoldPanelBar::GetPanelsHeight(int &collapsed, int &expanded)
332 {
333 int value = 0;
334
335 // assumed here that all the panels that are expanded
336 // are positioned after eachother from 0,0 to end.
337
338 for(size_t j = 0; j < _panels.GetCount(); j++)
339 {
340 int offset = _panels.Item(j)->GetPanelHeight();
341 value += offset;
342 if(_panels.Item(j)->IsExpanded())
343 expanded += offset;
344 else
345 collapsed += offset;
346 }
347
348 return value;
349
350 }