149 SetVehicleListsFlag(VL_RESORT); |
141 SetVehicleListsFlag(VL_RESORT); |
150 } |
142 } |
151 |
143 |
152 void BuildVehicleList(vehiclelist_d *vl, PlayerID owner, uint16 index, uint16 window_type) |
144 void BuildVehicleList(vehiclelist_d *vl, PlayerID owner, uint16 index, uint16 window_type) |
153 { |
145 { |
154 if (!(vl->l.flags & VL_REBUILD)) return; |
146 if (!(vl->vehicles.flags & VL_REBUILD)) return; |
155 |
147 |
156 DEBUG(misc, 3, "Building vehicle list for player %d at station %d", owner, index); |
148 DEBUG(misc, 3, "Building vehicle list for player %d at station %d", owner, index); |
157 |
149 |
158 vl->l.list_length = GenerateVehicleSortList(&vl->sort_list, &vl->length_of_sort_list, vl->vehicle_type, owner, index, window_type); |
150 vl->vehicles.list_length = GenerateVehicleSortList(&vl->vehicles.sort_list, &vl->vehicles.list_length, vl->vehicle_type, owner, index, window_type); |
159 |
151 |
160 vl->l.flags &= ~VL_REBUILD; |
152 vl->vehicles.flags &= ~VL_REBUILD; |
161 vl->l.flags |= VL_RESORT; |
153 vl->vehicles.flags |= VL_RESORT; |
162 } |
154 } |
163 |
155 |
164 /* cached values for VehicleNameSorter to spare many GetString() calls */ |
156 /* cached values for VehicleNameSorter to spare many GetString() calls */ |
165 static const Vehicle *_last_vehicle[2] = { NULL, NULL }; |
157 static const Vehicle *_last_vehicle[2] = { NULL, NULL }; |
166 static char _last_name[2][64] = { "", "" }; |
158 static char _last_name[2][64] = { "", "" }; |
167 |
159 |
168 void SortVehicleList(vehiclelist_d *vl) |
160 void SortVehicleList(vehiclelist_d *vl) |
169 { |
161 { |
170 if (!(vl->l.flags & VL_RESORT)) return; |
162 if (!(vl->vehicles.flags & VL_RESORT)) return; |
171 |
163 |
172 /* invalidate cached values for name sorter - vehicle names could change */ |
164 /* invalidate cached values for name sorter - vehicle names could change */ |
173 _last_vehicle[0] = _last_vehicle[1] = NULL; |
165 _last_vehicle[0] = _last_vehicle[1] = NULL; |
174 |
166 |
175 _internal_sort_order = (vl->l.flags & VL_DESC) != 0; |
167 _internal_sort_order = (vl->vehicles.flags & VL_DESC) != 0; |
176 qsort((void*)vl->sort_list, vl->l.list_length, sizeof(vl->sort_list[0]), |
168 qsort((void*)vl->vehicles.sort_list, vl->vehicles.list_length, sizeof(vl->vehicles.sort_list[0]), |
177 _vehicle_sorter[vl->l.sort_type]); |
169 _vehicle_sorter[vl->vehicles.sort_type]); |
178 |
170 |
179 vl->l.resort_timer = DAY_TICKS * PERIODIC_RESORT_DAYS; |
171 vl->vehicles.resort_timer = DAY_TICKS * PERIODIC_RESORT_DAYS; |
180 vl->l.flags &= ~VL_RESORT; |
172 vl->vehicles.flags &= ~VL_RESORT; |
181 } |
173 } |
182 |
174 |
183 void DepotSortList(Vehicle **v, uint16 length) |
175 void DepotSortList(Vehicle **v, uint16 length) |
184 { |
176 { |
185 _internal_sort_order = 0; |
177 _internal_sort_order = 0; |
820 vehiclelist_d *vl = &WP(w, vehiclelist_d); |
812 vehiclelist_d *vl = &WP(w, vehiclelist_d); |
821 uint16 window_type = w->window_number & VLW_MASK; |
813 uint16 window_type = w->window_number & VLW_MASK; |
822 PlayerID player = (PlayerID)GB(w->window_number, 0, 8); |
814 PlayerID player = (PlayerID)GB(w->window_number, 0, 8); |
823 |
815 |
824 vl->vehicle_type = (VehicleType)GB(w->window_number, 11, 5); |
816 vl->vehicle_type = (VehicleType)GB(w->window_number, 11, 5); |
825 vl->length_of_sort_list = 0; |
817 vl->vehicles.list_length = 0; |
826 vl->sort_list = NULL; |
818 vl->vehicles.sort_list = NULL; |
827 w->caption_color = player; |
819 w->caption_color = player; |
828 |
820 |
829 /* Hide the widgets that we will not use in this window |
821 /* Hide the widgets that we will not use in this window |
830 * Some windows contains actions only fit for the owner */ |
822 * Some windows contains actions only fit for the owner */ |
831 if (player == _local_player) { |
823 if (player == _local_player) { |
922 |
914 |
923 /* Set up sorting. Make the window-specific _sorting variable |
915 /* Set up sorting. Make the window-specific _sorting variable |
924 * point to the correct global _sorting struct so we are freed |
916 * point to the correct global _sorting struct so we are freed |
925 * from having conditionals during window operation */ |
917 * from having conditionals during window operation */ |
926 switch (vl->vehicle_type) { |
918 switch (vl->vehicle_type) { |
927 case VEH_TRAIN: vl->_sorting = &_sorting.train; break; |
919 case VEH_TRAIN: vl->sorting = &_sorting.train; break; |
928 case VEH_ROAD: vl->_sorting = &_sorting.roadveh; break; |
920 case VEH_ROAD: vl->sorting = &_sorting.roadveh; break; |
929 case VEH_SHIP: vl->_sorting = &_sorting.ship; break; |
921 case VEH_SHIP: vl->sorting = &_sorting.ship; break; |
930 case VEH_AIRCRAFT: vl->_sorting = &_sorting.aircraft; break; |
922 case VEH_AIRCRAFT: vl->sorting = &_sorting.aircraft; break; |
931 default: NOT_REACHED(); break; |
923 default: NOT_REACHED(); break; |
932 } |
924 } |
933 |
925 |
934 vl->l.flags = VL_REBUILD | (vl->_sorting->order ? VL_DESC : VL_NONE); |
926 vl->vehicles.flags = VL_REBUILD | (vl->sorting->order ? VL_DESC : VL_NONE); |
935 vl->l.sort_type = vl->_sorting->criteria; |
927 vl->vehicles.sort_type = vl->sorting->criteria; |
936 vl->sort_list = NULL; |
928 vl->vehicles.resort_timer = DAY_TICKS * PERIODIC_RESORT_DAYS; // Set up resort timer |
937 vl->l.resort_timer = DAY_TICKS * PERIODIC_RESORT_DAYS; // Set up resort timer |
|
938 } |
929 } |
939 |
930 |
940 void DrawSmallOrderList(const Vehicle *v, int x, int y) |
931 void DrawSmallOrderList(const Vehicle *v, int x, int y) |
941 { |
932 { |
942 const Order *order; |
933 const Order *order; |
971 const uint16 window_type = w->window_number & VLW_MASK; |
962 const uint16 window_type = w->window_number & VLW_MASK; |
972 const uint16 index = GB(w->window_number, 16, 16); |
963 const uint16 index = GB(w->window_number, 16, 16); |
973 |
964 |
974 BuildVehicleList(vl, owner, index, window_type); |
965 BuildVehicleList(vl, owner, index, window_type); |
975 SortVehicleList(vl); |
966 SortVehicleList(vl); |
976 SetVScrollCount(w, vl->l.list_length); |
967 SetVScrollCount(w, vl->vehicles.list_length); |
977 |
968 |
978 /* draw the widgets */ |
969 /* draw the widgets */ |
979 switch (window_type) { |
970 switch (window_type) { |
980 case VLW_SHARED_ORDERS: /* Shared Orders */ |
971 case VLW_SHARED_ORDERS: /* Shared Orders */ |
981 if (vl->l.list_length == 0) { |
972 if (vl->vehicles.list_length == 0) { |
982 /* We can't open this window without vehicles using this order |
973 /* We can't open this window without vehicles using this order |
983 * and we should close the window when deleting the order */ |
974 * and we should close the window when deleting the order */ |
984 NOT_REACHED(); |
975 NOT_REACHED(); |
985 } |
976 } |
986 SetDParam(0, w->vscroll.count); |
977 SetDParam(0, w->vscroll.count); |
1012 SetDParam(2, w->vscroll.count); |
1003 SetDParam(2, w->vscroll.count); |
1013 break; |
1004 break; |
1014 default: NOT_REACHED(); break; |
1005 default: NOT_REACHED(); break; |
1015 } |
1006 } |
1016 |
1007 |
1017 w->SetWidgetsDisabledState(vl->l.list_length == 0, |
1008 w->SetWidgetsDisabledState(vl->vehicles.list_length == 0, |
1018 VLW_WIDGET_MANAGE_VEHICLES_DROPDOWN, |
1009 VLW_WIDGET_MANAGE_VEHICLES_DROPDOWN, |
1019 VLW_WIDGET_STOP_ALL, |
1010 VLW_WIDGET_STOP_ALL, |
1020 VLW_WIDGET_START_ALL, |
1011 VLW_WIDGET_START_ALL, |
1021 WIDGET_LIST_END); |
1012 WIDGET_LIST_END); |
1022 |
1013 |
1023 DrawWindowWidgets(w); |
1014 DrawWindowWidgets(w); |
1024 |
1015 |
1025 /* draw sorting criteria string */ |
1016 /* draw sorting criteria string */ |
1026 DrawString(85, 15, _vehicle_sort_listing[vl->l.sort_type], TC_BLACK); |
1017 DrawString(85, 15, _vehicle_sort_listing[vl->vehicles.sort_type], TC_BLACK); |
1027 /* draw arrow pointing up/down for ascending/descending sorting */ |
1018 /* draw arrow pointing up/down for ascending/descending sorting */ |
1028 DrawSortButtonState(w, VLW_WIDGET_SORT_ORDER, vl->l.flags & VL_DESC ? SBS_DOWN : SBS_UP); |
1019 DrawSortButtonState(w, VLW_WIDGET_SORT_ORDER, vl->vehicles.flags & VL_DESC ? SBS_DOWN : SBS_UP); |
1029 |
1020 |
1030 max = min(w->vscroll.pos + w->vscroll.cap, vl->l.list_length); |
1021 max = min(w->vscroll.pos + w->vscroll.cap, vl->vehicles.list_length); |
1031 for (i = w->vscroll.pos; i < max; ++i) { |
1022 for (i = w->vscroll.pos; i < max; ++i) { |
1032 const Vehicle *v = vl->sort_list[i]; |
1023 const Vehicle *v = vl->vehicles.sort_list[i]; |
1033 StringID str; |
1024 StringID str; |
1034 |
1025 |
1035 SetDParam(0, v->GetDisplayProfitThisYear()); |
1026 SetDParam(0, v->GetDisplayProfitThisYear()); |
1036 SetDParam(1, v->GetDisplayProfitLastYear()); |
1027 SetDParam(1, v->GetDisplayProfitLastYear()); |
1037 |
1028 |
1082 break; |
1073 break; |
1083 |
1074 |
1084 case WE_CLICK: { |
1075 case WE_CLICK: { |
1085 switch (e->we.click.widget) { |
1076 switch (e->we.click.widget) { |
1086 case VLW_WIDGET_SORT_ORDER: /* Flip sorting method ascending/descending */ |
1077 case VLW_WIDGET_SORT_ORDER: /* Flip sorting method ascending/descending */ |
1087 vl->l.flags ^= VL_DESC; |
1078 vl->vehicles.flags ^= VL_DESC; |
1088 vl->l.flags |= VL_RESORT; |
1079 vl->vehicles.flags |= VL_RESORT; |
1089 |
1080 |
1090 vl->_sorting->order = !!(vl->l.flags & VL_DESC); |
1081 vl->sorting->order = !!(vl->vehicles.flags & VL_DESC); |
1091 w->SetDirty(); |
1082 w->SetDirty(); |
1092 break; |
1083 break; |
1093 case VLW_WIDGET_SORT_BY_PULLDOWN:/* Select sorting criteria dropdown menu */ |
1084 case VLW_WIDGET_SORT_BY_PULLDOWN:/* Select sorting criteria dropdown menu */ |
1094 ShowDropDownMenu(w, _vehicle_sort_listing, vl->l.sort_type, VLW_WIDGET_SORT_BY_PULLDOWN, 0, (vl->vehicle_type == VEH_TRAIN || vl->vehicle_type == VEH_ROAD) ? 0 : (1 << 10)); |
1085 ShowDropDownMenu(w, _vehicle_sort_listing, vl->vehicles.sort_type, VLW_WIDGET_SORT_BY_PULLDOWN, 0, (vl->vehicle_type == VEH_TRAIN || vl->vehicle_type == VEH_ROAD) ? 0 : (1 << 10)); |
1095 return; |
1086 return; |
1096 case VLW_WIDGET_LIST: { /* Matrix to show vehicles */ |
1087 case VLW_WIDGET_LIST: { /* Matrix to show vehicles */ |
1097 uint32 id_v = (e->we.click.pt.y - PLY_WND_PRC__OFFSET_TOP_WIDGET) / w->resize.step_height; |
1088 uint32 id_v = (e->we.click.pt.y - PLY_WND_PRC__OFFSET_TOP_WIDGET) / w->resize.step_height; |
1098 const Vehicle *v; |
1089 const Vehicle *v; |
1099 |
1090 |
1100 if (id_v >= w->vscroll.cap) return; // click out of bounds |
1091 if (id_v >= w->vscroll.cap) return; // click out of bounds |
1101 |
1092 |
1102 id_v += w->vscroll.pos; |
1093 id_v += w->vscroll.pos; |
1103 |
1094 |
1104 if (id_v >= vl->l.list_length) return; // click out of list bound |
1095 if (id_v >= vl->vehicles.list_length) return; // click out of list bound |
1105 |
1096 |
1106 v = vl->sort_list[id_v]; |
1097 v = vl->vehicles.sort_list[id_v]; |
1107 |
1098 |
1108 ShowVehicleViewWindow(v); |
1099 ShowVehicleViewWindow(v); |
1109 } break; |
1100 } break; |
1110 |
1101 |
1111 case VLW_WIDGET_AVAILABLE_VEHICLES: |
1102 case VLW_WIDGET_AVAILABLE_VEHICLES: |
1141 } break; |
1132 } break; |
1142 |
1133 |
1143 case WE_DROPDOWN_SELECT: /* we have selected a dropdown item in the list */ |
1134 case WE_DROPDOWN_SELECT: /* we have selected a dropdown item in the list */ |
1144 switch (e->we.dropdown.button) { |
1135 switch (e->we.dropdown.button) { |
1145 case VLW_WIDGET_SORT_BY_PULLDOWN: |
1136 case VLW_WIDGET_SORT_BY_PULLDOWN: |
1146 if (vl->l.sort_type != e->we.dropdown.index) { |
1137 if (vl->vehicles.sort_type != e->we.dropdown.index) { |
1147 /* value has changed -> resort */ |
1138 /* value has changed -> resort */ |
1148 vl->l.flags |= VL_RESORT; |
1139 vl->vehicles.flags |= VL_RESORT; |
1149 vl->l.sort_type = e->we.dropdown.index; |
1140 vl->vehicles.sort_type = e->we.dropdown.index; |
1150 vl->_sorting->criteria = vl->l.sort_type; |
1141 vl->sorting->criteria = vl->vehicles.sort_type; |
1151 } |
1142 } |
1152 break; |
1143 break; |
1153 case VLW_WIDGET_MANAGE_VEHICLES_DROPDOWN: |
1144 case VLW_WIDGET_MANAGE_VEHICLES_DROPDOWN: |
1154 assert(vl->l.list_length != 0); |
1145 assert(vl->vehicles.list_length != 0); |
1155 |
1146 |
1156 switch (e->we.dropdown.index) { |
1147 switch (e->we.dropdown.index) { |
1157 case 0: /* Replace window */ |
1148 case 0: /* Replace window */ |
1158 ShowReplaceGroupVehicleWindow(DEFAULT_GROUP, vl->vehicle_type); |
1149 ShowReplaceGroupVehicleWindow(DEFAULT_GROUP, vl->vehicle_type); |
1159 break; |
1150 break; |
1177 } |
1168 } |
1178 w->SetDirty(); |
1169 w->SetDirty(); |
1179 break; |
1170 break; |
1180 |
1171 |
1181 case WE_DESTROY: |
1172 case WE_DESTROY: |
1182 free((void*)vl->sort_list); |
1173 free((void*)vl->vehicles.sort_list); |
1183 break; |
1174 break; |
1184 |
1175 |
1185 case WE_TICK: /* resort the list every 20 seconds orso (10 days) */ |
1176 case WE_TICK: /* resort the list every 20 seconds orso (10 days) */ |
1186 if (_pause_game != 0) break; |
1177 if (_pause_game != 0) break; |
1187 if (--vl->l.resort_timer == 0) { |
1178 if (--vl->vehicles.resort_timer == 0) { |
1188 StationID station = ((w->window_number & VLW_MASK) == VLW_STATION_LIST) ? GB(w->window_number, 16, 16) : INVALID_STATION; |
1179 StationID station = ((w->window_number & VLW_MASK) == VLW_STATION_LIST) ? GB(w->window_number, 16, 16) : INVALID_STATION; |
1189 PlayerID owner = (PlayerID)w->caption_color; |
1180 PlayerID owner = (PlayerID)w->caption_color; |
1190 |
1181 |
1191 DEBUG(misc, 3, "Periodic resort %d list player %d at station %d", vl->vehicle_type, owner, station); |
1182 DEBUG(misc, 3, "Periodic resort %d list player %d at station %d", vl->vehicle_type, owner, station); |
1192 vl->l.resort_timer = DAY_TICKS * PERIODIC_RESORT_DAYS; |
1183 vl->vehicles.resort_timer = DAY_TICKS * PERIODIC_RESORT_DAYS; |
1193 vl->l.flags |= VL_RESORT; |
1184 vl->vehicles.flags |= VL_RESORT; |
1194 w->SetDirty(); |
1185 w->SetDirty(); |
1195 } |
1186 } |
1196 break; |
1187 break; |
1197 |
1188 |
1198 case WE_RESIZE: /* Update the scroll + matrix */ |
1189 case WE_RESIZE: /* Update the scroll + matrix */ |