]>
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_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 | { | |
43 | ||
44 | } | |
45 | ||
46 | wxFoldPanelBar::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 | ||
55 | void 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 | ||
100 | wxFoldPanelBar::~wxFoldPanelBar() | |
101 | { | |
102 | delete m_images; | |
103 | delete m_moreBmp; | |
104 | } | |
105 | ||
106 | wxFoldPanel 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 | ||
128 | int 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 | ||
141 | int 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 | ||
150 | void 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 | ||
213 | void 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 | ||
233 | void 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 | ||
244 | void 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 | ||
253 | void 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 | ||
285 | void 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 | ||
299 | wxRect 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 | ||
350 | int 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 | } |