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