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