27 |
27 |
28 #include "table/strings.h" |
28 #include "table/strings.h" |
29 #include "table/sprites.h" |
29 #include "table/sprites.h" |
30 |
30 |
31 typedef GUIList<const Group*> GUIGroupList; |
31 typedef GUIList<const Group*> GUIGroupList; |
32 |
|
33 static void BuildGroupList(GUIGroupList *gl, PlayerID owner, VehicleType vehicle_type) |
|
34 { |
|
35 if (!(gl->flags & VL_REBUILD)) return; |
|
36 |
|
37 gl->Clear(); |
|
38 |
|
39 const Group *g; |
|
40 FOR_ALL_GROUPS(g) { |
|
41 if (g->owner == owner && g->vehicle_type != vehicle_type) *gl->Append() = g; |
|
42 } |
|
43 |
|
44 gl->Compact(); |
|
45 |
|
46 gl->flags &= ~VL_REBUILD; |
|
47 gl->flags |= VL_RESORT; |
|
48 } |
|
49 |
|
50 |
|
51 static int CDECL GroupNameSorter(const void *a, const void *b) |
|
52 { |
|
53 static const Group *last_group[2] = { NULL, NULL }; |
|
54 static char last_name[2][64] = { "", "" }; |
|
55 |
|
56 const Group *ga = *(const Group**)a; |
|
57 const Group *gb = *(const Group**)b; |
|
58 int r; |
|
59 |
|
60 if (ga != last_group[0]) { |
|
61 last_group[0] = ga; |
|
62 SetDParam(0, ga->index); |
|
63 GetString(last_name[0], STR_GROUP_NAME, lastof(last_name[0])); |
|
64 } |
|
65 |
|
66 if (gb != last_group[1]) { |
|
67 last_group[1] = gb; |
|
68 SetDParam(0, gb->index); |
|
69 GetString(last_name[1], STR_GROUP_NAME, lastof(last_name[1])); |
|
70 } |
|
71 |
|
72 r = strcmp(last_name[0], last_name[1]); // sort by name |
|
73 |
|
74 if (r == 0) return ga->index - gb->index; |
|
75 |
|
76 return r; |
|
77 } |
|
78 |
|
79 |
|
80 static void SortGroupList(GUIGroupList *gl) |
|
81 { |
|
82 if (!(gl->flags & VL_RESORT)) return; |
|
83 |
|
84 qsort((void*)gl->Begin(), gl->Length(), sizeof(gl->Begin()), GroupNameSorter); |
|
85 |
|
86 gl->resort_timer = DAY_TICKS * PERIODIC_RESORT_DAYS; |
|
87 gl->flags &= ~VL_RESORT; |
|
88 } |
|
89 |
|
90 |
32 |
91 enum GroupListWidgets { |
33 enum GroupListWidgets { |
92 GRP_WIDGET_CLOSEBOX = 0, |
34 GRP_WIDGET_CLOSEBOX = 0, |
93 GRP_WIDGET_CAPTION, |
35 GRP_WIDGET_CAPTION, |
94 GRP_WIDGET_STICKY, |
36 GRP_WIDGET_STICKY, |
174 { WWT_RESIZEBOX, RESIZE_LRTB, 14, 448, 459, 182, 193, 0x0, STR_RESIZE_BUTTON}, |
116 { WWT_RESIZEBOX, RESIZE_LRTB, 14, 448, 459, 182, 193, 0x0, STR_RESIZE_BUTTON}, |
175 { WIDGETS_END}, |
117 { WIDGETS_END}, |
176 }; |
118 }; |
177 |
119 |
178 |
120 |
179 struct VehicleGroupWindow : public Window, public VehicleListBase { |
121 class VehicleGroupWindow : public Window, public VehicleListBase { |
|
122 private: |
180 GroupID group_sel; |
123 GroupID group_sel; |
181 VehicleID vehicle_sel; |
124 VehicleID vehicle_sel; |
182 GUIGroupList groups; |
125 GUIGroupList groups; |
183 |
126 |
|
127 /** |
|
128 * (Re)Build the group list. |
|
129 * |
|
130 * @param owner The owner of the window |
|
131 */ |
|
132 void BuildGroupList(PlayerID owner) |
|
133 { |
|
134 if (!this->groups.NeedRebuild()) return; |
|
135 |
|
136 this->groups.Clear(); |
|
137 |
|
138 const Group *g; |
|
139 FOR_ALL_GROUPS(g) { |
|
140 if (g->owner == owner && g->vehicle_type == this->vehicle_type) { |
|
141 *this->groups.Append() = g; |
|
142 } |
|
143 } |
|
144 |
|
145 this->groups.Compact(); |
|
146 this->groups.RebuildDone(); |
|
147 } |
|
148 |
|
149 /** Sort the groups by their name */ |
|
150 static int GroupNameSorter(const Group* const *a, const Group* const *b) |
|
151 { |
|
152 static const Group *last_group[2] = { NULL, NULL }; |
|
153 static char last_name[2][64] = { "", "" }; |
|
154 |
|
155 if (*a != last_group[0]) { |
|
156 last_group[0] = *a; |
|
157 SetDParam(0, (*a)->index); |
|
158 GetString(last_name[0], STR_GROUP_NAME, lastof(last_name[0])); |
|
159 } |
|
160 |
|
161 if (*b != last_group[1]) { |
|
162 last_group[1] = *b; |
|
163 SetDParam(0, (*b)->index); |
|
164 GetString(last_name[1], STR_GROUP_NAME, lastof(last_name[1])); |
|
165 } |
|
166 |
|
167 int r = strcmp(last_name[0], last_name[1]); // sort by name |
|
168 if (r == 0) return (*a)->index - (*b)->index; |
|
169 return r; |
|
170 } |
|
171 |
|
172 public: |
184 VehicleGroupWindow(const WindowDesc *desc, WindowNumber window_number) : Window(desc, window_number) |
173 VehicleGroupWindow(const WindowDesc *desc, WindowNumber window_number) : Window(desc, window_number) |
185 { |
174 { |
186 const PlayerID owner = (PlayerID)GB(this->window_number, 0, 8); |
175 const PlayerID owner = (PlayerID)GB(this->window_number, 0, 8); |
187 this->vehicle_type = (VehicleType)GB(this->window_number, 11, 5); |
176 this->vehicle_type = (VehicleType)GB(this->window_number, 11, 5); |
188 |
177 |
219 |
208 |
220 this->vehicles.sort_type = this->sorting->criteria; |
209 this->vehicles.sort_type = this->sorting->criteria; |
221 this->vehicles.flags = VL_REBUILD | (this->sorting->order ? VL_DESC : VL_NONE); |
210 this->vehicles.flags = VL_REBUILD | (this->sorting->order ? VL_DESC : VL_NONE); |
222 this->vehicles.resort_timer = DAY_TICKS * PERIODIC_RESORT_DAYS; // Set up resort timer |
211 this->vehicles.resort_timer = DAY_TICKS * PERIODIC_RESORT_DAYS; // Set up resort timer |
223 |
212 |
224 this->groups.flags = VL_REBUILD | VL_NONE; |
213 this->groups.ForceRebuild(); |
225 this->groups.resort_timer = DAY_TICKS * PERIODIC_RESORT_DAYS; // Set up resort timer |
214 this->groups.NeedResort(); |
226 |
215 |
227 this->group_sel = ALL_GROUP; |
216 this->group_sel = ALL_GROUP; |
228 this->vehicle_sel = INVALID_VEHICLE; |
217 this->vehicle_sel = INVALID_VEHICLE; |
229 |
218 |
230 switch (this->vehicle_type) { |
219 switch (this->vehicle_type) { |
275 } |
264 } |
276 |
265 |
277 virtual void OnInvalidateData(int data) |
266 virtual void OnInvalidateData(int data) |
278 { |
267 { |
279 this->vehicles.flags |= (data == 0 ? VL_REBUILD : VL_RESORT); |
268 this->vehicles.flags |= (data == 0 ? VL_REBUILD : VL_RESORT); |
280 this->groups.flags |= (data == 0 ? VL_REBUILD : VL_RESORT); |
269 |
|
270 if (data == 0) { |
|
271 this->groups.ForceRebuild(); |
|
272 } else { |
|
273 this->groups.ForceResort(); |
|
274 } |
|
275 |
281 if (!(IsAllGroupID(this->group_sel) || IsDefaultGroupID(this->group_sel) || IsValidGroupID(this->group_sel))) { |
276 if (!(IsAllGroupID(this->group_sel) || IsDefaultGroupID(this->group_sel) || IsValidGroupID(this->group_sel))) { |
282 this->group_sel = ALL_GROUP; |
277 this->group_sel = ALL_GROUP; |
283 HideDropDownMenu(this); |
278 HideDropDownMenu(this); |
284 } |
279 } |
285 this->SetDirty(); |
280 this->SetDirty(); |
297 /* If we select the all vehicles, this->list will contain all vehicles of the player |
292 /* If we select the all vehicles, this->list will contain all vehicles of the player |
298 * else this->list will contain all vehicles which belong to the selected group */ |
293 * else this->list will contain all vehicles which belong to the selected group */ |
299 BuildVehicleList(this, owner, this->group_sel, IsAllGroupID(this->group_sel) ? VLW_STANDARD : VLW_GROUP_LIST); |
294 BuildVehicleList(this, owner, this->group_sel, IsAllGroupID(this->group_sel) ? VLW_STANDARD : VLW_GROUP_LIST); |
300 SortVehicleList(this); |
295 SortVehicleList(this); |
301 |
296 |
302 |
297 this->BuildGroupList(owner); |
303 BuildGroupList(&this->groups, owner, this->vehicle_type); |
298 this->groups.Sort(GroupNameSorter); |
304 SortGroupList(&this->groups); |
|
305 |
299 |
306 SetVScrollCount(this, this->groups.Length()); |
300 SetVScrollCount(this, this->groups.Length()); |
307 SetVScroll2Count(this, this->vehicles.Length()); |
301 SetVScroll2Count(this, this->vehicles.Length()); |
308 |
302 |
309 /* The drop down menu is out, *but* it may not be used, retract it. */ |
303 /* The drop down menu is out, *but* it may not be used, retract it. */ |
724 if (--this->vehicles.resort_timer == 0) { |
718 if (--this->vehicles.resort_timer == 0) { |
725 this->vehicles.resort_timer = DAY_TICKS * PERIODIC_RESORT_DAYS; |
719 this->vehicles.resort_timer = DAY_TICKS * PERIODIC_RESORT_DAYS; |
726 this->vehicles.flags |= VL_RESORT; |
720 this->vehicles.flags |= VL_RESORT; |
727 this->SetDirty(); |
721 this->SetDirty(); |
728 } |
722 } |
729 if (--this->groups.resort_timer == 0) { |
723 if (this->groups.NeedResort()) { |
730 this->groups.resort_timer = DAY_TICKS * PERIODIC_RESORT_DAYS; |
|
731 this->groups.flags |= VL_RESORT; |
|
732 this->SetDirty(); |
724 this->SetDirty(); |
733 } |
725 } |
734 } |
726 } |
735 |
727 |
736 virtual void OnPlaceObjectAbort() |
728 virtual void OnPlaceObjectAbort() |