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