00001
00002
00005 #include "stdafx.h"
00006 #include "openttd.h"
00007 #include "gui.h"
00008 #include "window_gui.h"
00009 #include "command_func.h"
00010 #include "economy_func.h"
00011 #include "variables.h"
00012 #include "bridge.h"
00013 #include "strings_func.h"
00014 #include "window_func.h"
00015 #include "sound_func.h"
00016 #include "map_func.h"
00017 #include "viewport_func.h"
00018 #include "gfx_func.h"
00019 #include "tunnelbridge.h"
00020 #include "sortlist_type.h"
00021 #include "widgets/dropdown_func.h"
00022
00023 #include "table/strings.h"
00024
00028 struct BuildBridgeData {
00029 BridgeType index;
00030 const BridgeSpec *spec;
00031 Money cost;
00032 };
00033
00034 typedef GUIList<BuildBridgeData> GUIBridgeList;
00035
00044 void CcBuildBridge(bool success, TileIndex tile, uint32 p1, uint32 p2)
00045 {
00046 if (success) SndPlayTileFx(SND_27_BLACKSMITH_ANVIL, tile);
00047 }
00048
00049
00050 enum BuildBridgeSelectionWidgets {
00051 BBSW_CLOSEBOX = 0,
00052 BBSW_CAPTION,
00053 BBSW_DROPDOWN_ORDER,
00054 BBSW_DROPDOWN_CRITERIA,
00055 BBSW_BRIDGE_LIST,
00056 BBSW_SCROLLBAR,
00057 BBSW_RESIZEBOX
00058 };
00059
00060 class BuildBridgeWindow : public Window {
00061 private:
00062
00063 static uint16 last_size;
00064 static Listing last_sorting;
00065
00066
00067 static const StringID sorter_names[];
00068 static GUIBridgeList::SortFunction *const sorter_funcs[];
00069
00070
00071 TileIndex start_tile;
00072 TileIndex end_tile;
00073 uint32 type;
00074 GUIBridgeList *bridges;
00075
00077 static int CDECL BridgeIndexSorter(const BuildBridgeData *a, const BuildBridgeData *b)
00078 {
00079 return a->index - b->index;
00080 }
00081
00083 static int CDECL BridgePriceSorter(const BuildBridgeData *a, const BuildBridgeData *b)
00084 {
00085 return a->cost - b->cost;
00086 }
00087
00089 static int CDECL BridgeSpeedSorter(const BuildBridgeData *a, const BuildBridgeData *b)
00090 {
00091 return a->spec->speed - b->spec->speed;
00092 }
00093
00094 void BuildBridge(uint8 i)
00095 {
00096 DoCommandP(this->end_tile, this->start_tile, this->type | this->bridges->Get(i)->index,
00097 CcBuildBridge, CMD_BUILD_BRIDGE | CMD_MSG(STR_5015_CAN_T_BUILD_BRIDGE_HERE));
00098 }
00099
00101 void SortBridgeList()
00102 {
00103 this->bridges->Sort();
00104
00105
00106 this->widget[BBSW_DROPDOWN_CRITERIA].data = this->sorter_names[this->bridges->SortType()];
00107
00108
00109 this->InvalidateWidget(BBSW_DROPDOWN_CRITERIA);
00110 this->InvalidateWidget(BBSW_BRIDGE_LIST);
00111 }
00112
00113 public:
00114 BuildBridgeWindow(const WindowDesc *desc, TileIndex start, TileIndex end, uint32 br_type, GUIBridgeList *bl) : Window(desc),
00115 start_tile(start),
00116 end_tile(end),
00117 type(br_type),
00118 bridges(bl)
00119 {
00120 this->bridges->SetListing(this->last_sorting);
00121 this->bridges->SetSortFuncs(this->sorter_funcs);
00122 this->bridges->NeedResort();
00123 this->SortBridgeList();
00124
00125
00126 this->widget[BBSW_CAPTION].data = (GB(this->type, 15, 2) == TRANSPORT_ROAD) ? STR_1803_SELECT_ROAD_BRIDGE : STR_100D_SELECT_RAIL_BRIDGE;
00127
00128 this->resize.step_height = 22;
00129 this->vscroll.count = bl->Length();
00130
00131 if (this->last_size <= 4) {
00132 this->vscroll.cap = 4;
00133 } else {
00134
00135 this->vscroll.cap = min(this->last_size, this->vscroll.count);
00136 ResizeWindow(this, 0, (this->vscroll.cap - 4) * this->resize.step_height);
00137 }
00138
00139 this->FindWindowPlacementAndResize(desc);
00140 }
00141
00142 ~BuildBridgeWindow()
00143 {
00144 this->last_sorting = this->bridges->GetListing();
00145
00146 delete bridges;
00147 }
00148
00149 virtual void OnPaint()
00150 {
00151 this->DrawWidgets();
00152
00153 this->DrawSortButtonState(BBSW_DROPDOWN_ORDER, this->bridges->IsDescSortOrder() ? SBS_DOWN : SBS_UP);
00154
00155 uint y = this->widget[BBSW_BRIDGE_LIST].top + 2;
00156
00157 for (int i = this->vscroll.pos; (i < (this->vscroll.cap + this->vscroll.pos)) && (i < (int)this->bridges->Length()); i++) {
00158 const BridgeSpec *b = this->bridges->Get(i)->spec;
00159
00160 SetDParam(2, this->bridges->Get(i)->cost);
00161 SetDParam(1, b->speed * 10 / 16);
00162 SetDParam(0, b->material);
00163
00164 DrawSprite(b->sprite, b->pal, 3, y);
00165 DrawString(44, y, STR_500D, TC_FROMSTRING);
00166 y += this->resize.step_height;
00167
00168 }
00169 }
00170
00171 virtual EventState OnKeyPress(uint16 key, uint16 keycode)
00172 {
00173 const uint8 i = keycode - '1';
00174 if (i < 9 && i < this->bridges->Length()) {
00175
00176 this->BuildBridge(i);
00177 delete this;
00178 return ES_HANDLED;
00179 }
00180 return ES_NOT_HANDLED;
00181 }
00182
00183 virtual void OnClick(Point pt, int widget)
00184 {
00185 switch (widget) {
00186 default: break;
00187 case BBSW_BRIDGE_LIST: {
00188 uint i = ((int)pt.y - this->widget[BBSW_BRIDGE_LIST].top) / this->resize.step_height;
00189 if (i < this->vscroll.cap) {
00190 i += this->vscroll.pos;
00191 if (i < this->bridges->Length()) {
00192 this->BuildBridge(i);
00193 delete this;
00194 }
00195 }
00196 } break;
00197
00198 case BBSW_DROPDOWN_ORDER:
00199 this->bridges->ToggleSortOrder();
00200 this->SetDirty();
00201 break;
00202
00203 case BBSW_DROPDOWN_CRITERIA:
00204 ShowDropDownMenu(this, this->sorter_names, this->bridges->SortType(), BBSW_DROPDOWN_CRITERIA, 0, 0);
00205 break;
00206 }
00207 }
00208
00209 virtual void OnDropdownSelect(int widget, int index)
00210 {
00211 if (widget == BBSW_DROPDOWN_CRITERIA && this->bridges->SortType() != index) {
00212 this->bridges->SetSortType(index);
00213
00214 this->SortBridgeList();
00215 }
00216 }
00217
00218 virtual void OnResize(Point new_size, Point delta)
00219 {
00220 this->vscroll.cap += delta.y / (int)this->resize.step_height;
00221 this->widget[BBSW_BRIDGE_LIST].data = (this->vscroll.cap << 8) + 1;
00222 SetVScrollCount(this, this->bridges->Length());
00223
00224 this->last_size = max(this->vscroll.cap, this->last_size);
00225 }
00226 };
00227
00228
00229 uint16 BuildBridgeWindow::last_size = 4;
00230
00231 Listing BuildBridgeWindow::last_sorting = {false, 0};
00232
00233
00234 GUIBridgeList::SortFunction* const BuildBridgeWindow::sorter_funcs[] = {
00235 &BridgeIndexSorter,
00236 &BridgePriceSorter,
00237 &BridgeSpeedSorter
00238 };
00239
00240
00241 const StringID BuildBridgeWindow::sorter_names[] = {
00242 STR_SORT_BY_NUMBER,
00243 STR_ENGINE_SORT_COST,
00244 STR_SORT_BY_MAX_SPEED,
00245 INVALID_STRING_ID
00246 };
00247
00248
00249 static const Widget _build_bridge_widgets[] = {
00250 { WWT_CLOSEBOX, RESIZE_NONE, COLOUR_DARK_GREEN, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
00251 { WWT_CAPTION, RESIZE_NONE, COLOUR_DARK_GREEN, 11, 199, 0, 13, STR_100D_SELECT_RAIL_BRIDGE, STR_018C_WINDOW_TITLE_DRAG_THIS},
00252
00253 { WWT_TEXTBTN, RESIZE_NONE, COLOUR_DARK_GREEN, 0, 80, 14, 25, STR_SORT_BY, STR_SORT_ORDER_TIP},
00254 { WWT_DROPDOWN, RESIZE_NONE, COLOUR_DARK_GREEN, 81, 199, 14, 25, 0x0, STR_SORT_CRITERIA_TIP},
00255
00256 { WWT_MATRIX, RESIZE_BOTTOM, COLOUR_DARK_GREEN, 0, 187, 26, 113, 0x401, STR_101F_BRIDGE_SELECTION_CLICK},
00257 { WWT_SCROLLBAR, RESIZE_BOTTOM, COLOUR_DARK_GREEN, 188, 199, 26, 101, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST},
00258 { WWT_RESIZEBOX, RESIZE_TB, COLOUR_DARK_GREEN, 188, 199, 102, 113, 0x0, STR_RESIZE_BUTTON},
00259 { WIDGETS_END},
00260 };
00261
00262
00263 static const WindowDesc _build_bridge_desc = {
00264 WDP_AUTO, WDP_AUTO, 200, 114, 200, 114,
00265 WC_BUILD_BRIDGE, WC_BUILD_TOOLBAR,
00266 WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_RESIZABLE,
00267 _build_bridge_widgets,
00268 };
00269
00280 void ShowBuildBridgeWindow(TileIndex start, TileIndex end, TransportType transport_type, byte road_rail_type)
00281 {
00282 DeleteWindowById(WC_BUILD_BRIDGE, 0);
00283
00284
00285
00286
00287
00288 uint32 type = (transport_type << 15) | (road_rail_type << 8);
00289
00290
00291
00292 StringID errmsg = INVALID_STRING_ID;
00293 CommandCost ret = DoCommand(end, start, type, DC_AUTO | DC_QUERY_COST, CMD_BUILD_BRIDGE);
00294
00295 GUIBridgeList *bl = NULL;
00296 if (CmdFailed(ret)) {
00297 errmsg = _error_message;
00298 } else {
00299
00300
00301
00302 const uint bridge_len = GetTunnelBridgeLength(start, end);
00303
00304 const uint tot_bridgedata_len = CalcBridgeLenCostFactor(bridge_len + 2);
00305
00306 bl = new GUIBridgeList();
00307
00308
00309 for (BridgeType brd_type = 0; brd_type != MAX_BRIDGES; brd_type++) {
00310 if (CheckBridge_Stuff(brd_type, bridge_len)) {
00311
00312 BuildBridgeData *item = bl->Append();
00313 item->index = brd_type;
00314 item->spec = GetBridgeSpec(brd_type);
00315
00316
00317 item->cost = ret.GetCost() + (((int64)tot_bridgedata_len * _price.build_bridge * item->spec->price) >> 8);
00318 }
00319 }
00320 }
00321
00322 if (bl != NULL && bl->Length() != 0) {
00323 new BuildBridgeWindow(&_build_bridge_desc, start, end, type, bl);
00324 } else {
00325 if (bl != NULL) delete bl;
00326 ShowErrorMessage(errmsg, STR_5015_CAN_T_BUILD_BRIDGE_HERE, TileX(end) * TILE_SIZE, TileY(end) * TILE_SIZE);
00327 }
00328 }