]> git.saurik.com Git - wxWidgets.git/blame_incremental - contrib/src/foldbar/foldpanelbar.cpp
fix evaluation order bug (patch 1158099)
[wxWidgets.git] / contrib / src / foldbar / foldpanelbar.cpp
... / ...
CommitLineData
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
33IMPLEMENT_CLASS( wxFoldPanelBar, wxPanel )
34
35BEGIN_EVENT_TABLE(wxFoldPanelBar,wxPanel)
36 EVT_SIZE(wxFoldPanelBar::OnSizePanel)
37 //EVT_PAINT(wxFoldPanelBar::OnPaint)
38 EVT_CAPTIONBAR(wxID_ANY, wxFoldPanelBar::OnPressCaption)
39END_EVENT_TABLE()
40
41wxFoldPanelBar::wxFoldPanelBar()
42{
43
44}
45
46wxFoldPanelBar::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
55void 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
100wxFoldPanelBar::~wxFoldPanelBar()
101{
102 delete m_images;
103 delete m_moreBmp;
104}
105
106wxFoldPanel 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
128int 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
141int 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
150void 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
213void 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
233void 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
244void 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
253void 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
285void 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
299wxRect 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
350int 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}