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
9 // Copyright: (c) Jorgen Bodde
10 // Licence: wxWindows licence
11 /////////////////////////////////////////////////////////////////////////////
13 // For compilers that support precompilation, includes "wx/wx.h".
14 #include "wx/wxprec.h"
24 #include "wx/foldbar/foldpanelbar.h"
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
)
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
)
42 , m_rightIndent(wxFPB_BMP_RIGHTSPACE
)
47 // do initialisy thingy stuff
49 ApplyCaptionStyle(cbstyle
, true);
54 wxASSERT(m_foldIcons
->GetImageCount() > 1);
55 m_foldIcons
->GetSize(0, m_iconWidth
, m_iconHeight
);
59 wxCaptionBar::~wxCaptionBar()
64 void wxCaptionBar::ApplyCaptionStyle(const wxCaptionBarStyle
&cbstyle
, bool applyDefault
)
66 wxASSERT(GetParent());
68 wxCaptionBarStyle newstyle
= cbstyle
;
70 // set defaults in newly created style copy if needed
73 // get first colour from style or make it default
74 if(!newstyle
.FirstColourUsed())
75 newstyle
.SetFirstColour(*wxWHITE
);
77 // get second colour from style or make it default
78 if(!newstyle
.SecondColourUsed())
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
);
89 if(!newstyle
.CaptionColourUsed())
90 newstyle
.SetCaptionColour(*wxBLACK
);
93 if(!newstyle
.CaptionFontUsed())
94 newstyle
.SetCaptionFont(GetParent()->GetFont());
96 // apply caption style
97 if(!newstyle
.CaptionStyleUsed())
98 newstyle
.SetCaptionStyle(wxCAPTIONBAR_GRADIENT_V
);
102 m_captionStyle
= newstyle
;
105 void wxCaptionBar::OnPaint(wxPaintEvent
& WXUNUSED(event
))
108 wxRect wndRect
= GetRect();
109 bool vertical
= IsVertical();
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
116 FillCaptionBackground(dc
);
118 dc
.SetFont(m_captionStyle
.GetCaptionFont());
120 dc
.DrawText(m_caption
, 4, (wxFPB_EXTRA_Y
/ 2));
122 dc
.DrawRotatedText(m_caption
, (wxFPB_EXTRA_Y
/ 2) , wndRect
.GetBottom() - 4 , 90 );
124 // draw small icon, either collapsed or expanded
125 // based on the state of the bar. If we have
130 wxCHECK2(m_foldIcons
->GetImageCount() > 1, return);
137 m_foldIcons
->Draw(index
,
139 wndRect
.GetRight() - m_iconWidth
- m_rightIndent
,
140 (wndRect
.GetHeight() - m_iconHeight
) / 2,
141 wxIMAGELIST_DRAW_TRANSPARENT
);
143 m_foldIcons
->Draw(index
,
145 (wndRect
.GetWidth() - m_iconWidth
) / 2,
147 wxIMAGELIST_DRAW_TRANSPARENT
);
151 void wxCaptionBar::FillCaptionBackground(wxPaintDC
&dc
)
153 // dispatch right style for caption drawing
155 switch(m_captionStyle
.GetCaptionStyle())
157 case wxCAPTIONBAR_GRADIENT_V
:
159 DrawVerticalGradient(dc
, GetRect());
161 DrawHorizontalGradient(dc
, GetRect());
163 case wxCAPTIONBAR_GRADIENT_H
:
165 DrawHorizontalGradient(dc
, GetRect());
167 DrawVerticalGradient(dc
, GetRect());
169 case wxCAPTIONBAR_SINGLE
:
170 DrawSingleColour(dc
, GetRect());
172 case wxCAPTIONBAR_RECTANGLE
:
173 case wxCAPTIONBAR_FILLED_RECTANGLE
:
174 DrawSingleRectangle(dc
, GetRect());
181 void wxCaptionBar::OnMouseEvent(wxMouseEvent
& event
)
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
187 bool send_event
= false;
189 if (event
.LeftDown() && m_foldIcons
)
191 wxPoint
pt(event
.GetPosition());
192 wxRect rect
= GetRect();
193 bool vertical
= IsVertical();
195 if((vertical
&& pt
.x
> (rect
.GetWidth() - m_iconWidth
- m_rightIndent
))||
196 (!vertical
&& pt
.y
< m_iconHeight
+ m_rightIndent
))
199 else if(event
.LeftDClick())
202 // send the collapse, expand event to the parent
206 wxCaptionBarEvent
event(wxEVT_CAPTIONBAR
);
207 event
.SetCaptionBar(this);
209 ::wxPostEvent(this, event
);
214 void wxCaptionBar::OnChar(wxKeyEvent
&event
)
216 // TODO: Anything here?
221 wxSize
wxCaptionBar::DoGetBestSize() const
226 GetTextExtent(m_caption
, &x
, &y
);
228 GetTextExtent(m_caption
, &y
, &x
);
236 // TODO: The extra wxFPB_EXTRA_X constants should be adjustable as well
238 return wxSize(x
+ wxFPB_EXTRA_X
, y
+ wxFPB_EXTRA_Y
);
242 void wxCaptionBar::DrawVerticalGradient(wxDC
&dc
, const wxRect
&rect
)
244 // gradient fill from colour 1 to colour 2 with top to bottom
246 if(rect
.height
< 1 || rect
.width
< 1)
249 int size
= rect
.height
;
251 dc
.SetPen(*wxTRANSPARENT_PEN
);
254 // calculate gradient coefficients
255 wxColour col2
= m_captionStyle
.GetSecondColour(),
256 col1
= m_captionStyle
.GetFirstColour();
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;
263 for(int y
= rect
.y
; y
< rect
.y
+ size
; y
++)
266 (unsigned char)(col1
.Red() + rf
),
267 (unsigned char)(col1
.Green() + gf
),
268 (unsigned char)(col1
.Blue() + bf
)
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
;
277 void wxCaptionBar::DrawHorizontalGradient(wxDC
&dc
, const wxRect
&rect
)
279 // gradient fill from colour 1 to colour 2 with left to right
281 if(rect
.height
< 1 || rect
.width
< 1)
284 int size
= rect
.width
;
286 dc
.SetPen(*wxTRANSPARENT_PEN
);
288 // calculate gradient coefficients
289 wxColour col2
= m_captionStyle
.GetSecondColour(),
290 col1
= m_captionStyle
.GetFirstColour();
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;
297 for(int x
= rect
.x
; x
< rect
.x
+ size
; x
++)
300 (unsigned char)(col1
.Red() + rf
),
301 (unsigned char)(col1
.Green() + gf
),
302 (unsigned char)(col1
.Blue() + bf
)
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
;
310 void wxCaptionBar::DrawSingleColour(wxDC
&dc
, const wxRect
&rect
)
312 // single colour fill. This is the most easy one to find
314 if(rect
.height
< 1 || rect
.width
< 1)
317 dc
.SetPen(*wxTRANSPARENT_PEN
);
319 // draw simple rectangle
320 dc
.SetBrush( wxBrush( m_captionStyle
.GetFirstColour(), wxSOLID
) );
321 dc
.DrawRectangle( rect
.x
, rect
.y
, rect
.width
, rect
.height
);
324 void wxCaptionBar::DrawSingleRectangle(wxDC
&dc
, const wxRect
&rect
)
326 wxASSERT(GetParent());
328 // single colour fill. This is the most easy one to find
330 if(rect
.height
< 2 || rect
.width
< 1)
333 // single frame, set up internal fill colour
336 br
.SetStyle(wxSOLID
);
338 if(m_captionStyle
.GetCaptionStyle() == wxCAPTIONBAR_RECTANGLE
)
339 br
.SetColour(GetParent()->GetBackgroundColour());
341 br
.SetColour(m_captionStyle
.GetFirstColour());
343 // setup the pen frame
345 wxPen
pen(m_captionStyle
.GetSecondColour());
349 dc
.DrawRectangle( rect
.x
, rect
.y
, rect
.width
, rect
.height
- 1);
351 wxPen
bgpen(GetParent()->GetBackgroundColour());
353 dc
.DrawLine(rect
.x
, rect
.y
+ rect
.height
- 1, rect
.x
+ rect
.width
, rect
.y
+ rect
.height
- 1);
357 void wxCaptionBar::OnSize(wxSizeEvent
&event
)
359 wxSize size
= event
.GetSize();
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
368 // set rect to redraw as old bitmap area which is entitled to redraw
370 wxRect
rect(size
.GetWidth() - m_iconWidth
- m_rightIndent
, 0, m_iconWidth
+ m_rightIndent
,
371 m_iconWidth
+ m_rightIndent
);
373 // adjust rectangle when more is slided so we need to redraw all
374 // the old stuff but not all (ugly flickering)
376 int diffX
= size
.GetWidth() - m_oldSize
.GetWidth();
379 // adjust the rect with all the crap to redraw
381 rect
.SetWidth(rect
.GetWidth() + diffX
+ 10);
382 rect
.SetX(rect
.GetX() - diffX
- 10);
389 wxRect rect
= GetRect();
396 void wxCaptionBar::RedrawIconBitmap()
400 // invalidate the bitmap area and force a redraw
402 wxRect rect
= GetRect();
404 rect
.SetX(rect
.GetWidth() - m_iconWidth
- m_rightIndent
);
405 rect
.SetWidth(m_iconWidth
+ m_rightIndent
);
410 bool wxCaptionBar::IsVertical() const
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();
423 DEFINE_EVENT_TYPE(wxEVT_CAPTIONBAR
)
425 wxCaptionBarEvent::wxCaptionBarEvent(const wxCaptionBarEvent
&event
)
426 : wxCommandEvent(event
)
428 m_captionBar
= event
.m_captionBar
;
431 //DEFINE_EVENT_TYPE(wxEVT_CAPTIONBAR)
432 //IMPLEMENT_DYNAMIC_CLASS(wxCaptionBarEvent, wxEvent)
433 IMPLEMENT_DYNAMIC_CLASS(wxCaptionBarEvent
, wxCommandEvent
)