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