1 /////////////////////////////////////////////////////////////////////////////
2 // Name: captionbar.cpp
3 // Purpose: wxCaptionBar class belonging to the wxFoldPanel (but can be used independent)
4 // Author: Jorgen Bodde
8 // Copyright: (c) Jorgen Bodde
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
13 #pragma implementation "foldpanelbar.h"
16 // For compilers that support precompilation, includes "wx/wx.h".
17 #include "wx/wxprec.h"
24 #include "wx/dcmemory.h"
25 #include "wx/dcclient.h"
30 #include "wx/foldbar/captionbar.h"
36 BEGIN_EVENT_TABLE(wxCaptionBar
, wxWindow
)
37 EVT_PAINT(wxCaptionBar::OnPaint
)
38 EVT_CHAR(wxCaptionBar::OnChar
)
39 EVT_MOUSE_EVENTS(wxCaptionBar::OnMouseEvent
)
40 EVT_SIZE(wxCaptionBar::OnSize
)
43 wxCaptionBar::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
)
48 , _rightIndent(wxFPB_BMP_RIGHTSPACE
)
53 // do initialisy thingy stuff
55 ApplyCaptionStyle(cbstyle
, true);
60 wxASSERT(_foldIcons
->GetImageCount() > 1);
61 _foldIcons
->GetSize(0, _iconWidth
, _iconHeight
);
65 wxCaptionBar::~wxCaptionBar()
70 void wxCaptionBar::ApplyCaptionStyle(const wxCaptionBarStyle
&cbstyle
, bool applyDefault
)
72 wxASSERT(GetParent());
74 wxCaptionBarStyle newstyle
= cbstyle
;
76 // set defaults in newly created style copy if needed
79 // get first colour from style or make it default
80 if(!newstyle
.FirstColourUsed())
81 newstyle
.SetFirstColour(*wxWHITE
);
83 // get second colour from style or make it default
84 if(!newstyle
.SecondColourUsed())
86 // make the second colour slightly darker then the background
87 wxColour col
= GetParent()->GetBackgroundColour();
88 col
.Set((unsigned char)((col
.Red() >> 1) + 20),
89 (unsigned char)((col
.Green() >> 1) + 20),
90 (unsigned char)((col
.Blue() >> 1) + 20));
91 newstyle
.SetSecondColour(col
);
95 if(!newstyle
.CaptionColourUsed())
96 newstyle
.SetCaptionColour(*wxBLACK
);
99 if(!newstyle
.CaptionFontUsed())
100 newstyle
.SetCaptionFont(GetParent()->GetFont());
102 // apply caption style
103 if(!newstyle
.CaptionStyleUsed())
104 newstyle
.SetCaptionStyle(wxCAPTIONBAR_GRADIENT_V
);
111 void wxCaptionBar::OnPaint(wxPaintEvent
& WXUNUSED(event
))
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
120 FillCaptionBackground(dc
);
122 dc
.SetFont(_style
.GetCaptionFont());
123 dc
.DrawText(_caption
, 4, (wxFPB_EXTRA_Y
/ 2));
125 // draw small icon, either collapsed or expanded
126 // based on the state of the bar. If we have
131 wxCHECK2(_foldIcons
->GetImageCount() > 1, return);
137 wxRect wndRect
= GetRect();
138 _foldIcons
->Draw(index
, dc
, wndRect
.GetRight() - _iconWidth
- _rightIndent
, (wndRect
.GetHeight() - _iconHeight
) / 2,
139 wxIMAGELIST_DRAW_TRANSPARENT
);
143 void wxCaptionBar::FillCaptionBackground(wxPaintDC
&dc
)
145 // dispatch right style for caption drawing
147 switch(_style
.GetCaptionStyle())
149 case wxCAPTIONBAR_GRADIENT_V
:
150 DrawVerticalGradient(dc
, GetRect());
152 case wxCAPTIONBAR_GRADIENT_H
:
153 DrawHorizontalGradient(dc
, GetRect());
155 case wxCAPTIONBAR_SINGLE
:
156 DrawSingleColour(dc
, GetRect());
158 case wxCAPTIONBAR_RECTANGLE
:
159 case wxCAPTIONBAR_FILLED_RECTANGLE
:
160 DrawSingleRectangle(dc
, GetRect());
167 void wxCaptionBar::OnMouseEvent(wxMouseEvent
& event
)
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
173 bool send_event
= false;
175 if (event
.LeftDown() && _foldIcons
)
177 wxPoint
pt(event
.GetPosition());
178 wxRect rect
= GetRect();
180 if(pt
.x
> (rect
.GetWidth() - _iconWidth
- _rightIndent
))
183 else if(event
.LeftDClick())
186 // send the collapse, expand event to the parent
190 wxCaptionBarEvent
event(wxEVT_CAPTIONBAR
);
193 ::wxPostEvent(this, event
);
198 void wxCaptionBar::OnChar(wxKeyEvent
&event
)
200 // TODO: Anything here?
205 wxSize
wxCaptionBar::DoGetBestSize() const
209 GetTextExtent(_caption
, &x
, &y
);
217 // TODO: The extra wxFPB_EXTRA_X constants should be adjustable as well
219 return wxSize(x
+ wxFPB_EXTRA_X
, y
+ wxFPB_EXTRA_Y
);
223 void wxCaptionBar::DrawVerticalGradient(wxDC
&dc
, const wxRect
&rect
)
225 // gradient fill from colour 1 to colour 2 with top to bottom
227 if(rect
.height
< 1 || rect
.width
< 1)
230 dc
.SetPen(*wxTRANSPARENT_PEN
);
233 // calculate gradient coefficients
234 wxColour col2
= _style
.GetSecondColour(),
235 col1
= _style
.GetFirstColour();
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;
242 for(int y
= rect
.y
; y
< rect
.y
+ rect
.height
; y
++)
245 (unsigned char)(col1
.Red() + rf
),
246 (unsigned char)(col1
.Green() + gf
),
247 (unsigned char)(col1
.Blue() + bf
)
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
;
256 void wxCaptionBar::DrawHorizontalGradient(wxDC
&dc
, const wxRect
&rect
)
258 // gradient fill from colour 1 to colour 2 with left to right
260 if(rect
.height
< 1 || rect
.width
< 1)
263 dc
.SetPen(*wxTRANSPARENT_PEN
);
265 // calculate gradient coefficients
266 wxColour col2
= _style
.GetSecondColour(),
267 col1
= _style
.GetFirstColour();
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;
274 for(int x
= rect
.x
; x
< rect
.x
+ rect
.width
; x
++)
277 (unsigned char)(col1
.Red() + rf
),
278 (unsigned char)(col1
.Green() + gf
),
279 (unsigned char)(col1
.Blue() + bf
)
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
;
287 void wxCaptionBar::DrawSingleColour(wxDC
&dc
, const wxRect
&rect
)
289 // single colour fill. This is the most easy one to find
291 if(rect
.height
< 1 || rect
.width
< 1)
294 dc
.SetPen(*wxTRANSPARENT_PEN
);
296 // draw simple rectangle
297 dc
.SetBrush( wxBrush( _style
.GetFirstColour(), wxSOLID
) );
298 dc
.DrawRectangle( rect
.x
, rect
.y
, rect
.width
, rect
.height
);
301 void wxCaptionBar::DrawSingleRectangle(wxDC
&dc
, const wxRect
&rect
)
303 wxASSERT(GetParent());
305 // single colour fill. This is the most easy one to find
307 if(rect
.height
< 2 || rect
.width
< 1)
310 // single frame, set up internal fill colour
313 br
.SetStyle(wxSOLID
);
315 if(_style
.GetCaptionStyle() == wxCAPTIONBAR_RECTANGLE
)
316 br
.SetColour(GetParent()->GetBackgroundColour());
318 br
.SetColour(_style
.GetFirstColour());
320 // setup the pen frame
322 wxPen
pen(_style
.GetSecondColour());
326 dc
.DrawRectangle( rect
.x
, rect
.y
, rect
.width
, rect
.height
- 1);
328 wxPen
bgpen(GetParent()->GetBackgroundColour());
330 dc
.DrawLine(rect
.x
, rect
.y
+ rect
.height
- 1, rect
.x
+ rect
.width
, rect
.y
+ rect
.height
- 1);
334 void wxCaptionBar::OnSize(wxSizeEvent
&event
)
336 wxSize size
= event
.GetSize();
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
345 // set rect to redraw as old bitmap area which is entitled to redraw
347 wxRect
rect(size
.GetWidth() - _iconWidth
- _rightIndent
, 0, _iconWidth
+ _rightIndent
,
348 _iconWidth
+ _rightIndent
);
350 // adjust rectangle when more is slided so we need to redraw all
351 // the old stuff but not all (ugly flickering)
353 int diffX
= size
.GetWidth() - _oldSize
.GetWidth();
356 // adjust the rect with all the crap to redraw
358 rect
.SetWidth(rect
.GetWidth() + diffX
+ 10);
359 rect
.SetX(rect
.GetX() - diffX
- 10);
366 wxRect rect
= GetRect();
373 void wxCaptionBar::RedrawIconBitmap()
377 // invalidate the bitmap area and force a redraw
379 wxRect rect
= GetRect();
381 rect
.SetX(rect
.GetWidth() - _iconWidth
- _rightIndent
);
382 rect
.SetWidth(_iconWidth
+ _rightIndent
);
391 DEFINE_EVENT_TYPE(wxEVT_CAPTIONBAR
)
393 wxCaptionBarEvent::wxCaptionBarEvent(const wxCaptionBarEvent
&event
)
394 : wxCommandEvent(event
)
399 //DEFINE_EVENT_TYPE(wxEVT_CAPTIONBAR)
400 //IMPLEMENT_DYNAMIC_CLASS(wxCaptionBarEvent, wxEvent)
401 IMPLEMENT_DYNAMIC_CLASS(wxCaptionBarEvent
, wxCommandEvent
)