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 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
14 #pragma implementation "foldpanelbar.h"
17 // For compilers that support precompilation, includes "wx/wx.h".
18 #include "wx/wxprec.h"
28 #include "wx/foldbar/foldpanelbar.h"
34 BEGIN_EVENT_TABLE(wxCaptionBar
, wxWindow
)
35 EVT_PAINT(wxCaptionBar::OnPaint
)
36 EVT_CHAR(wxCaptionBar::OnChar
)
37 EVT_MOUSE_EVENTS(wxCaptionBar::OnMouseEvent
)
38 EVT_SIZE(wxCaptionBar::OnSize
)
41 wxCaptionBar::wxCaptionBar(wxWindow
* parent
, const wxString
&caption
, wxImageList
*images
, wxWindowID id
,
42 const wxCaptionBarStyle
&cbstyle
, const wxPoint
& pos
, const wxSize
& size
, long style
)
43 : wxWindow(parent
, id
, pos
, size
, style
)
46 , m_rightIndent(wxFPB_BMP_RIGHTSPACE
)
51 // do initialisy thingy stuff
53 ApplyCaptionStyle(cbstyle
, true);
58 wxASSERT(m_foldIcons
->GetImageCount() > 1);
59 m_foldIcons
->GetSize(0, m_iconWidth
, m_iconHeight
);
63 wxCaptionBar::~wxCaptionBar()
68 void wxCaptionBar::ApplyCaptionStyle(const wxCaptionBarStyle
&cbstyle
, bool applyDefault
)
70 wxASSERT(GetParent());
72 wxCaptionBarStyle newstyle
= cbstyle
;
74 // set defaults in newly created style copy if needed
77 // get first colour from style or make it default
78 if(!newstyle
.FirstColourUsed())
79 newstyle
.SetFirstColour(*wxWHITE
);
81 // get second colour from style or make it default
82 if(!newstyle
.SecondColourUsed())
84 // make the second colour slightly darker then the background
85 wxColour col
= GetParent()->GetBackgroundColour();
86 col
.Set((unsigned char)((col
.Red() >> 1) + 20),
87 (unsigned char)((col
.Green() >> 1) + 20),
88 (unsigned char)((col
.Blue() >> 1) + 20));
89 newstyle
.SetSecondColour(col
);
93 if(!newstyle
.CaptionColourUsed())
94 newstyle
.SetCaptionColour(*wxBLACK
);
97 if(!newstyle
.CaptionFontUsed())
98 newstyle
.SetCaptionFont(GetParent()->GetFont());
100 // apply caption style
101 if(!newstyle
.CaptionStyleUsed())
102 newstyle
.SetCaptionStyle(wxCAPTIONBAR_GRADIENT_V
);
106 m_captionStyle
= newstyle
;
109 void wxCaptionBar::OnPaint(wxPaintEvent
& WXUNUSED(event
))
112 wxRect wndRect
= GetRect();
113 bool vertical
= IsVertical();
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(m_captionStyle
.GetCaptionFont());
124 dc
.DrawText(m_caption
, 4, (wxFPB_EXTRA_Y
/ 2));
126 dc
.DrawRotatedText(m_caption
, (wxFPB_EXTRA_Y
/ 2) , wndRect
.GetBottom() - 4 , 90 );
128 // draw small icon, either collapsed or expanded
129 // based on the state of the bar. If we have
134 wxCHECK2(m_foldIcons
->GetImageCount() > 1, return);
141 m_foldIcons
->Draw(index
,
143 wndRect
.GetRight() - m_iconWidth
- m_rightIndent
,
144 (wndRect
.GetHeight() - m_iconHeight
) / 2,
145 wxIMAGELIST_DRAW_TRANSPARENT
);
147 m_foldIcons
->Draw(index
,
149 (wndRect
.GetWidth() - m_iconWidth
) / 2,
151 wxIMAGELIST_DRAW_TRANSPARENT
);
155 void wxCaptionBar::FillCaptionBackground(wxPaintDC
&dc
)
157 // dispatch right style for caption drawing
159 switch(m_captionStyle
.GetCaptionStyle())
161 case wxCAPTIONBAR_GRADIENT_V
:
163 DrawVerticalGradient(dc
, GetRect());
165 DrawHorizontalGradient(dc
, GetRect());
167 case wxCAPTIONBAR_GRADIENT_H
:
169 DrawHorizontalGradient(dc
, GetRect());
171 DrawVerticalGradient(dc
, GetRect());
173 case wxCAPTIONBAR_SINGLE
:
174 DrawSingleColour(dc
, GetRect());
176 case wxCAPTIONBAR_RECTANGLE
:
177 case wxCAPTIONBAR_FILLED_RECTANGLE
:
178 DrawSingleRectangle(dc
, GetRect());
185 void wxCaptionBar::OnMouseEvent(wxMouseEvent
& event
)
187 // if clicked on the arrow (single) or double on the caption
188 // we change state and an event must be fired to let this
189 // panel collapse or expand
191 bool send_event
= false;
193 if (event
.LeftDown() && m_foldIcons
)
195 wxPoint
pt(event
.GetPosition());
196 wxRect rect
= GetRect();
197 bool vertical
= IsVertical();
199 if((vertical
&& pt
.x
> (rect
.GetWidth() - m_iconWidth
- m_rightIndent
))||
200 (!vertical
&& pt
.y
< m_iconHeight
+ m_rightIndent
))
203 else if(event
.LeftDClick())
206 // send the collapse, expand event to the parent
210 wxCaptionBarEvent
event(wxEVT_CAPTIONBAR
);
211 event
.SetCaptionBar(this);
213 ::wxPostEvent(this, event
);
218 void wxCaptionBar::OnChar(wxKeyEvent
&event
)
220 // TODO: Anything here?
225 wxSize
wxCaptionBar::DoGetBestSize() const
230 GetTextExtent(m_caption
, &x
, &y
);
232 GetTextExtent(m_caption
, &y
, &x
);
240 // TODO: The extra wxFPB_EXTRA_X constants should be adjustable as well
242 return wxSize(x
+ wxFPB_EXTRA_X
, y
+ wxFPB_EXTRA_Y
);
246 void wxCaptionBar::DrawVerticalGradient(wxDC
&dc
, const wxRect
&rect
)
248 // gradient fill from colour 1 to colour 2 with top to bottom
250 if(rect
.height
< 1 || rect
.width
< 1)
253 int size
= rect
.height
;
255 dc
.SetPen(*wxTRANSPARENT_PEN
);
258 // calculate gradient coefficients
259 wxColour col2
= m_captionStyle
.GetSecondColour(),
260 col1
= m_captionStyle
.GetFirstColour();
262 double rstep
= double((col2
.Red() - col1
.Red())) / double(size
), rf
= 0,
263 gstep
= double((col2
.Green() - col1
.Green())) / double(size
), gf
= 0,
264 bstep
= double((col2
.Blue() - col1
.Blue())) / double(size
), bf
= 0;
267 for(int y
= rect
.y
; y
< rect
.y
+ size
; y
++)
270 (unsigned char)(col1
.Red() + rf
),
271 (unsigned char)(col1
.Green() + gf
),
272 (unsigned char)(col1
.Blue() + bf
)
274 dc
.SetBrush( wxBrush( currCol
, wxSOLID
) );
275 dc
.DrawRectangle( rect
.x
, rect
.y
+ (y
- rect
.y
), rect
.width
, size
);
276 //currCol.Set(currCol.Red() + rstep, currCol.Green() + gstep, currCol.Blue() + bstep);
277 rf
+= rstep
; gf
+= gstep
; bf
+= bstep
;
281 void wxCaptionBar::DrawHorizontalGradient(wxDC
&dc
, const wxRect
&rect
)
283 // gradient fill from colour 1 to colour 2 with left to right
285 if(rect
.height
< 1 || rect
.width
< 1)
288 int size
= rect
.width
;
290 dc
.SetPen(*wxTRANSPARENT_PEN
);
292 // calculate gradient coefficients
293 wxColour col2
= m_captionStyle
.GetSecondColour(),
294 col1
= m_captionStyle
.GetFirstColour();
296 double rstep
= double((col2
.Red() - col1
.Red())) / double(size
), rf
= 0,
297 gstep
= double((col2
.Green() - col1
.Green())) / double(size
), gf
= 0,
298 bstep
= double((col2
.Blue() - col1
.Blue())) / double(size
), bf
= 0;
301 for(int x
= rect
.x
; x
< rect
.x
+ size
; x
++)
304 (unsigned char)(col1
.Red() + rf
),
305 (unsigned char)(col1
.Green() + gf
),
306 (unsigned char)(col1
.Blue() + bf
)
308 dc
.SetBrush( wxBrush( currCol
, wxSOLID
) );
309 dc
.DrawRectangle( rect
.x
+ (x
- rect
.x
), rect
.y
, 1, rect
.height
);
310 rf
+= rstep
; gf
+= gstep
; bf
+= bstep
;
314 void wxCaptionBar::DrawSingleColour(wxDC
&dc
, const wxRect
&rect
)
316 // single colour fill. This is the most easy one to find
318 if(rect
.height
< 1 || rect
.width
< 1)
321 dc
.SetPen(*wxTRANSPARENT_PEN
);
323 // draw simple rectangle
324 dc
.SetBrush( wxBrush( m_captionStyle
.GetFirstColour(), wxSOLID
) );
325 dc
.DrawRectangle( rect
.x
, rect
.y
, rect
.width
, rect
.height
);
328 void wxCaptionBar::DrawSingleRectangle(wxDC
&dc
, const wxRect
&rect
)
330 wxASSERT(GetParent());
332 // single colour fill. This is the most easy one to find
334 if(rect
.height
< 2 || rect
.width
< 1)
337 // single frame, set up internal fill colour
340 br
.SetStyle(wxSOLID
);
342 if(m_captionStyle
.GetCaptionStyle() == wxCAPTIONBAR_RECTANGLE
)
343 br
.SetColour(GetParent()->GetBackgroundColour());
345 br
.SetColour(m_captionStyle
.GetFirstColour());
347 // setup the pen frame
349 wxPen
pen(m_captionStyle
.GetSecondColour());
353 dc
.DrawRectangle( rect
.x
, rect
.y
, rect
.width
, rect
.height
- 1);
355 wxPen
bgpen(GetParent()->GetBackgroundColour());
357 dc
.DrawLine(rect
.x
, rect
.y
+ rect
.height
- 1, rect
.x
+ rect
.width
, rect
.y
+ rect
.height
- 1);
361 void wxCaptionBar::OnSize(wxSizeEvent
&event
)
363 wxSize size
= event
.GetSize();
367 // What I am doing here is simply invalidating the part of the window exposed. So when I
368 // make a rect with as width the newly exposed part, and the x,y of the old window size origin,
369 // I don't need a bitmap calulation in it, or do I ? The bitmap needs redrawing anyway. Leave it
370 // like this until I figured it out
372 // set rect to redraw as old bitmap area which is entitled to redraw
374 wxRect
rect(size
.GetWidth() - m_iconWidth
- m_rightIndent
, 0, m_iconWidth
+ m_rightIndent
,
375 m_iconWidth
+ m_rightIndent
);
377 // adjust rectangle when more is slided so we need to redraw all
378 // the old stuff but not all (ugly flickering)
380 int diffX
= size
.GetWidth() - m_oldSize
.GetWidth();
383 // adjust the rect with all the crap to redraw
385 rect
.SetWidth(rect
.GetWidth() + diffX
+ 10);
386 rect
.SetX(rect
.GetX() - diffX
- 10);
393 wxRect rect
= GetRect();
400 void wxCaptionBar::RedrawIconBitmap()
404 // invalidate the bitmap area and force a redraw
406 wxRect rect
= GetRect();
408 rect
.SetX(rect
.GetWidth() - m_iconWidth
- m_rightIndent
);
409 rect
.SetWidth(m_iconWidth
+ m_rightIndent
);
414 bool wxCaptionBar::IsVertical() const
416 // parent of wxCaptionBar is wxFoldPanelItem
417 // default is vertical
418 wxFoldPanelItem
*bar
= wxDynamicCast(GetParent(), wxFoldPanelItem
);
419 wxCHECK_MSG( bar
, true, _T("wrong parent") );
420 return bar
->IsVertical();
427 DEFINE_EVENT_TYPE(wxEVT_CAPTIONBAR
)
429 wxCaptionBarEvent::wxCaptionBarEvent(const wxCaptionBarEvent
&event
)
430 : wxCommandEvent(event
)
432 m_captionBar
= event
.m_captionBar
;
435 //DEFINE_EVENT_TYPE(wxEVT_CAPTIONBAR)
436 //IMPLEMENT_DYNAMIC_CLASS(wxCaptionBarEvent, wxEvent)
437 IMPLEMENT_DYNAMIC_CLASS(wxCaptionBarEvent
, wxCommandEvent
)