]>
Commit | Line | Data |
---|---|---|
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_DYNAMIC_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 | : wxPanel() | |
43 | , m_foldPanel(NULL) | |
44 | , m_bottomPanel(NULL) | |
45 | , m_controlCreated(false) | |
46 | { | |
47 | ||
48 | } | |
49 | ||
50 | wxFoldPanelBar::wxFoldPanelBar( wxWindow *parent, wxWindowID id, const wxPoint &position, | |
51 | const wxSize& size, long style, long extraStyle) | |
52 | : wxPanel() | |
53 | , m_foldPanel(NULL) | |
54 | , m_bottomPanel(NULL) | |
55 | , m_controlCreated(false) | |
56 | { | |
57 | Create( parent, id, position, size, style, extraStyle); | |
58 | } | |
59 | ||
60 | void wxFoldPanelBar::Create( wxWindow *parent, wxWindowID id, const wxPoint &position, | |
61 | const wxSize& size, long style, long extraStyle ) | |
62 | { | |
63 | ||
64 | m_extraStyle = extraStyle; | |
65 | ||
66 | // make sure there is any orientation | |
67 | if ( ( style & wxFPB_HORIZONTAL ) != wxFPB_HORIZONTAL ) | |
68 | style |= wxFPB_VERTICAL; | |
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 | ||
77 | m_foldPanel = new wxPanel(this, wxID_ANY, position, size, wxNO_BORDER|wxTAB_TRAVERSAL); | |
78 | ||
79 | // the extra area for some icons / context menu etc | |
80 | ||
81 | #if 0 | |
82 | m_bottomPanel = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(wxDefaultCoord,22), wxNO_BORDER|wxTAB_TRAVERSAL); | |
83 | m_bottomPanel->SetBackgroundColour(*wxWHITE); | |
84 | #endif | |
85 | ||
86 | // create the fold icons to be used in the captions | |
87 | ||
88 | m_images = new wxImageList(16, 16); | |
89 | ||
90 | wxBitmap *bmp = new wxBitmap(icon_expanded); | |
91 | m_images->Add(*bmp); | |
92 | delete bmp; | |
93 | ||
94 | bmp = new wxBitmap(icon_collapsed); | |
95 | m_images->Add(*bmp); | |
96 | delete bmp; | |
97 | ||
98 | m_moreBmp = new wxBitmap(icon_theresmore); | |
99 | ||
100 | // do this as last, to check if create is already called | |
101 | ||
102 | m_controlCreated = true; | |
103 | } | |
104 | ||
105 | wxFoldPanelBar::~wxFoldPanelBar() | |
106 | { | |
107 | delete m_images; | |
108 | delete m_moreBmp; | |
109 | } | |
110 | ||
111 | wxFoldPanel wxFoldPanelBar::AddFoldPanel(const wxString &caption, bool collapsedInitially, const wxCaptionBarStyle &style) | |
112 | { | |
113 | wxASSERT(m_controlCreated); | |
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. | |
118 | ||
119 | wxFoldPanelItem *item = new wxFoldPanelItem(m_foldPanel, caption, m_images, collapsedInitially, style); | |
120 | ||
121 | // look at the last added one and reposition this one | |
122 | int pos = 0; | |
123 | if(m_panels.GetCount() > 0) | |
124 | pos = m_panels.Last()->GetItemPos() + m_panels.Last()->GetPanelLength(); | |
125 | ||
126 | item->Reposition(pos); | |
127 | m_panels.Add(item); | |
128 | ||
129 | //return wxFoldPanel(item); | |
130 | return wxFoldPanel(item); | |
131 | } | |
132 | ||
133 | int wxFoldPanelBar::AddFoldPanelWindow(const wxFoldPanel &panel, wxWindow *window, int flags, int ySpacing, int leftSpacing, | |
134 | int rightSpacing) | |
135 | { | |
136 | wxCHECK(panel.IsOk(), -1); | |
137 | panel.GetItem()->AddWindow(window, flags, ySpacing, leftSpacing, rightSpacing); | |
138 | ||
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. | |
142 | ||
143 | return 0; | |
144 | } | |
145 | ||
146 | int wxFoldPanelBar::AddFoldPanelSeperator(const wxFoldPanel &panel, const wxColour &color, int ySpacing, int leftSpacing, | |
147 | int rightSpacing) | |
148 | { | |
149 | wxCHECK(panel.IsOk(), -1); | |
150 | panel.GetItem()->AddSeparator(color, ySpacing, leftSpacing, rightSpacing); | |
151 | ||
152 | return 0; | |
153 | } | |
154 | ||
155 | void wxFoldPanelBar::OnSizePanel(wxSizeEvent &event) | |
156 | { | |
157 | // skip all stuff when we are not initialised yet | |
158 | ||
159 | if(!m_controlCreated) | |
160 | { | |
161 | event.Skip(); | |
162 | return; | |
163 | } | |
164 | ||
165 | // now size the fold panel area and the | |
166 | // lower bar in such a way that the bar is always | |
167 | // visible | |
168 | ||
169 | wxRect foldrect = GetRect(); | |
170 | ||
171 | // fold panel itself. If too little space, | |
172 | // don't show it | |
173 | ||
174 | #if 0 | |
175 | if(foldrect.GetHeight() < 23) | |
176 | foldrect.SetHeight(0); | |
177 | else | |
178 | foldrect.SetHeight(foldrect.GetHeight() - 22); | |
179 | #endif | |
180 | ||
181 | foldrect.SetX(0); | |
182 | foldrect.SetY(0); | |
183 | m_foldPanel->SetSize(foldrect); | |
184 | ||
185 | if(m_extraStyle & wxFPB_COLLAPSE_TO_BOTTOM) | |
186 | { | |
187 | wxRect rect = RepositionCollapsedToBottom(); | |
188 | bool vertical = IsVertical(); | |
189 | if((vertical && rect.GetHeight() > 0) || (!vertical && rect.GetWidth() > 0)) | |
190 | RefreshRect(rect); | |
191 | } | |
192 | ||
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 | |
195 | ||
196 | RedisplayFoldPanelItems(); | |
197 | ||
198 | // tool panel for icons and other stuff | |
199 | ||
200 | #if 0 | |
201 | wxRect bottomrect = GetRect(); | |
202 | if(bottomrect.GetHeight() < 22) | |
203 | bottomrect.SetY(0); | |
204 | else | |
205 | bottomrect.SetY(bottomrect.GetHeight() - 22); | |
206 | ||
207 | bottomrect.SetHeight(22); | |
208 | bottomrect.SetX(0); | |
209 | m_bottomPanel->SetSize(bottomrect); | |
210 | ||
211 | // TODO: redraw the bitmap properly | |
212 | // use the captionbar algorithm for that | |
213 | ||
214 | m_bottomPanel->Refresh(); | |
215 | #endif | |
216 | } | |
217 | ||
218 | void wxFoldPanelBar::OnPaint(wxPaintEvent &event) | |
219 | { | |
220 | if(!m_controlCreated) | |
221 | return; | |
222 | #if 0 | |
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 | |
226 | ||
227 | wxPaintDC dc(m_bottomPanel); | |
228 | ||
229 | wxSize size = m_bottomPanel->GetSize(); | |
230 | int offset = (size.GetHeight() - m_moreBmp->GetHeight()) / 2; | |
231 | ||
232 | dc.DrawBitmap(*m_moreBmp, size.GetWidth() - m_moreBmp->GetWidth() - 2, offset, true); | |
233 | #endif | |
234 | ||
235 | event.Skip(); | |
236 | } | |
237 | ||
238 | void wxFoldPanelBar::OnPressCaption(wxCaptionBarEvent &event) | |
239 | { | |
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())); | |
247 | } | |
248 | ||
249 | void wxFoldPanelBar::RefreshPanelsFrom(wxFoldPanelItem *item) | |
250 | { | |
251 | wxASSERT(item); | |
252 | ||
253 | int i = m_panels.Index(item); | |
254 | if(i != wxNOT_FOUND) | |
255 | RefreshPanelsFrom(i); | |
256 | } | |
257 | ||
258 | void wxFoldPanelBar::RefreshPanelsFrom(size_t i) | |
259 | { | |
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 | ||
266 | if(m_extraStyle & wxFPB_COLLAPSE_TO_BOTTOM) | |
267 | { | |
268 | int offset = 0; | |
269 | ||
270 | for(size_t j = 0; j < m_panels.GetCount(); j++) | |
271 | { | |
272 | if(m_panels.Item(j)->IsExpanded()) | |
273 | offset += m_panels.Item(j)->Reposition(offset); | |
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 | { | |
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); | |
286 | } | |
287 | Thaw(); | |
288 | } | |
289 | ||
290 | void wxFoldPanelBar::RedisplayFoldPanelItems() | |
291 | { | |
292 | // resize them all. No need to reposition | |
293 | ||
294 | wxFoldPanelItem *item; | |
295 | for(size_t i = 0; i < m_panels.GetCount(); i++) | |
296 | { | |
297 | item = m_panels.Item(i); | |
298 | wxASSERT(item); | |
299 | ||
300 | item->ResizePanel(); | |
301 | } | |
302 | } | |
303 | ||
304 | wxRect wxFoldPanelBar::RepositionCollapsedToBottom() | |
305 | { | |
306 | wxRect value(0,0,0,0); | |
307 | bool vertical = IsVertical(); | |
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; | |
314 | GetPanelsLength(collapsed, expanded); | |
315 | ||
316 | // if no room stick them behind the normal ones, else | |
317 | // at the bottom | |
318 | ||
319 | if(((vertical ? GetSize().GetHeight() : GetSize().GetWidth()) - expanded - collapsed) < 0) | |
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 | ||
327 | value.SetHeight(GetSize().GetHeight()); | |
328 | value.SetWidth(GetSize().GetWidth()); | |
329 | ||
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 | } | |
340 | ||
341 | offset = (vertical ? GetSize().GetHeight() : GetSize().GetWidth()) - collapsed; | |
342 | } | |
343 | ||
344 | // go reposition | |
345 | ||
346 | for(size_t i = 0; i < m_panels.GetCount(); i++) | |
347 | { | |
348 | if(!m_panels.Item(i)->IsExpanded()) | |
349 | offset += m_panels.Item(i)->Reposition(offset); | |
350 | } | |
351 | ||
352 | return value; | |
353 | } | |
354 | ||
355 | int wxFoldPanelBar::GetPanelsLength(int &collapsed, int &expanded) | |
356 | { | |
357 | int value = 0; | |
358 | ||
359 | // assumed here that all the panels that are expanded | |
360 | // are positioned after each other from 0,0 to end. | |
361 | ||
362 | for(size_t j = 0; j < m_panels.GetCount(); j++) | |
363 | { | |
364 | int offset = m_panels.Item(j)->GetPanelLength(); | |
365 | value += offset; | |
366 | if(m_panels.Item(j)->IsExpanded()) | |
367 | expanded += offset; | |
368 | else | |
369 | collapsed += offset; | |
370 | } | |
371 | ||
372 | return value; | |
373 | } |