|
@@ -132,157 +132,157 @@ private:
|
|
|
/* Set the modified widgets dirty */
|
|
|
this->SetWidgetDirty(WID_BBS_DROPDOWN_CRITERIA);
|
|
|
this->SetWidgetDirty(WID_BBS_BRIDGE_LIST);
|
|
|
}
|
|
|
|
|
|
public:
|
|
|
BuildBridgeWindow(WindowDesc *desc, TileIndex start, TileIndex end, uint32 br_type, GUIBridgeList *bl) : Window(desc),
|
|
|
start_tile(start),
|
|
|
end_tile(end),
|
|
|
type(br_type),
|
|
|
bridges(bl)
|
|
|
{
|
|
|
this->CreateNestedTree();
|
|
|
this->vscroll = this->GetScrollbar(WID_BBS_SCROLLBAR);
|
|
|
/* Change the data, or the caption of the gui. Set it to road or rail, accordingly. */
|
|
|
this->GetWidget<NWidgetCore>(WID_BBS_CAPTION)->widget_data = (GB(this->type, 15, 2) == TRANSPORT_ROAD) ? STR_SELECT_ROAD_BRIDGE_CAPTION : STR_SELECT_RAIL_BRIDGE_CAPTION;
|
|
|
this->FinishInitNested(GB(br_type, 15, 2)); // Initializes 'this->bridgetext_offset'.
|
|
|
|
|
|
this->parent = FindWindowById(WC_BUILD_TOOLBAR, GB(this->type, 15, 2));
|
|
|
this->bridges->SetListing(this->last_sorting);
|
|
|
this->bridges->SetSortFuncs(this->sorter_funcs);
|
|
|
this->bridges->NeedResort();
|
|
|
this->SortBridgeList();
|
|
|
|
|
|
this->vscroll->SetCount(bl->Length());
|
|
|
this->vscroll->SetCount(bl->size());
|
|
|
}
|
|
|
|
|
|
~BuildBridgeWindow()
|
|
|
{
|
|
|
this->last_sorting = this->bridges->GetListing();
|
|
|
|
|
|
delete bridges;
|
|
|
}
|
|
|
|
|
|
void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override
|
|
|
{
|
|
|
switch (widget) {
|
|
|
case WID_BBS_DROPDOWN_ORDER: {
|
|
|
Dimension d = GetStringBoundingBox(this->GetWidget<NWidgetCore>(widget)->widget_data);
|
|
|
d.width += padding.width + Window::SortButtonWidth() * 2; // Doubled since the string is centred and it also looks better.
|
|
|
d.height += padding.height;
|
|
|
*size = maxdim(*size, d);
|
|
|
break;
|
|
|
}
|
|
|
case WID_BBS_DROPDOWN_CRITERIA: {
|
|
|
Dimension d = {0, 0};
|
|
|
for (const StringID *str = this->sorter_names; *str != INVALID_STRING_ID; str++) {
|
|
|
d = maxdim(d, GetStringBoundingBox(*str));
|
|
|
}
|
|
|
d.width += padding.width;
|
|
|
d.height += padding.height;
|
|
|
*size = maxdim(*size, d);
|
|
|
break;
|
|
|
}
|
|
|
case WID_BBS_BRIDGE_LIST: {
|
|
|
Dimension sprite_dim = {0, 0}; // Biggest bridge sprite dimension
|
|
|
Dimension text_dim = {0, 0}; // Biggest text dimension
|
|
|
for (int i = 0; i < (int)this->bridges->Length(); i++) {
|
|
|
for (int i = 0; i < (int)this->bridges->size(); i++) {
|
|
|
const BridgeSpec *b = this->bridges->Get(i)->spec;
|
|
|
sprite_dim = maxdim(sprite_dim, GetSpriteSize(b->sprite));
|
|
|
|
|
|
SetDParam(2, this->bridges->Get(i)->cost);
|
|
|
SetDParam(1, b->speed);
|
|
|
SetDParam(0, b->material);
|
|
|
text_dim = maxdim(text_dim, GetStringBoundingBox(_game_mode == GM_EDITOR ? STR_SELECT_BRIDGE_SCENEDIT_INFO : STR_SELECT_BRIDGE_INFO));
|
|
|
}
|
|
|
sprite_dim.height++; // Sprite is rendered one pixel down in the matrix field.
|
|
|
text_dim.height++; // Allowing the bottom row pixels to be rendered on the edge of the matrix field.
|
|
|
resize->height = max(sprite_dim.height, text_dim.height) + 2; // Max of both sizes + account for matrix edges.
|
|
|
|
|
|
this->bridgetext_offset = WD_MATRIX_LEFT + sprite_dim.width + 1; // Left edge of text, 1 pixel distance from the sprite.
|
|
|
size->width = this->bridgetext_offset + text_dim.width + WD_MATRIX_RIGHT;
|
|
|
size->height = 4 * resize->height; // Smallest bridge gui is 4 entries high in the matrix.
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
Point OnInitialPosition(int16 sm_width, int16 sm_height, int window_number) override
|
|
|
{
|
|
|
/* Position the window so hopefully the first bridge from the list is under the mouse pointer. */
|
|
|
NWidgetBase *list = this->GetWidget<NWidgetBase>(WID_BBS_BRIDGE_LIST);
|
|
|
Point corner; // point of the top left corner of the window.
|
|
|
corner.y = Clamp(_cursor.pos.y - list->pos_y - 5, GetMainViewTop(), GetMainViewBottom() - sm_height);
|
|
|
corner.x = Clamp(_cursor.pos.x - list->pos_x - 5, 0, _screen.width - sm_width);
|
|
|
return corner;
|
|
|
}
|
|
|
|
|
|
void DrawWidget(const Rect &r, int widget) const override
|
|
|
{
|
|
|
switch (widget) {
|
|
|
case WID_BBS_DROPDOWN_ORDER:
|
|
|
this->DrawSortButtonState(widget, this->bridges->IsDescSortOrder() ? SBS_DOWN : SBS_UP);
|
|
|
break;
|
|
|
|
|
|
case WID_BBS_BRIDGE_LIST: {
|
|
|
uint y = r.top;
|
|
|
for (int i = this->vscroll->GetPosition(); this->vscroll->IsVisible(i) && i < (int)this->bridges->Length(); i++) {
|
|
|
for (int i = this->vscroll->GetPosition(); this->vscroll->IsVisible(i) && i < (int)this->bridges->size(); i++) {
|
|
|
const BridgeSpec *b = this->bridges->Get(i)->spec;
|
|
|
|
|
|
SetDParam(2, this->bridges->Get(i)->cost);
|
|
|
SetDParam(1, b->speed);
|
|
|
SetDParam(0, b->material);
|
|
|
|
|
|
DrawSprite(b->sprite, b->pal, r.left + WD_MATRIX_LEFT, y + this->resize.step_height - 1 - GetSpriteSize(b->sprite).height);
|
|
|
DrawStringMultiLine(r.left + this->bridgetext_offset, r.right, y + 2, y + this->resize.step_height,
|
|
|
_game_mode == GM_EDITOR ? STR_SELECT_BRIDGE_SCENEDIT_INFO : STR_SELECT_BRIDGE_INFO);
|
|
|
y += this->resize.step_height;
|
|
|
}
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
EventState OnKeyPress(WChar key, uint16 keycode) override
|
|
|
{
|
|
|
const uint8 i = keycode - '1';
|
|
|
if (i < 9 && i < this->bridges->Length()) {
|
|
|
if (i < 9 && i < this->bridges->size()) {
|
|
|
/* Build the requested bridge */
|
|
|
this->BuildBridge(i);
|
|
|
delete this;
|
|
|
return ES_HANDLED;
|
|
|
}
|
|
|
return ES_NOT_HANDLED;
|
|
|
}
|
|
|
|
|
|
void OnClick(Point pt, int widget, int click_count) override
|
|
|
{
|
|
|
switch (widget) {
|
|
|
default: break;
|
|
|
case WID_BBS_BRIDGE_LIST: {
|
|
|
uint i = this->vscroll->GetScrolledRowFromWidget(pt.y, this, WID_BBS_BRIDGE_LIST);
|
|
|
if (i < this->bridges->Length()) {
|
|
|
if (i < this->bridges->size()) {
|
|
|
this->BuildBridge(i);
|
|
|
delete this;
|
|
|
}
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
case WID_BBS_DROPDOWN_ORDER:
|
|
|
this->bridges->ToggleSortOrder();
|
|
|
this->SetDirty();
|
|
|
break;
|
|
|
|
|
|
case WID_BBS_DROPDOWN_CRITERIA:
|
|
|
ShowDropDownMenu(this, this->sorter_names, this->bridges->SortType(), WID_BBS_DROPDOWN_CRITERIA, 0, 0);
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void OnDropdownSelect(int widget, int index) override
|
|
|
{
|
|
|
if (widget == WID_BBS_DROPDOWN_CRITERIA && this->bridges->SortType() != index) {
|
|
|
this->bridges->SetSortType(index);
|
|
|
|
|
|
this->SortBridgeList();
|
|
|
}
|
|
@@ -405,31 +405,31 @@ void ShowBuildBridgeWindow(TileIndex sta
|
|
|
switch (transport_type) {
|
|
|
case TRANSPORT_ROAD:
|
|
|
infra_cost = (bridge_len + 2) * _price[PR_BUILD_ROAD] * 2;
|
|
|
/* In case we add a new road type as well, we must be aware of those costs. */
|
|
|
if (IsBridgeTile(start)) infra_cost *= CountBits(GetRoadTypes(start) | (RoadTypes)road_rail_type);
|
|
|
break;
|
|
|
case TRANSPORT_RAIL: infra_cost = (bridge_len + 2) * RailBuildCost((RailType)road_rail_type); break;
|
|
|
default: break;
|
|
|
}
|
|
|
|
|
|
/* loop for all bridgetypes */
|
|
|
for (BridgeType brd_type = 0; brd_type != MAX_BRIDGES; brd_type++) {
|
|
|
if (CheckBridgeAvailability(brd_type, bridge_len).Succeeded()) {
|
|
|
/* bridge is accepted, add to list */
|
|
|
BuildBridgeData *item = bl->Append();
|
|
|
item->index = brd_type;
|
|
|
item->spec = GetBridgeSpec(brd_type);
|
|
|
/* Add to terraforming & bulldozing costs the cost of the
|
|
|
* bridge itself (not computed with DC_QUERY_COST) */
|
|
|
item->cost = ret.GetCost() + (((int64)tot_bridgedata_len * _price[PR_BUILD_BRIDGE] * item->spec->price) >> 8) + infra_cost;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if (bl != NULL && bl->Length() != 0) {
|
|
|
if (bl != NULL && bl->size() != 0) {
|
|
|
new BuildBridgeWindow(&_build_bridge_desc, start, end, type, bl);
|
|
|
} else {
|
|
|
delete bl;
|
|
|
ShowErrorMessage(STR_ERROR_CAN_T_BUILD_BRIDGE_HERE, errmsg, WL_INFO, TileX(end) * TILE_SIZE, TileY(end) * TILE_SIZE);
|
|
|
}
|
|
|
}
|