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"
33 // ----------------------------------------------------------------------------
35 // ----------------------------------------------------------------------------
37 BEGIN_EVENT_TABLE(wxVListBox
, wxVScrolledWindow
)
38 EVT_PAINT(wxVListBox::OnPaint
)
40 EVT_KEY_DOWN(wxVListBox::OnKeyDown
)
41 EVT_LEFT_DOWN(wxVListBox::OnLeftDown
)
42 EVT_LEFT_DCLICK(wxVListBox::OnLeftDClick
)
45 // ============================================================================
47 // ============================================================================
49 // ----------------------------------------------------------------------------
50 // wxVListBox creation
51 // ----------------------------------------------------------------------------
53 void wxVListBox::Init()
58 bool wxVListBox::Create(wxWindow
*parent
,
66 if ( !wxVScrolledWindow::Create(parent
, id
, pos
, size
, style
, name
) )
69 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_LISTBOX
));
71 SetItemCount(countItems
);
76 // ----------------------------------------------------------------------------
78 // ----------------------------------------------------------------------------
80 void wxVListBox::DoSetSelection(int selection
, bool sendEvent
)
82 if ( selection
== m_selection
)
88 if ( m_selection
!= -1 )
89 RefreshLine(m_selection
);
91 m_selection
= selection
;
93 if ( m_selection
!= -1 )
95 // if the line is not visible at all, we scroll it into view but we
96 // don't need to refresh it -- it will be redrawn anyhow
97 if ( !IsVisible(m_selection
) )
99 ScrollToLine(m_selection
);
101 else // line is at least partly visible
103 // it is, indeed, only partly visible, so scroll it into view to
104 // make it entirely visible
105 if ( (size_t)m_selection
== GetLastVisibleLine() )
107 ScrollToLine(m_selection
);
110 // but in any case refresh it as even if it was only partly visible
111 // before we need to redraw it entirely as its background changed
112 RefreshLine(m_selection
);
115 // send a notification event if we were not called directly by user
118 wxCommandEvent
event(wxEVT_COMMAND_LISTBOX_SELECTED
, GetId());
119 event
.SetEventObject(this);
120 event
.m_commandInt
= selection
;
122 (void)GetEventHandler()->ProcessEvent(event
);
127 // ----------------------------------------------------------------------------
128 // wxVListBox painting
129 // ----------------------------------------------------------------------------
131 void wxVListBox::SetMargins(const wxPoint
& pt
)
133 if ( pt
!= m_ptMargins
)
141 wxCoord
wxVListBox::OnGetLineHeight(size_t line
) const
143 return OnMeasureItem(line
) + 2*m_ptMargins
.y
;
146 void wxVListBox::OnDrawSeparator(wxDC
& WXUNUSED(dc
),
147 wxRect
& WXUNUSED(rect
),
148 size_t WXUNUSED(n
)) const
152 void wxVListBox::OnPaint(wxPaintEvent
& event
)
156 // the update rectangle
157 wxRect rectUpdate
= GetUpdateClientRect();
159 // the bounding rectangle of the current line
161 rectLine
.width
= GetClientSize().x
;
163 // iterate over all visible lines
164 const size_t lineMax
= GetLastVisibleLine();
165 for ( size_t line
= GetFirstVisibleLine(); line
<= lineMax
; line
++ )
167 const wxCoord hLine
= OnGetLineHeight(line
);
169 rectLine
.height
= hLine
;
171 // and draw the ones which intersect the update rect
172 if ( rectLine
.Intersects(rectUpdate
) )
174 // don't allow drawing outside of the lines rectangle
175 wxDCClipper
clip(dc
, rectLine
);
177 if ( IsSelected(line
) )
179 wxBrush
brush(wxSystemSettings::
180 GetColour(wxSYS_COLOUR_HIGHLIGHT
),
183 dc
.SetPen(*wxTRANSPARENT_PEN
);
184 dc
.DrawRectangle(rectLine
);
187 wxRect rect
= rectLine
;
188 OnDrawSeparator(dc
, rect
, line
);
190 rect
.Deflate(m_ptMargins
.x
, m_ptMargins
.y
);
191 OnDrawItem(dc
, rect
, line
);
193 else // no intersection
195 if ( rectLine
.GetTop() > rectUpdate
.GetBottom() )
197 // we are already below the update rect, no need to continue
201 //else: the next line may intersect the update rect
208 // ----------------------------------------------------------------------------
209 // wxVListBox keyboard handling
210 // ----------------------------------------------------------------------------
212 void wxVListBox::OnKeyDown(wxKeyEvent
& event
)
214 int selection
= 0; // just to silent the stupid compiler warnings
215 switch ( event
.GetKeyCode() )
222 selection
= GetLineCount() - 1;
226 if ( m_selection
== (int)GetLineCount() - 1 )
229 selection
= m_selection
+ 1;
233 if ( m_selection
== -1 )
234 selection
= GetLineCount() - 1;
235 else if ( m_selection
!= 0 )
236 selection
= m_selection
- 1;
237 else // m_selection == 0
244 selection
= GetFirstVisibleLine();
249 if ( m_selection
== (int)GetFirstVisibleLine() )
254 selection
= GetFirstVisibleLine();
262 DoSetSelection(selection
);
265 // ----------------------------------------------------------------------------
266 // wxVListBox mouse handling
267 // ----------------------------------------------------------------------------
269 void wxVListBox::OnLeftDown(wxMouseEvent
& event
)
271 int item
= HitTest(event
.GetPosition());
273 DoSetSelection(item
);
276 void wxVListBox::OnLeftDClick(wxMouseEvent
& event
)
278 int item
= HitTest(event
.GetPosition());
281 wxCommandEvent
event(wxEVT_COMMAND_LISTBOX_DOUBLECLICKED
, GetId());
282 event
.SetEventObject(this);
283 event
.m_commandInt
= item
;
285 (void)GetEventHandler()->ProcessEvent(event
);