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