]> git.saurik.com Git - wxWidgets.git/blob - src/common/listctrlcmn.cpp
fixing overrelease and out-of-bounds write, fixes #13725
[wxWidgets.git] / src / common / listctrlcmn.cpp
1 ////////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/listctrlcmn.cpp
3 // Purpose: Common defines for wxListCtrl and wxListCtrl-based classes.
4 // Author: Kevin Ollivier
5 // Created: 09/15/06
6 // RCS-ID: $Id$
7 // Copyright: (c) Kevin Ollivier
8 // Licence: wxWindows licence
9 ////////////////////////////////////////////////////////////////////////////////
10
11 // =============================================================================
12 // declarations
13 // =============================================================================
14
15 // -----------------------------------------------------------------------------
16 // headers
17 // -----------------------------------------------------------------------------
18
19 // For compilers that support precompilation, includes "wx.h".
20 #include "wx/wxprec.h"
21
22 #ifdef __BORLANDC__
23 #pragma hdrstop
24 #endif
25
26 #if wxUSE_LISTCTRL
27
28 #include "wx/listctrl.h"
29
30 #ifndef WX_PRECOMP
31 #include "wx/dcclient.h"
32 #endif
33
34 const char wxListCtrlNameStr[] = "listCtrl";
35
36 // ListCtrl events
37 wxDEFINE_EVENT( wxEVT_COMMAND_LIST_BEGIN_DRAG, wxListEvent );
38 wxDEFINE_EVENT( wxEVT_COMMAND_LIST_BEGIN_RDRAG, wxListEvent );
39 wxDEFINE_EVENT( wxEVT_COMMAND_LIST_BEGIN_LABEL_EDIT, wxListEvent );
40 wxDEFINE_EVENT( wxEVT_COMMAND_LIST_END_LABEL_EDIT, wxListEvent );
41 wxDEFINE_EVENT( wxEVT_COMMAND_LIST_DELETE_ITEM, wxListEvent );
42 wxDEFINE_EVENT( wxEVT_COMMAND_LIST_DELETE_ALL_ITEMS, wxListEvent );
43 wxDEFINE_EVENT( wxEVT_COMMAND_LIST_ITEM_SELECTED, wxListEvent );
44 wxDEFINE_EVENT( wxEVT_COMMAND_LIST_ITEM_DESELECTED, wxListEvent );
45 wxDEFINE_EVENT( wxEVT_COMMAND_LIST_KEY_DOWN, wxListEvent );
46 wxDEFINE_EVENT( wxEVT_COMMAND_LIST_INSERT_ITEM, wxListEvent );
47 wxDEFINE_EVENT( wxEVT_COMMAND_LIST_COL_CLICK, wxListEvent );
48 wxDEFINE_EVENT( wxEVT_COMMAND_LIST_COL_RIGHT_CLICK, wxListEvent );
49 wxDEFINE_EVENT( wxEVT_COMMAND_LIST_COL_BEGIN_DRAG, wxListEvent );
50 wxDEFINE_EVENT( wxEVT_COMMAND_LIST_COL_DRAGGING, wxListEvent );
51 wxDEFINE_EVENT( wxEVT_COMMAND_LIST_COL_END_DRAG, wxListEvent );
52 wxDEFINE_EVENT( wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK, wxListEvent );
53 wxDEFINE_EVENT( wxEVT_COMMAND_LIST_ITEM_MIDDLE_CLICK, wxListEvent );
54 wxDEFINE_EVENT( wxEVT_COMMAND_LIST_ITEM_ACTIVATED, wxListEvent );
55 wxDEFINE_EVENT( wxEVT_COMMAND_LIST_ITEM_FOCUSED, wxListEvent );
56 wxDEFINE_EVENT( wxEVT_COMMAND_LIST_CACHE_HINT, wxListEvent );
57
58 // -----------------------------------------------------------------------------
59 // XTI
60 // -----------------------------------------------------------------------------
61
62 wxDEFINE_FLAGS( wxListCtrlStyle )
63 wxBEGIN_FLAGS( wxListCtrlStyle )
64 // new style border flags, we put them first to
65 // use them for streaming out
66 wxFLAGS_MEMBER(wxBORDER_SIMPLE)
67 wxFLAGS_MEMBER(wxBORDER_SUNKEN)
68 wxFLAGS_MEMBER(wxBORDER_DOUBLE)
69 wxFLAGS_MEMBER(wxBORDER_RAISED)
70 wxFLAGS_MEMBER(wxBORDER_STATIC)
71 wxFLAGS_MEMBER(wxBORDER_NONE)
72
73 // old style border flags
74 wxFLAGS_MEMBER(wxSIMPLE_BORDER)
75 wxFLAGS_MEMBER(wxSUNKEN_BORDER)
76 wxFLAGS_MEMBER(wxDOUBLE_BORDER)
77 wxFLAGS_MEMBER(wxRAISED_BORDER)
78 wxFLAGS_MEMBER(wxSTATIC_BORDER)
79 wxFLAGS_MEMBER(wxBORDER)
80
81 // standard window styles
82 wxFLAGS_MEMBER(wxTAB_TRAVERSAL)
83 wxFLAGS_MEMBER(wxCLIP_CHILDREN)
84 wxFLAGS_MEMBER(wxTRANSPARENT_WINDOW)
85 wxFLAGS_MEMBER(wxWANTS_CHARS)
86 wxFLAGS_MEMBER(wxFULL_REPAINT_ON_RESIZE)
87 wxFLAGS_MEMBER(wxALWAYS_SHOW_SB )
88 wxFLAGS_MEMBER(wxVSCROLL)
89 wxFLAGS_MEMBER(wxHSCROLL)
90
91 wxFLAGS_MEMBER(wxLC_LIST)
92 wxFLAGS_MEMBER(wxLC_REPORT)
93 wxFLAGS_MEMBER(wxLC_ICON)
94 wxFLAGS_MEMBER(wxLC_SMALL_ICON)
95 wxFLAGS_MEMBER(wxLC_ALIGN_TOP)
96 wxFLAGS_MEMBER(wxLC_ALIGN_LEFT)
97 wxFLAGS_MEMBER(wxLC_AUTOARRANGE)
98 wxFLAGS_MEMBER(wxLC_USER_TEXT)
99 wxFLAGS_MEMBER(wxLC_EDIT_LABELS)
100 wxFLAGS_MEMBER(wxLC_NO_HEADER)
101 wxFLAGS_MEMBER(wxLC_SINGLE_SEL)
102 wxFLAGS_MEMBER(wxLC_SORT_ASCENDING)
103 wxFLAGS_MEMBER(wxLC_SORT_DESCENDING)
104 wxFLAGS_MEMBER(wxLC_VIRTUAL)
105 wxEND_FLAGS( wxListCtrlStyle )
106
107 #if ((!defined(__WXMSW__) && !(defined(__WXMAC__) && wxOSX_USE_CARBON)) || defined(__WXUNIVERSAL__))
108 wxIMPLEMENT_DYNAMIC_CLASS_XTI(wxListCtrl, wxGenericListCtrl, "wx/listctrl.h")
109 #else
110 wxIMPLEMENT_DYNAMIC_CLASS_XTI(wxListCtrl, wxControl, "wx/listctrl.h")
111 #endif
112
113 wxBEGIN_PROPERTIES_TABLE(wxListCtrl)
114 wxEVENT_PROPERTY( TextUpdated, wxEVT_COMMAND_TEXT_UPDATED, wxCommandEvent )
115
116 wxPROPERTY_FLAGS( WindowStyle, wxListCtrlStyle, long, SetWindowStyleFlag, \
117 GetWindowStyleFlag, wxEMPTY_PARAMETER_VALUE, 0 /*flags*/, \
118 wxT("Helpstring"), wxT("group")) // style
119 wxEND_PROPERTIES_TABLE()
120
121 wxEMPTY_HANDLERS_TABLE(wxListCtrl)
122
123 wxCONSTRUCTOR_5( wxListCtrl, wxWindow*, Parent, wxWindowID, Id, \
124 wxPoint, Position, wxSize, Size, long, WindowStyle )
125
126 /*
127 TODO : Expose more information of a list's layout etc. via appropriate objects
128 (see NotebookPageInfo)
129 */
130
131 IMPLEMENT_DYNAMIC_CLASS(wxListView, wxListCtrl)
132 IMPLEMENT_DYNAMIC_CLASS(wxListItem, wxObject)
133 IMPLEMENT_DYNAMIC_CLASS(wxListEvent, wxNotifyEvent)
134
135 // ----------------------------------------------------------------------------
136 // wxListCtrlBase implementation
137 // ----------------------------------------------------------------------------
138
139 long
140 wxListCtrlBase::AppendColumn(const wxString& heading,
141 int format,
142 int width)
143 {
144 return InsertColumn(GetColumnCount(), heading, format, width);
145 }
146
147 long
148 wxListCtrlBase::InsertColumn(long col,
149 const wxString& heading,
150 int format,
151 int width)
152 {
153 wxListItem item;
154 item.m_mask = wxLIST_MASK_TEXT | wxLIST_MASK_FORMAT;
155 item.m_text = heading;
156 if ( width >= 0
157 || width == wxLIST_AUTOSIZE
158 || width == wxLIST_AUTOSIZE_USEHEADER )
159 {
160 item.m_mask |= wxLIST_MASK_WIDTH;
161 item.m_width = width;
162 }
163 item.m_format = format;
164
165 return InsertColumn(col, item);
166 }
167
168 long wxListCtrlBase::InsertColumn(long col, const wxListItem& info)
169 {
170 long rc = DoInsertColumn(col, info);
171 if ( rc != -1 )
172 {
173 // As our best size calculation depends on the column headers,
174 // invalidate the previously cached best size when a column is added.
175 InvalidateBestSize();
176 }
177
178 return rc;
179 }
180
181 wxSize wxListCtrlBase::DoGetBestClientSize() const
182 {
183 // There is no obvious way to determine the best size in icon and list
184 // modes so just don't do it for now.
185 if ( !InReportView() )
186 return wxControl::DoGetBestClientSize();
187
188 int totalWidth;
189 wxClientDC dc(const_cast<wxListCtrlBase*>(this));
190
191 // In report mode, we use only the column headers, not items, to determine
192 // the best width. The reason for this is that it's easier (we can't just
193 // iterate over all items, especially not in a virtual control, so we'd
194 // have to do something relatively complicated such as checking the size of
195 // some items in the beginning and the end only) and also because the
196 // columns are usually static while the list contents is dynamic so it
197 // usually doesn't make much sense to adjust the control size to it anyhow.
198 // And finally, scrollbars can always be used with the items while the
199 // headers are just truncated if there is not enough place for them.
200 const int columns = GetColumnCount();
201 if ( HasFlag(wxLC_NO_HEADER) || !columns )
202 {
203 // Use some arbitrary width.
204 totalWidth = 50*dc.GetCharWidth();
205 }
206 else // We do have columns, use them to determine the best width.
207 {
208 totalWidth = 0;
209 for ( int col = 0; col < columns; col++ )
210 {
211 totalWidth += GetColumnWidth(col);
212 }
213 }
214
215 // Use some arbitrary height, there is no good way to determine it.
216 return wxSize(totalWidth, 10*dc.GetCharHeight());
217 }
218
219 #endif // wxUSE_LISTCTRL