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