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: foldpanelbar.cpp 34972 2005-07-28 23:23:27Z VZ $ 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 33IMPLEMENT_DYNAMIC_CLASS( wxFoldPanelBar, wxPanel ) 34 35BEGIN_EVENT_TABLE(wxFoldPanelBar,wxPanel) 36 EVT_SIZE(wxFoldPanelBar::OnSizePanel) 37 //EVT_PAINT(wxFoldPanelBar::OnPaint) 38 EVT_CAPTIONBAR(wxID_ANY, wxFoldPanelBar::OnPressCaption) 39END_EVENT_TABLE() 40 41wxFoldPanelBar::wxFoldPanelBar() 42 : wxPanel() 43 , m_foldPanel(NULL) 44 , m_bottomPanel(NULL) 45 , m_controlCreated(false) 46{ 47 48} 49 50wxFoldPanelBar::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 60void 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 105wxFoldPanelBar::~wxFoldPanelBar() 106{ 107 delete m_images; 108 delete m_moreBmp; 109} 110 111wxFoldPanel 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 133int 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 146int 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 155void 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 218void 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 238void 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 249void 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 258void 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 290void 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 304wxRect 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 355int 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} 374