File: | ui_basic/table.cc |
Location: | line 162, column 3 |
Description: | Called C++ object pointer is null |
1 | /* | |||
2 | * Copyright (C) 2002, 2006-2011 by the Widelands Development Team | |||
3 | * | |||
4 | * This program is free software; you can redistribute it and/or | |||
5 | * modify it under the terms of the GNU General Public License | |||
6 | * as published by the Free Software Foundation; either version 2 | |||
7 | * of the License, or (at your option) any later version. | |||
8 | * | |||
9 | * This program is distributed in the hope that it will be useful, | |||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
12 | * GNU General Public License for more details. | |||
13 | * | |||
14 | * You should have received a copy of the GNU General Public License | |||
15 | * along with this program; if not, write to the Free Software | |||
16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
17 | * | |||
18 | */ | |||
19 | ||||
20 | #include "table.h" | |||
21 | ||||
22 | #include "graphic/font.h" | |||
23 | #include "graphic/font_handler.h" | |||
24 | #include "graphic/rendertarget.h" | |||
25 | #include "graphic/surface.h" | |||
26 | ||||
27 | #include "button.h" | |||
28 | #include "mouse_constants.h" | |||
29 | #include "scrollbar.h" | |||
30 | #include "wlapplication.h" | |||
31 | ||||
32 | #include "container_iterate.h" | |||
33 | #include <boost/bind.hpp> | |||
34 | ||||
35 | namespace UI { | |||
36 | ||||
37 | /** | |||
38 | * Args: parent parent panel | |||
39 | * x coordinates of the Table | |||
40 | * y | |||
41 | * w dimensions, in pixels, of the Table | |||
42 | * h | |||
43 | */ | |||
44 | Table<void *>::Table | |||
45 | (Panel * const parent, | |||
46 | int32_t x, int32_t y, uint32_t w, uint32_t h, | |||
47 | const bool descending) | |||
48 | : | |||
49 | Panel (parent, x, y, w, h), | |||
50 | m_total_width (0), | |||
51 | m_max_pic_width (0), | |||
52 | m_fontname (UI_FONT_NAME"DejaVuSerif.ttf"), | |||
53 | m_fontsize (UI_FONT_SIZE_SMALL14), | |||
54 | m_headerheight (15), | |||
55 | m_lineheight (g_fh->get_fontheight(m_fontname, m_fontsize)), | |||
56 | m_scrollbar (0), | |||
57 | m_scrollpos (0), | |||
58 | m_selection (no_selection_index()), | |||
59 | m_last_click_time (-10000), | |||
60 | m_last_selection (no_selection_index()), | |||
61 | m_sort_column (0), | |||
62 | m_sort_descending (descending) | |||
63 | { | |||
64 | set_think(false); | |||
65 | } | |||
66 | ||||
67 | ||||
68 | /** | |||
69 | * Free allocated resources | |||
70 | */ | |||
71 | Table<void *>::~Table() | |||
72 | { | |||
73 | container_iterate_const(Entry_Record_vector, m_entry_records, i)for (wl_const_range< Entry_Record_vector > i(m_entry_records ); i; ++i) | |||
74 | delete *i.current; | |||
75 | } | |||
76 | ||||
77 | /// Add a new column to this table. | |||
78 | void Table<void *>::add_column | |||
79 | (uint32_t const width, | |||
80 | std::string const & title, | |||
81 | Align const alignment, | |||
82 | bool const is_checkbox_column) | |||
83 | { | |||
84 | ||||
85 | // If there would be existing entries, they would not get the new column. | |||
86 | assert(size() == 0)((size() == 0) ? static_cast<void> (0) : __assert_fail ( "size() == 0", "/home/arch/widelands/src/ui_basic/table.cc", 86 , __PRETTY_FUNCTION__)); | |||
87 | ||||
88 | uint32_t complete_width = 0; | |||
89 | container_iterate_const(Columns, m_columns, i)for (wl_const_range< Columns > i(m_columns); i; ++i) | |||
90 | complete_width += i.current->width; | |||
91 | ||||
92 | m_total_width += width; | |||
93 | set_desired_size(m_total_width, get_h()); | |||
94 | ||||
95 | { | |||
96 | Column c; | |||
97 | c.btn = 0; | |||
98 | if (title.size()) { | |||
99 | c.btn = | |||
100 | new Button | |||
101 | (this, title, | |||
102 | complete_width, 0, width, m_headerheight, | |||
103 | g_gr->imgcache().load(PicMod_UI, "pics/but3.png"), | |||
104 | title, "", true, false); | |||
105 | c.btn->sigclicked.connect | |||
106 | (boost::bind(&Table::header_button_clicked, boost::ref(*this), m_columns.size())); | |||
107 | c.btn->set_font(Font::get(m_fontname, m_fontsize)); | |||
108 | } | |||
109 | c.width = width; | |||
110 | c.alignment = alignment; | |||
111 | c.is_checkbox_column = is_checkbox_column; | |||
112 | ||||
113 | if (is_checkbox_column) { | |||
114 | c.compare = boost::bind | |||
115 | (&Table<void *>::default_compare_checkbox, | |||
116 | this, m_columns.size(), _1, _2); | |||
117 | } else { | |||
118 | c.compare = boost::bind | |||
119 | (&Table<void *>::default_compare_string, | |||
120 | this, m_columns.size(), _1, _2); | |||
121 | } | |||
122 | ||||
123 | m_columns.push_back(c); | |||
124 | } | |||
125 | if (not m_scrollbar) { | |||
126 | m_scrollbar = | |||
127 | new Scrollbar | |||
128 | (get_parent(), | |||
129 | get_x() + get_w() - 24, get_y() + m_headerheight, | |||
130 | 24, get_h() - m_headerheight, | |||
131 | false); | |||
132 | m_scrollbar->moved.connect(boost::bind(&Table::set_scrollpos, this, _1)); | |||
133 | m_scrollbar->set_steps(1); | |||
134 | uint32_t const lineheight = g_fh->get_fontheight(m_fontname, m_fontsize); | |||
135 | m_scrollbar->set_singlestepsize(lineheight); | |||
136 | m_scrollbar->set_pagesize(get_h() - lineheight); | |||
137 | } | |||
138 | } | |||
139 | ||||
140 | void Table<void *>::set_column_title | |||
141 | (uint8_t const col, std::string const & title) | |||
142 | { | |||
143 | assert(col < m_columns.size())((col < m_columns.size()) ? static_cast<void> (0) : __assert_fail ("col < m_columns.size()", "/home/arch/widelands/src/ui_basic/table.cc" , 143, __PRETTY_FUNCTION__)); | |||
144 | Column & column = m_columns.at(col); | |||
145 | if (not column.btn and title.size()) { // no title before, but now | |||
| ||||
146 | uint32_t complete_width = 0; | |||
147 | for (uint8_t i = 0; i < col; ++i) | |||
148 | complete_width += m_columns.at(i).width; | |||
149 | column.btn = | |||
150 | new Button | |||
151 | (this, title, | |||
152 | complete_width, 0, column.width, m_headerheight, | |||
153 | g_gr->imgcache().load(PicMod_UI, "pics/but3.png"), | |||
154 | title, "", true, false); | |||
155 | column.btn->sigclicked.connect | |||
156 | (boost::bind(&Table::header_button_clicked, boost::ref(*this), col)); | |||
157 | column.btn->set_font(Font::get(m_fontname, m_fontsize)); | |||
158 | } else if (column.btn and title.empty()) { // had title before, not now | |||
159 | delete column.btn; | |||
160 | column.btn = 0; | |||
161 | } else | |||
162 | column.btn->set_title(title); | |||
| ||||
163 | } | |||
164 | ||||
165 | /** | |||
166 | * Set a custom comparison function for sorting of the given column. | |||
167 | */ | |||
168 | void Table<void *>::set_column_compare | |||
169 | (uint8_t col, const Table<void *>::CompareFn & fn) | |||
170 | { | |||
171 | assert(col < m_columns.size())((col < m_columns.size()) ? static_cast<void> (0) : __assert_fail ("col < m_columns.size()", "/home/arch/widelands/src/ui_basic/table.cc" , 171, __PRETTY_FUNCTION__)); | |||
172 | Column & column = m_columns.at(col); | |||
173 | column.compare = fn; | |||
174 | } | |||
175 | ||||
176 | void Table<void *>::Entry_Record::set_checked | |||
177 | (uint8_t const col, bool const checked) | |||
178 | { | |||
179 | _data & cell = m_data.at(col); | |||
180 | ||||
181 | cell.d_checked = checked; | |||
182 | cell.d_picture = | |||
183 | g_gr->imgcache().load | |||
184 | (PicMod_UI, | |||
185 | checked ? "pics/checkbox_checked.png" : "pics/checkbox_empty.png"); | |||
186 | } | |||
187 | ||||
188 | void Table<void *>::Entry_Record::toggle(uint8_t const col) | |||
189 | { | |||
190 | set_checked(col, !is_checked(col)); | |||
191 | } | |||
192 | ||||
193 | ||||
194 | bool Table<void *>::Entry_Record::is_checked(uint8_t const col) const { | |||
195 | _data const & cell = m_data.at(col); | |||
196 | ||||
197 | return cell.d_checked; | |||
198 | } | |||
199 | ||||
200 | Table<void *>::Entry_Record * Table<void *>::find | |||
201 | (const void * const entry) const | |||
202 | throw () | |||
203 | { | |||
204 | container_iterate_const(Entry_Record_vector, m_entry_records, i)for (wl_const_range< Entry_Record_vector > i(m_entry_records ); i; ++i) | |||
205 | if ((*i.current)->entry() == entry) | |||
206 | return *i.current; | |||
207 | ||||
208 | return 0; | |||
209 | } | |||
210 | ||||
211 | /** | |||
212 | * A header button has been clicked | |||
213 | */ | |||
214 | void Table<void *>::header_button_clicked(Columns::size_type const n) { | |||
215 | assert(m_columns.at(n).btn)((m_columns.at(n).btn) ? static_cast<void> (0) : __assert_fail ("m_columns.at(n).btn", "/home/arch/widelands/src/ui_basic/table.cc" , 215, __PRETTY_FUNCTION__)); | |||
216 | if (get_sort_colum() == n) { | |||
217 | set_sort_descending(not get_sort_descending()); // change sort direction | |||
218 | sort(); | |||
219 | return; | |||
220 | } | |||
221 | ||||
222 | set_sort_column(n); | |||
223 | sort(); | |||
224 | return; | |||
225 | } | |||
226 | ||||
227 | /** | |||
228 | * Remove all entries from the table | |||
229 | */ | |||
230 | void Table<void *>::clear() | |||
231 | { | |||
232 | container_iterate_const(Entry_Record_vector, m_entry_records, i)for (wl_const_range< Entry_Record_vector > i(m_entry_records ); i; ++i) | |||
233 | delete *i.current; | |||
234 | m_entry_records.clear(); | |||
235 | ||||
236 | if (m_scrollbar) | |||
237 | m_scrollbar->set_steps(1); | |||
238 | m_scrollpos = 0; | |||
239 | m_selection = no_selection_index(); | |||
240 | m_last_click_time = -10000; | |||
241 | m_last_selection = no_selection_index(); | |||
242 | } | |||
243 | ||||
244 | /** | |||
245 | * Redraw the table | |||
246 | */ | |||
247 | void Table<void *>::draw(RenderTarget & dst) | |||
248 | { | |||
249 | // draw text lines | |||
250 | int32_t lineheight = get_lineheight(); | |||
251 | uint32_t idx = m_scrollpos / lineheight; | |||
252 | int32_t y = 1 + idx * lineheight - m_scrollpos + m_headerheight; | |||
253 | ||||
254 | dst.brighten_rect(Rect(Point(0, 0), get_w(), get_h()), ms_darken_value); | |||
255 | ||||
256 | while (idx < m_entry_records.size()) { | |||
257 | if (y >= static_cast<int32_t>(get_h())) | |||
258 | return; | |||
259 | ||||
260 | const Entry_Record & er = *m_entry_records[idx]; | |||
261 | ||||
262 | if (idx == m_selection) { | |||
263 | assert(2 <= get_eff_w())((2 <= get_eff_w()) ? static_cast<void> (0) : __assert_fail ("2 <= get_eff_w()", "/home/arch/widelands/src/ui_basic/table.cc" , 263, __PRETTY_FUNCTION__)); | |||
264 | dst.brighten_rect | |||
265 | (Rect(Point(1, y), get_eff_w() - 2, m_lineheight), | |||
266 | -ms_darken_value); | |||
267 | } | |||
268 | ||||
269 | const RGBColor col = er.use_clr ? er.clr : UI_FONT_CLR_FGRGBColor(255, 255, 0); | |||
270 | ||||
271 | Columns::size_type const nr_columns = m_columns.size(); | |||
272 | for (uint32_t i = 0, curx = 0; i < nr_columns; ++i) { | |||
273 | Column const & column = m_columns[i]; | |||
274 | uint32_t const curw = column.width; | |||
275 | Align const alignment = column.alignment; | |||
276 | ||||
277 | const IPicture* entry_picture = er.get_picture(i); | |||
278 | std::string const & entry_string = er.get_string (i); | |||
279 | uint32_t picw = 0; | |||
280 | uint32_t pich = 0; | |||
281 | uint32_t stringw = 0; | |||
282 | uint32_t stringh = g_fh->get_fontheight(m_fontname, m_fontsize); | |||
283 | if (entry_picture) { | |||
284 | picw = entry_picture->get_w(); | |||
285 | pich = entry_picture->get_h(); | |||
286 | } | |||
287 | Point point = | |||
288 | Point(curx, y) | |||
289 | + | |||
290 | Point | |||
291 | (alignment & Align_Right ? curw - (picw + stringw) - 1 : | |||
292 | alignment & Align_HCenter ? (curw - (picw + stringw)) / 2 : | |||
293 | 1, | |||
294 | 0); | |||
295 | if (entry_picture) | |||
296 | dst.blit | |||
297 | (point + | |||
298 | Point | |||
299 | (0, | |||
300 | (static_cast<int32_t>(lineheight) - | |||
301 | static_cast<int32_t>(pich)) | |||
302 | / 2), | |||
303 | entry_picture); | |||
304 | ||||
305 | UI::g_fh->draw_text | |||
306 | (dst, | |||
307 | TextStyle::makebold(Font::get(m_fontname, m_fontsize), col), | |||
308 | point + | |||
309 | Point | |||
310 | (picw, | |||
311 | (static_cast<int32_t>(lineheight) - | |||
312 | static_cast<int32_t>(stringh)) | |||
313 | / 2), | |||
314 | entry_string, | |||
315 | alignment); | |||
316 | ||||
317 | curx += curw; | |||
318 | } | |||
319 | ||||
320 | y += lineheight; | |||
321 | ++idx; | |||
322 | } | |||
323 | } | |||
324 | ||||
325 | /** | |||
326 | * handle key presses | |||
327 | */ | |||
328 | bool Table<void *>::handle_key(bool down, SDL_keysym code) | |||
329 | { | |||
330 | if (down) { | |||
331 | switch (code.sym) { | |||
332 | case SDLK_UP: | |||
333 | case SDLK_KP8: | |||
334 | move_selection(-1); | |||
335 | return true; | |||
336 | ||||
337 | case SDLK_DOWN: | |||
338 | case SDLK_KP2: | |||
339 | move_selection(1); | |||
340 | return true; | |||
341 | ||||
342 | default: | |||
343 | break; // not handled | |||
344 | } | |||
345 | } | |||
346 | ||||
347 | return UI::Panel::handle_key(down, code); | |||
348 | } | |||
349 | ||||
350 | /** | |||
351 | * Handle mouse presses: select the appropriate entry | |||
352 | */ | |||
353 | bool Table<void *>::handle_mousepress | |||
354 | (Uint8 const btn, int32_t x, int32_t const y) | |||
355 | { | |||
356 | if (get_can_focus()) | |||
357 | focus(); | |||
358 | ||||
359 | switch (btn) { | |||
360 | case SDL_BUTTON_WHEELDOWN5: | |||
361 | case SDL_BUTTON_WHEELUP4: | |||
362 | return m_scrollbar ? m_scrollbar->handle_mousepress(btn, 0, y) : false; | |||
363 | case SDL_BUTTON_LEFT1: { | |||
364 | int32_t const time = WLApplication::get()->get_time(); | |||
365 | ||||
366 | // This hick hack is needed if any of the callback functions calls clear | |||
367 | // to forget the last clicked time. | |||
368 | int32_t const real_last_click_time = m_last_click_time; | |||
369 | ||||
370 | m_last_selection = m_selection; | |||
371 | m_last_click_time = time; | |||
372 | ||||
373 | uint32_t const row = | |||
374 | (y + m_scrollpos - m_headerheight) / get_lineheight(); | |||
375 | if (row < m_entry_records.size()) { | |||
376 | select(row); | |||
377 | Columns::size_type const nr_cols = m_columns.size(); | |||
378 | for (uint8_t col = 0; col < nr_cols; ++col) { | |||
379 | Column const & column = m_columns.at(col); | |||
380 | x -= column.width; | |||
381 | if (x <= 0) { | |||
382 | if (column.is_checkbox_column) { | |||
383 | play_click(); | |||
384 | m_entry_records.at(row)->toggle(col); | |||
385 | update(0, 0, get_eff_w(), get_h()); | |||
386 | } | |||
387 | break; | |||
388 | } | |||
389 | } | |||
390 | } | |||
391 | ||||
392 | if // check if doubleclicked | |||
393 | (time - real_last_click_time < DOUBLE_CLICK_INTERVAL500 | |||
394 | and | |||
395 | m_last_selection == m_selection | |||
396 | and m_selection != no_selection_index()) | |||
397 | double_clicked(m_selection); | |||
398 | ||||
399 | return true; | |||
400 | } | |||
401 | default: | |||
402 | return false; | |||
403 | } | |||
404 | } | |||
405 | bool Table<void *>::handle_mouserelease(const Uint8 btn, int32_t, int32_t) | |||
406 | { | |||
407 | return btn == SDL_BUTTON_LEFT1; | |||
408 | } | |||
409 | ||||
410 | /** | |||
411 | * move the currently selected entry up or down. | |||
412 | * \param offset positive value move the selection down and | |||
413 | * negative values up. | |||
414 | */ | |||
415 | void Table<void *>::move_selection(const int32_t offset) | |||
416 | { | |||
417 | if (!has_selection()) return; | |||
418 | int32_t new_selection = m_selection + offset; | |||
419 | ||||
420 | if (new_selection < 0) new_selection = 0; | |||
421 | else if (static_cast<uint32_t>(new_selection) > m_entry_records.size() - 1) | |||
422 | new_selection = m_entry_records.size() - 1; | |||
423 | ||||
424 | select(static_cast<uint32_t>(new_selection)); | |||
425 | ||||
426 | //scroll to newly selected entry | |||
427 | if (m_scrollbar) | |||
428 | { | |||
429 | int32_t scroll_offset = 0; | |||
430 | if (new_selection > 0) scroll_offset = -1; | |||
431 | ||||
432 | m_scrollbar->set_scrollpos | |||
433 | ((new_selection + scroll_offset) * get_lineheight()); | |||
434 | } | |||
435 | } | |||
436 | ||||
437 | /** | |||
438 | * Change the currently selected entry | |||
439 | * | |||
440 | * Args: i the entry to select | |||
441 | */ | |||
442 | void Table<void *>::select(const uint32_t i) | |||
443 | { | |||
444 | if (m_selection == i) | |||
445 | return; | |||
446 | ||||
447 | m_selection = i; | |||
448 | ||||
449 | selected(m_selection); | |||
450 | update(0, 0, get_eff_w(), get_h()); | |||
451 | } | |||
452 | ||||
453 | /** | |||
454 | * Add a new entry to the table. | |||
455 | */ | |||
456 | Table<void *>::Entry_Record & Table<void *>::add | |||
457 | (void * const entry, const bool do_select) | |||
458 | { | |||
459 | int32_t entry_height = g_fh->get_fontheight(m_fontname, m_fontsize); | |||
460 | if (entry_height > m_lineheight) | |||
461 | m_lineheight = entry_height; | |||
462 | ||||
463 | Entry_Record & result = *new Entry_Record(entry); | |||
464 | m_entry_records.push_back(&result); | |||
465 | result.m_data.resize(m_columns.size()); | |||
466 | for | |||
467 | (wl_index_range<Columns::size_type> i(0, m_columns.size()); | |||
468 | i; ++i) | |||
469 | if (m_columns.at(i.current).is_checkbox_column) { | |||
470 | result.m_data.at(i.current).d_picture = | |||
471 | g_gr->imgcache().load(PicMod_UI, "pics/checkbox_empty.png"); | |||
472 | } | |||
473 | ||||
474 | m_scrollbar->set_steps | |||
475 | (m_entry_records.size() * get_lineheight() | |||
476 | - | |||
477 | (get_h() - m_headerheight - 2)); | |||
478 | ||||
479 | if (do_select) { | |||
480 | select(m_entry_records.size() - 1); | |||
481 | m_scrollbar->set_scrollpos(std::numeric_limits<int32_t>::max()); | |||
482 | } | |||
483 | ||||
484 | update(0, 0, get_eff_w(), get_h()); | |||
485 | return result; | |||
486 | } | |||
487 | ||||
488 | /** | |||
489 | * Scroll to the given position, in pixels. | |||
490 | */ | |||
491 | void Table<void *>::set_scrollpos(int32_t const i) | |||
492 | { | |||
493 | m_scrollpos = i; | |||
494 | ||||
495 | update(0, 0, get_eff_w(), get_h()); | |||
496 | } | |||
497 | ||||
498 | /** | |||
499 | * Remove the table entry at the given (zero-based) index. | |||
500 | */ | |||
501 | void Table<void *>::remove(const uint32_t i) { | |||
502 | assert(i < m_entry_records.size())((i < m_entry_records.size()) ? static_cast<void> (0 ) : __assert_fail ("i < m_entry_records.size()", "/home/arch/widelands/src/ui_basic/table.cc" , 502, __PRETTY_FUNCTION__)); | |||
503 | ||||
504 | const Entry_Record_vector::iterator it = m_entry_records.begin() + i; | |||
505 | delete *it; | |||
506 | m_entry_records.erase(it); | |||
507 | if (m_selection == i) | |||
508 | m_selection = no_selection_index(); | |||
509 | else if (m_selection > i && m_selection != no_selection_index()) | |||
510 | m_selection--; | |||
511 | ||||
512 | m_scrollbar->set_steps | |||
513 | (m_entry_records.size() * get_lineheight() | |||
514 | - | |||
515 | (get_h() - m_headerheight - 2)); | |||
516 | } | |||
517 | ||||
518 | bool Table<void *>::sort_helper(uint32_t a, uint32_t b) | |||
519 | { | |||
520 | if (m_sort_descending) | |||
521 | return m_columns[m_sort_column].compare(b, a); | |||
522 | else | |||
523 | return m_columns[m_sort_column].compare(a, b); | |||
524 | } | |||
525 | ||||
526 | /** | |||
527 | * Sort the table alphabetically. Make sure that the current selection stays | |||
528 | * valid (though it might scroll out of visibility). | |||
529 | * Only the subarea [start,end) is sorted. | |||
530 | * For example you might want to sort directories for themselves at the | |||
531 | * top of list and files at the bottom. | |||
532 | */ | |||
533 | void Table<void *>::sort(const uint32_t Begin, uint32_t End) | |||
534 | { | |||
535 | assert(m_columns.at(m_sort_column).btn)((m_columns.at(m_sort_column).btn) ? static_cast<void> ( 0) : __assert_fail ("m_columns.at(m_sort_column).btn", "/home/arch/widelands/src/ui_basic/table.cc" , 535, __PRETTY_FUNCTION__)); | |||
536 | assert(m_sort_column < m_columns.size())((m_sort_column < m_columns.size()) ? static_cast<void> (0) : __assert_fail ("m_sort_column < m_columns.size()", "/home/arch/widelands/src/ui_basic/table.cc" , 536, __PRETTY_FUNCTION__)); | |||
537 | ||||
538 | if (End > size()) | |||
539 | End = size(); | |||
540 | ||||
541 | std::vector<uint32_t> indices; | |||
542 | std::vector<Entry_Record *> copy; | |||
543 | ||||
544 | indices.reserve(End - Begin); | |||
545 | copy.reserve(End - Begin); | |||
546 | for (uint32_t i = Begin; i < End; ++i) { | |||
547 | indices.push_back(i); | |||
548 | copy.push_back(m_entry_records[i]); | |||
549 | } | |||
550 | ||||
551 | std::stable_sort | |||
552 | (indices.begin(), indices.end(), | |||
553 | boost::bind(&Table<void *>::sort_helper, this, _1, _2)); | |||
554 | ||||
555 | uint32_t newselection = m_selection; | |||
556 | for (uint32_t i = Begin; i < End; ++i) { | |||
557 | uint32_t from = indices[i - Begin]; | |||
558 | m_entry_records[i] = copy[from - Begin]; | |||
559 | if (m_selection == from) | |||
560 | newselection = i; | |||
561 | } | |||
562 | m_selection = newselection; | |||
563 | ||||
564 | update(); | |||
565 | } | |||
566 | ||||
567 | /** | |||
568 | * Default comparison for checkbox columns: | |||
569 | * checked items come before unchecked ones. | |||
570 | */ | |||
571 | bool Table<void *>::default_compare_checkbox | |||
572 | (uint32_t column, uint32_t a, uint32_t b) | |||
573 | { | |||
574 | Entry_Record & ea = get_record(a); | |||
575 | Entry_Record & eb = get_record(b); | |||
576 | return ea.is_checked(column) && !eb.is_checked(column); | |||
577 | } | |||
578 | ||||
579 | bool Table<void *>::default_compare_string | |||
580 | (uint32_t column, uint32_t a, uint32_t b) | |||
581 | { | |||
582 | Entry_Record & ea = get_record(a); | |||
583 | Entry_Record & eb = get_record(b); | |||
584 | return ea.get_string(column) < eb.get_string(column); | |||
585 | } | |||
586 | ||||
587 | Table<void *>::Entry_Record::Entry_Record(void * const e) | |||
588 | : m_entry(e), use_clr(false) | |||
589 | {} | |||
590 | ||||
591 | void Table<void *>::Entry_Record::set_picture | |||
592 | (uint8_t const col, const IPicture* pic, std::string const & str) | |||
593 | { | |||
594 | assert(col < m_data.size())((col < m_data.size()) ? static_cast<void> (0) : __assert_fail ("col < m_data.size()", "/home/arch/widelands/src/ui_basic/table.cc" , 594, __PRETTY_FUNCTION__)); | |||
595 | ||||
596 | m_data.at(col).d_picture = pic; | |||
597 | m_data.at(col).d_string = str; | |||
598 | } | |||
599 | void Table<void *>::Entry_Record::set_string | |||
600 | (uint8_t const col, std::string const & str) | |||
601 | { | |||
602 | assert(col < m_data.size())((col < m_data.size()) ? static_cast<void> (0) : __assert_fail ("col < m_data.size()", "/home/arch/widelands/src/ui_basic/table.cc" , 602, __PRETTY_FUNCTION__)); | |||
603 | ||||
604 | m_data.at(col).d_picture = NULL__null; | |||
605 | m_data.at(col).d_string = str; | |||
606 | } | |||
607 | const IPicture* Table<void *>::Entry_Record::get_picture(uint8_t const col) const | |||
608 | { | |||
609 | assert(col < m_data.size())((col < m_data.size()) ? static_cast<void> (0) : __assert_fail ("col < m_data.size()", "/home/arch/widelands/src/ui_basic/table.cc" , 609, __PRETTY_FUNCTION__)); | |||
610 | ||||
611 | return m_data.at(col).d_picture; | |||
612 | } | |||
613 | const std::string & Table<void *>::Entry_Record::get_string | |||
614 | (uint8_t const col) const | |||
615 | { | |||
616 | assert(col < m_data.size())((col < m_data.size()) ? static_cast<void> (0) : __assert_fail ("col < m_data.size()", "/home/arch/widelands/src/ui_basic/table.cc" , 616, __PRETTY_FUNCTION__)); | |||
617 | ||||
618 | return m_data.at(col).d_string; | |||
619 | } | |||
620 | ||||
621 | } |