tron@2186: /* $Id$ */ tron@2186: belugas@6527: /** @file industry_gui.cpp */ belugas@6527: truelight@0: #include "stdafx.h" Darkvater@1891: #include "openttd.h" tron@1299: #include "debug.h" tron@1386: #include "gui.h" rubidium@9723: #include "window_gui.h" rubidium@9723: #include "textbuf_gui.h" rubidium@9723: #include "command_func.h" rubidium@9723: #include "viewport_func.h" rubidium@9723: #include "gfx_func.h" truelight@0: #include "industry.h" truelight@0: #include "town.h" tron@2159: #include "variables.h" peter1138@6417: #include "cargotype.h" truelight@9641: #include "newgrf.h" truelight@9641: #include "newgrf_callbacks.h" truelight@9641: #include "newgrf_industries.h" truelight@9641: #include "newgrf_text.h" rubidium@9723: #include "strings_func.h" rubidium@9723: #include "map_func.h" rubidium@9724: #include "player_func.h" rubidium@9724: #include "settings_type.h" rubidium@9724: rubidium@9724: #include "table/strings.h" rubidium@9724: #include "table/sprites.h" truelight@9641: truelight@9641: bool _ignore_restrictions; truelight@9641: rubidium@9723: /** Names of the widgets of the dynamic place industries gui */ rubidium@9723: enum DynamicPlaceIndustriesWidgets { rubidium@9723: DPIW_CLOSEBOX = 0, rubidium@9723: DPIW_CAPTION, rubidium@9723: DPIW_MATRIX_WIDGET, rubidium@9723: DPIW_SCROLLBAR, rubidium@9723: DPIW_INFOPANEL, rubidium@9723: DPIW_FUND_WIDGET, rubidium@9723: DPIW_RESIZE_WIDGET, belugas@4995: }; truelight@0: rubidium@9686: /** Attached struct to the window extended data */ rubidium@9686: struct fnd_d { rubidium@9686: int index; ///< index of the element in the matrix rubidium@9686: IndustryType select; ///< industry corresponding to the above index rubidium@9686: uint16 callback_timer; ///< timer counter for callback eventual verification rubidium@9686: bool timer_enabled; ///< timer can be used rubidium@9686: }; rubidium@9686: assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(fnd_d)); rubidium@9686: rubidium@9686: /** Helper struct holding the available industries for current situation */ truelight@9641: static struct IndustryData { rubidium@9686: uint16 count; ///< How many industries are loaded rubidium@9686: IndustryType index[NUM_INDUSTRYTYPES + 1]; ///< Type of industry, in the order it was loaded rubidium@9686: StringID text[NUM_INDUSTRYTYPES + 1]; ///< Text coming from CBM_IND_FUND_MORE_TEXT (if ever) rubidium@9686: bool enabled[NUM_INDUSTRYTYPES + 1]; ///< availability state, coming from CBID_INDUSTRY_AVAILABLE (if ever) rubidium@9686: } _fund_gui; miham@1004: rubidium@9724: assert_compile(lengthof(_fund_gui.index) == lengthof(_fund_gui.text)); rubidium@9724: assert_compile(lengthof(_fund_gui.index) == lengthof(_fund_gui.enabled)); rubidium@9724: truelight@9641: static void BuildDynamicIndustryWndProc(Window *w, WindowEvent *e) truelight@0: { tron@2951: switch (e->event) { truelight@9641: case WE_CREATE: { truelight@9641: IndustryType ind; truelight@9641: const IndustrySpec *indsp; truelight@0: truelight@9641: /* Shorten the window to the equivalant of the additionnal purchase truelight@9641: * info coming from the callback. SO it will only be available to tis full truelight@9641: * height when newindistries are loaded */ truelight@9641: if (!_loaded_newgrf_features.has_newindustries) { rubidium@9723: w->widget[DPIW_INFOPANEL].bottom -= 44; rubidium@9723: w->widget[DPIW_FUND_WIDGET].bottom -= 44; rubidium@9723: w->widget[DPIW_FUND_WIDGET].top -= 44; rubidium@9723: w->widget[DPIW_RESIZE_WIDGET].bottom -= 44; rubidium@9723: w->widget[DPIW_RESIZE_WIDGET].top -= 44; truelight@9641: w->resize.height = w->height -= 44; truelight@9641: } truelight@0: rubidium@9686: WP(w, fnd_d).timer_enabled = _loaded_newgrf_features.has_newindustries; rubidium@9686: truelight@9641: /* Initilialize structures */ rubidium@9686: _fund_gui.count = 0; truelight@9641: rubidium@9724: for (uint i = 0; i < lengthof(_fund_gui.index); i++) { rubidium@9724: _fund_gui.index[i] = 0xFF; rubidium@9724: _fund_gui.text[i] = STR_NULL; rubidium@9724: _fund_gui.enabled[i] = false; rubidium@9724: } rubidium@9724: truelight@9641: w->vscroll.cap = 8; // rows in grid, same in scroller truelight@9641: w->resize.step_height = 13; truelight@9641: truelight@9641: if (_game_mode == GM_EDITOR) { // give room for the Many Random "button" rubidium@9686: _fund_gui.index[_fund_gui.count] = INVALID_INDUSTRYTYPE; rubidium@9686: _fund_gui.count++; rubidium@9686: WP(w, fnd_d).timer_enabled = false; truelight@9641: } truelight@9641: truelight@9718: /* Fill the _fund_gui structure with industries. truelight@9718: * The tests performed after the enabled allow to load the industries truelight@9718: * In the same way they are inserted by grf (if any) truelight@9718: */ rubidium@9694: for (ind = 0; ind < NUM_INDUSTRYTYPES; ind++) { truelight@9641: indsp = GetIndustrySpec(ind); truelight@9718: if (indsp->enabled){ truelight@9718: /* Rule is that editor mode loads all industries. truelight@9718: * In game mode, all non raw industries are loaded too truelight@9718: * and raw ones are loaded only when setting allows it */ truelight@9718: if (_game_mode != GM_EDITOR && indsp->IsRawIndustry() && _patches.raw_industry_construction == 0) continue; rubidium@9686: _fund_gui.index[_fund_gui.count] = ind; glx@9704: _fund_gui.enabled[_fund_gui.count] = (_game_mode == GM_EDITOR) || CheckIfCallBackAllowsAvailability(ind, IACT_USERCREATION); rubidium@9686: _fund_gui.count++; truelight@9641: } truelight@9641: } truelight@9641: rubidium@9686: /* first indutry type is selected. rubidium@9686: * I'll be damned if there are none available ;) */ rubidium@9686: WP(w, fnd_d).index = 0; rubidium@9686: WP(w, fnd_d).select = _fund_gui.index[0]; rubidium@9686: WP(w, fnd_d).callback_timer = DAY_TICKS; truelight@9641: } break; truelight@9641: truelight@9641: case WE_PAINT: { rubidium@9686: const IndustrySpec *indsp = (WP(w, fnd_d).select == INVALID_INDUSTRYTYPE) ? NULL : GetIndustrySpec(WP(w, fnd_d).select); rubidium@9723: int x_str = w->widget[DPIW_INFOPANEL].left + 3; rubidium@9723: int y_str = w->widget[DPIW_INFOPANEL].top + 3; rubidium@9723: const Widget *wi = &w->widget[DPIW_INFOPANEL]; truelight@9641: int max_width = wi->right - wi->left - 4; truelight@9641: rubidium@9686: /* Raw industries might be prospected. Show this fact by changing the string rubidium@9686: * In Editor, you just build, while ingame, or you fund or you prospect */ truelight@9641: if (_game_mode == GM_EDITOR) { rubidium@9686: /* We've chosen many random industries but no industries have been specified */ rubidium@9694: if (indsp == NULL) _fund_gui.enabled[WP(w, fnd_d).index] = _opt.diff.number_industries != 0; rubidium@9723: w->widget[DPIW_FUND_WIDGET].data = STR_BUILD_NEW_INDUSTRY; truelight@9641: } else { rubidium@9723: w->widget[DPIW_FUND_WIDGET].data = (_patches.raw_industry_construction == 2 && indsp->IsRawIndustry()) ? STR_PROSPECT_NEW_INDUSTRY : STR_FUND_NEW_INDUSTRY; truelight@9641: } rubidium@9723: w->SetWidgetDisabledState(DPIW_FUND_WIDGET, !_fund_gui.enabled[WP(w, fnd_d).index]); truelight@9641: rubidium@9686: SetVScrollCount(w, _fund_gui.count); truelight@9641: truelight@9641: DrawWindowWidgets(w); truelight@9641: truelight@9641: /* and now with the matrix painting */ rubidium@9686: for (byte i = 0; i < w->vscroll.cap && ((i + w->vscroll.pos) < _fund_gui.count); i++) { truelight@9641: int offset = i * 13; truelight@9641: int x = 3; truelight@9641: int y = 16; rubidium@9686: bool selected = WP(w, fnd_d).index == i + w->vscroll.pos; truelight@9641: rubidium@9686: if (_fund_gui.index[i + w->vscroll.pos] == INVALID_INDUSTRYTYPE) { rubidium@9722: DrawStringTruncated(20, y + offset, STR_MANY_RANDOM_INDUSTRIES, selected ? TC_WHITE : TC_ORANGE, max_width - 25); truelight@9641: continue; truelight@9641: } rubidium@9686: const IndustrySpec *indsp = GetIndustrySpec(_fund_gui.index[i + w->vscroll.pos]); truelight@9641: truelight@9641: /* Draw the name of the industry in white is selected, otherwise, in orange */ rubidium@9722: DrawStringTruncated(20, y + offset, indsp->name, selected ? TC_WHITE : TC_ORANGE, max_width - 25); truelight@9641: GfxFillRect(x, y + 1 + offset, x + 10, y + 7 + offset, selected ? 15 : 0); truelight@9641: GfxFillRect(x + 1, y + 2 + offset, x + 9, y + 6 + offset, indsp->map_colour); truelight@9641: } truelight@9641: rubidium@9686: if (WP(w, fnd_d).select == INVALID_INDUSTRYTYPE) { truelight@9641: DrawStringMultiLine(x_str, y_str, STR_RANDOM_INDUSTRIES_TIP, max_width, wi->bottom - wi->top - 40); truelight@9641: break; truelight@9641: } truelight@9641: truelight@9641: if (_game_mode != GM_EDITOR) { truelight@9641: SetDParam(0, indsp->GetConstructionCost()); rubidium@9722: DrawStringTruncated(x_str, y_str, STR_482F_COST, TC_FROMSTRING, max_width); truelight@9641: y_str += 11; truelight@9641: } truelight@9641: truelight@9641: /* Draw the accepted cargos, if any. Otherwhise, will print "Nothing" */ rubidium@9722: StringID str = STR_4827_REQUIRES; rubidium@9722: byte p = 0; rubidium@9722: SetDParam(0, STR_00D0_NOTHING); rubidium@9722: for (byte j = 0; j < lengthof(indsp->accepts_cargo); j++) { rubidium@9722: if (indsp->accepts_cargo[j] == CT_INVALID) continue; rubidium@9722: if (p > 0) str++; rubidium@9722: SetDParam(p++, GetCargo(indsp->accepts_cargo[j])->name); truelight@9641: } rubidium@9722: DrawStringTruncated(x_str, y_str, str, TC_FROMSTRING, max_width); rubidium@9722: y_str += 11; truelight@9641: truelight@9641: /* Draw the produced cargos, if any. Otherwhise, will print "Nothing" */ truelight@9641: str = STR_4827_PRODUCES; rubidium@9722: p = 0; rubidium@9722: SetDParam(0, STR_00D0_NOTHING); rubidium@9722: for (byte j = 0; j < lengthof(indsp->produced_cargo); j++) { rubidium@9722: if (indsp->produced_cargo[j] == CT_INVALID) continue; rubidium@9722: if (p > 0) str++; rubidium@9722: SetDParam(p++, GetCargo(indsp->produced_cargo[j])->name); truelight@9641: } rubidium@9722: DrawStringTruncated(x_str, y_str, str, TC_FROMSTRING, max_width); rubidium@9722: y_str += 11; truelight@9641: truelight@9641: /* Get the additional purchase info text, if it has not already been */ rubidium@9686: if (_fund_gui.text[WP(w, fnd_d).index] == STR_NULL) { // Have i been called already? rubidium@9722: if (HasBit(indsp->callback_flags, CBM_IND_FUND_MORE_TEXT)) { // No. Can it be called? rubidium@9686: uint16 callback_res = GetIndustryCallback(CBID_INDUSTRY_FUND_MORE_TEXT, 0, 0, NULL, WP(w, fnd_d).select, INVALID_TILE); truelight@9641: if (callback_res != CALLBACK_FAILED) { // Did it failed? truelight@9641: StringID newtxt = GetGRFStringID(indsp->grf_prop.grffile->grfid, 0xD000 + callback_res); // No. here's the new string rubidium@9686: _fund_gui.text[WP(w, fnd_d).index] = newtxt; // Store it for further usage truelight@9641: } truelight@9641: } truelight@9641: } truelight@9641: truelight@9641: /* Draw the Additional purchase text, provided by newgrf callback, if any. truelight@9641: * Otherwhise, will print Nothing */ rubidium@9686: str = _fund_gui.text[WP(w, fnd_d).index]; rubidium@9686: if (str != STR_NULL && str != STR_UNDEFINED) { rubidium@9686: SetDParam(0, str); rubidium@9686: DrawStringMultiLine(x_str, y_str, STR_JUST_STRING, max_width, wi->bottom - wi->top - 40); truelight@9641: } truelight@9641: } break; truelight@9641: rubidium@9723: case WE_DOUBLE_CLICK: rubidium@9723: if (e->we.click.widget != DPIW_MATRIX_WIDGET) break; rubidium@9723: e->we.click.widget = DPIW_FUND_WIDGET; rubidium@9723: /* Fall through */ rubidium@9723: truelight@9641: case WE_CLICK: truelight@9641: switch (e->we.click.widget) { rubidium@9723: case DPIW_MATRIX_WIDGET: { rubidium@9686: const IndustrySpec *indsp; rubidium@9723: int y = (e->we.click.pt.y - w->widget[DPIW_MATRIX_WIDGET].top) / 13 + w->vscroll.pos ; truelight@9641: rubidium@9686: if (y >= 0 && y < _fund_gui.count) { // Is it within the boundaries of available data? rubidium@9686: WP(w, fnd_d).index = y; rubidium@9686: WP(w, fnd_d).select = _fund_gui.index[WP(w, fnd_d).index]; rubidium@9686: indsp = (WP(w, fnd_d).select == INVALID_INDUSTRYTYPE) ? NULL : GetIndustrySpec(WP(w, fnd_d).select); truelight@9641: truelight@9641: SetWindowDirty(w); rubidium@9686: rubidium@9686: if ((_game_mode != GM_EDITOR && _patches.raw_industry_construction == 2 && indsp != NULL && indsp->IsRawIndustry()) || rubidium@9686: WP(w, fnd_d).select == INVALID_INDUSTRYTYPE) { truelight@9641: /* Reset the button state if going to prospecting or "build many industries" */ rubidium@9723: w->RaiseButtons(); truelight@9641: ResetObjectToPlace(); truelight@9641: } truelight@9641: } truelight@9641: } break; truelight@9641: rubidium@9723: case DPIW_FUND_WIDGET: { rubidium@9686: if (WP(w, fnd_d).select == INVALID_INDUSTRYTYPE) { rubidium@9723: w->HandleButtonClick(DPIW_FUND_WIDGET); truelight@9641: truelight@9641: if (GetNumTowns() == 0) { truelight@9641: ShowErrorMessage(STR_0286_MUST_BUILD_TOWN_FIRST, STR_CAN_T_GENERATE_INDUSTRIES, 0, 0); truelight@9641: } else { truelight@9641: extern void GenerateIndustries(); truelight@9641: _generating_world = true; truelight@9641: GenerateIndustries(); truelight@9641: _generating_world = false; truelight@9641: } rubidium@9686: } else if (_game_mode != GM_EDITOR && _patches.raw_industry_construction == 2 && GetIndustrySpec(WP(w, fnd_d).select)->IsRawIndustry()) { rubidium@9724: DoCommandP(0, WP(w, fnd_d).select, InteractiveRandom(), NULL, CMD_BUILD_INDUSTRY | CMD_MSG(STR_4830_CAN_T_CONSTRUCT_THIS_INDUSTRY)); rubidium@9723: w->HandleButtonClick(DPIW_FUND_WIDGET); rubidium@9686: } else { rubidium@9723: HandlePlacePushButton(w, DPIW_FUND_WIDGET, SPR_CURSOR_INDUSTRY, VHM_RECT, NULL); rubidium@9686: } rubidium@9686: } break; rubidium@9686: } rubidium@9686: break; rubidium@9686: rubidium@9686: case WE_RESIZE: { rubidium@9686: /* Adjust the number of items in the matrix depending of the rezise */ rubidium@9686: w->vscroll.cap += e->we.sizing.diff.y / (int)w->resize.step_height; rubidium@9723: w->widget[DPIW_MATRIX_WIDGET].data = (w->vscroll.cap << 8) + 1; rubidium@9686: } break; rubidium@9686: rubidium@9686: case WE_PLACE_OBJ: { truelight@9718: bool success = true; rubidium@9686: /* We do not need to protect ourselves against "Random Many Industries" in this mode */ rubidium@9686: const IndustrySpec *indsp = GetIndustrySpec(WP(w, fnd_d).select); rubidium@9724: uint32 seed = InteractiveRandom(); rubidium@9686: rubidium@9686: if (_game_mode == GM_EDITOR) { rubidium@9686: /* Show error if no town exists at all */ rubidium@9686: if (GetNumTowns() == 0) { rubidium@9686: SetDParam(0, indsp->name); rubidium@9686: ShowErrorMessage(STR_0286_MUST_BUILD_TOWN_FIRST, STR_0285_CAN_T_BUILD_HERE, e->we.place.pt.x, e->we.place.pt.y); rubidium@9686: return; rubidium@9686: } rubidium@9686: rubidium@9686: _current_player = OWNER_NONE; rubidium@9686: _generating_world = true; rubidium@9686: _ignore_restrictions = true; rubidium@9724: success = DoCommandP(e->we.place.tile, (InteractiveRandomRange(indsp->num_table) << 16) | WP(w, fnd_d).select, seed, NULL, CMD_BUILD_INDUSTRY | CMD_MSG(STR_4830_CAN_T_CONSTRUCT_THIS_INDUSTRY)); truelight@9718: if (!success) { rubidium@9686: SetDParam(0, indsp->name); rubidium@9686: ShowErrorMessage(_error_message, STR_0285_CAN_T_BUILD_HERE, e->we.place.pt.x, e->we.place.pt.y); rubidium@9686: } rubidium@9686: rubidium@9686: _ignore_restrictions = false; rubidium@9686: _generating_world = false; truelight@9718: } else { rubidium@9724: success = DoCommandP(e->we.place.tile, (InteractiveRandomRange(indsp->num_table) << 16) | WP(w, fnd_d).select, seed, NULL, CMD_BUILD_INDUSTRY | CMD_MSG(STR_4830_CAN_T_CONSTRUCT_THIS_INDUSTRY)); truelight@9718: } rubidium@9686: truelight@9718: /* If an industry has been built, just reset the cursor and the system */ truelight@9718: if (success) ResetObjectToPlace(); rubidium@9686: } break; rubidium@9686: rubidium@9686: case WE_TICK: rubidium@9723: if (_pause_game != 0) break; rubidium@9686: if (!WP(w, fnd_d).timer_enabled) break; rubidium@9686: if (--WP(w, fnd_d).callback_timer == 0) { rubidium@9686: /* We have just passed another day. rubidium@9686: * See if we need to update availability of currently selected industry */ rubidium@9686: WP(w, fnd_d).callback_timer = DAY_TICKS; //restart counter rubidium@9686: rubidium@9686: const IndustrySpec *indsp = GetIndustrySpec(WP(w, fnd_d).select); rubidium@9686: rubidium@9686: if (indsp->enabled) { rubidium@9686: bool call_back_result = CheckIfCallBackAllowsAvailability(WP(w, fnd_d).select, IACT_USERCREATION); rubidium@9686: rubidium@9686: /* Only if result does match the previous state would it require a redraw. */ rubidium@9686: if (call_back_result != _fund_gui.enabled[WP(w, fnd_d).index]) { rubidium@9686: _fund_gui.enabled[WP(w, fnd_d).index] = call_back_result; rubidium@9686: SetWindowDirty(w); truelight@9641: } truelight@9641: } truelight@9641: } rubidium@9686: break; truelight@9641: rubidium@9686: case WE_TIMEOUT: rubidium@9686: case WE_ABORT_PLACE_OBJ: rubidium@9723: w->RaiseButtons(); rubidium@9686: break; truelight@0: } truelight@0: } truelight@0: rubidium@9723: /** Widget definition of the dynamic place industries gui */ truelight@9641: static const Widget _build_dynamic_industry_widgets[] = { rubidium@9723: { WWT_CLOSEBOX, RESIZE_NONE, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, // DPIW_CLOSEBOX rubidium@9723: { WWT_CAPTION, RESIZE_RIGHT, 7, 11, 169, 0, 13, STR_0314_FUND_NEW_INDUSTRY, STR_018C_WINDOW_TITLE_DRAG_THIS}, // DPIW_CAPTION rubidium@9723: { WWT_MATRIX, RESIZE_RB, 7, 0, 157, 14, 118, 0x801, STR_INDUSTRY_SELECTION_HINT}, // DPIW_MATRIX_WIDGET rubidium@9723: { WWT_SCROLLBAR, RESIZE_LRB, 7, 158, 169, 14, 118, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST}, // DPIW_SCROLLBAR rubidium@9723: { WWT_PANEL, RESIZE_RTB, 7, 0, 169, 119, 199, 0x0, STR_NULL}, // DPIW_INFOPANEL rubidium@9723: { WWT_TEXTBTN, RESIZE_RTB, 7, 0, 157, 200, 211, STR_FUND_NEW_INDUSTRY, STR_NULL}, // DPIW_FUND_WIDGET rubidium@9723: { WWT_RESIZEBOX, RESIZE_LRTB, 7, 158, 169, 200, 211, 0x0, STR_RESIZE_BUTTON}, // DPIW_RESIZE_WIDGET darkvater@176: { WIDGETS_END}, truelight@0: }; truelight@0: rubidium@9723: /** Window definition of the dynamic place industries gui */ truelight@9641: static const WindowDesc _build_industry_dynamic_desc = { rubidium@9694: WDP_AUTO, WDP_AUTO, 170, 212, 170, 212, rubidium@6144: WC_BUILD_INDUSTRY, WC_NONE, truelight@9641: WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_RESIZABLE, truelight@9641: _build_dynamic_industry_widgets, truelight@9641: BuildDynamicIndustryWndProc, truelight@0: }; truelight@0: rubidium@6573: void ShowBuildIndustryWindow() truelight@193: { truelight@9641: if (_game_mode != GM_EDITOR && !IsValidPlayer(_current_player)) return; truelight@9641: AllocateWindowDescFront(&_build_industry_dynamic_desc, 0); truelight@0: } truelight@0: truelight@9641: static void UpdateIndustryProduction(Industry *i); truelight@9641: rubidium@9686: static inline bool isProductionMinimum(const Industry *i, int pt) rubidium@9686: { rubidium@9722: return i->production_rate[pt] == 0; miham@4211: } miham@4211: rubidium@9686: static inline bool isProductionMaximum(const Industry *i, int pt) rubidium@9686: { rubidium@9722: return i->production_rate[pt] >= 255; miham@4211: } miham@4211: Darkvater@4194: static inline bool IsProductionAlterable(const Industry *i) Darkvater@4194: { Darkvater@4194: return ((_game_mode == GM_EDITOR || _cheats.setup_prod.value) && glx@9704: (i->accepts_cargo[0] == CT_INVALID || i->accepts_cargo[0] == CT_VALUABLES)); Darkvater@4194: } Darkvater@4194: rubidium@9723: /** Names of the widgets of the view industry gui */ rubidium@9723: enum IndustryViewWidgets { rubidium@9723: IVW_CLOSEBOX = 0, rubidium@9723: IVW_CAPTION, rubidium@9723: IVW_STICKY, rubidium@9723: IVW_BACKGROUND, rubidium@9723: IVW_VIEWPORT, rubidium@9723: IVW_INFO, rubidium@9723: IVW_GOTO, rubidium@9723: IVW_SPACER, rubidium@9724: IVW_RESIZE_WIDGET, rubidium@9723: }; rubidium@9723: rubidium@9686: /** Information to store about the industry window */ rubidium@9686: struct indview_d : public vp_d { rubidium@9686: byte editbox_line; ///< The line clicked to open the edit box rubidium@9686: byte clicked_line; ///< The line of the button that has been clicked rubidium@9686: byte clicked_button; ///< The button that has been clicked (to raise) rubidium@9686: byte production_offset_y; ///< The offset of the production texts/buttons rubidium@9686: }; rubidium@9686: assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(indview_d)); rubidium@9686: rubidium@9686: truelight@0: static void IndustryViewWndProc(Window *w, WindowEvent *e) truelight@0: { tron@2951: switch (e->event) { truelight@9641: case WE_CREATE: { truelight@9641: /* Count the number of lines that we need to resize the GUI with */ glx@9704: const Industry *i = GetIndustry(w->window_number); glx@9704: const IndustrySpec *ind = GetIndustrySpec(i->type); truelight@9641: int lines = -3; rubidium@9722: bool first = true; rubidium@9722: bool has_accept = false; truelight@9641: rubidium@9722: if (HasBit(ind->callback_flags, CBM_IND_PRODUCTION_CARGO_ARRIVAL) || HasBit(ind->callback_flags, CBM_IND_PRODUCTION_256_TICKS)) { rubidium@9722: for (byte j = 0; j < lengthof(i->accepts_cargo); j++) { rubidium@9722: if (i->accepts_cargo[j] == CT_INVALID) continue; rubidium@9722: has_accept = true; rubidium@9722: if (first) { rubidium@9722: lines++; rubidium@9722: first = false; rubidium@9722: } truelight@9641: lines++; truelight@9641: } rubidium@9722: } else { rubidium@9722: for (byte j = 0; j < lengthof(i->accepts_cargo); j++) { rubidium@9722: if (i->accepts_cargo[j] == CT_INVALID) continue; rubidium@9722: has_accept = true; rubidium@9722: lines++; rubidium@9722: break; rubidium@9722: } truelight@9641: } truelight@9641: rubidium@9722: first = true; rubidium@9722: for (byte j = 0; j < lengthof(i->produced_cargo); j++) { rubidium@9722: if (i->produced_cargo[j] == CT_INVALID) continue; rubidium@9722: if (first) { rubidium@9722: if (has_accept) lines++; truelight@9641: lines++; rubidium@9722: first = false; truelight@9641: } truelight@9641: lines++; truelight@9641: } truelight@9641: rubidium@9724: if (HasBit(ind->callback_flags, CBM_IND_WINDOW_MORE_TEXT)) { rubidium@9724: lines += 2; rubidium@9724: } else { rubidium@9724: /* Remove the resizing option from the widgets. Do it before the Hiding since it will be overwritten */ rubidium@9724: for (byte j = IVW_INFO; j <= IVW_RESIZE_WIDGET; j++) { rubidium@9724: w->widget[j].display_flags = RESIZE_NONE; rubidium@9724: } rubidium@9724: /* Hide the resize button and enlarge the spacer so it will take its place */ rubidium@9724: w->HideWidget(IVW_RESIZE_WIDGET); rubidium@9724: w->widget[IVW_SPACER].right = w->widget[IVW_RESIZE_WIDGET].right; rubidium@9724: } truelight@9641: rubidium@9724: lines *= 10; rubidium@9724: rubidium@9724: /* Resize the widgets for the new size, given by the addition of cargos */ rubidium@9724: for (byte j = IVW_INFO; j <= IVW_RESIZE_WIDGET; j++) { rubidium@9724: if (j != IVW_INFO) w->widget[j].top += lines; rubidium@9724: w->widget[j].bottom += lines; truelight@9641: } rubidium@9724: w->height += lines; rubidium@9724: w->resize.height += lines; truelight@9641: } break; truelight@9641: miham@1004: case WE_PAINT: { truelight@9641: Industry *i = GetIndustry(w->window_number); glx@9624: const IndustrySpec *ind = GetIndustrySpec(i->type); truelight@9641: int y = 111; rubidium@9722: bool first = true; rubidium@9722: bool has_accept = false; tron@2557: ludde@2070: SetDParam(0, w->window_number); truelight@0: DrawWindowWidgets(w); truelight@0: rubidium@9722: if (HasBit(ind->callback_flags, CBM_IND_PRODUCTION_CARGO_ARRIVAL) || HasBit(ind->callback_flags, CBM_IND_PRODUCTION_256_TICKS)) { rubidium@9722: for (byte j = 0; j < lengthof(i->accepts_cargo); j++) { rubidium@9722: if (i->accepts_cargo[j] == CT_INVALID) continue; rubidium@9722: has_accept = true; rubidium@9722: if (first) { rubidium@9722: DrawString(2, y, STR_INDUSTRY_WINDOW_WAITING_FOR_PROCESSING, TC_FROMSTRING); truelight@9641: y += 10; rubidium@9722: first = false; truelight@9641: } glx@9704: SetDParam(0, i->accepts_cargo[j]); truelight@9641: SetDParam(1, i->incoming_cargo_waiting[j]); rubidium@9722: DrawString(4, y, STR_INDUSTRY_WINDOW_WAITING_STOCKPILE_CARGO, TC_FROMSTRING); truelight@9641: y += 10; truelight@9641: } rubidium@9722: } else { rubidium@9722: StringID str = STR_4827_REQUIRES; rubidium@9722: byte p = 0; rubidium@9722: for (byte j = 0; j < lengthof(i->accepts_cargo); j++) { rubidium@9722: if (i->accepts_cargo[j] == CT_INVALID) continue; rubidium@9722: has_accept = true; rubidium@9722: if (p > 0) str++; rubidium@9722: SetDParam(p++, GetCargo(i->accepts_cargo[j])->name); truelight@0: } rubidium@9722: if (has_accept) { rubidium@9722: DrawString(2, y, str, TC_FROMSTRING); rubidium@9722: y += 10; rubidium@9722: } truelight@0: } truelight@193: rubidium@9722: first = true; rubidium@9722: for (byte j = 0; j < lengthof(i->produced_cargo); j++) { rubidium@9722: if (i->produced_cargo[j] == CT_INVALID) continue; rubidium@9722: if (first) { rubidium@9722: if (has_accept) y += 10; rubidium@9722: DrawString(2, y, STR_482A_PRODUCTION_LAST_MONTH, TC_FROMSTRING); truelight@9641: y += 10; rubidium@9686: WP(w, indview_d).production_offset_y = y; rubidium@9722: first = false; truelight@9641: } truelight@0: glx@9704: SetDParam(0, i->produced_cargo[j]); truelight@9641: SetDParam(1, i->last_month_production[j]); ludde@2063: truelight@9641: SetDParam(2, i->last_month_pct_transported[j] * 100 >> 8); rubidium@9722: DrawString(4 + (IsProductionAlterable(i) ? 30 : 0), y, STR_482B_TRANSPORTED, TC_FROMSTRING); belugas@6527: /* Let's put out those buttons.. */ miham@4211: if (IsProductionAlterable(i)) { rubidium@9686: DrawArrowButtons(5, y, 3, (WP(w, indview_d).clicked_line == j + 1) ? WP(w, indview_d).clicked_button : 0, truelight@9641: !isProductionMinimum(i, j), !isProductionMaximum(i, j)); miham@4211: } truelight@9641: y += 10; truelight@9641: } truelight@0: truelight@9641: /* Get the extra message for the GUI */ rubidium@9722: if (HasBit(ind->callback_flags, CBM_IND_WINDOW_MORE_TEXT)) { truelight@9641: uint16 callback_res = GetIndustryCallback(CBID_INDUSTRY_WINDOW_MORE_TEXT, 0, 0, i, i->type, i->xy); truelight@9641: if (callback_res != CALLBACK_FAILED) { truelight@9641: StringID message = GetGRFStringID(ind->grf_prop.grffile->grfid, 0xD000 + callback_res); truelight@9641: if (message != STR_NULL && message != STR_UNDEFINED) { rubidium@9724: const Widget *wi = &w->widget[IVW_INFO]; truelight@9641: y += 10; rubidium@9703: truelight@9718: PrepareTextRefStackUsage(6); rubidium@9724: /* Use all the available space left from where we stand up to the end of the window */ rubidium@9724: DrawStringMultiLine(2, y, message, wi->right - wi->left - 4, wi->bottom - y); rubidium@9703: StopTextRefStackUsage(); miham@4211: } truelight@0: } truelight@0: } truelight@0: truelight@0: DrawWindowViewport(w); truelight@9641: } break; truelight@0: miham@1004: case WE_CLICK: { miham@1004: Industry *i; miham@1004: belugas@4634: switch (e->we.click.widget) { rubidium@9723: case IVW_INFO: { Darkvater@4193: int line, x; miham@1004: miham@1004: i = GetIndustry(w->window_number); miham@1004: belugas@6527: /* We should work if needed.. */ Darkvater@4194: if (!IsProductionAlterable(i)) return; belugas@4634: x = e->we.click.pt.x; rubidium@9686: line = (e->we.click.pt.y - WP(w, indview_d).production_offset_y) / 10; rubidium@9723: if (e->we.click.pt.y >= WP(w, indview_d).production_offset_y && IsInsideMM(line, 0, 2) && i->produced_cargo[line] != CT_INVALID) { rubidium@9723: if (IsInsideMM(x, 5, 25) ) { Darkvater@4193: /* Clicked buttons, decrease or increase production */ tron@1019: if (x < 15) { miham@4211: if (isProductionMinimum(i, line)) return; rubidium@9722: i->production_rate[line] = max(i->production_rate[line] / 2, 0); miham@1004: } else { rubidium@9722: /* a zero production industry is unlikely to give anything but zero, so push it a little bit */ rubidium@9722: int new_prod = i->production_rate[line] == 0 ? 1 : i->production_rate[line] * 2; miham@4211: if (isProductionMaximum(i, line)) return; rubidium@9722: i->production_rate[line] = minu(new_prod, 255); miham@1004: } Darkvater@4193: miham@1004: UpdateIndustryProduction(i); miham@1004: SetWindowDirty(w); miham@1004: w->flags4 |= 5 << WF_TIMEOUT_SHL; rubidium@9686: WP(w, indview_d).clicked_line = line + 1; rubidium@9686: WP(w, indview_d).clicked_button = (x < 15 ? 1 : 2); rubidium@9723: } else if (IsInsideMM(x, 34, 160)) { belugas@6527: /* clicked the text */ rubidium@9686: WP(w, indview_d).editbox_line = line; miham@1004: SetDParam(0, i->production_rate[line] * 8); Darkvater@5682: ShowQueryString(STR_CONFIG_PATCHES_INT32, STR_CONFIG_GAME_PRODUCTION, 10, 100, w, CS_ALPHANUMERAL); miham@1004: } tron@1019: } Darkvater@4193: } break; rubidium@9723: case IVW_GOTO: truelight@919: i = GetIndustry(w->window_number); tron@1981: ScrollMainWindowToTile(i->xy + TileDiffXY(1, 1)); rubidium@9601: } break; Darkvater@4193: miham@1004: } truelight@0: break; miham@1004: case WE_TIMEOUT: rubidium@9686: WP(w, indview_d).clicked_line = 0; rubidium@9686: WP(w, indview_d).clicked_button = 0; miham@1004: SetWindowDirty(w); miham@1004: break; miham@1004: miham@1004: case WE_ON_EDIT_TEXT: belugas@4634: if (e->we.edittext.str[0] != '\0') { tron@3017: Industry* i = GetIndustry(w->window_number); rubidium@9686: int line = WP(w, indview_d).editbox_line; miham@1004: rubidium@9722: i->production_rate[line] = ClampU(atoi(e->we.edittext.str), 0, 255); miham@1004: UpdateIndustryProduction(i); miham@1004: SetWindowDirty(w); miham@1004: } truelight@0: } truelight@0: } truelight@0: miham@1004: static void UpdateIndustryProduction(Industry *i) miham@1004: { glx@9704: for (byte j = 0; j < lengthof(i->produced_cargo); j++) { glx@9704: if (i->produced_cargo[j] != CT_INVALID) { glx@9626: i->last_month_production[j] = 8 * i->production_rate[j]; glx@9624: } glx@9624: } miham@1004: } miham@1004: rubidium@9723: /** Widget definition of the view industy gui */ truelight@0: static const Widget _industry_view_widgets[] = { rubidium@9723: { WWT_CLOSEBOX, RESIZE_NONE, 9, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, // IVW_CLOSEBOX rubidium@9723: { WWT_CAPTION, RESIZE_NONE, 9, 11, 247, 0, 13, STR_4801, STR_018C_WINDOW_TITLE_DRAG_THIS}, // IVW_CAPTION rubidium@9723: { WWT_STICKYBOX, RESIZE_NONE, 9, 248, 259, 0, 13, 0x0, STR_STICKY_BUTTON}, // IVW_STICKY rubidium@9723: { WWT_PANEL, RESIZE_NONE, 9, 0, 259, 14, 105, 0x0, STR_NULL}, // IVW_BACKGROUND rubidium@9723: { WWT_INSET, RESIZE_NONE, 9, 2, 257, 16, 103, 0x0, STR_NULL}, // IVW_VIEWPORT rubidium@9724: { WWT_PANEL, RESIZE_BOTTOM, 9, 0, 259, 106, 147, 0x0, STR_NULL}, // IVW_INFO rubidium@9724: { WWT_PUSHTXTBTN, RESIZE_TB, 9, 0, 129, 148, 159, STR_00E4_LOCATION, STR_482C_CENTER_THE_MAIN_VIEW_ON}, // IVW_GOTO rubidium@9724: { WWT_PANEL, RESIZE_TB, 9, 130, 247, 148, 159, 0x0, STR_NULL}, // IVW_SPACER rubidium@9724: { WWT_RESIZEBOX, RESIZE_TB, 9, 248, 259, 148, 159, 0x0, STR_RESIZE_BUTTON}, // IVW_RESIZE_WIDGET darkvater@176: { WIDGETS_END}, truelight@0: }; truelight@0: rubidium@9723: /** Window definition of the view industy gui */ truelight@0: static const WindowDesc _industry_view_desc = { rubidium@9694: WDP_AUTO, WDP_AUTO, 260, 160, 260, 160, rubidium@6144: WC_INDUSTRY_VIEW, WC_NONE, rubidium@9724: WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON | WDF_RESIZABLE, truelight@0: _industry_view_widgets, truelight@0: IndustryViewWndProc truelight@0: }; truelight@0: truelight@0: void ShowIndustryViewWindow(int industry) truelight@0: { belugas@4171: Window *w = AllocateWindowDescFront(&_industry_view_desc, industry); truelight@0: tron@2989: if (w != NULL) { truelight@0: w->flags4 |= WF_DISABLE_VP_SCROLL; rubidium@9686: WP(w, indview_d).editbox_line = 0; rubidium@9686: WP(w, indview_d).clicked_line = 0; rubidium@9686: WP(w, indview_d).clicked_button = 0; glx@9624: AssignWindowViewport(w, 3, 17, 0xFE, 0x56, GetIndustry(w->window_number)->xy + TileDiffXY(1, 1), ZOOM_LVL_INDUSTRY); truelight@0: } truelight@0: } truelight@0: rubidium@9723: /** Names of the widgets of the industry directory gui */ rubidium@9723: enum IndustryDirectoryWidgets { rubidium@9723: IDW_CLOSEBOX = 0, rubidium@9723: IDW_CAPTION, rubidium@9723: IDW_STICKY, rubidium@9723: IDW_SORTBYNAME, rubidium@9723: IDW_SORTBYTYPE, rubidium@9723: IDW_SORTBYPROD, rubidium@9723: IDW_SORTBYTRANSPORT, rubidium@9723: IDW_SPACER, rubidium@9723: IDW_INDUSRTY_LIST, rubidium@9723: IDW_SCROLLBAR, rubidium@9723: IDW_RESIZE, rubidium@9686: }; rubidium@9686: rubidium@9723: /** Widget definition of the industy directory gui */ truelight@0: static const Widget _industry_directory_widgets[] = { rubidium@9723: { WWT_CLOSEBOX, RESIZE_NONE, 13, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, // IDW_CLOSEBOX rubidium@9723: { WWT_CAPTION, RESIZE_NONE, 13, 11, 495, 0, 13, STR_INDUSTRYDIR_CAPTION, STR_018C_WINDOW_TITLE_DRAG_THIS}, // IDW_CAPTION rubidium@9723: { WWT_STICKYBOX, RESIZE_NONE, 13, 496, 507, 0, 13, 0x0, STR_STICKY_BUTTON}, // IDW_STICKY rubidium@9723: { WWT_PUSHTXTBTN, RESIZE_NONE, 13, 0, 100, 14, 25, STR_SORT_BY_NAME, STR_SORT_ORDER_TIP}, // IDW_SORTBYNAME rubidium@9723: { WWT_PUSHTXTBTN, RESIZE_NONE, 13, 101, 200, 14, 25, STR_SORT_BY_TYPE, STR_SORT_ORDER_TIP}, // IDW_SORTBYTYPE rubidium@9723: { WWT_PUSHTXTBTN, RESIZE_NONE, 13, 201, 300, 14, 25, STR_SORT_BY_PRODUCTION, STR_SORT_ORDER_TIP}, // IDW_SORTBYPROD rubidium@9723: { WWT_PUSHTXTBTN, RESIZE_NONE, 13, 301, 400, 14, 25, STR_SORT_BY_TRANSPORTED, STR_SORT_ORDER_TIP}, // IDW_SORTBYTRANSPORT rubidium@9723: { WWT_PANEL, RESIZE_NONE, 13, 401, 495, 14, 25, 0x0, STR_NULL}, // IDW_SPACER rubidium@9723: { WWT_PANEL, RESIZE_BOTTOM, 13, 0, 495, 26, 189, 0x0, STR_200A_TOWN_NAMES_CLICK_ON_NAME}, // IDW_INDUSRTY_LIST rubidium@9723: { WWT_SCROLLBAR, RESIZE_BOTTOM, 13, 496, 507, 14, 177, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST}, // IDW_SCROLLBAR rubidium@9723: { WWT_RESIZEBOX, RESIZE_TB, 13, 496, 507, 178, 189, 0x0, STR_RESIZE_BUTTON}, // IDW_RESIZE darkvater@176: { WIDGETS_END}, truelight@0: }; truelight@0: truelight@0: static uint _num_industry_sort; truelight@0: truelight@0: static char _bufcache[96]; tron@4277: static const Industry* _last_industry; truelight@0: truelight@0: static byte _industry_sort_order; truelight@0: darkvater@164: static int CDECL GeneralIndustrySorter(const void *a, const void *b) truelight@0: { tron@4277: const Industry* i = *(const Industry**)a; tron@4277: const Industry* j = *(const Industry**)b; tron@4282: int r; truelight@0: truelight@0: switch (_industry_sort_order >> 1) { tron@4282: default: NOT_REACHED(); tron@4282: case 0: /* Sort by Name (handled later) */ truelight@0: r = 0; tron@4282: break; tron@4282: tron@4282: case 1: /* Sort by Type */ tron@4282: r = i->type - j->type; tron@4282: break; tron@4282: tron@4282: case 2: /* Sort by Production */ glx@9704: if (i->produced_cargo[0] == CT_INVALID) { glx@9704: r = (j->produced_cargo[0] == CT_INVALID ? 0 : -1); tron@4282: } else { glx@9704: if (j->produced_cargo[0] == CT_INVALID) { tron@4282: r = 1; tron@4282: } else { tron@4282: r = glx@9626: (i->last_month_production[0] + i->last_month_production[1]) - glx@9626: (j->last_month_production[0] + j->last_month_production[1]); tron@4282: } tron@4282: } tron@4282: break; tron@4282: tron@4282: case 3: /* Sort by transported fraction */ glx@9704: if (i->produced_cargo[0] == CT_INVALID) { glx@9704: r = (j->produced_cargo[0] == CT_INVALID ? 0 : -1); tron@4282: } else { glx@9704: if (j->produced_cargo[0] == CT_INVALID) { tron@4282: r = 1; tron@4282: } else { tron@4282: int pi; tron@4282: int pj; tron@4282: glx@9626: pi = i->last_month_pct_transported[0] * 100 >> 8; glx@9704: if (i->produced_cargo[1] != CT_INVALID) { glx@9626: int p = i->last_month_pct_transported[1] * 100 >> 8; tron@4282: if (p < pi) pi = p; tron@4282: } tron@4282: glx@9626: pj = j->last_month_pct_transported[0] * 100 >> 8; glx@9704: if (j->produced_cargo[1] != CT_INVALID) { glx@9626: int p = j->last_month_pct_transported[1] * 100 >> 8; tron@4282: if (p < pj) pj = p; tron@4282: } tron@4282: tron@4282: r = pi - pj; tron@4282: } tron@4282: } tron@4282: break; truelight@0: } truelight@0: belugas@6527: /* default to string sorting if they are otherwise equal */ truelight@0: if (r == 0) { tron@4282: char buf1[96]; tron@4282: ludde@2070: SetDParam(0, i->town->index); Darkvater@4912: GetString(buf1, STR_TOWN, lastof(buf1)); truelight@0: tron@4277: if (j != _last_industry) { tron@4277: _last_industry = j; ludde@2070: SetDParam(0, j->town->index); Darkvater@4912: GetString(_bufcache, STR_TOWN, lastof(_bufcache)); truelight@0: } truelight@0: r = strcmp(buf1, _bufcache); truelight@0: } truelight@193: truelight@193: if (_industry_sort_order & 1) r = -r; truelight@0: return r; truelight@0: } truelight@0: rubidium@6526: /** rubidium@6526: * Makes a sorted industry list. rubidium@6526: * When there are no industries, the list has to be made. This so when one rubidium@6526: * starts a new game without industries after playing a game with industries rubidium@6526: * the list is not populated with invalid industries from the previous game. rubidium@6526: */ rubidium@6573: static void MakeSortedIndustryList() truelight@0: { tron@4277: const Industry* i; truelight@919: int n = 0; truelight@919: truelight@919: /* Create array for sorting */ KUDr@5860: _industry_sort = ReallocT(_industry_sort, GetMaxIndustryIndex() + 1); truelight@0: rubidium@6526: /* Don't attempt a sort if there are no industries */ rubidium@6526: if (GetNumIndustries() != 0) { rubidium@6526: FOR_ALL_INDUSTRIES(i) _industry_sort[n++] = i; rubidium@6526: qsort((void*)_industry_sort, n, sizeof(_industry_sort[0]), GeneralIndustrySorter); rubidium@6526: } truelight@4346: truelight@0: _num_industry_sort = n; tron@4277: _last_industry = NULL; // used for "cache" truelight@0: Darkvater@5568: DEBUG(misc, 3, "Resorting industries list"); truelight@0: } truelight@0: truelight@0: truelight@0: static void IndustryDirectoryWndProc(Window *w, WindowEvent *e) truelight@0: { tron@2951: switch (e->event) { truelight@0: case WE_PAINT: { truelight@0: if (_industry_sort_dirty) { truelight@0: _industry_sort_dirty = false; truelight@0: MakeSortedIndustryList(); truelight@0: } truelight@0: bjarni@1666: SetVScrollCount(w, _num_industry_sort); truelight@0: truelight@0: DrawWindowWidgets(w); rubidium@9724: DrawSortButtonState(w, IDW_SORTBYNAME + (_industry_sort_order >> 1), _industry_sort_order & 1 ? SBS_DOWN : SBS_UP); truelight@0: rubidium@9724: uint p = w->vscroll.pos; rubidium@9724: int n = 0; truelight@0: truelight@0: while (p < _num_industry_sort) { tron@4277: const Industry* i = _industry_sort[p]; tron@2989: ludde@2070: SetDParam(0, i->index); glx@9704: if (i->produced_cargo[0] != CT_INVALID) { glx@9704: SetDParam(1, i->produced_cargo[0]); glx@9626: SetDParam(2, i->last_month_production[0]); truelight@193: glx@9704: if (i->produced_cargo[1] != CT_INVALID) { glx@9704: SetDParam(3, i->produced_cargo[1]); glx@9626: SetDParam(4, i->last_month_production[1]); glx@9626: SetDParam(5, i->last_month_pct_transported[0] * 100 >> 8); glx@9626: SetDParam(6, i->last_month_pct_transported[1] * 100 >> 8); rubidium@9722: DrawString(4, 28 + n * 10, STR_INDUSTRYDIR_ITEM_TWO, TC_FROMSTRING); truelight@0: } else { glx@9626: SetDParam(3, i->last_month_pct_transported[0] * 100 >> 8); rubidium@9722: DrawString(4, 28 + n * 10, STR_INDUSTRYDIR_ITEM, TC_FROMSTRING); truelight@0: } truelight@0: } else { rubidium@9722: DrawString(4, 28 + n * 10, STR_INDUSTRYDIR_ITEM_NOPROD, TC_FROMSTRING); truelight@0: } truelight@0: p++; tron@2951: if (++n == w->vscroll.cap) break; truelight@0: } truelight@0: } break; truelight@0: truelight@0: case WE_CLICK: belugas@4634: switch (e->we.click.widget) { rubidium@9723: case IDW_SORTBYNAME: { rubidium@9686: _industry_sort_order = _industry_sort_order == 0 ? 1 : 0; rubidium@9686: _industry_sort_dirty = true; rubidium@9686: SetWindowDirty(w); rubidium@9686: } break; truelight@0: rubidium@9723: case IDW_SORTBYTYPE: { rubidium@9686: _industry_sort_order = _industry_sort_order == 2 ? 3 : 2; rubidium@9686: _industry_sort_dirty = true; rubidium@9686: SetWindowDirty(w); rubidium@9686: } break; truelight@0: rubidium@9723: case IDW_SORTBYPROD: { rubidium@9686: _industry_sort_order = _industry_sort_order == 4 ? 5 : 4; rubidium@9686: _industry_sort_dirty = true; rubidium@9686: SetWindowDirty(w); rubidium@9686: } break; truelight@193: rubidium@9723: case IDW_SORTBYTRANSPORT: { rubidium@9686: _industry_sort_order = _industry_sort_order == 6 ? 7 : 6; rubidium@9686: _industry_sort_dirty = true; rubidium@9686: SetWindowDirty(w); rubidium@9686: } break; truelight@0: rubidium@9723: case IDW_INDUSRTY_LIST: { rubidium@9686: int y = (e->we.click.pt.y - 28) / 10; rubidium@9686: uint16 p; rubidium@9686: rubidium@9723: if (!IsInsideMM(y, 0, w->vscroll.cap)) return; rubidium@9686: p = y + w->vscroll.pos; rubidium@9686: if (p < _num_industry_sort) { rubidium@9686: ScrollMainWindowToTile(_industry_sort[p]->xy); rubidium@9686: } rubidium@9686: } break; truelight@0: } truelight@0: break; truelight@0: truelight@0: case WE_4: truelight@0: SetWindowDirty(w); truelight@0: break; truelight@867: truelight@867: case WE_RESIZE: belugas@4634: w->vscroll.cap += e->we.sizing.diff.y / 10; truelight@867: break; truelight@193: } truelight@0: } truelight@0: rubidium@9723: /** Window definition of the industy directory gui */ truelight@0: static const WindowDesc _industry_directory_desc = { rubidium@9694: WDP_AUTO, WDP_AUTO, 508, 190, 508, 190, rubidium@6144: WC_INDUSTRY_DIRECTORY, WC_NONE, truelight@867: WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON | WDF_RESIZABLE, truelight@0: _industry_directory_widgets, truelight@0: IndustryDirectoryWndProc truelight@0: }; truelight@0: rubidium@6573: void ShowIndustryDirectory() truelight@0: { belugas@4171: Window *w = AllocateWindowDescFront(&_industry_directory_desc, 0); truelight@0: tron@2989: if (w != NULL) { truelight@0: w->vscroll.cap = 16; truelight@867: w->resize.height = w->height - 6 * 10; // minimum 10 items truelight@867: w->resize.step_height = 10; truelight@0: SetWindowDirty(w); truelight@0: } truelight@0: }