]> git.saurik.com Git - wxWidgets.git/blob - contrib/src/foldbar/captionbar.cpp
Only support detection of "near the edge" coordinates, if dragging grid lines
[wxWidgets.git] / contrib / src / foldbar / captionbar.cpp
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: ABX - 19/12/2004 : possibility of horizontal orientation
6 // : wxWidgets coding standards
7 // Created: 18/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
26 /*
27 * wxCaptionBar
28 */
29
30 BEGIN_EVENT_TABLE(wxCaptionBar, wxWindow)
31 EVT_PAINT(wxCaptionBar::OnPaint)
32 EVT_CHAR(wxCaptionBar::OnChar)
33 EVT_MOUSE_EVENTS(wxCaptionBar::OnMouseEvent)
34 EVT_SIZE(wxCaptionBar::OnSize)
35 END_EVENT_TABLE()
36
37 wxCaptionBar::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)
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)
46 {
47 // do initialisy thingy stuff
48
49 ApplyCaptionStyle(cbstyle, true);
50
51 // set initial size
52 if(m_foldIcons)
53 {
54 wxASSERT(m_foldIcons->GetImageCount() > 1);
55 m_foldIcons->GetSize(0, m_iconWidth, m_iconHeight);
56 }
57 }
58
59 wxCaptionBar::~wxCaptionBar()
60 {
61
62 }
63
64 void wxCaptionBar::ApplyCaptionStyle(const wxCaptionBarStyle &cbstyle, bool applyDefault)
65 {
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();
82 col.Set((unsigned char)((col.Red() >> 1) + 20),
83 (unsigned char)((col.Green() >> 1) + 20),
84 (unsigned char)((col.Blue() >> 1) + 20));
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
102 m_captionStyle = newstyle;
103 }
104
105 void wxCaptionBar::OnPaint(wxPaintEvent& WXUNUSED(event))
106 {
107 wxPaintDC dc(this);
108 wxRect wndRect = GetRect();
109 bool vertical = IsVertical();
110
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
113
114 // draw basics
115
116 FillCaptionBackground(dc);
117
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 );
123
124 // draw small icon, either collapsed or expanded
125 // based on the state of the bar. If we have
126 // any bmp's
127
128 if(m_foldIcons)
129 {
130 wxCHECK2(m_foldIcons->GetImageCount() > 1, return);
131
132 int index = 0;
133 if(m_collapsed)
134 index = 1;
135
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);
148 }
149 }
150
151 void wxCaptionBar::FillCaptionBackground(wxPaintDC &dc)
152 {
153 // dispatch right style for caption drawing
154
155 switch(m_captionStyle.GetCaptionStyle())
156 {
157 case wxCAPTIONBAR_GRADIENT_V:
158 if (IsVertical())
159 DrawVerticalGradient(dc, GetRect());
160 else
161 DrawHorizontalGradient(dc, GetRect());
162 break;
163 case wxCAPTIONBAR_GRADIENT_H:
164 if (IsVertical())
165 DrawHorizontalGradient(dc, GetRect());
166 else
167 DrawVerticalGradient(dc, GetRect());
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 }
179 }
180
181 void wxCaptionBar::OnMouseEvent(wxMouseEvent& event)
182 {
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
186
187 bool send_event = false;
188
189 if (event.LeftDown() && m_foldIcons)
190 {
191 wxPoint pt(event.GetPosition());
192 wxRect rect = GetRect();
193 bool vertical = IsVertical();
194
195 if((vertical && pt.x > (rect.GetWidth() - m_iconWidth - m_rightIndent))||
196 (!vertical && pt.y < m_iconHeight + m_rightIndent))
197 send_event = true;
198 }
199 else if(event.LeftDClick())
200 send_event = true;
201
202 // send the collapse, expand event to the parent
203
204 if(send_event)
205 {
206 wxCaptionBarEvent event(wxEVT_CAPTIONBAR);
207 event.SetCaptionBar(this);
208
209 ::wxPostEvent(this, event);
210
211 }
212 }
213
214 void wxCaptionBar::OnChar(wxKeyEvent &event)
215 {
216 // TODO: Anything here?
217
218 event.Skip();
219 }
220
221 wxSize wxCaptionBar::DoGetBestSize() const
222 {
223 int x,y;
224
225 if(IsVertical())
226 GetTextExtent(m_caption, &x, &y);
227 else
228 GetTextExtent(m_caption, &y, &x);
229
230 if(x < m_iconWidth)
231 x = m_iconWidth;
232
233 if(y < m_iconHeight)
234 y = m_iconHeight;
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);
239 }
240
241
242 void wxCaptionBar::DrawVerticalGradient(wxDC &dc, const wxRect &rect )
243 {
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
249 int size = rect.height;
250
251 dc.SetPen(*wxTRANSPARENT_PEN);
252
253
254 // calculate gradient coefficients
255 wxColour col2 = m_captionStyle.GetSecondColour(),
256 col1 = m_captionStyle.GetFirstColour();
257
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;
261
262 wxColour currCol;
263 for(int y = rect.y; y < rect.y + size; y++)
264 {
265 currCol.Set(
266 (unsigned char)(col1.Red() + rf),
267 (unsigned char)(col1.Green() + gf),
268 (unsigned char)(col1.Blue() + bf)
269 );
270 dc.SetBrush( wxBrush( currCol, wxSOLID ) );
271 dc.DrawRectangle( rect.x, rect.y + (y - rect.y), rect.width, size );
272 //currCol.Set(currCol.Red() + rstep, currCol.Green() + gstep, currCol.Blue() + bstep);
273 rf += rstep; gf += gstep; bf += bstep;
274 }
275 }
276
277 void wxCaptionBar::DrawHorizontalGradient(wxDC &dc, const wxRect &rect )
278 {
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
284 int size = rect.width;
285
286 dc.SetPen(*wxTRANSPARENT_PEN);
287
288 // calculate gradient coefficients
289 wxColour col2 = m_captionStyle.GetSecondColour(),
290 col1 = m_captionStyle.GetFirstColour();
291
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;
295
296 wxColour currCol;
297 for(int x = rect.x; x < rect.x + size; x++)
298 {
299 currCol.Set(
300 (unsigned char)(col1.Red() + rf),
301 (unsigned char)(col1.Green() + gf),
302 (unsigned char)(col1.Blue() + bf)
303 );
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 }
308 }
309
310 void wxCaptionBar::DrawSingleColour(wxDC &dc, const wxRect &rect )
311 {
312 // single colour fill. This is the most easy one to find
313
314 if(rect.height < 1 || rect.width < 1)
315 return;
316
317 dc.SetPen(*wxTRANSPARENT_PEN);
318
319 // draw simple rectangle
320 dc.SetBrush( wxBrush( m_captionStyle.GetFirstColour(), wxSOLID ) );
321 dc.DrawRectangle( rect.x, rect.y, rect.width, rect.height );
322 }
323
324 void wxCaptionBar::DrawSingleRectangle(wxDC &dc, const wxRect &rect )
325 {
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
338 if(m_captionStyle.GetCaptionStyle() == wxCAPTIONBAR_RECTANGLE)
339 br.SetColour(GetParent()->GetBackgroundColour());
340 else
341 br.SetColour(m_captionStyle.GetFirstColour());
342
343 // setup the pen frame
344
345 wxPen pen(m_captionStyle.GetSecondColour());
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);
354 }
355
356
357 void wxCaptionBar::OnSize(wxSizeEvent &event)
358 {
359 wxSize size = event.GetSize();
360
361 if(m_foldIcons)
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
367
368 // set rect to redraw as old bitmap area which is entitled to redraw
369
370 wxRect rect(size.GetWidth() - m_iconWidth - m_rightIndent, 0, m_iconWidth + m_rightIndent,
371 m_iconWidth + m_rightIndent);
372
373 // adjust rectangle when more is slided so we need to redraw all
374 // the old stuff but not all (ugly flickering)
375
376 int diffX = size.GetWidth() - m_oldSize.GetWidth();
377 if(diffX > 1)
378 {
379 // adjust the rect with all the crap to redraw
380
381 rect.SetWidth(rect.GetWidth() + diffX + 10);
382 rect.SetX(rect.GetX() - diffX - 10);
383 }
384
385 RefreshRect(rect);
386 }
387 else
388 {
389 wxRect rect = GetRect();
390 RefreshRect(rect);
391 }
392
393 m_oldSize = size;
394 }
395
396 void wxCaptionBar::RedrawIconBitmap()
397 {
398 if(m_foldIcons)
399 {
400 // invalidate the bitmap area and force a redraw
401
402 wxRect rect = GetRect();
403
404 rect.SetX(rect.GetWidth() - m_iconWidth - m_rightIndent);
405 rect.SetWidth(m_iconWidth + m_rightIndent);
406 RefreshRect(rect);
407 }
408 }
409
410 bool 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
419 /*
420 * wxCaptionBarEvent
421 */
422
423 DEFINE_EVENT_TYPE(wxEVT_CAPTIONBAR)
424
425 wxCaptionBarEvent::wxCaptionBarEvent(const wxCaptionBarEvent &event)
426 : wxCommandEvent(event)
427 {
428 m_captionBar = event.m_captionBar;
429 }
430
431 //DEFINE_EVENT_TYPE(wxEVT_CAPTIONBAR)
432 //IMPLEMENT_DYNAMIC_CLASS(wxCaptionBarEvent, wxEvent)
433 IMPLEMENT_DYNAMIC_CLASS(wxCaptionBarEvent, wxCommandEvent)