20 #include "player_func.h" |
20 #include "player_func.h" |
21 #include "widgets/dropdown_func.h" |
21 #include "widgets/dropdown_func.h" |
22 #include "engine_func.h" |
22 #include "engine_func.h" |
23 #include "engine_base.h" |
23 #include "engine_base.h" |
24 #include "window_gui.h" |
24 #include "window_gui.h" |
|
25 #include "engine_gui.h" |
25 |
26 |
26 #include "table/sprites.h" |
27 #include "table/sprites.h" |
27 #include "table/strings.h" |
28 #include "table/strings.h" |
28 |
29 |
29 void DrawEngineList(VehicleType type, int x, int y, const EngineList eng_list, uint16 min, uint16 max, EngineID selected_id, int count_location, GroupID selected_group); |
30 void DrawEngineList(VehicleType type, int x, int y, const GUIEngineList *eng_list, uint16 min, uint16 max, EngineID selected_id, int count_location, GroupID selected_group); |
30 |
31 |
31 static const StringID _rail_types_list[] = { |
32 static const StringID _rail_types_list[] = { |
32 STR_RAIL_VEHICLES, |
33 STR_RAIL_VEHICLES, |
33 STR_ELRAIL_VEHICLES, |
34 STR_ELRAIL_VEHICLES, |
34 STR_MONORAIL_VEHICLES, |
35 STR_MONORAIL_VEHICLES, |
182 { |
183 { |
183 EngineID selected_engine = INVALID_ENGINE; |
184 EngineID selected_engine = INVALID_ENGINE; |
184 VehicleType type = (VehicleType)this->window_number; |
185 VehicleType type = (VehicleType)this->window_number; |
185 byte i = draw_left ? 0 : 1; |
186 byte i = draw_left ? 0 : 1; |
186 |
187 |
187 EngineList *list = &this->list[i]; |
188 GUIEngineList *list = &this->list[i]; |
188 list->clear(); |
189 list->Clear(); |
189 |
190 |
190 const Engine *e; |
191 const Engine *e; |
191 FOR_ALL_ENGINES_OF_TYPE(e, type) { |
192 FOR_ALL_ENGINES_OF_TYPE(e, type) { |
192 EngineID eid = e->index; |
193 EngineID eid = e->index; |
193 if (type == VEH_TRAIN && !GenerateReplaceRailList(eid, draw_left, this->wagon_btnstate)) continue; // special rules for trains |
194 if (type == VEH_TRAIN && !GenerateReplaceRailList(eid, draw_left, this->wagon_btnstate)) continue; // special rules for trains |
206 /* Road vehicles can't be replaced by trams and vice-versa */ |
207 /* Road vehicles can't be replaced by trams and vice-versa */ |
207 if (type == VEH_ROAD && HasBit(EngInfo(this->sel_engine[0])->misc_flags, EF_ROAD_TRAM) != HasBit(e->info.misc_flags, EF_ROAD_TRAM)) continue; |
208 if (type == VEH_ROAD && HasBit(EngInfo(this->sel_engine[0])->misc_flags, EF_ROAD_TRAM) != HasBit(e->info.misc_flags, EF_ROAD_TRAM)) continue; |
208 if (eid == this->sel_engine[0]) continue; // we can't replace an engine into itself (that would be autorenew) |
209 if (eid == this->sel_engine[0]) continue; // we can't replace an engine into itself (that would be autorenew) |
209 } |
210 } |
210 |
211 |
211 list->push_back(eid); |
212 *list->Append() = eid; |
212 if (eid == this->sel_engine[i]) selected_engine = eid; // The selected engine is still in the list |
213 if (eid == this->sel_engine[i]) selected_engine = eid; // The selected engine is still in the list |
213 } |
214 } |
214 this->sel_engine[i] = selected_engine; // update which engine we selected (the same or none, if it's not in the list anymore) |
215 this->sel_engine[i] = selected_engine; // update which engine we selected (the same or none, if it's not in the list anymore) |
215 if (type == VEH_TRAIN) EngList_Sort(list, &TrainEngineNumberSorter); |
216 if (type == VEH_TRAIN) EngList_Sort(list, &TrainEngineNumberSorter); |
216 } |
217 } |
221 EngineID e = this->sel_engine[0]; |
222 EngineID e = this->sel_engine[0]; |
222 |
223 |
223 if (this->update_left == true) { |
224 if (this->update_left == true) { |
224 /* We need to rebuild the left list */ |
225 /* We need to rebuild the left list */ |
225 GenerateReplaceVehList(this, true); |
226 GenerateReplaceVehList(this, true); |
226 SetVScrollCount(this, this->list[0].size()); |
227 SetVScrollCount(this, this->list[0].Length()); |
227 if (this->init_lists && this->sel_engine[0] == INVALID_ENGINE && this->list[0].size() != 0) { |
228 if (this->init_lists && this->sel_engine[0] == INVALID_ENGINE && this->list[0].Length() != 0) { |
228 this->sel_engine[0] = this->list[0][0]; |
229 this->sel_engine[0] = this->list[0][0]; |
229 } |
230 } |
230 } |
231 } |
231 |
232 |
232 if (this->update_right || e != this->sel_engine[0]) { |
233 if (this->update_right || e != this->sel_engine[0]) { |
233 /* Either we got a request to rebuild the right list or the left list selected a different engine */ |
234 /* Either we got a request to rebuild the right list or the left list selected a different engine */ |
234 if (this->sel_engine[0] == INVALID_ENGINE) { |
235 if (this->sel_engine[0] == INVALID_ENGINE) { |
235 /* Always empty the right list when nothing is selected in the left list */ |
236 /* Always empty the right list when nothing is selected in the left list */ |
236 this->list[1].clear(); |
237 this->list[1].Clear(); |
237 this->sel_engine[1] = INVALID_ENGINE; |
238 this->sel_engine[1] = INVALID_ENGINE; |
238 } else { |
239 } else { |
239 GenerateReplaceVehList(this, false); |
240 GenerateReplaceVehList(this, false); |
240 SetVScroll2Count(this, this->list[1].size()); |
241 SetVScroll2Count(this, this->list[1].Length()); |
241 if (this->init_lists && this->sel_engine[1] == INVALID_ENGINE && this->list[1].size() != 0) { |
242 if (this->init_lists && this->sel_engine[1] == INVALID_ENGINE && this->list[1].Length() != 0) { |
242 this->sel_engine[1] = this->list[1][0]; |
243 this->sel_engine[1] = this->list[1][0]; |
243 } |
244 } |
244 } |
245 } |
245 } |
246 } |
246 /* Reset the flags about needed updates */ |
247 /* Reset the flags about needed updates */ |
251 |
252 |
252 public: |
253 public: |
253 ReplaceVehicleWindow(const WindowDesc *desc, VehicleType vehicletype, GroupID id_g) : Window(desc, vehicletype) |
254 ReplaceVehicleWindow(const WindowDesc *desc, VehicleType vehicletype, GroupID id_g) : Window(desc, vehicletype) |
254 { |
255 { |
255 this->wagon_btnstate = true; // start with locomotives (all other vehicles will not read this bool) |
256 this->wagon_btnstate = true; // start with locomotives (all other vehicles will not read this bool) |
256 new (&this->list[0]) EngineList(); |
|
257 new (&this->list[1]) EngineList(); |
|
258 this->update_left = true; |
257 this->update_left = true; |
259 this->update_right = true; |
258 this->update_right = true; |
260 this->init_lists = true; |
259 this->init_lists = true; |
261 this->sel_engine[0] = INVALID_ENGINE; |
260 this->sel_engine[0] = INVALID_ENGINE; |
262 this->sel_engine[1] = INVALID_ENGINE; |
261 this->sel_engine[1] = INVALID_ENGINE; |
378 DrawString(145, this->widget[RVW_WIDGET_INFO_TAB].top + 1, STR_02BD, TC_BLACK); |
377 DrawString(145, this->widget[RVW_WIDGET_INFO_TAB].top + 1, STR_02BD, TC_BLACK); |
379 |
378 |
380 /* Draw the lists */ |
379 /* Draw the lists */ |
381 for (byte i = 0; i < 2; i++) { |
380 for (byte i = 0; i < 2; i++) { |
382 uint widget = (i == 0) ? RVW_WIDGET_LEFT_MATRIX : RVW_WIDGET_RIGHT_MATRIX; |
381 uint widget = (i == 0) ? RVW_WIDGET_LEFT_MATRIX : RVW_WIDGET_RIGHT_MATRIX; |
383 EngineList list = this->list[i]; // which list to draw |
382 GUIEngineList *list = &this->list[i]; // which list to draw |
384 EngineID start = i == 0 ? this->vscroll.pos : this->vscroll2.pos; // what is the offset for the start (scrolling) |
383 EngineID start = i == 0 ? this->vscroll.pos : this->vscroll2.pos; // what is the offset for the start (scrolling) |
385 EngineID end = min((i == 0 ? this->vscroll.cap : this->vscroll2.cap) + start, list.size()); |
384 EngineID end = min((i == 0 ? this->vscroll.cap : this->vscroll2.cap) + start, list->Length()); |
386 |
385 |
387 /* Do the actual drawing */ |
386 /* Do the actual drawing */ |
388 DrawEngineList((VehicleType)this->window_number, this->widget[widget].left + 2, this->widget[widget].top + 1, list, start, end, this->sel_engine[i], i == 0 ? this->widget[RVW_WIDGET_LEFT_MATRIX].right - 2 : 0, selected_group); |
387 DrawEngineList((VehicleType)this->window_number, this->widget[widget].left + 2, this->widget[widget].top + 1, list, start, end, this->sel_engine[i], i == 0 ? this->widget[RVW_WIDGET_LEFT_MATRIX].right - 2 : 0, selected_group); |
389 |
388 |
390 /* Also draw the details if an engine is selected */ |
389 /* Also draw the details if an engine is selected */ |
434 case RVW_WIDGET_RIGHT_MATRIX: { |
433 case RVW_WIDGET_RIGHT_MATRIX: { |
435 uint i = (pt.y - 14) / this->resize.step_height; |
434 uint i = (pt.y - 14) / this->resize.step_height; |
436 uint16 click_scroll_pos = widget == RVW_WIDGET_LEFT_MATRIX ? this->vscroll.pos : this->vscroll2.pos; |
435 uint16 click_scroll_pos = widget == RVW_WIDGET_LEFT_MATRIX ? this->vscroll.pos : this->vscroll2.pos; |
437 uint16 click_scroll_cap = widget == RVW_WIDGET_LEFT_MATRIX ? this->vscroll.cap : this->vscroll2.cap; |
436 uint16 click_scroll_cap = widget == RVW_WIDGET_LEFT_MATRIX ? this->vscroll.cap : this->vscroll2.cap; |
438 byte click_side = widget == RVW_WIDGET_LEFT_MATRIX ? 0 : 1; |
437 byte click_side = widget == RVW_WIDGET_LEFT_MATRIX ? 0 : 1; |
439 size_t engine_count = this->list[click_side].size(); |
438 size_t engine_count = this->list[click_side].Length(); |
440 |
439 |
441 if (i < click_scroll_cap) { |
440 if (i < click_scroll_cap) { |
442 i += click_scroll_pos; |
441 i += click_scroll_pos; |
443 EngineID e = engine_count > i ? this->list[click_side][i] : INVALID_ENGINE; |
442 EngineID e = engine_count > i ? this->list[click_side][i] : INVALID_ENGINE; |
444 if (e == this->sel_engine[click_side]) break; // we clicked the one we already selected |
443 if (e == this->sel_engine[click_side]) break; // we clicked the one we already selected |