src/industry_gui.cpp
branchNewGRF_ports
changeset 10991 d8811e327d12
parent 10731 67db0d431d5e
equal deleted inserted replaced
10731:67db0d431d5e 10991:d8811e327d12
    25 #include "player_func.h"
    25 #include "player_func.h"
    26 #include "settings_type.h"
    26 #include "settings_type.h"
    27 #include "tilehighlight_func.h"
    27 #include "tilehighlight_func.h"
    28 #include "string_func.h"
    28 #include "string_func.h"
    29 #include "sortlist_type.h"
    29 #include "sortlist_type.h"
       
    30 #include "widgets/dropdown_func.h"
    30 
    31 
    31 #include "table/strings.h"
    32 #include "table/strings.h"
    32 #include "table/sprites.h"
    33 #include "table/sprites.h"
    33 
    34 
    34 bool _ignore_restrictions;
    35 bool _ignore_restrictions;
   129 			indsp = GetIndustrySpec(ind);
   130 			indsp = GetIndustrySpec(ind);
   130 			if (indsp->enabled){
   131 			if (indsp->enabled){
   131 				/* Rule is that editor mode loads all industries.
   132 				/* Rule is that editor mode loads all industries.
   132 				 * In game mode, all non raw industries are loaded too
   133 				 * In game mode, all non raw industries are loaded too
   133 				 * and raw ones are loaded only when setting allows it */
   134 				 * and raw ones are loaded only when setting allows it */
   134 				if (_game_mode != GM_EDITOR && indsp->IsRawIndustry() && _settings.construction.raw_industry_construction == 0) {
   135 				if (_game_mode != GM_EDITOR && indsp->IsRawIndustry() && _settings_game.construction.raw_industry_construction == 0) {
   135 					/* Unselect if the industry is no longer in the list */
   136 					/* Unselect if the industry is no longer in the list */
   136 					if (this->selected_type == ind) this->selected_index = -1;
   137 					if (this->selected_type == ind) this->selected_index = -1;
   137 					continue;
   138 					continue;
   138 				}
   139 				}
   139 				this->index[this->count] = ind;
   140 				this->index[this->count] = ind;
   193 
   194 
   194 		/* Raw industries might be prospected. Show this fact by changing the string
   195 		/* Raw industries might be prospected. Show this fact by changing the string
   195 		 * In Editor, you just build, while ingame, or you fund or you prospect */
   196 		 * In Editor, you just build, while ingame, or you fund or you prospect */
   196 		if (_game_mode == GM_EDITOR) {
   197 		if (_game_mode == GM_EDITOR) {
   197 			/* We've chosen many random industries but no industries have been specified */
   198 			/* We've chosen many random industries but no industries have been specified */
   198 			if (indsp == NULL) this->enabled[this->selected_index] = _settings.difficulty.number_industries != 0;
   199 			if (indsp == NULL) this->enabled[this->selected_index] = _settings_game.difficulty.number_industries != 0;
   199 			this->widget[DPIW_FUND_WIDGET].data = STR_BUILD_NEW_INDUSTRY;
   200 			this->widget[DPIW_FUND_WIDGET].data = STR_BUILD_NEW_INDUSTRY;
   200 		} else {
   201 		} else {
   201 			this->widget[DPIW_FUND_WIDGET].data = (_settings.construction.raw_industry_construction == 2 && indsp->IsRawIndustry()) ? STR_PROSPECT_NEW_INDUSTRY : STR_FUND_NEW_INDUSTRY;
   202 			this->widget[DPIW_FUND_WIDGET].data = (_settings_game.construction.raw_industry_construction == 2 && indsp->IsRawIndustry()) ? STR_PROSPECT_NEW_INDUSTRY : STR_FUND_NEW_INDUSTRY;
   202 		}
   203 		}
   203 		this->SetWidgetDisabledState(DPIW_FUND_WIDGET, !this->enabled[this->selected_index]);
   204 		this->SetWidgetDisabledState(DPIW_FUND_WIDGET, !this->enabled[this->selected_index]);
   204 
   205 
   205 		SetVScrollCount(this, this->count);
   206 		SetVScrollCount(this, this->count);
   206 
   207 
   302 					this->selected_type = this->index[y];
   303 					this->selected_type = this->index[y];
   303 					indsp = (this->selected_type == INVALID_INDUSTRYTYPE) ? NULL : GetIndustrySpec(this->selected_type);
   304 					indsp = (this->selected_type == INVALID_INDUSTRYTYPE) ? NULL : GetIndustrySpec(this->selected_type);
   304 
   305 
   305 					this->SetDirty();
   306 					this->SetDirty();
   306 
   307 
   307 					if ((_game_mode != GM_EDITOR && _settings.construction.raw_industry_construction == 2 && indsp != NULL && indsp->IsRawIndustry()) ||
   308 					if ((_game_mode != GM_EDITOR && _settings_game.construction.raw_industry_construction == 2 && indsp != NULL && indsp->IsRawIndustry()) ||
   308 							this->selected_type == INVALID_INDUSTRYTYPE) {
   309 							this->selected_type == INVALID_INDUSTRYTYPE) {
   309 						/* Reset the button state if going to prospecting or "build many industries" */
   310 						/* Reset the button state if going to prospecting or "build many industries" */
   310 						this->RaiseButtons();
   311 						this->RaiseButtons();
   311 						ResetObjectToPlace();
   312 						ResetObjectToPlace();
   312 					}
   313 					}
   323 						extern void GenerateIndustries();
   324 						extern void GenerateIndustries();
   324 						_generating_world = true;
   325 						_generating_world = true;
   325 						GenerateIndustries();
   326 						GenerateIndustries();
   326 						_generating_world = false;
   327 						_generating_world = false;
   327 					}
   328 					}
   328 				} else if (_game_mode != GM_EDITOR && _settings.construction.raw_industry_construction == 2 && GetIndustrySpec(this->selected_type)->IsRawIndustry()) {
   329 				} else if (_game_mode != GM_EDITOR && _settings_game.construction.raw_industry_construction == 2 && GetIndustrySpec(this->selected_type)->IsRawIndustry()) {
   329 					DoCommandP(0, this->selected_type, InteractiveRandom(), NULL, CMD_BUILD_INDUSTRY | CMD_MSG(STR_4830_CAN_T_CONSTRUCT_THIS_INDUSTRY));
   330 					DoCommandP(0, this->selected_type, InteractiveRandom(), NULL, CMD_BUILD_INDUSTRY | CMD_MSG(STR_4830_CAN_T_CONSTRUCT_THIS_INDUSTRY));
   330 					this->HandleButtonClick(DPIW_FUND_WIDGET);
   331 					this->HandleButtonClick(DPIW_FUND_WIDGET);
   331 				} else {
   332 				} else {
   332 					HandlePlacePushButton(this, DPIW_FUND_WIDGET, SPR_CURSOR_INDUSTRY, VHM_RECT, NULL);
   333 					HandlePlacePushButton(this, DPIW_FUND_WIDGET, SPR_CURSOR_INDUSTRY, VHM_RECT, NULL);
   333 				}
   334 				}
   689 /** Names of the widgets of the industry directory gui */
   690 /** Names of the widgets of the industry directory gui */
   690 enum IndustryDirectoryWidgets {
   691 enum IndustryDirectoryWidgets {
   691 	IDW_CLOSEBOX = 0,
   692 	IDW_CLOSEBOX = 0,
   692 	IDW_CAPTION,
   693 	IDW_CAPTION,
   693 	IDW_STICKY,
   694 	IDW_STICKY,
   694 	IDW_SORTBYNAME,
   695 	IDW_DROPDOWN_ORDER,
   695 	IDW_SORTBYTYPE,
   696 	IDW_DROPDOWN_CRITERIA,
   696 	IDW_SORTBYPROD,
       
   697 	IDW_SORTBYTRANSPORT,
       
   698 	IDW_SPACER,
   697 	IDW_SPACER,
   699 	IDW_INDUSTRY_LIST,
   698 	IDW_INDUSTRY_LIST,
   700 	IDW_SCROLLBAR,
   699 	IDW_SCROLLBAR,
   701 	IDW_RESIZE,
   700 	IDW_RESIZE,
   702 };
   701 };
   703 
   702 
   704 /** Widget definition of the industy directory gui */
   703 /** Widget definition of the industy directory gui */
   705 static const Widget _industry_directory_widgets[] = {
   704 static const Widget _industry_directory_widgets[] = {
   706 {   WWT_CLOSEBOX,   RESIZE_NONE,    13,     0,    10,     0,    13, STR_00C5,                STR_018B_CLOSE_WINDOW},             // IDW_CLOSEBOX
   705 {   WWT_CLOSEBOX,   RESIZE_NONE,    13,     0,    10,     0,    13, STR_00C5,                STR_018B_CLOSE_WINDOW},             // IDW_CLOSEBOX
   707 {    WWT_CAPTION,  RESIZE_RIGHT,    13,    11,   495,     0,    13, STR_INDUSTRYDIR_CAPTION, STR_018C_WINDOW_TITLE_DRAG_THIS},   // IDW_CAPTION
   706 {    WWT_CAPTION,  RESIZE_RIGHT,    13,    11,   415,     0,    13, STR_INDUSTRYDIR_CAPTION, STR_018C_WINDOW_TITLE_DRAG_THIS},   // IDW_CAPTION
   708 {  WWT_STICKYBOX,     RESIZE_LR,    13,   496,   507,     0,    13, 0x0,                     STR_STICKY_BUTTON},                 // IDW_STICKY
   707 {  WWT_STICKYBOX,     RESIZE_LR,    13,   416,   427,     0,    13, 0x0,                     STR_STICKY_BUTTON},                 // IDW_STICKY
   709 { WWT_PUSHTXTBTN,   RESIZE_NONE,    13,     0,   100,    14,    25, STR_SORT_BY_NAME,        STR_SORT_ORDER_TIP},                // IDW_SORTBYNAME
   708 
   710 { WWT_PUSHTXTBTN,   RESIZE_NONE,    13,   101,   200,    14,    25, STR_SORT_BY_TYPE,        STR_SORT_ORDER_TIP},                // IDW_SORTBYTYPE
   709 {    WWT_TEXTBTN,   RESIZE_NONE,    13,     0,    80,    14,    25, STR_SORT_BY,             STR_SORT_ORDER_TIP},                // IDW_DROPDOWN_ORDER
   711 { WWT_PUSHTXTBTN,   RESIZE_NONE,    13,   201,   300,    14,    25, STR_SORT_BY_PRODUCTION,  STR_SORT_ORDER_TIP},                // IDW_SORTBYPROD
   710 {   WWT_DROPDOWN,   RESIZE_NONE,    13,    81,   243,    14,    25, 0x0,                     STR_SORT_CRITERIA_TIP},             // IDW_DROPDOWN_CRITERIA
   712 { WWT_PUSHTXTBTN,   RESIZE_NONE,    13,   301,   400,    14,    25, STR_SORT_BY_TRANSPORTED, STR_SORT_ORDER_TIP},                // IDW_SORTBYTRANSPORT
   711 {      WWT_PANEL,  RESIZE_RIGHT,    13,   244,   415,    14,    25, 0x0,                     STR_NULL},                          // IDW_SPACER
   713 {      WWT_PANEL,  RESIZE_RIGHT,    13,   401,   495,    14,    25, 0x0,                     STR_NULL},                          // IDW_SPACER
   712 
   714 {      WWT_PANEL,     RESIZE_RB,    13,     0,   495,    26,   189, 0x0,                     STR_200A_TOWN_NAMES_CLICK_ON_NAME}, // IDW_INDUSRTY_LIST
   713 {      WWT_PANEL,     RESIZE_RB,    13,     0,   415,    26,   189, 0x0,                     STR_200A_TOWN_NAMES_CLICK_ON_NAME}, // IDW_INDUSRTY_LIST
   715 {  WWT_SCROLLBAR,    RESIZE_LRB,    13,   496,   507,    14,   177, 0x0,                     STR_0190_SCROLL_BAR_SCROLLS_LIST},  // IDW_SCROLLBAR
   714 {  WWT_SCROLLBAR,    RESIZE_LRB,    13,   416,   427,    14,   177, 0x0,                     STR_0190_SCROLL_BAR_SCROLLS_LIST},  // IDW_SCROLLBAR
   716 {  WWT_RESIZEBOX,   RESIZE_LRTB,    13,   496,   507,   178,   189, 0x0,                     STR_RESIZE_BUTTON},                 // IDW_RESIZE
   715 {  WWT_RESIZEBOX,   RESIZE_LRTB,    13,   416,   427,   178,   189, 0x0,                     STR_RESIZE_BUTTON},                 // IDW_RESIZE
   717 {   WIDGETS_END},
   716 {   WIDGETS_END},
   718 };
   717 };
   719 
   718 
   720 static char _bufcache[96];
       
   721 static const Industry* _last_industry;
       
   722 static int _internal_sort_order;
       
   723 
       
   724 /** Returns percents of cargo transported if industry produces this cargo, else -1
       
   725  * @param i industry to check
       
   726  * @param id cargo slot
       
   727  * @return percents of cargo transported, or -1 if industry doesn't use this cargo slot
       
   728  */
       
   729 static inline int GetCargoTransportedPercentsIfValid(const Industry *i, uint id)
       
   730 {
       
   731 	assert(id < lengthof(i->produced_cargo));
       
   732 
       
   733 	if (i->produced_cargo[id] == CT_INVALID) return 101;
       
   734 	return i->last_month_pct_transported[id] * 100 >> 8;
       
   735 }
       
   736 
       
   737 /** Returns value representing industry's transported cargo
       
   738  * percentage for industry sorting
       
   739  * @param i industry to check
       
   740  * @return value used for sorting
       
   741  */
       
   742 static int GetCargoTransportedSortValue(const Industry *i)
       
   743 {
       
   744 	int p1 = GetCargoTransportedPercentsIfValid(i, 0);
       
   745 	int p2 = GetCargoTransportedPercentsIfValid(i, 1);
       
   746 
       
   747 	if (p1 > p2) Swap(p1, p2); // lower value has higher priority
       
   748 
       
   749 	return (p1 << 8) + p2;
       
   750 }
       
   751 
       
   752 static int CDECL GeneralIndustrySorter(const void *a, const void *b)
       
   753 {
       
   754 	const Industry* i = *(const Industry**)a;
       
   755 	const Industry* j = *(const Industry**)b;
       
   756 	int r;
       
   757 
       
   758 	switch (_internal_sort_order >> 1) {
       
   759 		default: NOT_REACHED();
       
   760 		case 0: /* Sort by Name (handled later) */
       
   761 			r = 0;
       
   762 			break;
       
   763 
       
   764 		case 1: /* Sort by Type */
       
   765 			r = i->type - j->type;
       
   766 			break;
       
   767 
       
   768 		case 2: /* Sort by Production */
       
   769 			if (i->produced_cargo[0] == CT_INVALID) {
       
   770 				r = (j->produced_cargo[0] == CT_INVALID ? 0 : -1);
       
   771 			} else {
       
   772 				if (j->produced_cargo[0] == CT_INVALID) {
       
   773 					r = 1;
       
   774 				} else {
       
   775 					r =
       
   776 						(i->last_month_production[0] + i->last_month_production[1]) -
       
   777 						(j->last_month_production[0] + j->last_month_production[1]);
       
   778 				}
       
   779 			}
       
   780 			break;
       
   781 
       
   782 		case 3: /* Sort by transported fraction */
       
   783 			r = GetCargoTransportedSortValue(i) - GetCargoTransportedSortValue(j);
       
   784 			break;
       
   785 	}
       
   786 
       
   787 	/* default to string sorting if they are otherwise equal */
       
   788 	if (r == 0) {
       
   789 		char buf1[96];
       
   790 
       
   791 		SetDParam(0, i->town->index);
       
   792 		GetString(buf1, STR_TOWN, lastof(buf1));
       
   793 
       
   794 		if (j != _last_industry) {
       
   795 			_last_industry = j;
       
   796 			SetDParam(0, j->town->index);
       
   797 			GetString(_bufcache, STR_TOWN, lastof(_bufcache));
       
   798 		}
       
   799 		r = strcmp(buf1, _bufcache);
       
   800 	}
       
   801 
       
   802 	if (_internal_sort_order & 1) r = -r;
       
   803 	return r;
       
   804 }
       
   805 
       
   806 typedef GUIList<const Industry*> GUIIndustryList;
   719 typedef GUIList<const Industry*> GUIIndustryList;
   807 
   720 
   808 /**
       
   809  * Rebuild industries list if the VL_REBUILD flag is set
       
   810  *
       
   811  * @param sl pointer to industry list
       
   812  */
       
   813 static void BuildIndustriesList(GUIIndustryList *sl)
       
   814 {
       
   815 	if (!(sl->flags & VL_REBUILD)) return;
       
   816 
       
   817 	sl->Clear();
       
   818 
       
   819 	DEBUG(misc, 3, "Building industry list");
       
   820 
       
   821 	const Industry *i;
       
   822 	FOR_ALL_INDUSTRIES(i) {
       
   823 		*sl->Append() = i;
       
   824 	}
       
   825 
       
   826 	sl->Compact();
       
   827 
       
   828 	sl->flags &= ~VL_REBUILD;
       
   829 	sl->flags |= VL_RESORT;
       
   830 }
       
   831 
       
   832 
       
   833 /**
       
   834  * Sort industry list if the VL_RESORT flag is set
       
   835  *
       
   836  * @param sl pointer to industry list
       
   837  */
       
   838 static void SortIndustriesList(GUIIndustryList *sl)
       
   839 {
       
   840 	if (!(sl->flags & VL_RESORT)) return;
       
   841 
       
   842 	_internal_sort_order = (sl->sort_type << 1) | (sl->flags & VL_DESC);
       
   843 	_last_industry = NULL; // used for "cache" in namesorting
       
   844 	qsort((void*)sl->Begin(), sl->Length(), sizeof(sl->Begin()), &GeneralIndustrySorter);
       
   845 
       
   846 	sl->flags &= ~VL_RESORT;
       
   847 }
       
   848 
   721 
   849 /**
   722 /**
   850  * The list of industries.
   723  * The list of industries.
   851  */
   724  */
   852 struct IndustryDirectoryWindow : public Window, public GUIIndustryList {
   725 class IndustryDirectoryWindow : public Window {
   853 	static Listing industry_sort;
   726 protected:
   854 
   727 	/* Runtime saved values */
       
   728 	static Listing last_sorting;
       
   729 	static const Industry *last_industry;
       
   730 
       
   731 	/* Constants for sorting stations */
       
   732 	static const StringID sorter_names[];
       
   733 	static GUIIndustryList::SortFunction *const sorter_funcs[];
       
   734 
       
   735 	GUIIndustryList industries;
       
   736 
       
   737 	/** (Re)Build industries list */
       
   738 	void BuildIndustriesList()
       
   739 	{
       
   740 		if (!this->industries.NeedRebuild()) return;
       
   741 
       
   742 		this->industries.Clear();
       
   743 
       
   744 		DEBUG(misc, 3, "Building industry list");
       
   745 
       
   746 		const Industry *i;
       
   747 		FOR_ALL_INDUSTRIES(i) {
       
   748 			*this->industries.Append() = i;
       
   749 		}
       
   750 
       
   751 		this->industries.Compact();
       
   752 		this->industries.RebuildDone();
       
   753 	}
       
   754 
       
   755 	/**
       
   756 	 * Returns percents of cargo transported if industry produces this cargo, else -1
       
   757 	 *
       
   758 	 * @param i industry to check
       
   759 	 * @param id cargo slot
       
   760 	 * @return percents of cargo transported, or -1 if industry doesn't use this cargo slot
       
   761 	 */
       
   762 	static inline int GetCargoTransportedPercentsIfValid(const Industry *i, uint id)
       
   763 	{
       
   764 		assert(id < lengthof(i->produced_cargo));
       
   765 
       
   766 		if (i->produced_cargo[id] == CT_INVALID) return 101;
       
   767 		return i->last_month_pct_transported[id] * 100 >> 8;
       
   768 	}
       
   769 
       
   770 	/**
       
   771 	 * Returns value representing industry's transported cargo
       
   772 	 *  percentage for industry sorting
       
   773 	 *
       
   774 	 * @param i industry to check
       
   775 	 * @return value used for sorting
       
   776 	 */
       
   777 	static int GetCargoTransportedSortValue(const Industry *i)
       
   778 	{
       
   779 		int p1 = GetCargoTransportedPercentsIfValid(i, 0);
       
   780 		int p2 = GetCargoTransportedPercentsIfValid(i, 1);
       
   781 
       
   782 		if (p1 > p2) Swap(p1, p2); // lower value has higher priority
       
   783 
       
   784 		return (p1 << 8) + p2;
       
   785 	}
       
   786 
       
   787 	/** Sort industries by name */
       
   788 	static int CDECL IndustryNameSorter(const Industry* const *a, const Industry* const *b)
       
   789 	{
       
   790 		static char buf_cache[96];
       
   791 		static char buf[96];
       
   792 
       
   793 		SetDParam(0, (*a)->town->index);
       
   794 		GetString(buf, STR_TOWN, lastof(buf));
       
   795 
       
   796 		if (*b != last_industry) {
       
   797 			last_industry = *b;
       
   798 			SetDParam(0, (*b)->town->index);
       
   799 			GetString(buf_cache, STR_TOWN, lastof(buf_cache));
       
   800 		}
       
   801 
       
   802 		return strcmp(buf, buf_cache);
       
   803 	}
       
   804 
       
   805 	/** Sort industries by type and name */
       
   806 	static int CDECL IndustryTypeSorter(const Industry* const *a, const Industry* const *b)
       
   807 	{
       
   808 		int r = (*a)->type - (*b)->type;
       
   809 		return (r == 0) ? IndustryNameSorter(a, b) : r;
       
   810 	}
       
   811 
       
   812 	/** Sort industries by production and name */
       
   813 	static int CDECL IndustryProductionSorter(const Industry* const *a, const Industry* const *b)
       
   814 	{
       
   815 		int r = 0;
       
   816 
       
   817 		if ((*a)->produced_cargo[0] == CT_INVALID) {
       
   818 			if ((*b)->produced_cargo[0] != CT_INVALID) return -1;
       
   819 		} else {
       
   820 			if ((*b)->produced_cargo[0] == CT_INVALID) return 1;
       
   821 
       
   822 			r = ((*a)->last_month_production[0] + (*a)->last_month_production[1]) -
       
   823 			    ((*b)->last_month_production[0] + (*b)->last_month_production[1]);
       
   824 		}
       
   825 
       
   826 		return (r == 0) ? IndustryNameSorter(a, b) : r;
       
   827 	}
       
   828 
       
   829 	/** Sort industries by transported cargo and name */
       
   830 	static int CDECL IndustryTransportedCargoSorter(const Industry* const *a, const Industry* const *b)
       
   831 	{
       
   832 		int r = GetCargoTransportedSortValue(*a) - GetCargoTransportedSortValue(*b);
       
   833 		return (r == 0) ? IndustryNameSorter(a, b) : r;
       
   834 	}
       
   835 
       
   836 	/** Sort the industries list */
       
   837 	void SortIndustriesList()
       
   838 	{
       
   839 		if (!this->industries.Sort()) return;
       
   840 
       
   841 		/* Reset name sorter sort cache */
       
   842 		this->last_industry = NULL;
       
   843 
       
   844 		/* Set the modified widget dirty */
       
   845 		this->InvalidateWidget(IDW_INDUSTRY_LIST);
       
   846 	}
       
   847 
       
   848 public:
   855 	IndustryDirectoryWindow(const WindowDesc *desc, WindowNumber number) : Window(desc, number)
   849 	IndustryDirectoryWindow(const WindowDesc *desc, WindowNumber number) : Window(desc, number)
   856 	{
   850 	{
   857 		this->vscroll.cap = 16;
   851 		this->vscroll.cap = 16;
   858 		this->resize.height = this->height - 6 * 10; // minimum 10 items
   852 		this->resize.height = this->height - 6 * 10; // minimum 10 items
   859 		this->resize.step_height = 10;
   853 		this->resize.step_height = 10;
   860 		this->FindWindowPlacementAndResize(desc);
   854 		this->FindWindowPlacementAndResize(desc);
   861 
   855 
   862 		this->flags = VL_REBUILD;
   856 		this->industries.SetListing(this->last_sorting);
   863 		this->sort_type = industry_sort.criteria;
   857 		this->industries.SetSortFuncs(this->sorter_funcs);
   864 		if (industry_sort.order) this->flags |= VL_DESC;
   858 		this->industries.ForceRebuild();
       
   859 		this->industries.NeedResort();
       
   860 		this->SortIndustriesList();
       
   861 
       
   862 		this->widget[IDW_DROPDOWN_CRITERIA].data = this->sorter_names[this->industries.SortType()];
       
   863 	}
       
   864 
       
   865 	~IndustryDirectoryWindow()
       
   866 	{
       
   867 		this->last_sorting = this->industries.GetListing();
   865 	}
   868 	}
   866 
   869 
   867 	virtual void OnPaint()
   870 	virtual void OnPaint()
   868 	{
   871 	{
   869 		BuildIndustriesList(this);
   872 		BuildIndustriesList();
   870 		SortIndustriesList(this);
   873 		SortIndustriesList();
   871 
   874 
   872 		SetVScrollCount(this, this->Length());
   875 		SetVScrollCount(this, this->industries.Length());
   873 
   876 
   874 		this->DrawWidgets();
   877 		this->DrawWidgets();
   875 		this->DrawSortButtonState(IDW_SORTBYNAME + this->sort_type, this->flags & VL_DESC ? SBS_DOWN : SBS_UP);
   878 		this->DrawSortButtonState(IDW_DROPDOWN_ORDER, this->industries.IsDescSortOrder() ? SBS_DOWN : SBS_UP);
   876 
   879 
   877 		int max = min(this->vscroll.pos + this->vscroll.cap, this->Length());
   880 		int max = min(this->vscroll.pos + this->vscroll.cap, this->industries.Length());
   878 		int y = 28; // start of the list-widget
   881 		int y = 28; // start of the list-widget
   879 
   882 
   880 		for (int n = this->vscroll.pos; n < max; ++n) {
   883 		for (int n = this->vscroll.pos; n < max; ++n) {
   881 			const Industry* i = *this->Get(n);
   884 			const Industry* i = this->industries[n];
   882 			const IndustrySpec *indsp = GetIndustrySpec(i->type);
   885 			const IndustrySpec *indsp = GetIndustrySpec(i->type);
   883 			byte p = 0;
   886 			byte p = 0;
   884 
   887 
   885 			/* Industry name */
   888 			/* Industry name */
   886 			SetDParam(p++, i->index);
   889 			SetDParam(p++, i->index);
   909 	}
   912 	}
   910 
   913 
   911 	virtual void OnClick(Point pt, int widget)
   914 	virtual void OnClick(Point pt, int widget)
   912 	{
   915 	{
   913 		switch (widget) {
   916 		switch (widget) {
   914 			case IDW_SORTBYNAME:
   917 			case IDW_DROPDOWN_ORDER:
   915 			case IDW_SORTBYTYPE:
   918 				this->industries.ToggleSortOrder();
   916 			case IDW_SORTBYPROD:
       
   917 			case IDW_SORTBYTRANSPORT:
       
   918 				if (this->sort_type == (widget - IDW_SORTBYNAME)) {
       
   919 					this->flags ^= VL_DESC;
       
   920 				} else {
       
   921 					this->sort_type = widget - IDW_SORTBYNAME;
       
   922 					this->flags &= ~VL_DESC;
       
   923 				}
       
   924 				industry_sort.criteria = this->sort_type;
       
   925 				industry_sort.order = HasBit(this->flags, 0);
       
   926 				this->flags |= VL_RESORT;
       
   927 				this->SetDirty();
   919 				this->SetDirty();
       
   920 				break;
       
   921 
       
   922 			case IDW_DROPDOWN_CRITERIA:
       
   923 				ShowDropDownMenu(this, this->sorter_names, this->industries.SortType(), IDW_DROPDOWN_CRITERIA, 0, 0);
   928 				break;
   924 				break;
   929 
   925 
   930 			case IDW_INDUSTRY_LIST: {
   926 			case IDW_INDUSTRY_LIST: {
   931 				int y = (pt.y - 28) / 10;
   927 				int y = (pt.y - 28) / 10;
   932 				uint16 p;
   928 				uint16 p;
   933 
   929 
   934 				if (!IsInsideMM(y, 0, this->vscroll.cap)) return;
   930 				if (!IsInsideMM(y, 0, this->vscroll.cap)) return;
   935 				p = y + this->vscroll.pos;
   931 				p = y + this->vscroll.pos;
   936 				if (p < this->Length()) {
   932 				if (p < this->industries.Length()) {
   937 					if (_ctrl_pressed) {
   933 					if (_ctrl_pressed) {
   938 						ShowExtraViewPortWindow((*this->Get(p))->xy);
   934 						ShowExtraViewPortWindow(this->industries[p]->xy);
   939 					} else {
   935 					} else {
   940 						ScrollMainWindowToTile((*this->Get(p))->xy);
   936 						ScrollMainWindowToTile(this->industries[p]->xy);
   941 					}
   937 					}
   942 				}
   938 				}
   943 			} break;
   939 			} break;
   944 		}
   940 		}
   945 	}
   941 	}
   946 
   942 
       
   943 	virtual void OnDropdownSelect(int widget, int index)
       
   944 	{
       
   945 		if (this->industries.SortType() != index) {
       
   946 			this->industries.SetSortType(index);
       
   947 			this->widget[IDW_DROPDOWN_CRITERIA].data = this->sorter_names[this->industries.SortType()];
       
   948 			this->SetDirty();
       
   949 		}
       
   950 	}
       
   951 
   947 	virtual void OnResize(Point new_size, Point delta)
   952 	virtual void OnResize(Point new_size, Point delta)
   948 	{
   953 	{
   949 		this->vscroll.cap += delta.y / 10;
   954 		this->vscroll.cap += delta.y / 10;
   950 	}
   955 	}
   951 
   956 
   952 	virtual void OnInvalidateData(int data)
   957 	virtual void OnInvalidateData(int data)
   953 	{
   958 	{
   954 		this->flags |= (data == 0 ? VL_REBUILD : VL_RESORT);
   959 		if (data == 0) {
       
   960 			this->industries.ForceRebuild();
       
   961 		} else {
       
   962 			this->industries.ForceResort();
       
   963 		}
   955 		this->InvalidateWidget(IDW_INDUSTRY_LIST);
   964 		this->InvalidateWidget(IDW_INDUSTRY_LIST);
   956 	}
   965 	}
   957 };
   966 };
   958 
   967 
   959 Listing IndustryDirectoryWindow::industry_sort = {0, 0};
   968 Listing IndustryDirectoryWindow::last_sorting = {false, 0};
       
   969 const Industry *IndustryDirectoryWindow::last_industry = NULL;
       
   970 
       
   971 /* Availible station sorting functions */
       
   972 GUIIndustryList::SortFunction* const IndustryDirectoryWindow::sorter_funcs[] = {
       
   973 	&IndustryNameSorter,
       
   974 	&IndustryTypeSorter,
       
   975 	&IndustryProductionSorter,
       
   976 	&IndustryTransportedCargoSorter
       
   977 };
       
   978 
       
   979 /* Names of the sorting functions */
       
   980 const StringID IndustryDirectoryWindow::sorter_names[] = {
       
   981 	STR_SORT_BY_DROPDOWN_NAME,
       
   982 	STR_SORT_BY_TYPE,
       
   983 	STR_SORT_BY_PRODUCTION,
       
   984 	STR_SORT_BY_TRANSPORTED,
       
   985 	INVALID_STRING_ID
       
   986 };
       
   987 
   960 
   988 
   961 /** Window definition of the industy directory gui */
   989 /** Window definition of the industy directory gui */
   962 static const WindowDesc _industry_directory_desc = {
   990 static const WindowDesc _industry_directory_desc = {
   963 	WDP_AUTO, WDP_AUTO, 508, 190, 508, 190,
   991 	WDP_AUTO, WDP_AUTO, 428, 190, 428, 190,
   964 	WC_INDUSTRY_DIRECTORY, WC_NONE,
   992 	WC_INDUSTRY_DIRECTORY, WC_NONE,
   965 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON | WDF_RESIZABLE,
   993 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON | WDF_RESIZABLE,
   966 	_industry_directory_widgets,
   994 	_industry_directory_widgets,
   967 };
   995 };
   968 
   996