1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: generic/vlbox.cpp
3 // Purpose: implementation of wxVListBox
4 // Author: Vadim Zeitlin
8 // Copyright: (c) 2003 Vadim Zeitlin <vadim@wxwindows.org>
9 // License: wxWindows license
10 ///////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
28 #include "wx/settings.h"
29 #include "wx/dcclient.h"
34 // ----------------------------------------------------------------------------
36 // ----------------------------------------------------------------------------
38 BEGIN_EVENT_TABLE(wxVListBox
, wxVScrolledWindow
)
39 EVT_PAINT(wxVListBox::OnPaint
)
41 EVT_KEY_DOWN(wxVListBox::OnKeyDown
)
42 EVT_LEFT_DOWN(wxVListBox::OnLeftDown
)
43 EVT_LEFT_DCLICK(wxVListBox::OnLeftDClick
)
46 // ============================================================================
48 // ============================================================================
50 // ----------------------------------------------------------------------------
51 // wxVListBox creation
52 // ----------------------------------------------------------------------------
54 void wxVListBox::Init()
59 bool wxVListBox::Create(wxWindow
*parent
,
67 if ( !wxVScrolledWindow::Create(parent
, id
, pos
, size
, style
, name
) )
70 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_LISTBOX
));
72 SetItemCount(countItems
);
77 // ----------------------------------------------------------------------------
79 // ----------------------------------------------------------------------------
81 void wxVListBox::DoSetSelection(int selection
, bool sendEvent
)
83 if ( selection
== m_selection
)
89 if ( m_selection
!= -1 )
90 RefreshLine(m_selection
);
92 m_selection
= selection
;
94 if ( m_selection
!= -1 )
96 // if the line is not visible at all, we scroll it into view but we
97 // don't need to refresh it -- it will be redrawn anyhow
98 if ( !IsVisible(m_selection
) )
100 ScrollToLine(m_selection
);
102 else // line is at least partly visible
104 // it is, indeed, only partly visible, so scroll it into view to
105 // make it entirely visible
106 if ( (size_t)m_selection
== GetLastVisibleLine() )
108 ScrollToLine(m_selection
);
111 // but in any case refresh it as even if it was only partly visible
112 // before we need to redraw it entirely as its background changed
113 RefreshLine(m_selection
);
116 // send a notification event if we were not called directly by user
119 wxCommandEvent
event(wxEVT_COMMAND_LISTBOX_SELECTED
, GetId());
120 event
.SetEventObject(this);
121 event
.m_commandInt
= selection
;
123 (void)GetEventHandler()->ProcessEvent(event
);
128 // ----------------------------------------------------------------------------
129 // wxVListBox painting
130 // ----------------------------------------------------------------------------
132 void wxVListBox::SetMargins(const wxPoint
& pt
)
134 if ( pt
!= m_ptMargins
)
142 wxCoord
wxVListBox::OnGetLineHeight(size_t line
) const
144 return OnMeasureItem(line
) + 2*m_ptMargins
.y
;
147 void wxVListBox::OnDrawSeparator(wxDC
& WXUNUSED(dc
),
148 wxRect
& WXUNUSED(rect
),
149 size_t WXUNUSED(n
)) const
153 void wxVListBox::OnPaint(wxPaintEvent
& event
)
157 // the update rectangle
158 wxRect rectUpdate
= GetUpdateClientRect();
160 // the bounding rectangle of the current line
162 rectLine
.width
= GetClientSize().x
;
164 // iterate over all visible lines
165 const size_t lineMax
= GetLastVisibleLine();
166 for ( size_t line
= GetFirstVisibleLine(); line
<= lineMax
; line
++ )
168 const wxCoord hLine
= OnGetLineHeight(line
);
170 rectLine
.height
= hLine
;
172 // and draw the ones which intersect the update rect
173 if ( rectLine
.Intersects(rectUpdate
) )
175 // don't allow drawing outside of the lines rectangle
176 wxDCClipper
clip(dc
, rectLine
);
178 if ( IsSelected(line
) )
180 wxBrush
brush(wxSystemSettings::
181 GetColour(wxSYS_COLOUR_HIGHLIGHT
),
184 dc
.SetPen(*wxTRANSPARENT_PEN
);
185 dc
.DrawRectangle(rectLine
);
188 wxRect rect
= rectLine
;
189 OnDrawSeparator(dc
, rect
, line
);
191 rect
.Deflate(m_ptMargins
.x
, m_ptMargins
.y
);
192 OnDrawItem(dc
, rect
, line
);
194 else // no intersection
196 if ( rectLine
.GetTop() > rectUpdate
.GetBottom() )
198 // we are already below the update rect, no need to continue
202 //else: the next line may intersect the update rect
209 // ----------------------------------------------------------------------------
210 // wxVListBox keyboard handling
211 // ----------------------------------------------------------------------------
213 void wxVListBox::OnKeyDown(wxKeyEvent
& event
)
215 int selection
= 0; // just to silent the stupid compiler warnings
216 switch ( event
.GetKeyCode() )
223 selection
= GetLineCount() - 1;
227 if ( m_selection
== (int)GetLineCount() - 1 )
230 selection
= m_selection
+ 1;
234 if ( m_selection
== -1 )
235 selection
= GetLineCount() - 1;
236 else if ( m_selection
!= 0 )
237 selection
= m_selection
- 1;
238 else // m_selection == 0
245 selection
= GetFirstVisibleLine();
250 if ( m_selection
== (int)GetFirstVisibleLine() )
255 selection
= GetFirstVisibleLine();
263 DoSetSelection(selection
);
266 // ----------------------------------------------------------------------------
267 // wxVListBox mouse handling
268 // ----------------------------------------------------------------------------
270 void wxVListBox::OnLeftDown(wxMouseEvent
& event
)
272 int item
= HitTest(event
.GetPosition());
274 DoSetSelection(item
);
277 void wxVListBox::OnLeftDClick(wxMouseEvent
& event
)
279 int item
= HitTest(event
.GetPosition());
282 wxCommandEvent
event(wxEVT_COMMAND_LISTBOX_DOUBLECLICKED
, GetId());
283 event
.SetEventObject(this);
284 event
.m_commandInt
= item
;
286 (void)GetEventHandler()->ProcessEvent(event
);