]> git.saurik.com Git - wxWidgets.git/blame - contrib/src/foldbar/foldpanelbar.cpp
wxFrameLayout contains wxPen by value, so the wxPen class declaration from wx/pen...
[wxWidgets.git] / contrib / src / foldbar / foldpanelbar.cpp
CommitLineData
957f5ab7 1/////////////////////////////////////////////////////////////////////////////
f857e441
WS
2// Name: foldpanelbar.cpp
3// Purpose:
4// Author: Jorgen Bodde
7a8d9418
WS
5// Modified by: ABX - 19/12/2004 : possibility of horizontal orientation
6// : wxWidgets coding standards
f857e441
WS
7// Created: 22/06/2004
8// RCS-ID: $Id$
9// Copyright: (c) Jorgen Bodde
10// Licence: wxWindows licence
957f5ab7
VZ
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
7a8d9418
WS
20#ifndef WX_PRECOMP
21 #include "wx/wx.h"
22#endif
23
957f5ab7
VZ
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)
f857e441
WS
36 EVT_SIZE(wxFoldPanelBar::OnSizePanel)
37 //EVT_PAINT(wxFoldPanelBar::OnPaint)
38 EVT_CAPTIONBAR(wxID_ANY, wxFoldPanelBar::OnPressCaption)
957f5ab7
VZ
39END_EVENT_TABLE()
40
41wxFoldPanelBar::wxFoldPanelBar()
42{
43
44}
45
f857e441
WS
46wxFoldPanelBar::wxFoldPanelBar( wxWindow *parent, wxWindowID id, const wxPoint &position,
47 const wxSize& size, long style, long extraStyle)
7a8d9418
WS
48 : m_foldPanel(NULL)
49 , m_bottomPanel(NULL)
50 , m_controlCreated(false)
957f5ab7 51{
f857e441 52 Create( parent, id, position, size, style, extraStyle);
957f5ab7
VZ
53}
54
f857e441
WS
55void wxFoldPanelBar::Create( wxWindow *parent, wxWindowID id, const wxPoint &position,
56 const wxSize& size, long style, long extraStyle )
957f5ab7 57{
f857e441 58
7a8d9418
WS
59 m_extraStyle = extraStyle;
60
61 // make sure there is any orientation
62 if ( ( style & wxFPB_HORIZONTAL ) != wxFPB_HORIZONTAL )
63 style |= wxFPB_VERTICAL;
f857e441
WS
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
60f94682 72 m_foldPanel = new wxPanel(this, wxID_ANY, position, size, wxNO_BORDER|wxTAB_TRAVERSAL);
f857e441
WS
73
74 // the extra area for some icons / context menu etc
957f5ab7
VZ
75
76#if 0
7a8d9418
WS
77 m_bottomPanel = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(wxDefaultCoord,22), wxNO_BORDER|wxTAB_TRAVERSAL);
78 m_bottomPanel->SetBackgroundColour(*wxWHITE);
957f5ab7
VZ
79#endif
80
f857e441 81 // create the fold icons to be used in the captions
957f5ab7 82
7a8d9418 83 m_images = new wxImageList(16, 16);
957f5ab7 84
f857e441 85 wxBitmap *bmp = new wxBitmap(icon_expanded);
7a8d9418 86 m_images->Add(*bmp);
f857e441 87 delete bmp;
957f5ab7 88
f857e441 89 bmp = new wxBitmap(icon_collapsed);
7a8d9418 90 m_images->Add(*bmp);
f857e441 91 delete bmp;
957f5ab7 92
7a8d9418 93 m_moreBmp = new wxBitmap(icon_theresmore);
f857e441
WS
94
95 // do this as last, to check if create is already called
96
7a8d9418 97 m_controlCreated = true;
957f5ab7
VZ
98}
99
100wxFoldPanelBar::~wxFoldPanelBar()
101{
7a8d9418
WS
102 delete m_images;
103 delete m_moreBmp;
957f5ab7
VZ
104}
105
106wxFoldPanel wxFoldPanelBar::AddFoldPanel(const wxString &caption, bool collapsedInitially, const wxCaptionBarStyle &style)
107{
7a8d9418 108 wxASSERT(m_controlCreated);
f857e441
WS
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.
957f5ab7 113
7a8d9418 114 wxFoldPanelItem *item = new wxFoldPanelItem(m_foldPanel, caption, m_images, collapsedInitially, style);
957f5ab7 115
f857e441 116 // look at the last added one and reposition this one
7a8d9418
WS
117 int pos = 0;
118 if(m_panels.GetCount() > 0)
119 pos = m_panels.Last()->GetItemPos() + m_panels.Last()->GetPanelLength();
957f5ab7 120
7a8d9418
WS
121 item->Reposition(pos);
122 m_panels.Add(item);
957f5ab7 123
f857e441
WS
124 //return wxFoldPanel(item);
125 return wxFoldPanel(item);
957f5ab7
VZ
126}
127
128int wxFoldPanelBar::AddFoldPanelWindow(const wxFoldPanel &panel, wxWindow *window, int flags, int ySpacing, int leftSpacing,
f857e441 129 int rightSpacing)
957f5ab7 130{
f857e441
WS
131 wxCHECK(panel.IsOk(), -1);
132 panel.GetItem()->AddWindow(window, flags, ySpacing, leftSpacing, rightSpacing);
957f5ab7 133
f857e441
WS
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.
957f5ab7 137
f857e441 138 return 0;
957f5ab7
VZ
139}
140
141int wxFoldPanelBar::AddFoldPanelSeperator(const wxFoldPanel &panel, const wxColour &color, int ySpacing, int leftSpacing,
f857e441 142 int rightSpacing)
957f5ab7 143{
f857e441
WS
144 wxCHECK(panel.IsOk(), -1);
145 panel.GetItem()->AddSeparator(color, ySpacing, leftSpacing, rightSpacing);
957f5ab7 146
f857e441 147 return 0;
957f5ab7
VZ
148}
149
150void wxFoldPanelBar::OnSizePanel(wxSizeEvent &event)
151{
f857e441 152 // skip all stuff when we are not initialised yet
957f5ab7 153
7a8d9418 154 if(!m_controlCreated)
f857e441
WS
155 {
156 event.Skip();
157 return;
158 }
957f5ab7 159
f857e441
WS
160 // now size the fold panel area and the
161 // lower bar in such a way that the bar is always
162 // visible
957f5ab7 163
f857e441
WS
164 wxRect foldrect = GetRect();
165
166 // fold panel itself. If too little space,
167 // don't show it
957f5ab7
VZ
168
169#if 0
f857e441
WS
170 if(foldrect.GetHeight() < 23)
171 foldrect.SetHeight(0);
172 else
173 foldrect.SetHeight(foldrect.GetHeight() - 22);
957f5ab7
VZ
174#endif
175
f857e441
WS
176 foldrect.SetX(0);
177 foldrect.SetY(0);
7a8d9418 178 m_foldPanel->SetSize(foldrect);
957f5ab7 179
7a8d9418 180 if(m_extraStyle & wxFPB_COLLAPSE_TO_BOTTOM)
f857e441
WS
181 {
182 wxRect rect = RepositionCollapsedToBottom();
7a8d9418
WS
183 bool vertical = IsVertical();
184 if((vertical && rect.GetHeight() > 0) || (!vertical && rect.GetWidth() > 0))
f857e441
WS
185 RefreshRect(rect);
186 }
957f5ab7 187
f857e441
WS
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
957f5ab7 190
f857e441 191 RedisplayFoldPanelItems();
957f5ab7 192
f857e441 193 // tool panel for icons and other stuff
957f5ab7
VZ
194
195#if 0
f857e441
WS
196 wxRect bottomrect = GetRect();
197 if(bottomrect.GetHeight() < 22)
198 bottomrect.SetY(0);
199 else
200 bottomrect.SetY(bottomrect.GetHeight() - 22);
957f5ab7 201
f857e441
WS
202 bottomrect.SetHeight(22);
203 bottomrect.SetX(0);
7a8d9418 204 m_bottomPanel->SetSize(bottomrect);
957f5ab7 205
f857e441
WS
206 // TODO: redraw the bitmap properly
207 // use the captionbar algorithm for that
957f5ab7 208
7a8d9418 209 m_bottomPanel->Refresh();
957f5ab7
VZ
210#endif
211}
212
213void wxFoldPanelBar::OnPaint(wxPaintEvent &event)
214{
7a8d9418 215 if(!m_controlCreated)
f857e441 216 return;
957f5ab7 217#if 0
f857e441
WS
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
957f5ab7 221
7a8d9418 222 wxPaintDC dc(m_bottomPanel);
957f5ab7 223
7a8d9418
WS
224 wxSize size = m_bottomPanel->GetSize();
225 int offset = (size.GetHeight() - m_moreBmp->GetHeight()) / 2;
957f5ab7 226
7a8d9418 227 dc.DrawBitmap(*m_moreBmp, size.GetWidth() - m_moreBmp->GetWidth() - 2, offset, true);
957f5ab7
VZ
228#endif
229
f857e441 230 event.Skip();
957f5ab7
VZ
231}
232
233void wxFoldPanelBar::OnPressCaption(wxCaptionBarEvent &event)
234{
f857e441
WS
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()));
957f5ab7
VZ
242}
243
244void wxFoldPanelBar::RefreshPanelsFrom(wxFoldPanelItem *item)
245{
f857e441 246 wxASSERT(item);
957f5ab7 247
7a8d9418 248 int i = m_panels.Index(item);
f857e441
WS
249 if(i != wxNOT_FOUND)
250 RefreshPanelsFrom(i);
957f5ab7
VZ
251}
252
253void wxFoldPanelBar::RefreshPanelsFrom(size_t i)
254{
f857e441
WS
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
7a8d9418 261 if(m_extraStyle & wxFPB_COLLAPSE_TO_BOTTOM)
f857e441
WS
262 {
263 int offset = 0;
264
7a8d9418 265 for(size_t j = 0; j < m_panels.GetCount(); j++)
f857e441 266 {
7a8d9418
WS
267 if(m_panels.Item(j)->IsExpanded())
268 offset += m_panels.Item(j)->Reposition(offset);
f857e441
WS
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 {
7a8d9418
WS
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);
f857e441
WS
281 }
282 Thaw();
957f5ab7
VZ
283}
284
285void wxFoldPanelBar::RedisplayFoldPanelItems()
286{
f857e441 287 // resize them all. No need to reposition
957f5ab7 288
f857e441 289 wxFoldPanelItem *item;
7a8d9418 290 for(size_t i = 0; i < m_panels.GetCount(); i++)
f857e441 291 {
7a8d9418 292 item = m_panels.Item(i);
f857e441 293 wxASSERT(item);
957f5ab7 294
f857e441
WS
295 item->ResizePanel();
296 }
957f5ab7
VZ
297}
298
299wxRect wxFoldPanelBar::RepositionCollapsedToBottom()
300{
f857e441 301 wxRect value(0,0,0,0);
7a8d9418 302 bool vertical = IsVertical();
f857e441
WS
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;
7a8d9418 309 GetPanelsLength(collapsed, expanded);
f857e441
WS
310
311 // if no room stick them behind the normal ones, else
312 // at the bottom
313
7a8d9418 314 if(((vertical ? GetSize().GetHeight() : GetSize().GetWidth()) - expanded - collapsed) < 0)
f857e441
WS
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
7a8d9418 322 value.SetHeight(GetSize().GetHeight());
f857e441
WS
323 value.SetWidth(GetSize().GetWidth());
324
7a8d9418
WS
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 }
f857e441 335
7a8d9418
WS
336 offset = (vertical ? GetSize().GetHeight() : GetSize().GetWidth()) - collapsed;
337 }
f857e441
WS
338
339 // go reposition
340
7a8d9418 341 for(size_t i = 0; i < m_panels.GetCount(); i++)
f857e441 342 {
7a8d9418
WS
343 if(!m_panels.Item(i)->IsExpanded())
344 offset += m_panels.Item(i)->Reposition(offset);
f857e441
WS
345 }
346
347 return value;
957f5ab7
VZ
348}
349
7a8d9418 350int wxFoldPanelBar::GetPanelsLength(int &collapsed, int &expanded)
957f5ab7 351{
f857e441
WS
352 int value = 0;
353
354 // assumed here that all the panels that are expanded
3103e8a9 355 // are positioned after each other from 0,0 to end.
f857e441 356
7a8d9418 357 for(size_t j = 0; j < m_panels.GetCount(); j++)
f857e441 358 {
7a8d9418 359 int offset = m_panels.Item(j)->GetPanelLength();
f857e441 360 value += offset;
7a8d9418 361 if(m_panels.Item(j)->IsExpanded())
f857e441
WS
362 expanded += offset;
363 else
364 collapsed += offset;
365 }
366
367 return value;
9cf662c4 368}