diff options
Diffstat (limited to 'src/cargodest_gui.cpp')
-rw-r--r-- | src/cargodest_gui.cpp | 176 |
1 files changed, 176 insertions, 0 deletions
diff --git a/src/cargodest_gui.cpp b/src/cargodest_gui.cpp new file mode 100644 index 000000000..bf5fdd1d4 --- /dev/null +++ b/src/cargodest_gui.cpp @@ -0,0 +1,176 @@ +/* $Id$ */ + +/* + * This file is part of OpenTTD. + * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2. + * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>. + */ + +/** @file cargodest_gui.cpp GUI for cargo destinations. */ + +#include "stdafx.h" +#include "window_gui.h" +#include "gfx_func.h" +#include "strings_func.h" +#include "cargodest_base.h" +#include "cargodest_gui.h" +#include "town.h" +#include "industry.h" +#include "string_func.h" +#include "gui.h" +#include "viewport_func.h" + +#include "table/strings.h" + +static const CargoSourceSink *_cur_cargo_source; + +int CDECL CargoLinkSorter(const GUICargoLink *a, const GUICargoLink *b) +{ + /* Sort by cargo type. */ + if (a->cid != b->cid) return a->cid < b->cid ? -1 : +1; + + /* Sort unspecified destination links always last. */ + if (a->link->dest == NULL) return +1; + if (b->link->dest == NULL) return -1; + + /* Sort link with the current source as destination first. */ + if (a->link->dest == _cur_cargo_source) return -1; + if (b->link->dest == _cur_cargo_source) return +1; + + /* Sort towns before industries. */ + if (a->link->dest->GetType() != b->link->dest->GetType()) { + return a->link->dest->GetType() < b->link->dest->GetType() ? +1 : -1; + } + + /* Sort by name. */ + static const CargoLink *last_b = NULL; + static char last_name[128]; + + char name[128]; + SetDParam(0, a->link->dest->GetID()); + GetString(name, a->link->dest->GetType() == ST_TOWN ? STR_TOWN_NAME : STR_INDUSTRY_NAME, lastof(name)); + + /* Cache name lookup of 'b', as the sorter is often called + * multiple times with the same 'b'. */ + if (b->link != last_b) { + last_b = b->link; + + SetDParam(0, b->link->dest->GetID()); + GetString(last_name, b->link->dest->GetType() == ST_TOWN ? STR_TOWN_NAME : STR_INDUSTRY_NAME, lastof(last_name)); + } + + return strcmp(name, last_name); +} + +CargoDestinationList::CargoDestinationList(const CargoSourceSink *o) : obj(o) +{ + this->InvalidateData(); +} + +/** Rebuild the link list from the source object. */ +void CargoDestinationList::RebuildList() +{ + if (!this->link_list.NeedRebuild()) return; + + this->link_list.Clear(); + for (CargoID i = 0; i < lengthof(this->obj->cargo_links); i++) { + for (const CargoLink *l = this->obj->cargo_links[i].Begin(); l != this->obj->cargo_links[i].End(); l++) { + *this->link_list.Append() = GUICargoLink(i, l); + } + } + + this->link_list.Compact(); + this->link_list.RebuildDone(); +} + +/** Sort the link list. */ +void CargoDestinationList::SortList() +{ + _cur_cargo_source = this->obj; + this->link_list.Sort(&CargoLinkSorter); +} + +/** Rebuild the list, e.g. when a new cargo link was added. */ +void CargoDestinationList::InvalidateData() +{ + this->link_list.ForceRebuild(); + this->RebuildList(); + this->SortList(); +} + +/** Resort the list, e.g. when a town is renamed. */ +void CargoDestinationList::Resort() +{ + this->link_list.ForceResort(); + this->SortList(); +} + +/** + * Get the height needed to display the destination list. + * @param obj Object to display the destinations of. + * @return Height needed for display. + */ +uint CargoDestinationList::GetListHeight() const +{ + uint lines = 2 + this->link_list.Length(); + return lines > 2 ? WD_PAR_VSEP_WIDE + lines * FONT_HEIGHT_NORMAL : 0; +} + +/** + * Draw the destination list. + * @param left The left most position to draw on. + * @param right The right most position to draw on. + * @param y The top position to start drawing. + * @return New \c y value below the drawn text. + */ +uint CargoDestinationList::DrawList(uint left, uint right, uint y) const +{ + if (this->link_list.Length() == 0) return y; + + DrawString(left + WD_FRAMERECT_LEFT, right - WD_FRAMERECT_RIGHT, y += WD_PAR_VSEP_WIDE + FONT_HEIGHT_NORMAL, STR_VIEW_CARGO_LAST_MONTH_OUT); + + for (const GUICargoLink *l = this->link_list.Begin(); l != this->link_list.End(); l++) { + SetDParam(0, l->cid); + SetDParam(1, l->link->amount.old_act); + SetDParam(2, l->cid); + SetDParam(3, l->link->amount.old_max); + + /* Select string according to the destination type. */ + if (l->link->dest == NULL) { + DrawString(left + 2 * WD_FRAMERECT_LEFT, right - WD_FRAMERECT_RIGHT, y += FONT_HEIGHT_NORMAL, STR_VIEW_CARGO_LAST_MONTH_OTHER); + } else if (l->link->dest == obj) { + DrawString(left + 2 * WD_FRAMERECT_LEFT, right - WD_FRAMERECT_RIGHT, y += FONT_HEIGHT_NORMAL, STR_VIEW_CARGO_LAST_MONTH_LOCAL); + } else { + SetDParam(4, l->link->dest->GetID()); + DrawString(left + 2 * WD_FRAMERECT_LEFT, right - WD_FRAMERECT_RIGHT, y += FONT_HEIGHT_NORMAL, l->link->dest->GetType() == ST_TOWN ? STR_VIEW_CARGO_LAST_MONTH_TOWN : STR_VIEW_CARGO_LAST_MONTH_INDUSTRY); + } + } + + return y + FONT_HEIGHT_NORMAL; +} + +/** + * Handle click event onto the destination list. + * @param y Position of the click in relative to the top of the destination list. + */ +void CargoDestinationList::OnClick(uint y) const +{ + /* Subtract caption height. */ + y -= WD_PAR_VSEP_WIDE + 2 * FONT_HEIGHT_NORMAL; + + /* Calculate line from click pos. */ + y /= FONT_HEIGHT_NORMAL; + if (y >= this->link_list.Length()) return; + + /* Move viewpoint to the position of the destination. */ + const CargoLink *l = this->link_list[y].link; + if (l->dest == NULL) return; + + TileIndex xy = l->dest->GetType() == ST_TOWN ? static_cast<const Town *>(l->dest)->xy : static_cast<const Industry *>(l->dest)->location.tile; + if (_ctrl_pressed) { + ShowExtraViewPortWindow(xy); + } else { + ScrollMainWindowToTile(xy); + } +} |