]>
Commit | Line | Data |
---|---|---|
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 | ||
33 | IMPLEMENT_CLASS( wxFoldPanelBar, wxPanel ) | |
34 | ||
35 | BEGIN_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 |
39 | END_EVENT_TABLE() |
40 | ||
41 | wxFoldPanelBar::wxFoldPanelBar() | |
42 | { | |
43 | ||
44 | } | |
45 | ||
f857e441 WS |
46 | wxFoldPanelBar::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 |
55 | void 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 | ||
100 | wxFoldPanelBar::~wxFoldPanelBar() | |
101 | { | |
7a8d9418 WS |
102 | delete m_images; |
103 | delete m_moreBmp; | |
957f5ab7 VZ |
104 | } |
105 | ||
106 | wxFoldPanel 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 | ||
128 | int 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 | ||
141 | int 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 | ||
150 | void 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 | ||
213 | void 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 | ||
233 | void 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 | ||
244 | void 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 | ||
253 | void 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 | ||
285 | void 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 | ||
299 | wxRect 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 | 350 | int 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 | |
355 | // are positioned after eachother from 0,0 to end. | |
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 | } |