00001
00002
00003
00004
00005
00006
00007
00008
00009
00012 #include "stdafx.h"
00013 #include "openttd.h"
00014 #include "gui.h"
00015 #include "textbuf_gui.h"
00016 #include "command_func.h"
00017 #include "viewport_func.h"
00018 #include "gfx_func.h"
00019 #include "industry.h"
00020 #include "town.h"
00021 #include "variables.h"
00022 #include "cheat_type.h"
00023 #include "newgrf.h"
00024 #include "newgrf_industries.h"
00025 #include "newgrf_text.h"
00026 #include "strings_func.h"
00027 #include "company_func.h"
00028 #include "tilehighlight_func.h"
00029 #include "string_func.h"
00030 #include "sortlist_type.h"
00031 #include "widgets/dropdown_func.h"
00032 #include "company_base.h"
00033 #include "core/geometry_func.hpp"
00034 #include "core/random_func.hpp"
00035
00036 #include "table/strings.h"
00037 #include "table/sprites.h"
00038
00039 bool _ignore_restrictions;
00040
00042 enum CargoSuffixType {
00043 CST_FUND,
00044 CST_VIEW,
00045 CST_DIR,
00046 };
00047
00063 static void GetCargoSuffix(uint cargo, CargoSuffixType cst, const Industry *ind, IndustryType ind_type, const IndustrySpec *indspec, char *suffix, const char *suffix_last)
00064 {
00065 suffix[0] = '\0';
00066 if (HasBit(indspec->callback_mask, CBM_IND_CARGO_SUFFIX)) {
00067 uint16 callback = GetIndustryCallback(CBID_INDUSTRY_CARGO_SUFFIX, 0, (cst << 8) | cargo, const_cast<Industry *>(ind), ind_type, (cst != CST_FUND) ? ind->location.tile : INVALID_TILE);
00068 if (GB(callback, 0, 8) != 0xFF) {
00069 PrepareTextRefStackUsage(6);
00070 GetString(suffix, GetGRFStringID(indspec->grf_prop.grffile->grfid, 0xD000 + callback), suffix_last);
00071 StopTextRefStackUsage();
00072 }
00073 }
00074 }
00075
00086 template <typename TC, typename TS>
00087 static inline void GetAllCargoSuffixes(uint cb_offset, CargoSuffixType cst, const Industry *ind, IndustryType ind_type, const IndustrySpec *indspec, const TC &cargos, TS &suffixes)
00088 {
00089 assert_compile(lengthof(cargos) <= lengthof(suffixes));
00090 for (uint j = 0; j < lengthof(cargos); j++) {
00091 if (cargos[j] != CT_INVALID) {
00092 GetCargoSuffix(cb_offset + j, cst, ind, ind_type, indspec, suffixes[j], lastof(suffixes[j]));
00093 } else {
00094 suffixes[j][0] = '\0';
00095 }
00096 }
00097 }
00098
00100 enum DynamicPlaceIndustriesWidgets {
00101 DPIW_MATRIX_WIDGET,
00102 DPIW_SCROLLBAR,
00103 DPIW_INFOPANEL,
00104 DPIW_FUND_WIDGET,
00105 };
00106
00107 static const NWidgetPart _nested_build_industry_widgets[] = {
00108 NWidget(NWID_HORIZONTAL),
00109 NWidget(WWT_CLOSEBOX, COLOUR_DARK_GREEN),
00110 NWidget(WWT_CAPTION, COLOUR_DARK_GREEN), SetDataTip(STR_FUND_INDUSTRY_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
00111 NWidget(WWT_SHADEBOX, COLOUR_DARK_GREEN),
00112 NWidget(WWT_STICKYBOX, COLOUR_DARK_GREEN),
00113 EndContainer(),
00114 NWidget(NWID_HORIZONTAL),
00115 NWidget(WWT_MATRIX, COLOUR_DARK_GREEN, DPIW_MATRIX_WIDGET), SetDataTip(0x801, STR_FUND_INDUSTRY_SELECTION_TOOLTIP), SetFill(1, 0), SetResize(1, 1),
00116 NWidget(WWT_SCROLLBAR, COLOUR_DARK_GREEN, DPIW_SCROLLBAR),
00117 EndContainer(),
00118 NWidget(WWT_PANEL, COLOUR_DARK_GREEN, DPIW_INFOPANEL), SetResize(1, 0),
00119 EndContainer(),
00120 NWidget(NWID_HORIZONTAL),
00121 NWidget(WWT_TEXTBTN, COLOUR_DARK_GREEN, DPIW_FUND_WIDGET), SetFill(1, 0), SetResize(1, 0), SetDataTip(STR_JUST_STRING, STR_NULL),
00122 NWidget(WWT_RESIZEBOX, COLOUR_DARK_GREEN),
00123 EndContainer(),
00124 };
00125
00127 static const WindowDesc _build_industry_desc(
00128 WDP_AUTO, 170, 212,
00129 WC_BUILD_INDUSTRY, WC_NONE,
00130 WDF_CONSTRUCTION,
00131 _nested_build_industry_widgets, lengthof(_nested_build_industry_widgets)
00132 );
00133
00135 class BuildIndustryWindow : public Window {
00136 int selected_index;
00137 IndustryType selected_type;
00138 uint16 callback_timer;
00139 bool timer_enabled;
00140 uint16 count;
00141 IndustryType index[NUM_INDUSTRYTYPES + 1];
00142 bool enabled[NUM_INDUSTRYTYPES + 1];
00143
00145 static const int MATRIX_TEXT_OFFSET = 17;
00146
00147 void SetupArrays()
00148 {
00149 this->count = 0;
00150
00151 for (uint i = 0; i < lengthof(this->index); i++) {
00152 this->index[i] = INVALID_INDUSTRYTYPE;
00153 this->enabled[i] = false;
00154 }
00155
00156 if (_game_mode == GM_EDITOR) {
00157 this->index[this->count] = INVALID_INDUSTRYTYPE;
00158 this->enabled[this->count] = true;
00159 this->count++;
00160 this->timer_enabled = false;
00161 }
00162
00163
00164
00165
00166 for (IndustryType ind = 0; ind < NUM_INDUSTRYTYPES; ind++) {
00167 const IndustrySpec *indsp = GetIndustrySpec(ind);
00168 if (indsp->enabled) {
00169
00170
00171
00172 if (_game_mode != GM_EDITOR && indsp->IsRawIndustry() && _settings_game.construction.raw_industry_construction == 0) {
00173
00174 if (this->selected_type == ind) this->selected_index = -1;
00175 continue;
00176 }
00177 this->index[this->count] = ind;
00178 this->enabled[this->count] = (_game_mode == GM_EDITOR) || CheckIfCallBackAllowsAvailability(ind, IACT_USERCREATION);
00179
00180 if (this->selected_type == ind) this->selected_index = this->count;
00181 this->count++;
00182 }
00183 }
00184
00185
00186
00187 if (this->selected_index == -1) {
00188 this->selected_index = 0;
00189 this->selected_type = this->index[0];
00190 }
00191
00192 this->vscroll.SetCount(this->count);
00193 }
00194
00195 public:
00196 BuildIndustryWindow() : Window()
00197 {
00198 this->timer_enabled = _loaded_newgrf_features.has_newindustries;
00199
00200 this->selected_index = -1;
00201 this->selected_type = INVALID_INDUSTRYTYPE;
00202
00203
00204 this->SetupArrays();
00205
00206 this->callback_timer = DAY_TICKS;
00207
00208 this->InitNested(&_build_industry_desc, 0);
00209 }
00210
00211 virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
00212 {
00213 switch (widget) {
00214 case DPIW_MATRIX_WIDGET: {
00215 Dimension d = GetStringBoundingBox(STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES);
00216 for (byte i = 0; i < this->count; i++) {
00217 if (this->index[i] == INVALID_INDUSTRYTYPE) continue;
00218 d = maxdim(d, GetStringBoundingBox(GetIndustrySpec(this->index[i])->name));
00219 }
00220 resize->height = FONT_HEIGHT_NORMAL + WD_MATRIX_TOP + WD_MATRIX_BOTTOM;
00221 d.width += MATRIX_TEXT_OFFSET + padding.width;
00222 d.height = 5 * resize->height;
00223 *size = maxdim(*size, d);
00224 break;
00225 }
00226
00227 case DPIW_INFOPANEL: {
00228
00229 int height = 2 + (_game_mode == GM_EDITOR ? 0 : 1) + (_loaded_newgrf_features.has_newindustries ? 4 : 0);
00230 Dimension d = {0, 0};
00231 for (byte i = 0; i < this->count; i++) {
00232 if (this->index[i] == INVALID_INDUSTRYTYPE) continue;
00233
00234 const IndustrySpec *indsp = GetIndustrySpec(this->index[i]);
00235
00236 char cargo_suffix[3][512];
00237 GetAllCargoSuffixes(0, CST_FUND, NULL, this->index[i], indsp, indsp->accepts_cargo, cargo_suffix);
00238 StringID str = STR_INDUSTRY_VIEW_REQUIRES_CARGO;
00239 byte p = 0;
00240 SetDParam(0, STR_JUST_NOTHING);
00241 SetDParamStr(1, "");
00242 for (byte j = 0; j < lengthof(indsp->accepts_cargo); j++) {
00243 if (indsp->accepts_cargo[j] == CT_INVALID) continue;
00244 if (p > 0) str++;
00245 SetDParam(p++, CargoSpec::Get(indsp->accepts_cargo[j])->name);
00246 SetDParamStr(p++, cargo_suffix[j]);
00247 }
00248 d = maxdim(d, GetStringBoundingBox(str));
00249
00250
00251 GetAllCargoSuffixes(3, CST_FUND, NULL, this->index[i], indsp, indsp->produced_cargo, cargo_suffix);
00252 str = STR_INDUSTRY_VIEW_PRODUCES_CARGO;
00253 p = 0;
00254 SetDParam(0, STR_JUST_NOTHING);
00255 SetDParamStr(1, "");
00256 for (byte j = 0; j < lengthof(indsp->produced_cargo); j++) {
00257 if (indsp->produced_cargo[j] == CT_INVALID) continue;
00258 if (p > 0) str++;
00259 SetDParam(p++, CargoSpec::Get(indsp->produced_cargo[j])->name);
00260 SetDParamStr(p++, cargo_suffix[j]);
00261 }
00262 d = maxdim(d, GetStringBoundingBox(str));
00263 }
00264
00265
00266 size->height = height * FONT_HEIGHT_NORMAL + WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM;
00267 size->width = d.width + WD_FRAMERECT_LEFT + WD_FRAMERECT_RIGHT;
00268 } break;
00269
00270 case DPIW_FUND_WIDGET: {
00271 Dimension d = GetStringBoundingBox(STR_FUND_INDUSTRY_BUILD_NEW_INDUSTRY);
00272 d = maxdim(d, GetStringBoundingBox(STR_FUND_INDUSTRY_PROSPECT_NEW_INDUSTRY));
00273 d = maxdim(d, GetStringBoundingBox(STR_FUND_INDUSTRY_FUND_NEW_INDUSTRY));
00274 d.width += padding.width;
00275 d.height += padding.height;
00276 *size = maxdim(*size, d);
00277 break;
00278 }
00279 }
00280 }
00281
00282 virtual void SetStringParameters(int widget) const
00283 {
00284 switch (widget) {
00285 case DPIW_FUND_WIDGET:
00286
00287
00288 if (_game_mode == GM_EDITOR) {
00289
00290 SetDParam(0, STR_FUND_INDUSTRY_BUILD_NEW_INDUSTRY);
00291 } else {
00292 const IndustrySpec *indsp = GetIndustrySpec(this->index[this->selected_index]);
00293 SetDParam(0, (_settings_game.construction.raw_industry_construction == 2 && indsp->IsRawIndustry()) ? STR_FUND_INDUSTRY_PROSPECT_NEW_INDUSTRY : STR_FUND_INDUSTRY_FUND_NEW_INDUSTRY);
00294 }
00295 break;
00296 }
00297 }
00298
00299 virtual void DrawWidget(const Rect &r, int widget) const
00300 {
00301 switch (widget) {
00302 case DPIW_MATRIX_WIDGET:
00303 for (byte i = 0; i < this->vscroll.GetCapacity() && i + this->vscroll.GetPosition() < this->count; i++) {
00304 int x = r.left + WD_MATRIX_LEFT;
00305 int y = r.top + WD_MATRIX_TOP + i * this->resize.step_height;
00306 bool selected = this->selected_index == i + this->vscroll.GetPosition();
00307
00308 if (this->index[i + this->vscroll.GetPosition()] == INVALID_INDUSTRYTYPE) {
00309 DrawString(x + MATRIX_TEXT_OFFSET, r.right - WD_MATRIX_RIGHT, y, STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES, selected ? TC_WHITE : TC_ORANGE);
00310 continue;
00311 }
00312 const IndustrySpec *indsp = GetIndustrySpec(this->index[i + this->vscroll.GetPosition()]);
00313
00314
00315 DrawString(x + MATRIX_TEXT_OFFSET, r.right - WD_MATRIX_RIGHT, y, indsp->name, selected ? TC_WHITE : TC_ORANGE);
00316 GfxFillRect(x, y + 1, x + 10, y + 7, selected ? 15 : 0);
00317 GfxFillRect(x + 1, y + 2, x + 9, y + 6, indsp->map_colour);
00318 }
00319 break;
00320
00321 case DPIW_INFOPANEL: {
00322 int y = r.top + WD_FRAMERECT_TOP;
00323 int bottom = r.bottom - WD_FRAMERECT_BOTTOM;
00324 int left = r.left + WD_FRAMERECT_LEFT;
00325 int right = r.right - WD_FRAMERECT_RIGHT;
00326
00327 if (this->selected_type == INVALID_INDUSTRYTYPE) {
00328 DrawStringMultiLine(left, right, y, bottom, STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES_TOOLTIP);
00329 break;
00330 }
00331
00332 const IndustrySpec *indsp = GetIndustrySpec(this->selected_type);
00333
00334 if (_game_mode != GM_EDITOR) {
00335 SetDParam(0, indsp->GetConstructionCost());
00336 DrawString(left, right, y, STR_FUND_INDUSTRY_INDUSTRY_BUILD_COST);
00337 y += FONT_HEIGHT_NORMAL;
00338 }
00339
00340
00341 char cargo_suffix[3][512];
00342 GetAllCargoSuffixes(0, CST_FUND, NULL, this->selected_type, indsp, indsp->accepts_cargo, cargo_suffix);
00343 StringID str = STR_INDUSTRY_VIEW_REQUIRES_CARGO;
00344 byte p = 0;
00345 SetDParam(0, STR_JUST_NOTHING);
00346 SetDParamStr(1, "");
00347 for (byte j = 0; j < lengthof(indsp->accepts_cargo); j++) {
00348 if (indsp->accepts_cargo[j] == CT_INVALID) continue;
00349 if (p > 0) str++;
00350 SetDParam(p++, CargoSpec::Get(indsp->accepts_cargo[j])->name);
00351 SetDParamStr(p++, cargo_suffix[j]);
00352 }
00353 DrawString(left, right, y, str);
00354 y += FONT_HEIGHT_NORMAL;
00355
00356
00357 GetAllCargoSuffixes(3, CST_FUND, NULL, this->selected_type, indsp, indsp->produced_cargo, cargo_suffix);
00358 str = STR_INDUSTRY_VIEW_PRODUCES_CARGO;
00359 p = 0;
00360 SetDParam(0, STR_JUST_NOTHING);
00361 SetDParamStr(1, "");
00362 for (byte j = 0; j < lengthof(indsp->produced_cargo); j++) {
00363 if (indsp->produced_cargo[j] == CT_INVALID) continue;
00364 if (p > 0) str++;
00365 SetDParam(p++, CargoSpec::Get(indsp->produced_cargo[j])->name);
00366 SetDParamStr(p++, cargo_suffix[j]);
00367 }
00368 DrawString(left, right, y, str);
00369 y += FONT_HEIGHT_NORMAL;
00370
00371
00372 str = STR_NULL;
00373 if (HasBit(indsp->callback_mask, CBM_IND_FUND_MORE_TEXT)) {
00374 uint16 callback_res = GetIndustryCallback(CBID_INDUSTRY_FUND_MORE_TEXT, 0, 0, NULL, this->selected_type, INVALID_TILE);
00375 if (callback_res != CALLBACK_FAILED) {
00376 str = GetGRFStringID(indsp->grf_prop.grffile->grfid, 0xD000 + callback_res);
00377 }
00378 }
00379
00380
00381
00382 if (str != STR_NULL && str != STR_UNDEFINED) {
00383 SetDParam(0, str);
00384 DrawStringMultiLine(left, right, y, bottom, STR_JUST_STRING);
00385 }
00386 } break;
00387 }
00388 }
00389
00390 virtual void OnPaint()
00391 {
00392 this->DrawWidgets();
00393 }
00394
00395 virtual void OnClick(Point pt, int widget, int click_count)
00396 {
00397 switch (widget) {
00398 case DPIW_MATRIX_WIDGET: {
00399 const IndustrySpec *indsp;
00400 int y = (pt.y - this->GetWidget<NWidgetBase>(DPIW_MATRIX_WIDGET)->pos_y) / this->resize.step_height + this->vscroll.GetPosition();
00401
00402 if (y >= 0 && y < count) {
00403 this->selected_index = y;
00404 this->selected_type = this->index[y];
00405 indsp = (this->selected_type == INVALID_INDUSTRYTYPE) ? NULL : GetIndustrySpec(this->selected_type);
00406
00407 this->SetDirty();
00408
00409 if ((_game_mode != GM_EDITOR && _settings_game.construction.raw_industry_construction == 2 && indsp != NULL && indsp->IsRawIndustry()) ||
00410 this->selected_type == INVALID_INDUSTRYTYPE) {
00411
00412 this->RaiseButtons();
00413 ResetObjectToPlace();
00414 }
00415
00416 this->SetWidgetDisabledState(DPIW_FUND_WIDGET, !this->enabled[this->selected_index]);
00417 if (this->enabled[this->selected_index] && click_count > 1) this->OnClick(pt, DPIW_FUND_WIDGET, 1);
00418 }
00419 } break;
00420
00421 case DPIW_FUND_WIDGET: {
00422 if (this->selected_type == INVALID_INDUSTRYTYPE) {
00423 this->HandleButtonClick(DPIW_FUND_WIDGET);
00424
00425 if (Town::GetNumItems() == 0) {
00426 ShowErrorMessage(STR_ERROR_CAN_T_GENERATE_INDUSTRIES, STR_ERROR_MUST_FOUND_TOWN_FIRST, 0, 0);
00427 } else {
00428 extern void GenerateIndustries();
00429 _generating_world = true;
00430 GenerateIndustries();
00431 _generating_world = false;
00432 }
00433 } else if (_game_mode != GM_EDITOR && _settings_game.construction.raw_industry_construction == 2 && GetIndustrySpec(this->selected_type)->IsRawIndustry()) {
00434 DoCommandP(0, this->selected_type, InteractiveRandom(), CMD_BUILD_INDUSTRY | CMD_MSG(STR_ERROR_CAN_T_CONSTRUCT_THIS_INDUSTRY));
00435 this->HandleButtonClick(DPIW_FUND_WIDGET);
00436 } else {
00437 HandlePlacePushButton(this, DPIW_FUND_WIDGET, SPR_CURSOR_INDUSTRY, HT_RECT, NULL);
00438 }
00439 } break;
00440 }
00441 }
00442
00443 virtual void OnResize()
00444 {
00445
00446 this->vscroll.SetCapacityFromWidget(this, DPIW_MATRIX_WIDGET);
00447 this->GetWidget<NWidgetCore>(DPIW_MATRIX_WIDGET)->widget_data = (this->vscroll.GetCapacity() << MAT_ROW_START) + (1 << MAT_COL_START);
00448 }
00449
00450 virtual void OnPlaceObject(Point pt, TileIndex tile)
00451 {
00452 bool success = true;
00453
00454 const IndustrySpec *indsp = GetIndustrySpec(this->selected_type);
00455 uint32 seed = InteractiveRandom();
00456
00457 if (_game_mode == GM_EDITOR) {
00458
00459 if (Town::GetNumItems() == 0) {
00460 SetDParam(0, indsp->name);
00461 ShowErrorMessage(STR_ERROR_CAN_T_BUILD_HERE, STR_ERROR_MUST_FOUND_TOWN_FIRST, pt.x, pt.y);
00462 return;
00463 }
00464
00465 _current_company = OWNER_NONE;
00466 _generating_world = true;
00467 _ignore_restrictions = true;
00468 success = DoCommandP(tile, (InteractiveRandomRange(indsp->num_table) << 8) | this->selected_type, seed, CMD_BUILD_INDUSTRY | CMD_MSG(STR_ERROR_CAN_T_CONSTRUCT_THIS_INDUSTRY));
00469 if (!success) {
00470 SetDParam(0, indsp->name);
00471 ShowErrorMessage(STR_ERROR_CAN_T_BUILD_HERE, _error_message, pt.x, pt.y);
00472 }
00473
00474 _ignore_restrictions = false;
00475 _generating_world = false;
00476 } else {
00477 success = DoCommandP(tile, (InteractiveRandomRange(indsp->num_table) << 8) | this->selected_type, seed, CMD_BUILD_INDUSTRY | CMD_MSG(STR_ERROR_CAN_T_CONSTRUCT_THIS_INDUSTRY));
00478 }
00479
00480
00481 if (success && !_settings_client.gui.persistent_buildingtools) ResetObjectToPlace();
00482 }
00483
00484 virtual void OnTick()
00485 {
00486 if (_pause_mode != PM_UNPAUSED) return;
00487 if (!this->timer_enabled) return;
00488 if (--this->callback_timer == 0) {
00489
00490
00491 this->callback_timer = DAY_TICKS;
00492
00493 const IndustrySpec *indsp = GetIndustrySpec(this->selected_type);
00494
00495 if (indsp->enabled) {
00496 bool call_back_result = CheckIfCallBackAllowsAvailability(this->selected_type, IACT_USERCREATION);
00497
00498
00499 if (call_back_result != this->enabled[this->selected_index]) {
00500 this->enabled[this->selected_index] = call_back_result;
00501 this->SetWidgetDisabledState(DPIW_FUND_WIDGET, !this->enabled[this->selected_index]);
00502 this->SetDirty();
00503 }
00504 }
00505 }
00506 }
00507
00508 virtual void OnTimeout()
00509 {
00510 this->RaiseButtons();
00511 }
00512
00513 virtual void OnPlaceObjectAbort()
00514 {
00515 this->RaiseButtons();
00516 }
00517
00518 virtual void OnInvalidateData(int data = 0)
00519 {
00520 this->SetupArrays();
00521
00522 const IndustrySpec *indsp = (this->selected_type == INVALID_INDUSTRYTYPE) ? NULL : GetIndustrySpec(this->selected_type);
00523 if (indsp == NULL) this->enabled[this->selected_index] = _settings_game.difficulty.number_industries != 0;
00524 this->SetWidgetDisabledState(DPIW_FUND_WIDGET, !this->enabled[this->selected_index]);
00525 }
00526 };
00527
00528 void ShowBuildIndustryWindow()
00529 {
00530 if (_game_mode != GM_EDITOR && !Company::IsValidID(_local_company)) return;
00531 if (BringWindowToFrontById(WC_BUILD_INDUSTRY, 0)) return;
00532 new BuildIndustryWindow();
00533 }
00534
00535 static void UpdateIndustryProduction(Industry *i);
00536
00537 static inline bool IsProductionMinimum(const Industry *i, int pt)
00538 {
00539 return i->production_rate[pt] == 0;
00540 }
00541
00542 static inline bool IsProductionMaximum(const Industry *i, int pt)
00543 {
00544 return i->production_rate[pt] >= 255;
00545 }
00546
00547 static inline bool IsProductionAlterable(const Industry *i)
00548 {
00549 return ((_game_mode == GM_EDITOR || _cheats.setup_prod.value) &&
00550 (i->accepts_cargo[0] == CT_INVALID || i->accepts_cargo[0] == CT_VALUABLES));
00551 }
00552
00554 enum IndustryViewWidgets {
00555 IVW_CAPTION,
00556 IVW_VIEWPORT,
00557 IVW_INFO,
00558 IVW_GOTO,
00559 };
00560
00561 class IndustryViewWindow : public Window
00562 {
00563 byte editbox_line;
00564 byte clicked_line;
00565 byte clicked_button;
00566 byte production_offset_y;
00567 int info_height;
00568
00569 public:
00570 IndustryViewWindow(const WindowDesc *desc, WindowNumber window_number) : Window()
00571 {
00572 this->flags4 |= WF_DISABLE_VP_SCROLL;
00573 this->editbox_line = 0;
00574 this->clicked_line = 0;
00575 this->clicked_button = 0;
00576 this->info_height = WD_FRAMERECT_TOP + 2 * FONT_HEIGHT_NORMAL + WD_FRAMERECT_BOTTOM + 1;
00577
00578 this->InitNested(desc, window_number);
00579 NWidgetViewport *nvp = this->GetWidget<NWidgetViewport>(IVW_VIEWPORT);
00580 nvp->InitializeViewport(this, Industry::Get(window_number)->location.tile + TileDiffXY(1, 1), ZOOM_LVL_INDUSTRY);
00581 }
00582
00583 virtual void OnPaint()
00584 {
00585 this->DrawWidgets();
00586
00587 if (this->IsShaded()) return;
00588
00589 NWidgetBase *nwi = this->GetWidget<NWidgetBase>(IVW_INFO);
00590 uint expected = this->DrawInfo(nwi->pos_x, nwi->pos_x + nwi->current_x - 1, nwi->pos_y) - nwi->pos_y;
00591 if (expected > nwi->current_y - 1) {
00592 this->info_height = expected + 1;
00593 this->ReInit();
00594 return;
00595 }
00596 }
00597
00604 int DrawInfo(uint left, uint right, uint top)
00605 {
00606 Industry *i = Industry::Get(this->window_number);
00607 const IndustrySpec *ind = GetIndustrySpec(i->type);
00608 int y = top + WD_FRAMERECT_TOP;
00609 bool first = true;
00610 bool has_accept = false;
00611 char cargo_suffix[3][512];
00612
00613 if (HasBit(ind->callback_mask, CBM_IND_PRODUCTION_CARGO_ARRIVAL) || HasBit(ind->callback_mask, CBM_IND_PRODUCTION_256_TICKS)) {
00614 GetAllCargoSuffixes(0, CST_VIEW, i, i->type, ind, i->accepts_cargo, cargo_suffix);
00615 for (byte j = 0; j < lengthof(i->accepts_cargo); j++) {
00616 if (i->accepts_cargo[j] == CT_INVALID) continue;
00617 has_accept = true;
00618 if (first) {
00619 DrawString(left + WD_FRAMERECT_LEFT, right - WD_FRAMERECT_RIGHT, y, STR_INDUSTRY_VIEW_WAITING_FOR_PROCESSING);
00620 y += FONT_HEIGHT_NORMAL;
00621 first = false;
00622 }
00623 SetDParam(0, i->accepts_cargo[j]);
00624 SetDParam(1, i->incoming_cargo_waiting[j]);
00625 SetDParamStr(2, cargo_suffix[j]);
00626 DrawString(left + WD_FRAMETEXT_LEFT, right - WD_FRAMERECT_RIGHT, y, STR_INDUSTRY_VIEW_WAITING_STOCKPILE_CARGO);
00627 y += FONT_HEIGHT_NORMAL;
00628 }
00629 } else {
00630 GetAllCargoSuffixes(0, CST_VIEW, i, i->type, ind, i->accepts_cargo, cargo_suffix);
00631 StringID str = STR_INDUSTRY_VIEW_REQUIRES_CARGO;
00632 byte p = 0;
00633 for (byte j = 0; j < lengthof(i->accepts_cargo); j++) {
00634 if (i->accepts_cargo[j] == CT_INVALID) continue;
00635 has_accept = true;
00636 if (p > 0) str++;
00637 SetDParam(p++, CargoSpec::Get(i->accepts_cargo[j])->name);
00638 SetDParamStr(p++, cargo_suffix[j]);
00639 }
00640 if (has_accept) {
00641 DrawString(left + WD_FRAMERECT_LEFT, right - WD_FRAMERECT_RIGHT, y, str);
00642 y += FONT_HEIGHT_NORMAL;
00643 }
00644 }
00645
00646 GetAllCargoSuffixes(3, CST_VIEW, i, i->type, ind, i->produced_cargo, cargo_suffix);
00647 first = true;
00648 for (byte j = 0; j < lengthof(i->produced_cargo); j++) {
00649 if (i->produced_cargo[j] == CT_INVALID) continue;
00650 if (first) {
00651 if (has_accept) y += WD_PAR_VSEP_WIDE;
00652 DrawString(left + WD_FRAMERECT_LEFT, right - WD_FRAMERECT_RIGHT, y, STR_INDUSTRY_VIEW_PRODUCTION_LAST_MONTH_TITLE);
00653 y += FONT_HEIGHT_NORMAL;
00654 this->production_offset_y = y;
00655 first = false;
00656 }
00657
00658 SetDParam(0, i->produced_cargo[j]);
00659 SetDParam(1, i->last_month_production[j]);
00660 SetDParamStr(2, cargo_suffix[j]);
00661 SetDParam(3, ToPercent8(i->last_month_pct_transported[j]));
00662 uint x = left + WD_FRAMETEXT_LEFT + (IsProductionAlterable(i) ? 30 : 0);
00663 DrawString(x, right - WD_FRAMERECT_RIGHT, y, STR_INDUSTRY_VIEW_TRANSPORTED);
00664
00665 if (IsProductionAlterable(i)) {
00666 DrawArrowButtons(left + WD_FRAMETEXT_LEFT, y, COLOUR_YELLOW, (this->clicked_line == j + 1) ? this->clicked_button : 0,
00667 !IsProductionMinimum(i, j), !IsProductionMaximum(i, j));
00668 }
00669 y += FONT_HEIGHT_NORMAL;
00670 }
00671
00672
00673 if (HasBit(ind->callback_mask, CBM_IND_WINDOW_MORE_TEXT)) {
00674 uint16 callback_res = GetIndustryCallback(CBID_INDUSTRY_WINDOW_MORE_TEXT, 0, 0, i, i->type, i->location.tile);
00675 if (callback_res != CALLBACK_FAILED) {
00676 StringID message = GetGRFStringID(ind->grf_prop.grffile->grfid, 0xD000 + callback_res);
00677 if (message != STR_NULL && message != STR_UNDEFINED) {
00678 y += WD_PAR_VSEP_WIDE;
00679
00680 PrepareTextRefStackUsage(6);
00681
00682
00683
00684 y = DrawStringMultiLine(left + WD_FRAMERECT_LEFT, right - WD_FRAMERECT_RIGHT, y, UINT16_MAX, message);
00685 StopTextRefStackUsage();
00686 }
00687 }
00688 }
00689 return y + WD_FRAMERECT_BOTTOM;
00690 }
00691
00692 virtual void SetStringParameters(int widget) const
00693 {
00694 if (widget== IVW_CAPTION) SetDParam(0, this->window_number);
00695 }
00696
00697 virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
00698 {
00699 if (widget == IVW_INFO) size->height = this->info_height;
00700 }
00701
00702 virtual void OnClick(Point pt, int widget, int click_count)
00703 {
00704 Industry *i;
00705
00706 switch (widget) {
00707 case IVW_INFO: {
00708 i = Industry::Get(this->window_number);
00709
00710
00711 if (!IsProductionAlterable(i)) return;
00712 uint x = pt.x;
00713 int line = (pt.y - this->production_offset_y) / FONT_HEIGHT_NORMAL;
00714 if (pt.y >= this->production_offset_y && IsInsideMM(line, 0, 2) && i->produced_cargo[line] != CT_INVALID) {
00715 NWidgetBase *nwi = this->GetWidget<NWidgetBase>(widget);
00716 uint left = nwi->pos_x + WD_FRAMETEXT_LEFT;
00717 uint right = nwi->pos_x + nwi->current_x - 1 - WD_FRAMERECT_RIGHT;
00718 if (IsInsideMM(x, left, left + 20) ) {
00719
00720 if (x < left + 10) {
00721 if (IsProductionMinimum(i, line)) return;
00722 i->production_rate[line] = max(i->production_rate[line] / 2, 0);
00723 } else {
00724
00725 int new_prod = i->production_rate[line] == 0 ? 1 : i->production_rate[line] * 2;
00726 if (IsProductionMaximum(i, line)) return;
00727 i->production_rate[line] = minu(new_prod, 255);
00728 }
00729
00730 UpdateIndustryProduction(i);
00731 this->SetDirty();
00732 this->flags4 |= WF_TIMEOUT_BEGIN;
00733 this->clicked_line = line + 1;
00734 this->clicked_button = (x < left + 10 ? 1 : 2);
00735 } else if (IsInsideMM(x, left + 30, right)) {
00736
00737 this->editbox_line = line;
00738 SetDParam(0, i->production_rate[line] * 8);
00739 ShowQueryString(STR_JUST_INT, STR_CONFIG_GAME_PRODUCTION, 10, 100, this, CS_ALPHANUMERAL, QSF_NONE);
00740 }
00741 }
00742 } break;
00743
00744 case IVW_GOTO:
00745 i = Industry::Get(this->window_number);
00746 if (_ctrl_pressed) {
00747 ShowExtraViewPortWindow(i->location.tile + TileDiffXY(1, 1));
00748 } else {
00749 ScrollMainWindowToTile(i->location.tile + TileDiffXY(1, 1));
00750 }
00751 break;
00752 }
00753 }
00754
00755 virtual void OnTimeout()
00756 {
00757 this->clicked_line = 0;
00758 this->clicked_button = 0;
00759 this->SetDirty();
00760 }
00761
00762 virtual void OnResize()
00763 {
00764 if (this->viewport != NULL) {
00765 NWidgetViewport *nvp = this->GetWidget<NWidgetViewport>(IVW_VIEWPORT);
00766 nvp->UpdateViewportCoordinates(this);
00767 }
00768 }
00769
00770 virtual void OnQueryTextFinished(char *str)
00771 {
00772 if (StrEmpty(str)) return;
00773
00774 Industry *i = Industry::Get(this->window_number);
00775 int line = this->editbox_line;
00776
00777 i->production_rate[line] = ClampU(atoi(str) / 8, 0, 255);
00778 UpdateIndustryProduction(i);
00779 this->SetDirty();
00780 }
00781 };
00782
00783 static void UpdateIndustryProduction(Industry *i)
00784 {
00785 for (byte j = 0; j < lengthof(i->produced_cargo); j++) {
00786 if (i->produced_cargo[j] != CT_INVALID) {
00787 i->last_month_production[j] = 8 * i->production_rate[j];
00788 }
00789 }
00790 }
00791
00793 static const NWidgetPart _nested_industry_view_widgets[] = {
00794 NWidget(NWID_HORIZONTAL),
00795 NWidget(WWT_CLOSEBOX, COLOUR_CREAM),
00796 NWidget(WWT_CAPTION, COLOUR_CREAM, IVW_CAPTION), SetDataTip(STR_INDUSTRY_VIEW_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
00797 NWidget(WWT_SHADEBOX, COLOUR_CREAM),
00798 NWidget(WWT_STICKYBOX, COLOUR_CREAM),
00799 EndContainer(),
00800 NWidget(WWT_PANEL, COLOUR_CREAM),
00801 NWidget(WWT_INSET, COLOUR_CREAM), SetPadding(2, 2, 2, 2),
00802 NWidget(NWID_VIEWPORT, INVALID_COLOUR, IVW_VIEWPORT), SetMinimalSize(254, 86), SetFill(1, 0), SetPadding(1, 1, 1, 1), SetResize(1, 1),
00803 EndContainer(),
00804 EndContainer(),
00805 NWidget(WWT_PANEL, COLOUR_CREAM, IVW_INFO), SetMinimalSize(260, 2), SetResize(1, 0),
00806 EndContainer(),
00807 NWidget(NWID_HORIZONTAL),
00808 NWidget(WWT_PUSHTXTBTN, COLOUR_CREAM, IVW_GOTO), SetMinimalSize(130, 12), SetDataTip(STR_BUTTON_LOCATION, STR_INDUSTRY_VIEW_LOCATION_TOOLTIP),
00809 NWidget(WWT_PANEL, COLOUR_CREAM), SetResize(1, 0), EndContainer(),
00810 NWidget(WWT_RESIZEBOX, COLOUR_CREAM),
00811 EndContainer(),
00812 };
00813
00815 static const WindowDesc _industry_view_desc(
00816 WDP_AUTO, 260, 120,
00817 WC_INDUSTRY_VIEW, WC_NONE,
00818 WDF_UNCLICK_BUTTONS,
00819 _nested_industry_view_widgets, lengthof(_nested_industry_view_widgets)
00820 );
00821
00822 void ShowIndustryViewWindow(int industry)
00823 {
00824 AllocateWindowDescFront<IndustryViewWindow>(&_industry_view_desc, industry);
00825 }
00826
00828 enum IndustryDirectoryWidgets {
00829 IDW_DROPDOWN_ORDER,
00830 IDW_DROPDOWN_CRITERIA,
00831 IDW_INDUSTRY_LIST,
00832 IDW_SCROLLBAR,
00833 };
00834
00836 static const NWidgetPart _nested_industry_directory_widgets[] = {
00837 NWidget(NWID_HORIZONTAL),
00838 NWidget(WWT_CLOSEBOX, COLOUR_BROWN),
00839 NWidget(WWT_CAPTION, COLOUR_BROWN), SetDataTip(STR_INDUSTRY_DIRECTORY_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
00840 NWidget(WWT_SHADEBOX, COLOUR_BROWN),
00841 NWidget(WWT_STICKYBOX, COLOUR_BROWN),
00842 EndContainer(),
00843 NWidget(NWID_HORIZONTAL),
00844 NWidget(NWID_VERTICAL),
00845 NWidget(NWID_HORIZONTAL),
00846 NWidget(WWT_TEXTBTN, COLOUR_BROWN, IDW_DROPDOWN_ORDER), SetDataTip(STR_BUTTON_SORT_BY, STR_TOOLTIP_SORT_ORDER),
00847 NWidget(WWT_DROPDOWN, COLOUR_BROWN, IDW_DROPDOWN_CRITERIA), SetDataTip(STR_JUST_STRING, STR_TOOLTIP_SORT_CRITERIA),
00848 NWidget(WWT_PANEL, COLOUR_BROWN), SetResize(1, 0), EndContainer(),
00849 EndContainer(),
00850 NWidget(WWT_PANEL, COLOUR_BROWN, IDW_INDUSTRY_LIST), SetDataTip(0x0, STR_INDUSTRY_DIRECTORY_LIST_CAPTION), SetResize(1, 1), EndContainer(),
00851 EndContainer(),
00852 NWidget(NWID_VERTICAL),
00853 NWidget(WWT_SCROLLBAR, COLOUR_BROWN, IDW_SCROLLBAR),
00854 NWidget(WWT_RESIZEBOX, COLOUR_BROWN),
00855 EndContainer(),
00856 EndContainer(),
00857 };
00858
00859 typedef GUIList<const Industry*> GUIIndustryList;
00860
00861
00865 class IndustryDirectoryWindow : public Window {
00866 protected:
00867
00868 static Listing last_sorting;
00869 static const Industry *last_industry;
00870
00871
00872 static const StringID sorter_names[];
00873 static GUIIndustryList::SortFunction * const sorter_funcs[];
00874
00875 GUIIndustryList industries;
00876
00878 void BuildSortIndustriesList()
00879 {
00880 if (this->industries.NeedRebuild()) {
00881 this->industries.Clear();
00882
00883 const Industry *i;
00884 FOR_ALL_INDUSTRIES(i) {
00885 *this->industries.Append() = i;
00886 }
00887
00888 this->industries.Compact();
00889 this->industries.RebuildDone();
00890 this->vscroll.SetCount(this->industries.Length());
00891 }
00892
00893 if (!this->industries.Sort()) return;
00894 IndustryDirectoryWindow::last_industry = NULL;
00895 this->SetWidgetDirty(IDW_INDUSTRY_LIST);
00896 }
00897
00905 static inline int GetCargoTransportedPercentsIfValid(const Industry *i, uint id)
00906 {
00907 assert(id < lengthof(i->produced_cargo));
00908
00909 if (i->produced_cargo[id] == CT_INVALID) return 101;
00910 return ToPercent8(i->last_month_pct_transported[id]);
00911 }
00912
00920 static int GetCargoTransportedSortValue(const Industry *i)
00921 {
00922 int p1 = GetCargoTransportedPercentsIfValid(i, 0);
00923 int p2 = GetCargoTransportedPercentsIfValid(i, 1);
00924
00925 if (p1 > p2) Swap(p1, p2);
00926
00927 return (p1 << 8) + p2;
00928 }
00929
00931 static int CDECL IndustryNameSorter(const Industry * const *a, const Industry * const *b)
00932 {
00933 static char buf_cache[96];
00934 static char buf[96];
00935
00936 SetDParam(0, (*a)->town->index);
00937 GetString(buf, STR_TOWN_NAME, lastof(buf));
00938
00939 if (*b != last_industry) {
00940 last_industry = *b;
00941 SetDParam(0, (*b)->town->index);
00942 GetString(buf_cache, STR_TOWN_NAME, lastof(buf_cache));
00943 }
00944
00945 return strcmp(buf, buf_cache);
00946 }
00947
00949 static int CDECL IndustryTypeSorter(const Industry * const *a, const Industry * const *b)
00950 {
00951 int r = (*a)->type - (*b)->type;
00952 return (r == 0) ? IndustryNameSorter(a, b) : r;
00953 }
00954
00956 static int CDECL IndustryProductionSorter(const Industry * const *a, const Industry * const *b)
00957 {
00958 uint prod_a = 0, prod_b = 0;
00959 for (uint i = 0; i < lengthof((*a)->produced_cargo); i++) {
00960 if ((*a)->produced_cargo[i] != CT_INVALID) prod_a += (*a)->last_month_production[i];
00961 if ((*b)->produced_cargo[i] != CT_INVALID) prod_b += (*b)->last_month_production[i];
00962 }
00963 int r = prod_a - prod_b;
00964
00965 return (r == 0) ? IndustryTypeSorter(a, b) : r;
00966 }
00967
00969 static int CDECL IndustryTransportedCargoSorter(const Industry * const *a, const Industry * const *b)
00970 {
00971 int r = GetCargoTransportedSortValue(*a) - GetCargoTransportedSortValue(*b);
00972 return (r == 0) ? IndustryNameSorter(a, b) : r;
00973 }
00974
00980 StringID GetIndustryString(const Industry *i) const
00981 {
00982 const IndustrySpec *indsp = GetIndustrySpec(i->type);
00983 byte p = 0;
00984
00985
00986 SetDParam(p++, i->index);
00987
00988 static char cargo_suffix[lengthof(i->produced_cargo)][512];
00989 GetAllCargoSuffixes(3, CST_DIR, i, i->type, indsp, i->produced_cargo, cargo_suffix);
00990
00991
00992 for (byte j = 0; j < lengthof(i->produced_cargo); j++) {
00993 if (i->produced_cargo[j] == CT_INVALID) continue;
00994 SetDParam(p++, i->produced_cargo[j]);
00995 SetDParam(p++, i->last_month_production[j]);
00996 SetDParamStr(p++, cargo_suffix[j]);
00997 }
00998
00999
01000 for (byte j = 0; j < lengthof(i->produced_cargo); j++) {
01001 if (i->produced_cargo[j] == CT_INVALID) continue;
01002 SetDParam(p++, ToPercent8(i->last_month_pct_transported[j]));
01003 }
01004
01005
01006 switch (p) {
01007 case 1: return STR_INDUSTRY_DIRECTORY_ITEM_NOPROD;
01008 case 5: return STR_INDUSTRY_DIRECTORY_ITEM;
01009 default: return STR_INDUSTRY_DIRECTORY_ITEM_TWO;
01010 }
01011 }
01012
01013 public:
01014 IndustryDirectoryWindow(const WindowDesc *desc, WindowNumber number) : Window()
01015 {
01016 this->industries.SetListing(this->last_sorting);
01017 this->industries.SetSortFuncs(IndustryDirectoryWindow::sorter_funcs);
01018 this->industries.ForceRebuild();
01019 this->BuildSortIndustriesList();
01020
01021 this->InitNested(desc, 0);
01022 }
01023
01024 ~IndustryDirectoryWindow()
01025 {
01026 this->last_sorting = this->industries.GetListing();
01027 }
01028
01029 virtual void SetStringParameters(int widget) const
01030 {
01031 if (widget == IDW_DROPDOWN_CRITERIA) SetDParam(0, IndustryDirectoryWindow::sorter_names[this->industries.SortType()]);
01032 }
01033
01034 virtual void OnPaint()
01035 {
01036 this->DrawWidgets();
01037 }
01038
01039 virtual void DrawWidget(const Rect &r, int widget) const
01040 {
01041 switch (widget) {
01042 case IDW_DROPDOWN_ORDER:
01043 this->DrawSortButtonState(widget, this->industries.IsDescSortOrder() ? SBS_DOWN : SBS_UP);
01044 break;
01045
01046 case IDW_INDUSTRY_LIST: {
01047 int n = 0;
01048 int y = r.top + WD_FRAMERECT_TOP;
01049 if (this->industries.Length() == 0) {
01050 DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_INDUSTRY_DIRECTORY_NONE);
01051 break;
01052 }
01053 for (uint i = this->vscroll.GetPosition(); i < this->industries.Length(); i++) {
01054 DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, this->GetIndustryString(this->industries[i]));
01055
01056 y += this->resize.step_height;
01057 if (++n == this->vscroll.GetCapacity()) break;
01058 }
01059 } break;
01060 }
01061 }
01062
01063 virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
01064 {
01065 switch (widget) {
01066 case IDW_DROPDOWN_ORDER: {
01067 Dimension d = GetStringBoundingBox(this->GetWidget<NWidgetCore>(widget)->widget_data);
01068 d.width += padding.width + WD_SORTBUTTON_ARROW_WIDTH * 2;
01069 d.height += padding.height;
01070 *size = maxdim(*size, d);
01071 break;
01072 }
01073
01074 case IDW_DROPDOWN_CRITERIA: {
01075 Dimension d = {0, 0};
01076 for (uint i = 0; IndustryDirectoryWindow::sorter_names[i] != INVALID_STRING_ID; i++) {
01077 d = maxdim(d, GetStringBoundingBox(IndustryDirectoryWindow::sorter_names[i]));
01078 }
01079 d.width += padding.width;
01080 d.height += padding.height;
01081 *size = maxdim(*size, d);
01082 break;
01083 }
01084
01085 case IDW_INDUSTRY_LIST: {
01086 Dimension d = GetStringBoundingBox(STR_INDUSTRY_DIRECTORY_NONE);
01087 for (uint i = 0; i < this->industries.Length(); i++) {
01088 d = maxdim(d, GetStringBoundingBox(this->GetIndustryString(this->industries[i])));
01089 }
01090 resize->height = d.height;
01091 d.width += padding.width + WD_FRAMERECT_LEFT + WD_FRAMERECT_RIGHT;
01092 d.height += padding.height + WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM;
01093 *size = maxdim(*size, d);
01094 break;
01095 }
01096 }
01097 }
01098
01099
01100 virtual void OnClick(Point pt, int widget, int click_count)
01101 {
01102 switch (widget) {
01103 case IDW_DROPDOWN_ORDER:
01104 this->industries.ToggleSortOrder();
01105 this->SetDirty();
01106 break;
01107
01108 case IDW_DROPDOWN_CRITERIA:
01109 ShowDropDownMenu(this, IndustryDirectoryWindow::sorter_names, this->industries.SortType(), IDW_DROPDOWN_CRITERIA, 0, 0);
01110 break;
01111
01112 case IDW_INDUSTRY_LIST: {
01113 int y = (pt.y - this->GetWidget<NWidgetBase>(widget)->pos_y - WD_FRAMERECT_TOP) / this->resize.step_height;
01114 uint16 p;
01115
01116 if (!IsInsideMM(y, 0, this->vscroll.GetCapacity())) return;
01117 p = y + this->vscroll.GetPosition();
01118 if (p < this->industries.Length()) {
01119 if (_ctrl_pressed) {
01120 ShowExtraViewPortWindow(this->industries[p]->location.tile);
01121 } else {
01122 ScrollMainWindowToTile(this->industries[p]->location.tile);
01123 }
01124 }
01125 } break;
01126 }
01127 }
01128
01129 virtual void OnDropdownSelect(int widget, int index)
01130 {
01131 if (this->industries.SortType() != index) {
01132 this->industries.SetSortType(index);
01133 this->BuildSortIndustriesList();
01134 }
01135 }
01136
01137 virtual void OnResize()
01138 {
01139 this->vscroll.SetCapacityFromWidget(this, IDW_INDUSTRY_LIST);
01140 }
01141
01142 virtual void OnHundredthTick()
01143 {
01144 this->industries.ForceResort();
01145 this->BuildSortIndustriesList();
01146 }
01147
01148 virtual void OnInvalidateData(int data)
01149 {
01150 if (data == 0) {
01151 this->industries.ForceRebuild();
01152 } else {
01153 this->industries.ForceResort();
01154 }
01155 this->BuildSortIndustriesList();
01156 }
01157 };
01158
01159 Listing IndustryDirectoryWindow::last_sorting = {false, 0};
01160 const Industry *IndustryDirectoryWindow::last_industry = NULL;
01161
01162
01163 GUIIndustryList::SortFunction * const IndustryDirectoryWindow::sorter_funcs[] = {
01164 &IndustryNameSorter,
01165 &IndustryTypeSorter,
01166 &IndustryProductionSorter,
01167 &IndustryTransportedCargoSorter
01168 };
01169
01170
01171 const StringID IndustryDirectoryWindow::sorter_names[] = {
01172 STR_SORT_BY_NAME,
01173 STR_SORT_BY_TYPE,
01174 STR_SORT_BY_PRODUCTION,
01175 STR_SORT_BY_TRANSPORTED,
01176 INVALID_STRING_ID
01177 };
01178
01179
01181 static const WindowDesc _industry_directory_desc(
01182 WDP_AUTO, 428, 190,
01183 WC_INDUSTRY_DIRECTORY, WC_NONE,
01184 WDF_UNCLICK_BUTTONS,
01185 _nested_industry_directory_widgets, lengthof(_nested_industry_directory_widgets)
01186 );
01187
01188 void ShowIndustryDirectory()
01189 {
01190 AllocateWindowDescFront<IndustryDirectoryWindow>(&_industry_directory_desc, 0);
01191 }