]> git.saurik.com Git - wxWidgets.git/blame - contrib/src/foldbar/captionbar.cpp
wxFoldBar now also horizontal (with API methods renamed to mean length rather than...
[wxWidgets.git] / contrib / src / foldbar / captionbar.cpp
CommitLineData
957f5ab7
VZ
1/////////////////////////////////////////////////////////////////////////////
2// Name: captionbar.cpp
3// Purpose: wxCaptionBar class belonging to the wxFoldPanel (but can be used independent)
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: 18/06/2004
8// RCS-ID: $Id$
957f5ab7
VZ
9// Copyright: (c) Jorgen Bodde
10// Licence: wxWindows licence
11/////////////////////////////////////////////////////////////////////////////
12
13#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
14#pragma implementation "foldpanelbar.h"
15#endif
16
17// For compilers that support precompilation, includes "wx/wx.h".
18#include "wx/wxprec.h"
19
20#ifdef __BORLANDC__
7a8d9418 21 #pragma hdrstop
957f5ab7
VZ
22#endif
23
24#ifndef WX_PRECOMP
7a8d9418 25 #include "wx/wx.h"
957f5ab7
VZ
26#endif
27
7a8d9418 28#include "wx/foldbar/foldpanelbar.h"
957f5ab7
VZ
29
30/*
31 * wxCaptionBar
32 */
33
34BEGIN_EVENT_TABLE(wxCaptionBar, wxWindow)
35 EVT_PAINT(wxCaptionBar::OnPaint)
36 EVT_CHAR(wxCaptionBar::OnChar)
37 EVT_MOUSE_EVENTS(wxCaptionBar::OnMouseEvent)
f857e441 38 EVT_SIZE(wxCaptionBar::OnSize)
957f5ab7
VZ
39END_EVENT_TABLE()
40
f857e441
WS
41wxCaptionBar::wxCaptionBar(wxWindow* parent, const wxString &caption, wxImageList *images, wxWindowID id,
42 const wxCaptionBarStyle &cbstyle, const wxPoint& pos, const wxSize& size, long style)
43 : wxWindow(parent, id, pos, size, style)
7a8d9418
WS
44 , m_caption(caption)
45 , m_foldIcons(images)
46 , m_rightIndent(wxFPB_BMP_RIGHTSPACE)
47 , m_iconWidth(16)
48 , m_iconHeight(16)
49 , m_collapsed(false)
957f5ab7 50{
f857e441
WS
51 // do initialisy thingy stuff
52
53 ApplyCaptionStyle(cbstyle, true);
54
55 // set initial size
7a8d9418 56 if(m_foldIcons)
f857e441 57 {
7a8d9418
WS
58 wxASSERT(m_foldIcons->GetImageCount() > 1);
59 m_foldIcons->GetSize(0, m_iconWidth, m_iconHeight);
f857e441 60 }
957f5ab7
VZ
61}
62
63wxCaptionBar::~wxCaptionBar()
64{
65
66}
67
68void wxCaptionBar::ApplyCaptionStyle(const wxCaptionBarStyle &cbstyle, bool applyDefault)
69{
f857e441
WS
70 wxASSERT(GetParent());
71
72 wxCaptionBarStyle newstyle = cbstyle;
73
74 // set defaults in newly created style copy if needed
75 if(applyDefault)
76 {
77 // get first colour from style or make it default
78 if(!newstyle.FirstColourUsed())
79 newstyle.SetFirstColour(*wxWHITE);
80
81 // get second colour from style or make it default
82 if(!newstyle.SecondColourUsed())
83 {
84 // make the second colour slightly darker then the background
85 wxColour col = GetParent()->GetBackgroundColour();
c193de84
WS
86 col.Set((unsigned char)((col.Red() >> 1) + 20),
87 (unsigned char)((col.Green() >> 1) + 20),
88 (unsigned char)((col.Blue() >> 1) + 20));
f857e441
WS
89 newstyle.SetSecondColour(col);
90 }
91
92 // get text colour
93 if(!newstyle.CaptionColourUsed())
94 newstyle.SetCaptionColour(*wxBLACK);
95
96 // get font colour
97 if(!newstyle.CaptionFontUsed())
98 newstyle.SetCaptionFont(GetParent()->GetFont());
99
100 // apply caption style
101 if(!newstyle.CaptionStyleUsed())
102 newstyle.SetCaptionStyle(wxCAPTIONBAR_GRADIENT_V);
103 }
104
105 // apply the style
7a8d9418 106 m_captionStyle = newstyle;
957f5ab7
VZ
107}
108
109void wxCaptionBar::OnPaint(wxPaintEvent& WXUNUSED(event))
110{
f857e441 111 wxPaintDC dc(this);
7a8d9418
WS
112 wxRect wndRect = GetRect();
113 bool vertical = IsVertical();
957f5ab7 114
f857e441
WS
115 // TODO: Maybe first a memory DC should draw all, and then paint it on the
116 // caption. This way a flickering arrow during resize is not visible
957f5ab7 117
f857e441 118 // draw basics
957f5ab7 119
f857e441 120 FillCaptionBackground(dc);
957f5ab7 121
7a8d9418
WS
122 dc.SetFont(m_captionStyle.GetCaptionFont());
123 if(vertical)
124 dc.DrawText(m_caption, 4, (wxFPB_EXTRA_Y / 2));
125 else
126 dc.DrawRotatedText(m_caption, (wxFPB_EXTRA_Y / 2) , wndRect.GetBottom() - 4 , 90 );
957f5ab7 127
f857e441
WS
128 // draw small icon, either collapsed or expanded
129 // based on the state of the bar. If we have
130 // any bmp's
957f5ab7 131
7a8d9418 132 if(m_foldIcons)
f857e441 133 {
7a8d9418 134 wxCHECK2(m_foldIcons->GetImageCount() > 1, return);
957f5ab7 135
f857e441 136 int index = 0;
7a8d9418 137 if(m_collapsed)
f857e441 138 index = 1;
957f5ab7 139
7a8d9418
WS
140 if(vertical)
141 m_foldIcons->Draw(index,
142 dc,
143 wndRect.GetRight() - m_iconWidth - m_rightIndent,
144 (wndRect.GetHeight() - m_iconHeight) / 2,
145 wxIMAGELIST_DRAW_TRANSPARENT);
146 else
147 m_foldIcons->Draw(index,
148 dc,
149 (wndRect.GetWidth() - m_iconWidth) / 2,
150 m_rightIndent,
151 wxIMAGELIST_DRAW_TRANSPARENT);
f857e441 152 }
957f5ab7
VZ
153}
154
155void wxCaptionBar::FillCaptionBackground(wxPaintDC &dc)
156{
f857e441
WS
157 // dispatch right style for caption drawing
158
7a8d9418 159 switch(m_captionStyle.GetCaptionStyle())
f857e441
WS
160 {
161 case wxCAPTIONBAR_GRADIENT_V:
7a8d9418
WS
162 if (IsVertical())
163 DrawVerticalGradient(dc, GetRect());
164 else
165 DrawHorizontalGradient(dc, GetRect());
f857e441
WS
166 break;
167 case wxCAPTIONBAR_GRADIENT_H:
7a8d9418
WS
168 if (IsVertical())
169 DrawHorizontalGradient(dc, GetRect());
170 else
171 DrawVerticalGradient(dc, GetRect());
f857e441
WS
172 break;
173 case wxCAPTIONBAR_SINGLE:
174 DrawSingleColour(dc, GetRect());
175 break;
176 case wxCAPTIONBAR_RECTANGLE:
177 case wxCAPTIONBAR_FILLED_RECTANGLE:
178 DrawSingleRectangle(dc, GetRect());
179 break;
180 default:
181 break;
182 }
957f5ab7
VZ
183}
184
185void wxCaptionBar::OnMouseEvent(wxMouseEvent& event)
186{
f857e441
WS
187 // if clicked on the arrow (single) or double on the caption
188 // we change state and an event must be fired to let this
189 // panel collapse or expand
957f5ab7 190
f857e441 191 bool send_event = false;
957f5ab7 192
7a8d9418 193 if (event.LeftDown() && m_foldIcons)
f857e441
WS
194 {
195 wxPoint pt(event.GetPosition());
196 wxRect rect = GetRect();
7a8d9418 197 bool vertical = IsVertical();
957f5ab7 198
7a8d9418
WS
199 if((vertical && pt.x > (rect.GetWidth() - m_iconWidth - m_rightIndent))||
200 (!vertical && pt.y < m_iconHeight + m_rightIndent))
f857e441
WS
201 send_event = true;
202 }
203 else if(event.LeftDClick())
204 send_event = true;
957f5ab7 205
f857e441 206 // send the collapse, expand event to the parent
957f5ab7 207
f857e441
WS
208 if(send_event)
209 {
210 wxCaptionBarEvent event(wxEVT_CAPTIONBAR);
7a8d9418 211 event.SetCaptionBar(this);
957f5ab7 212
f857e441 213 ::wxPostEvent(this, event);
957f5ab7 214
f857e441 215 }
957f5ab7
VZ
216}
217
218void wxCaptionBar::OnChar(wxKeyEvent &event)
219{
f857e441
WS
220 // TODO: Anything here?
221
222 event.Skip();
957f5ab7
VZ
223}
224
225wxSize wxCaptionBar::DoGetBestSize() const
226{
f857e441
WS
227 int x,y;
228
7a8d9418
WS
229 if(IsVertical())
230 GetTextExtent(m_caption, &x, &y);
231 else
232 GetTextExtent(m_caption, &y, &x);
f857e441 233
7a8d9418
WS
234 if(x < m_iconWidth)
235 x = m_iconWidth;
f857e441 236
7a8d9418
WS
237 if(y < m_iconHeight)
238 y = m_iconHeight;
f857e441
WS
239
240 // TODO: The extra wxFPB_EXTRA_X constants should be adjustable as well
241
242 return wxSize(x + wxFPB_EXTRA_X, y + wxFPB_EXTRA_Y);
957f5ab7
VZ
243}
244
245
246void wxCaptionBar::DrawVerticalGradient(wxDC &dc, const wxRect &rect )
247{
f857e441
WS
248 // gradient fill from colour 1 to colour 2 with top to bottom
249
250 if(rect.height < 1 || rect.width < 1)
251 return;
252
7a8d9418
WS
253 int size = rect.height;
254
f857e441
WS
255 dc.SetPen(*wxTRANSPARENT_PEN);
256
257
258 // calculate gradient coefficients
7a8d9418
WS
259 wxColour col2 = m_captionStyle.GetSecondColour(),
260 col1 = m_captionStyle.GetFirstColour();
f857e441 261
7a8d9418
WS
262 double rstep = double((col2.Red() - col1.Red())) / double(size), rf = 0,
263 gstep = double((col2.Green() - col1.Green())) / double(size), gf = 0,
264 bstep = double((col2.Blue() - col1.Blue())) / double(size), bf = 0;
f857e441
WS
265
266 wxColour currCol;
7a8d9418 267 for(int y = rect.y; y < rect.y + size; y++)
f857e441 268 {
9cf662c4
WS
269 currCol.Set(
270 (unsigned char)(col1.Red() + rf),
c193de84 271 (unsigned char)(col1.Green() + gf),
9cf662c4
WS
272 (unsigned char)(col1.Blue() + bf)
273 );
f857e441 274 dc.SetBrush( wxBrush( currCol, wxSOLID ) );
7a8d9418 275 dc.DrawRectangle( rect.x, rect.y + (y - rect.y), rect.width, size );
f857e441
WS
276 //currCol.Set(currCol.Red() + rstep, currCol.Green() + gstep, currCol.Blue() + bstep);
277 rf += rstep; gf += gstep; bf += bstep;
278 }
957f5ab7
VZ
279}
280
281void wxCaptionBar::DrawHorizontalGradient(wxDC &dc, const wxRect &rect )
282{
f857e441
WS
283 // gradient fill from colour 1 to colour 2 with left to right
284
285 if(rect.height < 1 || rect.width < 1)
286 return;
287
7a8d9418
WS
288 int size = rect.width;
289
f857e441
WS
290 dc.SetPen(*wxTRANSPARENT_PEN);
291
292 // calculate gradient coefficients
7a8d9418
WS
293 wxColour col2 = m_captionStyle.GetSecondColour(),
294 col1 = m_captionStyle.GetFirstColour();
f857e441 295
7a8d9418
WS
296 double rstep = double((col2.Red() - col1.Red())) / double(size), rf = 0,
297 gstep = double((col2.Green() - col1.Green())) / double(size), gf = 0,
298 bstep = double((col2.Blue() - col1.Blue())) / double(size), bf = 0;
f857e441
WS
299
300 wxColour currCol;
7a8d9418 301 for(int x = rect.x; x < rect.x + size; x++)
f857e441 302 {
9cf662c4 303 currCol.Set(
c193de84
WS
304 (unsigned char)(col1.Red() + rf),
305 (unsigned char)(col1.Green() + gf),
9cf662c4
WS
306 (unsigned char)(col1.Blue() + bf)
307 );
f857e441
WS
308 dc.SetBrush( wxBrush( currCol, wxSOLID ) );
309 dc.DrawRectangle( rect.x + (x - rect.x), rect.y, 1, rect.height );
310 rf += rstep; gf += gstep; bf += bstep;
311 }
957f5ab7
VZ
312}
313
314void wxCaptionBar::DrawSingleColour(wxDC &dc, const wxRect &rect )
315{
f857e441 316 // single colour fill. This is the most easy one to find
957f5ab7 317
f857e441
WS
318 if(rect.height < 1 || rect.width < 1)
319 return;
957f5ab7 320
f857e441 321 dc.SetPen(*wxTRANSPARENT_PEN);
957f5ab7 322
f857e441 323 // draw simple rectangle
7a8d9418 324 dc.SetBrush( wxBrush( m_captionStyle.GetFirstColour(), wxSOLID ) );
f857e441 325 dc.DrawRectangle( rect.x, rect.y, rect.width, rect.height );
957f5ab7
VZ
326}
327
328void wxCaptionBar::DrawSingleRectangle(wxDC &dc, const wxRect &rect )
329{
f857e441
WS
330 wxASSERT(GetParent());
331
332 // single colour fill. This is the most easy one to find
333
334 if(rect.height < 2 || rect.width < 1)
335 return;
336
337 // single frame, set up internal fill colour
338
339 wxBrush br;
340 br.SetStyle(wxSOLID);
341
7a8d9418 342 if(m_captionStyle.GetCaptionStyle() == wxCAPTIONBAR_RECTANGLE)
f857e441
WS
343 br.SetColour(GetParent()->GetBackgroundColour());
344 else
7a8d9418 345 br.SetColour(m_captionStyle.GetFirstColour());
f857e441
WS
346
347 // setup the pen frame
348
7a8d9418 349 wxPen pen(m_captionStyle.GetSecondColour());
f857e441
WS
350 dc.SetPen(pen);
351
352 dc.SetBrush( br );
353 dc.DrawRectangle( rect.x, rect.y, rect.width, rect.height - 1);
354
355 wxPen bgpen(GetParent()->GetBackgroundColour());
356 dc.SetPen(bgpen);
357 dc.DrawLine(rect.x, rect.y + rect.height - 1, rect.x + rect.width, rect.y + rect.height - 1);
957f5ab7
VZ
358}
359
360
361void wxCaptionBar::OnSize(wxSizeEvent &event)
362{
f857e441 363 wxSize size = event.GetSize();
957f5ab7 364
7a8d9418 365 if(m_foldIcons)
f857e441
WS
366 {
367 // What I am doing here is simply invalidating the part of the window exposed. So when I
368 // make a rect with as width the newly exposed part, and the x,y of the old window size origin,
369 // I don't need a bitmap calulation in it, or do I ? The bitmap needs redrawing anyway. Leave it
370 // like this until I figured it out
957f5ab7 371
f857e441 372 // set rect to redraw as old bitmap area which is entitled to redraw
957f5ab7 373
7a8d9418
WS
374 wxRect rect(size.GetWidth() - m_iconWidth - m_rightIndent, 0, m_iconWidth + m_rightIndent,
375 m_iconWidth + m_rightIndent);
957f5ab7 376
f857e441
WS
377 // adjust rectangle when more is slided so we need to redraw all
378 // the old stuff but not all (ugly flickering)
957f5ab7 379
7a8d9418 380 int diffX = size.GetWidth() - m_oldSize.GetWidth();
f857e441
WS
381 if(diffX > 1)
382 {
383 // adjust the rect with all the crap to redraw
957f5ab7 384
f857e441
WS
385 rect.SetWidth(rect.GetWidth() + diffX + 10);
386 rect.SetX(rect.GetX() - diffX - 10);
387 }
957f5ab7 388
f857e441
WS
389 RefreshRect(rect);
390 }
391 else
392 {
393 wxRect rect = GetRect();
394 RefreshRect(rect);
395 }
957f5ab7 396
7a8d9418 397 m_oldSize = size;
957f5ab7
VZ
398}
399
400void wxCaptionBar::RedrawIconBitmap()
401{
7a8d9418 402 if(m_foldIcons)
f857e441
WS
403 {
404 // invalidate the bitmap area and force a redraw
405
406 wxRect rect = GetRect();
407
7a8d9418
WS
408 rect.SetX(rect.GetWidth() - m_iconWidth - m_rightIndent);
409 rect.SetWidth(m_iconWidth + m_rightIndent);
f857e441
WS
410 RefreshRect(rect);
411 }
957f5ab7
VZ
412}
413
7a8d9418
WS
414bool wxCaptionBar::IsVertical() const
415{
416 // parent of wxCaptionBar is wxFoldPanelItem
417 // default is vertical
418 wxFoldPanelItem *bar = wxDynamicCast(GetParent(), wxFoldPanelItem);
419 wxCHECK_MSG( bar, true, _T("wrong parent") );
420 return bar->IsVertical();
421}
422
957f5ab7 423/*
f857e441 424 * wxCaptionBarEvent
957f5ab7
VZ
425 */
426
f857e441 427DEFINE_EVENT_TYPE(wxEVT_CAPTIONBAR)
957f5ab7
VZ
428
429wxCaptionBarEvent::wxCaptionBarEvent(const wxCaptionBarEvent &event)
f857e441 430 : wxCommandEvent(event)
957f5ab7 431{
7a8d9418 432 m_captionBar = event.m_captionBar;
957f5ab7
VZ
433}
434
435//DEFINE_EVENT_TYPE(wxEVT_CAPTIONBAR)
436//IMPLEMENT_DYNAMIC_CLASS(wxCaptionBarEvent, wxEvent)
f857e441 437IMPLEMENT_DYNAMIC_CLASS(wxCaptionBarEvent, wxCommandEvent)