163 } |
163 } |
164 |
164 |
165 return (_internal_sort_order & 1) ? maxr2 - maxr1 : maxr1 - maxr2; |
165 return (_internal_sort_order & 1) ? maxr2 - maxr1 : maxr1 - maxr2; |
166 } |
166 } |
167 |
167 |
168 /** Flags for station list */ |
168 typedef GUIList<const Station*> plstations_d; |
169 enum StationListFlags { |
|
170 SL_ORDER = 1 << 0, ///< Order - ascending (=0), descending (=1) |
|
171 SL_RESORT = 1 << 1, ///< Resort the list |
|
172 SL_REBUILD = 1 << 2, ///< Rebuild the list |
|
173 }; |
|
174 |
|
175 DECLARE_ENUM_AS_BIT_SET(StationListFlags); |
|
176 |
|
177 /** Information about station list */ |
|
178 struct plstations_d { |
|
179 const Station **sort_list; ///< Pointer to list of stations |
|
180 uint16 list_length; ///< Number of stations in list |
|
181 uint16 resort_timer; ///< Tick counter to resort the list |
|
182 byte sort_type; ///< Sort type - name, waiting, ... |
|
183 byte flags; ///< Flags - SL_ORDER, SL_RESORT, SL_REBUILD |
|
184 }; |
|
185 assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(plstations_d)); |
169 assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(plstations_d)); |
186 |
170 |
187 /** |
171 /** |
188 * Set the station sort flag for all station-list windows. |
172 * Set the station sort flag for all station-list windows. |
189 * @param sl_flag Sort list flag to set for all station-list windows |
173 * @param sl_flag Sort list flag to set for all station-list windows |
190 */ |
174 */ |
191 static void SetStationListsFlag(StationListFlags sl_flag) |
175 static void SetStationListsFlag(SortListFlags sl_flag) |
192 { |
176 { |
193 Window *const *wz; |
177 Window *const *wz; |
194 |
178 |
195 FOR_ALL_WINDOWS(wz) { |
179 FOR_ALL_WINDOWS(wz) { |
196 Window *w = *wz; |
180 Window *w = *wz; |
200 } |
184 } |
201 } |
185 } |
202 } |
186 } |
203 |
187 |
204 /** |
188 /** |
205 * Set the 'SL_REBUILD' flag for all station lists |
189 * Set the 'VL_REBUILD' flag for all station lists |
206 */ |
190 */ |
207 void RebuildStationLists() |
191 void RebuildStationLists() |
208 { |
192 { |
209 SetStationListsFlag(SL_REBUILD); |
193 SetStationListsFlag(VL_REBUILD); |
210 } |
194 } |
211 |
195 |
212 /** |
196 /** |
213 * Set the 'SL_RESORT' flag for all station lists |
197 * Set the 'VL_RESORT' flag for all station lists |
214 */ |
198 */ |
215 void ResortStationLists() |
199 void ResortStationLists() |
216 { |
200 { |
217 SetStationListsFlag(SL_RESORT); |
201 SetStationListsFlag(VL_RESORT); |
218 } |
202 } |
219 |
203 |
220 /** |
204 /** |
221 * Rebuild station list if the SL_REBUILD flag is set |
205 * Rebuild station list if the VL_REBUILD flag is set |
222 * |
206 * |
223 * @param sl pointer to plstations_d (station list and flags) |
207 * @param sl pointer to plstations_d (station list and flags) |
224 * @param owner player whose stations are to be in list |
208 * @param owner player whose stations are to be in list |
225 * @param facilities types of stations of interest |
209 * @param facilities types of stations of interest |
226 * @param cargo_filter bitmap of cargo types to include |
210 * @param cargo_filter bitmap of cargo types to include |
229 static void BuildStationsList(plstations_d *sl, PlayerID owner, byte facilities, uint32 cargo_filter, bool include_empty) |
213 static void BuildStationsList(plstations_d *sl, PlayerID owner, byte facilities, uint32 cargo_filter, bool include_empty) |
230 { |
214 { |
231 uint n = 0; |
215 uint n = 0; |
232 const Station *st; |
216 const Station *st; |
233 |
217 |
234 if (!(sl->flags & SL_REBUILD)) return; |
218 if (!(sl->flags & VL_REBUILD)) return; |
235 |
219 |
236 /* Create array for sorting */ |
220 /* Create array for sorting */ |
237 const Station **station_sort = MallocT<const Station*>(GetMaxStationIndex() + 1); |
221 const Station **station_sort = MallocT<const Station*>(GetMaxStationIndex() + 1); |
238 |
222 |
239 DEBUG(misc, 3, "Building station list for player %d", owner); |
223 DEBUG(misc, 3, "Building station list for player %d", owner); |
263 sl->sort_list = MallocT<const Station*>(n); |
247 sl->sort_list = MallocT<const Station*>(n); |
264 sl->list_length = n; |
248 sl->list_length = n; |
265 |
249 |
266 for (uint i = 0; i < n; ++i) sl->sort_list[i] = station_sort[i]; |
250 for (uint i = 0; i < n; ++i) sl->sort_list[i] = station_sort[i]; |
267 |
251 |
268 sl->flags &= ~SL_REBUILD; |
252 sl->flags &= ~VL_REBUILD; |
269 sl->flags |= SL_RESORT; |
253 sl->flags |= VL_RESORT; |
270 free((void*)station_sort); |
254 free((void*)station_sort); |
271 } |
255 } |
272 |
256 |
273 |
257 |
274 /** |
258 /** |
275 * Sort station list if the SL_RESORT flag is set |
259 * Sort station list if the VL_RESORT flag is set |
276 * |
260 * |
277 * @param sl pointer to plstations_d (station list and flags) |
261 * @param sl pointer to plstations_d (station list and flags) |
278 */ |
262 */ |
279 static void SortStationsList(plstations_d *sl) |
263 static void SortStationsList(plstations_d *sl) |
280 { |
264 { |
283 &StationTypeSorter, |
267 &StationTypeSorter, |
284 &StationWaitingSorter, |
268 &StationWaitingSorter, |
285 &StationRatingMaxSorter |
269 &StationRatingMaxSorter |
286 }; |
270 }; |
287 |
271 |
288 if (!(sl->flags & SL_RESORT)) return; |
272 if (!(sl->flags & VL_RESORT)) return; |
289 |
273 |
290 _internal_sort_order = sl->flags & SL_ORDER; |
274 _internal_sort_order = sl->flags & VL_DESC; |
291 _last_station = NULL; // used for "cache" in namesorting |
275 _last_station = NULL; // used for "cache" in namesorting |
292 qsort((void*)sl->sort_list, sl->list_length, sizeof(sl->sort_list[0]), _station_sorter[sl->sort_type]); |
276 qsort((void*)sl->sort_list, sl->list_length, sizeof(sl->sort_list[0]), _station_sorter[sl->sort_type]); |
293 |
277 |
294 sl->resort_timer = DAY_TICKS * PERIODIC_RESORT_DAYS; |
278 sl->resort_timer = DAY_TICKS * PERIODIC_RESORT_DAYS; |
295 sl->flags &= ~SL_RESORT; |
279 sl->flags &= ~VL_RESORT; |
296 } |
280 } |
297 |
281 |
298 /** |
282 /** |
299 * Fuction called when any WindowEvent occurs for PlayerStations window |
283 * Fuction called when any WindowEvent occurs for PlayerStations window |
300 * |
284 * |
320 w->SetWidgetLoweredState(SLW_FACILALL, facilities == (FACIL_TRAIN | FACIL_TRUCK_STOP | FACIL_BUS_STOP | FACIL_AIRPORT | FACIL_DOCK)); |
304 w->SetWidgetLoweredState(SLW_FACILALL, facilities == (FACIL_TRAIN | FACIL_TRUCK_STOP | FACIL_BUS_STOP | FACIL_AIRPORT | FACIL_DOCK)); |
321 w->SetWidgetLoweredState(SLW_CARGOALL, _cargo_filter == _cargo_mask && include_empty); |
305 w->SetWidgetLoweredState(SLW_CARGOALL, _cargo_filter == _cargo_mask && include_empty); |
322 w->SetWidgetLoweredState(SLW_NOCARGOWAITING, include_empty); |
306 w->SetWidgetLoweredState(SLW_NOCARGOWAITING, include_empty); |
323 |
307 |
324 sl->sort_list = NULL; |
308 sl->sort_list = NULL; |
325 sl->flags = SL_REBUILD; |
309 sl->flags = VL_REBUILD; |
326 sl->sort_type = station_sort.criteria; |
310 sl->sort_type = station_sort.criteria; |
327 if (station_sort.order) sl->flags |= SL_ORDER; |
311 if (station_sort.order) sl->flags |= VL_DESC; |
328 |
312 |
329 /* set up resort timer */ |
313 /* set up resort timer */ |
330 sl->resort_timer = DAY_TICKS * PERIODIC_RESORT_DAYS; |
314 sl->resort_timer = DAY_TICKS * PERIODIC_RESORT_DAYS; |
331 break; |
315 break; |
332 |
316 |
344 w->widget[SLW_SORTDROPBTN].data = _station_sort_listing[sl->sort_type]; |
328 w->widget[SLW_SORTDROPBTN].data = _station_sort_listing[sl->sort_type]; |
345 |
329 |
346 DrawWindowWidgets(w); |
330 DrawWindowWidgets(w); |
347 |
331 |
348 /* draw arrow pointing up/down for ascending/descending sorting */ |
332 /* draw arrow pointing up/down for ascending/descending sorting */ |
349 DrawSortButtonState(w, SLW_SORTBY, sl->flags & SL_ORDER ? SBS_DOWN : SBS_UP); |
333 DrawSortButtonState(w, SLW_SORTBY, sl->flags & VL_DESC ? SBS_DOWN : SBS_UP); |
350 |
334 |
351 int cg_ofst; |
335 int cg_ofst; |
352 int x = 89; |
336 int x = 89; |
353 int y = 14; |
337 int y = 14; |
354 int xb = 2; ///< offset from left of widget |
338 int xb = 2; ///< offset from left of widget |
447 } |
431 } |
448 SetBit(facilities, e->we.click.widget - SLW_TRAIN); |
432 SetBit(facilities, e->we.click.widget - SLW_TRAIN); |
449 w->LowerWidget(e->we.click.widget); |
433 w->LowerWidget(e->we.click.widget); |
450 } |
434 } |
451 w->SetWidgetLoweredState(SLW_FACILALL, facilities == (FACIL_TRAIN | FACIL_TRUCK_STOP | FACIL_BUS_STOP | FACIL_AIRPORT | FACIL_DOCK)); |
435 w->SetWidgetLoweredState(SLW_FACILALL, facilities == (FACIL_TRAIN | FACIL_TRUCK_STOP | FACIL_BUS_STOP | FACIL_AIRPORT | FACIL_DOCK)); |
452 sl->flags |= SL_REBUILD; |
436 sl->flags |= VL_REBUILD; |
453 w->SetDirty(); |
437 w->SetDirty(); |
454 break; |
438 break; |
455 |
439 |
456 case SLW_FACILALL: |
440 case SLW_FACILALL: |
457 for (uint i = 0; i < 5; i++) { |
441 for (uint i = 0; i < 5; i++) { |
458 w->LowerWidget(i + SLW_TRAIN); |
442 w->LowerWidget(i + SLW_TRAIN); |
459 } |
443 } |
460 w->LowerWidget(SLW_FACILALL); |
444 w->LowerWidget(SLW_FACILALL); |
461 |
445 |
462 facilities = FACIL_TRAIN | FACIL_TRUCK_STOP | FACIL_BUS_STOP | FACIL_AIRPORT | FACIL_DOCK; |
446 facilities = FACIL_TRAIN | FACIL_TRUCK_STOP | FACIL_BUS_STOP | FACIL_AIRPORT | FACIL_DOCK; |
463 sl->flags |= SL_REBUILD; |
447 sl->flags |= VL_REBUILD; |
464 w->SetDirty(); |
448 w->SetDirty(); |
465 break; |
449 break; |
466 |
450 |
467 case SLW_CARGOALL: { |
451 case SLW_CARGOALL: { |
468 uint i = 0; |
452 uint i = 0; |
474 w->LowerWidget(SLW_NOCARGOWAITING); |
458 w->LowerWidget(SLW_NOCARGOWAITING); |
475 w->LowerWidget(SLW_CARGOALL); |
459 w->LowerWidget(SLW_CARGOALL); |
476 |
460 |
477 _cargo_filter = _cargo_mask; |
461 _cargo_filter = _cargo_mask; |
478 include_empty = true; |
462 include_empty = true; |
479 sl->flags |= SL_REBUILD; |
463 sl->flags |= VL_REBUILD; |
480 w->SetDirty(); |
464 w->SetDirty(); |
481 break; |
465 break; |
482 } |
466 } |
483 |
467 |
484 case SLW_SORTBY: // flip sorting method asc/desc |
468 case SLW_SORTBY: // flip sorting method asc/desc |
485 sl->flags ^= SL_ORDER; //DESC-flag |
469 sl->flags ^= VL_DESC; //DESC-flag |
486 station_sort.order = HasBit(sl->flags, 0); |
470 station_sort.order = HasBit(sl->flags, 0); |
487 sl->flags |= SL_RESORT; |
471 sl->flags |= VL_RESORT; |
488 w->flags4 |= 5 << WF_TIMEOUT_SHL; |
472 w->flags4 |= 5 << WF_TIMEOUT_SHL; |
489 w->LowerWidget(SLW_SORTBY); |
473 w->LowerWidget(SLW_SORTBY); |
490 w->SetDirty(); |
474 w->SetDirty(); |
491 break; |
475 break; |
492 |
476 |
537 include_empty = false; |
521 include_empty = false; |
538 |
522 |
539 SetBit(_cargo_filter, c); |
523 SetBit(_cargo_filter, c); |
540 w->LowerWidget(e->we.click.widget); |
524 w->LowerWidget(e->we.click.widget); |
541 } |
525 } |
542 sl->flags |= SL_REBUILD; |
526 sl->flags |= VL_REBUILD; |
543 w->SetWidgetLoweredState(SLW_CARGOALL, _cargo_filter == _cargo_mask && include_empty); |
527 w->SetWidgetLoweredState(SLW_CARGOALL, _cargo_filter == _cargo_mask && include_empty); |
544 w->SetDirty(); |
528 w->SetDirty(); |
545 } |
529 } |
546 break; |
530 break; |
547 } |
531 } |
550 case WE_DROPDOWN_SELECT: // we have selected a dropdown item in the list |
534 case WE_DROPDOWN_SELECT: // we have selected a dropdown item in the list |
551 if (sl->sort_type != e->we.dropdown.index) { |
535 if (sl->sort_type != e->we.dropdown.index) { |
552 /* value has changed -> resort */ |
536 /* value has changed -> resort */ |
553 sl->sort_type = e->we.dropdown.index; |
537 sl->sort_type = e->we.dropdown.index; |
554 station_sort.criteria = sl->sort_type; |
538 station_sort.criteria = sl->sort_type; |
555 sl->flags |= SL_RESORT; |
539 sl->flags |= VL_RESORT; |
556 } |
540 } |
557 w->SetDirty(); |
541 w->SetDirty(); |
558 break; |
542 break; |
559 |
543 |
560 case WE_TICK: |
544 case WE_TICK: |
561 if (_pause_game != 0) break; |
545 if (_pause_game != 0) break; |
562 if (--sl->resort_timer == 0) { |
546 if (--sl->resort_timer == 0) { |
563 DEBUG(misc, 3, "Periodic rebuild station list player %d", owner); |
547 DEBUG(misc, 3, "Periodic rebuild station list player %d", owner); |
564 sl->resort_timer = DAY_TICKS * PERIODIC_RESORT_DAYS; |
548 sl->resort_timer = DAY_TICKS * PERIODIC_RESORT_DAYS; |
565 sl->flags |= SL_REBUILD; |
549 sl->flags |= VL_REBUILD; |
566 w->SetDirty(); |
550 w->SetDirty(); |
567 } |
551 } |
568 break; |
552 break; |
569 |
553 |
570 case WE_TIMEOUT: |
554 case WE_TIMEOUT: |