2005-07-24 14:12:37 +00:00
/* $Id$ */
2009-08-21 20:21:05 +00:00
/*
* 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/>.
*/
2008-05-06 15:11:33 +00:00
/** @file station_gui.cpp The GUI for stations. */
2007-04-04 01:35:16 +00:00
2004-08-09 17:04:08 +00:00
# include "stdafx.h"
2005-02-05 15:58:59 +00:00
# include "debug.h"
2004-08-09 17:04:08 +00:00
# include "gui.h"
2007-12-19 20:45:46 +00:00
# include "textbuf_gui.h"
2008-09-30 20:51:04 +00:00
# include "company_func.h"
2007-12-21 21:50:46 +00:00
# include "command_func.h"
2005-07-21 22:15:02 +00:00
# include "vehicle_gui.h"
2007-02-20 22:09:21 +00:00
# include "cargotype.h"
2007-12-05 17:08:10 +00:00
# include "station_gui.h"
2007-12-21 19:49:27 +00:00
# include "strings_func.h"
2014-11-18 20:12:42 +00:00
# include "string_func.h"
2007-12-25 11:26:07 +00:00
# include "window_func.h"
2008-01-09 09:45:45 +00:00
# include "viewport_func.h"
2008-01-14 16:10:58 +00:00
# include "widgets/dropdown_func.h"
2009-06-24 17:39:54 +00:00
# include "station_base.h"
2009-07-31 16:28:28 +00:00
# include "waypoint_base.h"
2009-01-08 16:35:45 +00:00
# include "tilehighlight_func.h"
2008-09-30 20:51:04 +00:00
# include "company_base.h"
2008-09-13 10:04:36 +00:00
# include "sortlist_type.h"
2010-01-15 16:41:15 +00:00
# include "core/geometry_func.hpp"
2010-09-08 21:37:13 +00:00
# include "vehiclelist.h"
2012-05-06 11:38:52 +00:00
# include "town.h"
2013-05-20 19:57:38 +00:00
# include "linkgraph/linkgraph.h"
2014-10-04 20:18:25 +00:00
# include "zoom_func.h"
2006-12-07 04:12:29 +00:00
2011-12-15 22:22:55 +00:00
# include "widgets/station_widget.h"
2008-01-13 01:21:35 +00:00
# include "table/strings.h"
2013-06-09 13:08:52 +00:00
# include <set>
# include <vector>
2014-04-23 20:13:33 +00:00
# include "safeguards.h"
2010-01-05 16:59:57 +00:00
/**
* Calculates and draws the accepted or supplied cargo around the selected tile ( s )
* @ param left x position where the string is to be drawn
* @ param right the right most position to draw on
* @ param top y position where the string is to be drawn
* @ param sct which type of cargo is to be displayed ( passengers / non - passengers )
* @ param rad radius around selected tile ( s ) to be searched
2011-12-15 21:56:00 +00:00
* @ param supplies if supplied cargoes should be drawn , else accepted cargoes
2010-01-05 16:59:57 +00:00
* @ return Returns the y value below the string that was drawn
*/
int DrawStationCoverageAreaText ( int left , int right , int top , StationCoverageType sct , int rad , bool supplies )
{
TileIndex tile = TileVirtXY ( _thd . pos . x , _thd . pos . y ) ;
2011-06-17 20:32:25 +00:00
uint32 cargo_mask = 0 ;
2011-06-16 09:46:24 +00:00
if ( _thd . drawstyle = = HT_RECT & & tile < MapSize ( ) ) {
2011-12-15 21:56:00 +00:00
CargoArray cargoes ;
2010-01-05 16:59:57 +00:00
if ( supplies ) {
2011-12-15 21:56:00 +00:00
cargoes = GetProductionAroundTiles ( tile , _thd . size . x / TILE_SIZE , _thd . size . y / TILE_SIZE , rad ) ;
2010-01-05 16:59:57 +00:00
} else {
2011-12-15 21:56:00 +00:00
cargoes = GetAcceptanceAroundTiles ( tile , _thd . size . x / TILE_SIZE , _thd . size . y / TILE_SIZE , rad ) ;
2010-01-05 16:59:57 +00:00
}
/* Convert cargo counts to a set of cargo bits, and draw the result. */
for ( CargoID i = 0 ; i < NUM_CARGO ; i + + ) {
switch ( sct ) {
case SCT_PASSENGERS_ONLY : if ( ! IsCargoInClass ( i , CC_PASSENGERS ) ) continue ; break ;
case SCT_NON_PASSENGERS_ONLY : if ( IsCargoInClass ( i , CC_PASSENGERS ) ) continue ; break ;
case SCT_ALL : break ;
default : NOT_REACHED ( ) ;
}
2011-12-15 21:56:00 +00:00
if ( cargoes [ i ] > = ( supplies ? 1U : 8U ) ) SetBit ( cargo_mask , i ) ;
2010-01-05 16:59:57 +00:00
}
}
2012-03-10 19:18:04 +00:00
SetDParam ( 0 , cargo_mask ) ;
return DrawStringMultiLine ( left , right , top , INT32_MAX , supplies ? STR_STATION_BUILD_SUPPLIES_CARGO : STR_STATION_BUILD_ACCEPTS_CARGO ) ;
2010-01-05 16:59:57 +00:00
}
/**
* Check whether we need to redraw the station coverage text .
* If it is needed actually make the window for redrawing .
* @ param w the window to check .
*/
void CheckRedrawStationCoverage ( const Window * w )
{
if ( _thd . dirty & 1 ) {
_thd . dirty & = ~ 1 ;
w - > SetDirty ( ) ;
}
}
2007-12-05 17:08:10 +00:00
/**
* Draw small boxes of cargo amount and ratings data at the given
2006-12-09 00:46:02 +00:00
* coordinates . If amount exceeds 576 units , it is shown ' full ' , same
* goes for the rating : at above 90 % orso ( 224 ) it is also ' full '
2007-12-05 17:08:10 +00:00
*
2009-03-22 14:55:49 +00:00
* @ param left left most coordinate to draw the box at
* @ param right right most coordinate to draw the box at
* @ param y coordinate to draw the box at
* @ param type Cargo type
2006-12-09 00:46:02 +00:00
* @ param amount Cargo amount
2007-12-05 17:08:10 +00:00
* @ param rating ratings data for that particular cargo
*
* @ note Each cargo - bar is 16 pixels wide and 6 pixels high
* @ note Each rating 14 pixels wide and 1 pixel high and is 1 pixel below the cargo - bar
*/
2009-03-22 14:55:49 +00:00
static void StationsWndShowStationRating ( int left , int right , int y , CargoID type , uint amount , byte rating )
2004-08-09 17:04:08 +00:00
{
2007-12-05 17:08:10 +00:00
static const uint units_full = 576 ; ///< number of units to show station as 'full'
static const uint rating_full = 224 ; ///< rating needed so it is shown as 'full'
2009-07-16 19:00:13 +00:00
const CargoSpec * cs = CargoSpec : : Get ( type ) ;
2007-02-23 09:56:20 +00:00
if ( ! cs - > IsValid ( ) ) return ;
2007-02-20 22:09:21 +00:00
int colour = cs - > rating_colour ;
2012-11-07 21:23:26 +00:00
TextColour tc = GetContrastColour ( colour ) ;
2007-12-05 17:08:10 +00:00
uint w = ( minu ( amount , units_full ) + 5 ) / 36 ;
2006-12-09 00:46:02 +00:00
2009-11-17 12:05:55 +00:00
int height = GetCharacterHeight ( FS_SMALL ) ;
2006-12-09 00:46:02 +00:00
/* Draw total cargo (limited) on station (fits into 16 pixels) */
2009-11-17 12:05:55 +00:00
if ( w ! = 0 ) GfxFillRect ( left , y , left + w - 1 , y + height , colour ) ;
2006-12-09 00:46:02 +00:00
/* Draw a one pixel-wide bar of additional cargo meter, useful
* for stations with only a small amount ( < = 30 ) */
if ( w = = 0 ) {
uint rest = amount / 5 ;
if ( rest ! = 0 ) {
2009-03-22 14:55:49 +00:00
w + = left ;
2009-11-17 12:05:55 +00:00
GfxFillRect ( w , y + height - rest , w , y + height , colour ) ;
2006-12-09 00:46:02 +00:00
}
2004-08-09 17:04:08 +00:00
}
2012-11-07 21:23:26 +00:00
DrawString ( left + 1 , right , y , cs - > abbrev , tc ) ;
2004-08-09 17:04:08 +00:00
2006-12-09 00:46:02 +00:00
/* Draw green/red ratings bar (fits into 14 pixels) */
2009-11-17 12:05:55 +00:00
y + = height + 2 ;
2011-05-06 21:13:29 +00:00
GfxFillRect ( left + 1 , y , left + 14 , y , PC_RED ) ;
2007-12-05 17:08:10 +00:00
rating = minu ( rating , rating_full ) / 16 ;
2011-05-06 21:13:29 +00:00
if ( rating ! = 0 ) GfxFillRect ( left + 1 , y , left + rating , y , PC_GREEN ) ;
2004-08-09 17:04:08 +00:00
}
2008-05-27 09:57:29 +00:00
typedef GUIList < const Station * > GUIStationList ;
2004-08-09 17:04:08 +00:00
2008-05-27 09:57:29 +00:00
/**
2008-09-30 20:39:50 +00:00
* The list of stations per company .
2008-05-27 09:57:29 +00:00
*/
2008-09-30 20:39:50 +00:00
class CompanyStationsWindow : public Window
2004-08-09 17:04:08 +00:00
{
2008-05-27 09:57:29 +00:00
protected :
/* Runtime saved values */
static Listing last_sorting ;
static byte facilities ; // types of stations of interest
static bool include_empty ; // whether we should include stations without waiting cargo
static const uint32 cargo_filter_max ;
static uint32 cargo_filter ; // bitmap of cargo types to include
static const Station * last_station ;
/* Constants for sorting stations */
static const StringID sorter_names [ ] ;
2009-03-15 16:04:39 +00:00
static GUIStationList : : SortFunction * const sorter_funcs [ ] ;
2004-09-06 18:15:13 +00:00
2008-05-27 09:57:29 +00:00
GUIStationList stations ;
2010-08-12 08:37:01 +00:00
Scrollbar * vscroll ;
2004-09-06 18:15:13 +00:00
2008-05-27 09:57:29 +00:00
/**
* ( Re ) Build station list
*
2008-09-30 20:39:50 +00:00
* @ param owner company whose stations are to be in list
2008-05-27 09:57:29 +00:00
*/
2008-09-30 20:39:50 +00:00
void BuildStationsList ( const Owner owner )
2008-05-27 09:57:29 +00:00
{
if ( ! this - > stations . NeedRebuild ( ) ) return ;
2008-09-30 20:39:50 +00:00
DEBUG ( misc , 3 , " Building station list for company %d " , owner ) ;
2008-05-27 09:57:29 +00:00
this - > stations . Clear ( ) ;
const Station * st ;
FOR_ALL_STATIONS ( st ) {
2010-08-20 12:50:59 +00:00
if ( st - > owner = = owner | | ( st - > owner = = OWNER_NONE & & HasStationInUse ( st - > index , true , owner ) ) ) {
2008-05-27 09:57:29 +00:00
if ( this - > facilities & st - > facilities ) { // only stations with selected facilities
int num_waiting_cargo = 0 ;
for ( CargoID j = 0 ; j < NUM_CARGO ; j + + ) {
2013-04-06 12:10:16 +00:00
if ( st - > goods [ j ] . HasRating ( ) ) {
2008-05-27 09:57:29 +00:00
num_waiting_cargo + + ; // count number of waiting cargo
if ( HasBit ( this - > cargo_filter , j ) ) {
* this - > stations . Append ( ) = st ;
break ;
}
}
}
/* stations without waiting cargo */
if ( num_waiting_cargo = = 0 & & this - > include_empty ) {
* this - > stations . Append ( ) = st ;
}
}
}
}
2006-05-11 10:33:58 +00:00
2008-05-27 09:57:29 +00:00
this - > stations . Compact ( ) ;
this - > stations . RebuildDone ( ) ;
2009-09-02 08:40:31 +00:00
2010-08-12 08:37:01 +00:00
this - > vscroll - > SetCount ( this - > stations . Length ( ) ) ; // Update the scrollbar
2008-05-27 09:57:29 +00:00
}
2006-05-11 10:33:58 +00:00
2008-05-27 09:57:29 +00:00
/** Sort stations by their name */
2009-01-10 00:31:47 +00:00
static int CDECL StationNameSorter ( const Station * const * a , const Station * const * b )
2008-05-27 09:57:29 +00:00
{
static char buf_cache [ 64 ] ;
char buf [ 64 ] ;
2007-11-15 17:54:46 +00:00
2008-05-27 09:57:29 +00:00
SetDParam ( 0 , ( * a ) - > index ) ;
2009-07-20 11:21:57 +00:00
GetString ( buf , STR_STATION_NAME , lastof ( buf ) ) ;
2006-05-11 10:33:58 +00:00
2008-05-27 09:57:29 +00:00
if ( * b ! = last_station ) {
last_station = * b ;
SetDParam ( 0 , ( * b ) - > index ) ;
2009-07-20 11:21:57 +00:00
GetString ( buf_cache , STR_STATION_NAME , lastof ( buf_cache ) ) ;
2008-05-27 09:57:29 +00:00
}
2006-05-11 10:33:58 +00:00
2014-11-18 20:12:42 +00:00
int r = strnatcmp ( buf , buf_cache ) ; // Sort by name (natural sorting).
if ( r = = 0 ) return ( * a ) - > index - ( * b ) - > index ;
return r ;
2006-05-11 10:33:58 +00:00
}
2008-05-27 09:57:29 +00:00
/** Sort stations by their type */
2009-01-10 00:31:47 +00:00
static int CDECL StationTypeSorter ( const Station * const * a , const Station * const * b )
2008-05-27 09:57:29 +00:00
{
return ( * a ) - > facilities - ( * b ) - > facilities ;
}
2006-05-11 10:33:58 +00:00
2008-05-27 09:57:29 +00:00
/** Sort stations by their waiting cargo */
2013-06-15 15:26:24 +00:00
static int CDECL StationWaitingTotalSorter ( const Station * const * a , const Station * const * b )
2008-05-27 09:57:29 +00:00
{
2013-06-15 15:26:24 +00:00
int diff = 0 ;
2006-05-11 10:33:58 +00:00
2010-05-11 21:01:01 +00:00
CargoID j ;
FOR_EACH_SET_CARGO_ID ( j , cargo_filter ) {
2013-06-15 15:26:24 +00:00
diff + = ( * a ) - > goods [ j ] . cargo . TotalCount ( ) - ( * b ) - > goods [ j ] . cargo . TotalCount ( ) ;
2004-08-09 17:04:08 +00:00
}
2013-06-15 15:26:24 +00:00
return diff ;
}
/** Sort stations by their available waiting cargo */
static int CDECL StationWaitingAvailableSorter ( const Station * const * a , const Station * const * b )
{
int diff = 0 ;
CargoID j ;
FOR_EACH_SET_CARGO_ID ( j , cargo_filter ) {
diff + = ( * a ) - > goods [ j ] . cargo . AvailableCount ( ) - ( * b ) - > goods [ j ] . cargo . AvailableCount ( ) ;
}
return diff ;
2008-05-27 09:57:29 +00:00
}
2004-09-14 14:19:53 +00:00
2008-05-27 09:57:29 +00:00
/** Sort stations by their rating */
2009-01-10 00:31:47 +00:00
static int CDECL StationRatingMaxSorter ( const Station * const * a , const Station * const * b )
2008-05-27 09:57:29 +00:00
{
byte maxr1 = 0 ;
byte maxr2 = 0 ;
2007-12-05 17:08:10 +00:00
2010-05-11 21:01:01 +00:00
CargoID j ;
FOR_EACH_SET_CARGO_ID ( j , cargo_filter ) {
2013-04-06 12:10:16 +00:00
if ( ( * a ) - > goods [ j ] . HasRating ( ) ) maxr1 = max ( maxr1 , ( * a ) - > goods [ j ] . rating ) ;
if ( ( * b ) - > goods [ j ] . HasRating ( ) ) maxr2 = max ( maxr2 , ( * b ) - > goods [ j ] . rating ) ;
2008-05-27 09:57:29 +00:00
}
2004-09-07 19:01:06 +00:00
2008-05-27 09:57:29 +00:00
return maxr1 - maxr2 ;
}
2004-09-14 14:19:53 +00:00
2009-04-12 19:15:53 +00:00
/** Sort stations by their rating */
static int CDECL StationRatingMinSorter ( const Station * const * a , const Station * const * b )
{
2009-04-12 19:23:26 +00:00
byte minr1 = 255 ;
byte minr2 = 255 ;
2009-04-12 19:15:53 +00:00
for ( CargoID j = 0 ; j < NUM_CARGO ; j + + ) {
2009-04-12 19:23:26 +00:00
if ( ! HasBit ( cargo_filter , j ) ) continue ;
2013-04-06 12:10:16 +00:00
if ( ( * a ) - > goods [ j ] . HasRating ( ) ) minr1 = min ( minr1 , ( * a ) - > goods [ j ] . rating ) ;
if ( ( * b ) - > goods [ j ] . HasRating ( ) ) minr2 = min ( minr2 , ( * b ) - > goods [ j ] . rating ) ;
2009-04-12 19:15:53 +00:00
}
2009-04-12 19:23:26 +00:00
return - ( minr1 - minr2 ) ;
2009-04-12 19:15:53 +00:00
}
2008-05-27 09:57:29 +00:00
/** Sort the stations list */
void SortStationsList ( )
{
2008-05-27 10:27:30 +00:00
if ( ! this - > stations . Sort ( ) ) return ;
2004-09-10 19:02:27 +00:00
2008-05-27 09:57:29 +00:00
/* Reset name sorter sort cache */
this - > last_station = NULL ;
2004-08-09 17:04:08 +00:00
2008-05-27 20:33:44 +00:00
/* Set the modified widget dirty */
2011-12-16 18:33:02 +00:00
this - > SetWidgetDirty ( WID_STL_LIST ) ;
2008-05-27 09:57:29 +00:00
}
2008-05-27 09:24:45 +00:00
2008-05-27 09:57:29 +00:00
public :
2013-05-26 19:23:42 +00:00
CompanyStationsWindow ( WindowDesc * desc , WindowNumber window_number ) : Window ( desc )
2008-05-11 18:50:12 +00:00
{
2009-11-08 19:31:57 +00:00
this - > stations . SetListing ( this - > last_sorting ) ;
this - > stations . SetSortFuncs ( this - > sorter_funcs ) ;
this - > stations . ForceRebuild ( ) ;
this - > stations . NeedResort ( ) ;
this - > SortStationsList ( ) ;
2007-01-11 15:30:35 +00:00
2013-05-26 19:23:42 +00:00
this - > CreateNestedTree ( ) ;
2011-12-16 18:33:02 +00:00
this - > vscroll = this - > GetScrollbar ( WID_STL_SCROLLBAR ) ;
2013-05-26 19:23:42 +00:00
this - > FinishInitNested ( window_number ) ;
2009-11-08 19:31:57 +00:00
this - > owner = ( Owner ) this - > window_number ;
2008-05-11 18:50:12 +00:00
2012-10-20 08:44:07 +00:00
const CargoSpec * cs ;
FOR_ALL_SORTED_STANDARD_CARGOSPECS ( cs ) {
if ( ! HasBit ( this - > cargo_filter , cs - > Index ( ) ) ) continue ;
this - > LowerWidget ( WID_STL_CARGOSTART + index ) ;
2008-05-11 18:50:12 +00:00
}
2006-05-11 15:14:50 +00:00
2008-05-27 09:57:29 +00:00
if ( this - > cargo_filter = = this - > cargo_filter_max ) this - > cargo_filter = _cargo_mask ;
2007-12-05 17:08:10 +00:00
2008-05-11 18:50:12 +00:00
for ( uint i = 0 ; i < 5 ; i + + ) {
2011-12-16 18:33:02 +00:00
if ( HasBit ( this - > facilities , i ) ) this - > LowerWidget ( i + WID_STL_TRAIN ) ;
2008-05-11 18:50:12 +00:00
}
2011-12-16 18:33:02 +00:00
this - > SetWidgetLoweredState ( WID_STL_NOCARGOWAITING , this - > include_empty ) ;
2008-05-11 18:50:12 +00:00
2011-12-16 18:33:02 +00:00
this - > GetWidget < NWidgetCore > ( WID_STL_SORTDROPBTN ) - > widget_data = this - > sorter_names [ this - > stations . SortType ( ) ] ;
2008-05-11 18:50:12 +00:00
}
2004-08-09 17:04:08 +00:00
2008-09-30 20:39:50 +00:00
~ CompanyStationsWindow ( )
2008-05-27 09:24:45 +00:00
{
2008-05-27 09:57:29 +00:00
this - > last_sorting = this - > stations . GetListing ( ) ;
2008-05-27 09:24:45 +00:00
}
2009-11-22 18:28:14 +00:00
virtual void UpdateWidgetSize ( int widget , Dimension * size , const Dimension & padding , Dimension * fill , Dimension * resize )
2008-05-11 18:50:12 +00:00
{
2009-11-08 19:31:57 +00:00
switch ( widget ) {
2011-12-16 18:33:02 +00:00
case WID_STL_SORTBY : {
2009-11-23 20:13:37 +00:00
Dimension d = GetStringBoundingBox ( this - > GetWidget < NWidgetCore > ( widget ) - > widget_data ) ;
2014-10-05 11:20:02 +00:00
d . width + = padding . width + Window : : SortButtonWidth ( ) * 2 ; // Doubled since the string is centred and it also looks better.
2009-11-23 20:13:37 +00:00
d . height + = padding . height ;
* size = maxdim ( * size , d ) ;
break ;
}
2011-12-16 18:33:02 +00:00
case WID_STL_SORTDROPBTN : {
2009-11-08 19:31:57 +00:00
Dimension d = { 0 , 0 } ;
for ( int i = 0 ; this - > sorter_names [ i ] ! = INVALID_STRING_ID ; i + + ) {
d = maxdim ( d , GetStringBoundingBox ( this - > sorter_names [ i ] ) ) ;
}
d . width + = padding . width ;
d . height + = padding . height ;
* size = maxdim ( * size , d ) ;
break ;
}
2004-08-09 17:04:08 +00:00
2011-12-16 18:33:02 +00:00
case WID_STL_LIST :
2009-11-08 19:31:57 +00:00
resize - > height = FONT_HEIGHT_NORMAL ;
size - > height = WD_FRAMERECT_TOP + 5 * resize - > height + WD_FRAMERECT_BOTTOM ;
break ;
2009-11-23 20:13:37 +00:00
2011-12-16 18:33:02 +00:00
case WID_STL_TRAIN :
case WID_STL_TRUCK :
case WID_STL_BUS :
case WID_STL_AIRPLANE :
case WID_STL_SHIP :
2009-11-23 20:13:37 +00:00
size - > height = max < uint > ( FONT_HEIGHT_SMALL , 10 ) + padding . height ;
break ;
2011-12-16 18:33:02 +00:00
case WID_STL_CARGOALL :
case WID_STL_FACILALL :
case WID_STL_NOCARGOWAITING : {
Dimension d = GetStringBoundingBox ( widget = = WID_STL_NOCARGOWAITING ? STR_ABBREV_NONE : STR_ABBREV_ALL ) ;
2009-11-23 20:13:37 +00:00
d . width + = padding . width + 2 ;
d . height + = padding . height ;
* size = maxdim ( * size , d ) ;
break ;
}
default :
2011-12-16 18:33:02 +00:00
if ( widget > = WID_STL_CARGOSTART ) {
2012-10-20 08:44:07 +00:00
Dimension d = GetStringBoundingBox ( _sorted_cargo_specs [ widget - WID_STL_CARGOSTART ] - > abbrev ) ;
d . width + = padding . width + 2 ;
d . height + = padding . height ;
* size = maxdim ( * size , d ) ;
2009-11-23 20:13:37 +00:00
}
break ;
2009-11-08 19:31:57 +00:00
}
}
2008-01-17 18:49:39 +00:00
2009-11-08 19:31:57 +00:00
virtual void OnPaint ( )
{
this - > BuildStationsList ( ( Owner ) this - > window_number ) ;
this - > SortStationsList ( ) ;
2006-05-11 10:33:58 +00:00
2008-05-17 12:48:06 +00:00
this - > DrawWidgets ( ) ;
2009-11-08 19:31:57 +00:00
}
2006-05-11 10:33:58 +00:00
2009-11-08 19:31:57 +00:00
virtual void DrawWidget ( const Rect & r , int widget ) const
{
switch ( widget ) {
2011-12-16 18:33:02 +00:00
case WID_STL_SORTBY :
2009-11-08 19:31:57 +00:00
/* draw arrow pointing up/down for ascending/descending sorting */
2011-12-16 18:33:02 +00:00
this - > DrawSortButtonState ( WID_STL_SORTBY , this - > stations . IsDescSortOrder ( ) ? SBS_DOWN : SBS_UP ) ;
2009-11-08 19:31:57 +00:00
break ;
2006-12-07 04:12:29 +00:00
2011-12-16 18:33:02 +00:00
case WID_STL_LIST : {
2010-11-13 09:56:25 +00:00
bool rtl = _current_text_dir = = TD_RTL ;
2010-08-12 08:37:01 +00:00
int max = min ( this - > vscroll - > GetPosition ( ) + this - > vscroll - > GetCapacity ( ) , this - > stations . Length ( ) ) ;
2009-11-08 19:31:57 +00:00
int y = r . top + WD_FRAMERECT_TOP ;
2010-08-12 08:37:01 +00:00
for ( int i = this - > vscroll - > GetPosition ( ) ; i < max ; + + i ) { // do until max number of stations of owner
2009-11-08 19:31:57 +00:00
const Station * st = this - > stations [ i ] ;
assert ( st - > xy ! = INVALID_TILE ) ;
2004-08-09 17:04:08 +00:00
2009-11-08 19:31:57 +00:00
/* Do not do the complex check HasStationInUse here, it may be even false
* when the order had been removed and the station list hasn ' t been removed yet */
assert ( st - > owner = = owner | | st - > owner = = OWNER_NONE ) ;
2004-09-10 19:02:27 +00:00
2009-11-08 19:31:57 +00:00
SetDParam ( 0 , st - > index ) ;
SetDParam ( 1 , st - > facilities ) ;
2009-11-16 14:48:22 +00:00
int x = DrawString ( r . left + WD_FRAMERECT_LEFT , r . right - WD_FRAMERECT_RIGHT , y , STR_STATION_LIST_STATION ) ;
x + = rtl ? - 5 : 5 ;
2004-08-09 17:04:08 +00:00
2009-11-08 19:31:57 +00:00
/* show cargo waiting and station ratings */
2012-10-20 08:44:07 +00:00
for ( uint j = 0 ; j < _sorted_standard_cargo_specs_size ; j + + ) {
CargoID cid = _sorted_cargo_specs [ j ] - > Index ( ) ;
2013-04-13 13:42:08 +00:00
if ( st - > goods [ cid ] . cargo . TotalCount ( ) > 0 ) {
2009-11-16 14:48:22 +00:00
/* For RTL we work in exactly the opposite direction. So
* decrement the space needed first , then draw to the left
* instead of drawing to the left and then incrementing
* the space . */
if ( rtl ) {
x - = 20 ;
if ( x < r . left + WD_FRAMERECT_LEFT ) break ;
}
2013-04-13 13:42:08 +00:00
StationsWndShowStationRating ( x , x + 16 , y , cid , st - > goods [ cid ] . cargo . TotalCount ( ) , st - > goods [ cid ] . rating ) ;
2009-11-16 14:48:22 +00:00
if ( ! rtl ) {
x + = 20 ;
if ( x > r . right - WD_FRAMERECT_RIGHT ) break ;
}
2009-11-08 19:31:57 +00:00
}
}
y + = FONT_HEIGHT_NORMAL ;
}
2004-08-09 17:04:08 +00:00
2010-08-12 08:37:01 +00:00
if ( this - > vscroll - > GetCount ( ) = = 0 ) { // company has no stations
2009-11-08 19:31:57 +00:00
DrawString ( r . left + WD_FRAMERECT_LEFT , r . right - WD_FRAMERECT_RIGHT , y , STR_STATION_LIST_NONE ) ;
return ;
}
break ;
}
2007-12-19 23:35:14 +00:00
2011-12-16 18:33:02 +00:00
case WID_STL_NOCARGOWAITING : {
2009-11-08 19:31:57 +00:00
int cg_ofst = this - > IsWidgetLowered ( widget ) ? 2 : 1 ;
2010-07-02 13:53:05 +00:00
DrawString ( r . left + cg_ofst , r . right + cg_ofst , r . top + cg_ofst , STR_ABBREV_NONE , TC_BLACK , SA_HOR_CENTER ) ;
2009-11-08 19:31:57 +00:00
break ;
}
2004-09-07 19:01:06 +00:00
2011-12-16 18:33:02 +00:00
case WID_STL_CARGOALL : {
2009-11-08 19:31:57 +00:00
int cg_ofst = this - > IsWidgetLowered ( widget ) ? 2 : 1 ;
2010-07-02 13:53:05 +00:00
DrawString ( r . left + cg_ofst , r . right + cg_ofst , r . top + cg_ofst , STR_ABBREV_ALL , TC_BLACK , SA_HOR_CENTER ) ;
2009-11-08 19:31:57 +00:00
break ;
}
2004-08-09 17:04:08 +00:00
2011-12-16 18:33:02 +00:00
case WID_STL_FACILALL : {
2009-11-08 19:31:57 +00:00
int cg_ofst = this - > IsWidgetLowered ( widget ) ? 2 : 1 ;
2013-08-18 19:30:25 +00:00
DrawString ( r . left + cg_ofst , r . right + cg_ofst , r . top + cg_ofst , STR_ABBREV_ALL , TC_BLACK , SA_HOR_CENTER ) ;
2009-11-08 19:31:57 +00:00
break ;
}
2008-05-11 18:50:12 +00:00
2009-11-08 19:31:57 +00:00
default :
2011-12-16 18:33:02 +00:00
if ( widget > = WID_STL_CARGOSTART ) {
2012-10-20 08:44:07 +00:00
const CargoSpec * cs = _sorted_cargo_specs [ widget - WID_STL_CARGOSTART ] ;
int cg_ofst = HasBit ( this - > cargo_filter , cs - > Index ( ) ) ? 2 : 1 ;
GfxFillRect ( r . left + cg_ofst , r . top + cg_ofst , r . right - 2 + cg_ofst , r . bottom - 2 + cg_ofst , cs - > rating_colour ) ;
2012-11-07 21:23:26 +00:00
TextColour tc = GetContrastColour ( cs - > rating_colour ) ;
DrawString ( r . left + cg_ofst , r . right + cg_ofst , r . top + cg_ofst , cs - > abbrev , tc , SA_HOR_CENTER ) ;
2004-08-09 17:04:08 +00:00
}
2009-11-08 19:36:17 +00:00
break ;
2009-11-08 19:31:57 +00:00
}
}
virtual void SetStringParameters ( int widget ) const
{
2011-12-16 18:33:02 +00:00
if ( widget = = WID_STL_CAPTION ) {
2009-11-08 19:31:57 +00:00
SetDParam ( 0 , this - > window_number ) ;
2010-08-12 08:37:01 +00:00
SetDParam ( 1 , this - > vscroll - > GetCount ( ) ) ;
2004-08-09 17:04:08 +00:00
}
2008-05-11 18:50:12 +00:00
}
2006-12-07 04:12:29 +00:00
2010-01-30 18:34:48 +00:00
virtual void OnClick ( Point pt , int widget , int click_count )
2008-05-11 18:50:12 +00:00
{
switch ( widget ) {
2011-12-16 18:33:02 +00:00
case WID_STL_LIST : {
uint id_v = this - > vscroll - > GetScrolledRowFromWidget ( pt . y , this , WID_STL_LIST , 0 , FONT_HEIGHT_NORMAL ) ;
2008-05-27 09:24:45 +00:00
if ( id_v > = this - > stations . Length ( ) ) return ; // click out of list bound
2008-05-05 11:36:43 +00:00
2008-05-27 09:24:45 +00:00
const Station * st = this - > stations [ id_v ] ;
2008-05-11 18:50:12 +00:00
/* do not check HasStationInUse - it is slow and may be invalid */
2009-07-22 08:59:57 +00:00
assert ( st - > owner = = ( Owner ) this - > window_number | | st - > owner = = OWNER_NONE ) ;
2008-05-11 18:50:12 +00:00
if ( _ctrl_pressed ) {
ShowExtraViewPortWindow ( st - > xy ) ;
} else {
ScrollMainWindowToTile ( st - > xy ) ;
2007-03-03 09:40:34 +00:00
}
2008-05-11 18:50:12 +00:00
break ;
}
2004-09-07 19:01:06 +00:00
2011-12-16 18:33:02 +00:00
case WID_STL_TRAIN :
case WID_STL_TRUCK :
case WID_STL_BUS :
case WID_STL_AIRPLANE :
case WID_STL_SHIP :
2008-05-11 18:50:12 +00:00
if ( _ctrl_pressed ) {
2011-12-16 18:33:02 +00:00
ToggleBit ( this - > facilities , widget - WID_STL_TRAIN ) ;
2008-05-11 18:50:12 +00:00
this - > ToggleWidgetLoweredState ( widget ) ;
} else {
uint i ;
2008-05-27 09:57:29 +00:00
FOR_EACH_SET_BIT ( i , this - > facilities ) {
2011-12-16 18:33:02 +00:00
this - > RaiseWidget ( i + WID_STL_TRAIN ) ;
2007-03-03 09:40:34 +00:00
}
2011-12-16 18:33:02 +00:00
this - > facilities = 1 < < ( widget - WID_STL_TRAIN ) ;
2008-05-11 18:50:12 +00:00
this - > LowerWidget ( widget ) ;
}
2008-05-27 09:24:45 +00:00
this - > stations . ForceRebuild ( ) ;
2008-05-11 18:50:12 +00:00
this - > SetDirty ( ) ;
break ;
2011-12-16 18:33:02 +00:00
case WID_STL_FACILALL :
for ( uint i = WID_STL_TRAIN ; i < = WID_STL_SHIP ; i + + ) {
2010-04-07 21:33:03 +00:00
this - > LowerWidget ( i ) ;
2008-05-11 18:50:12 +00:00
}
2008-05-27 09:57:29 +00:00
this - > facilities = FACIL_TRAIN | FACIL_TRUCK_STOP | FACIL_BUS_STOP | FACIL_AIRPORT | FACIL_DOCK ;
2008-05-27 09:24:45 +00:00
this - > stations . ForceRebuild ( ) ;
2008-05-11 18:50:12 +00:00
this - > SetDirty ( ) ;
break ;
2011-12-16 18:33:02 +00:00
case WID_STL_CARGOALL : {
2012-10-20 08:44:07 +00:00
for ( uint i = 0 ; i < _sorted_standard_cargo_specs_size ; i + + ) {
this - > LowerWidget ( WID_STL_CARGOSTART + i ) ;
2008-05-11 18:50:12 +00:00
}
2011-12-16 18:33:02 +00:00
this - > LowerWidget ( WID_STL_NOCARGOWAITING ) ;
2008-05-11 18:50:12 +00:00
2008-05-27 09:57:29 +00:00
this - > cargo_filter = _cargo_mask ;
this - > include_empty = true ;
2008-05-27 09:24:45 +00:00
this - > stations . ForceRebuild ( ) ;
2008-05-11 18:50:12 +00:00
this - > SetDirty ( ) ;
break ;
}
2011-12-16 18:33:02 +00:00
case WID_STL_SORTBY : // flip sorting method asc/desc
2008-05-27 09:24:45 +00:00
this - > stations . ToggleSortOrder ( ) ;
2008-05-11 18:50:12 +00:00
this - > SetDirty ( ) ;
break ;
2011-12-16 18:33:02 +00:00
case WID_STL_SORTDROPBTN : // select sorting criteria dropdown menu
ShowDropDownMenu ( this , this - > sorter_names , this - > stations . SortType ( ) , WID_STL_SORTDROPBTN , 0 , 0 ) ;
2008-05-11 18:50:12 +00:00
break ;
2011-12-16 18:33:02 +00:00
case WID_STL_NOCARGOWAITING :
2008-05-11 18:50:12 +00:00
if ( _ctrl_pressed ) {
2008-05-27 09:57:29 +00:00
this - > include_empty = ! this - > include_empty ;
2011-12-16 18:33:02 +00:00
this - > ToggleWidgetLoweredState ( WID_STL_NOCARGOWAITING ) ;
2008-05-11 18:50:12 +00:00
} else {
2012-10-20 08:44:07 +00:00
for ( uint i = 0 ; i < _sorted_standard_cargo_specs_size ; i + + ) {
this - > RaiseWidget ( WID_STL_CARGOSTART + i ) ;
2007-03-03 09:40:34 +00:00
}
2004-09-07 19:01:06 +00:00
2008-05-27 09:57:29 +00:00
this - > cargo_filter = 0 ;
this - > include_empty = true ;
2006-12-07 04:12:29 +00:00
2011-12-16 18:33:02 +00:00
this - > LowerWidget ( WID_STL_NOCARGOWAITING ) ;
2008-05-11 18:50:12 +00:00
}
2008-05-27 09:24:45 +00:00
this - > stations . ForceRebuild ( ) ;
2008-05-11 18:50:12 +00:00
this - > SetDirty ( ) ;
break ;
default :
2011-12-16 18:33:02 +00:00
if ( widget > = WID_STL_CARGOSTART ) { // change cargo_filter
2008-05-11 18:50:12 +00:00
/* Determine the selected cargo type */
2012-10-20 08:44:07 +00:00
const CargoSpec * cs = _sorted_cargo_specs [ widget - WID_STL_CARGOSTART ] ;
2007-03-03 09:40:34 +00:00
2007-03-09 22:55:57 +00:00
if ( _ctrl_pressed ) {
2009-07-16 20:40:06 +00:00
ToggleBit ( this - > cargo_filter , cs - > Index ( ) ) ;
2008-05-11 18:50:12 +00:00
this - > ToggleWidgetLoweredState ( widget ) ;
2007-03-09 22:55:57 +00:00
} else {
2012-10-20 08:44:07 +00:00
for ( uint i = 0 ; i < _sorted_standard_cargo_specs_size ; i + + ) {
this - > RaiseWidget ( WID_STL_CARGOSTART + i ) ;
2007-03-09 22:55:57 +00:00
}
2011-12-16 18:33:02 +00:00
this - > RaiseWidget ( WID_STL_NOCARGOWAITING ) ;
2007-03-09 22:55:57 +00:00
2008-05-27 09:57:29 +00:00
this - > cargo_filter = 0 ;
this - > include_empty = false ;
2007-03-09 22:55:57 +00:00
2009-07-16 20:40:06 +00:00
SetBit ( this - > cargo_filter , cs - > Index ( ) ) ;
2008-05-11 18:50:12 +00:00
this - > LowerWidget ( widget ) ;
2007-03-09 22:55:57 +00:00
}
2008-05-27 09:24:45 +00:00
this - > stations . ForceRebuild ( ) ;
2008-05-11 18:50:12 +00:00
this - > SetDirty ( ) ;
}
break ;
}
}
2007-03-09 22:55:57 +00:00
2008-05-11 18:50:12 +00:00
virtual void OnDropdownSelect ( int widget , int index )
{
2008-05-27 09:24:45 +00:00
if ( this - > stations . SortType ( ) ! = index ) {
this - > stations . SetSortType ( index ) ;
2008-05-27 20:33:44 +00:00
/* Display the current sort variant */
2011-12-16 18:33:02 +00:00
this - > GetWidget < NWidgetCore > ( WID_STL_SORTDROPBTN ) - > widget_data = this - > sorter_names [ this - > stations . SortType ( ) ] ;
2008-05-27 20:33:44 +00:00
2008-05-27 09:24:45 +00:00
this - > SetDirty ( ) ;
2008-05-11 18:50:12 +00:00
}
}
2007-03-09 22:55:57 +00:00
2008-05-11 18:50:12 +00:00
virtual void OnTick ( )
{
2009-05-06 15:06:57 +00:00
if ( _pause_mode ! = PM_UNPAUSED ) return ;
2008-05-27 09:24:45 +00:00
if ( this - > stations . NeedResort ( ) ) {
2008-09-30 20:39:50 +00:00
DEBUG ( misc , 3 , " Periodic rebuild station list company %d " , this - > window_number ) ;
2008-05-11 18:50:12 +00:00
this - > SetDirty ( ) ;
}
}
2004-08-09 17:04:08 +00:00
2009-10-24 14:53:55 +00:00
virtual void OnResize ( )
2008-05-11 18:50:12 +00:00
{
2011-12-16 18:33:02 +00:00
this - > vscroll - > SetCapacityFromWidget ( this , WID_STL_LIST , WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM ) ;
2004-08-09 17:04:08 +00:00
}
2008-05-18 16:51:44 +00:00
2011-03-13 21:31:29 +00:00
/**
* Some data on this window has become invalid .
* @ param data Information about the changed data .
* @ param gui_scope Whether the call is done from GUI scope . You may not do everything when not in GUI scope . See # InvalidateWindowData ( ) for details .
*/
virtual void OnInvalidateData ( int data = 0 , bool gui_scope = true )
2008-05-18 16:51:44 +00:00
{
2008-05-27 09:24:45 +00:00
if ( data = = 0 ) {
2011-03-13 21:34:21 +00:00
/* This needs to be done in command-scope to enforce rebuilding before resorting invalid data */
2008-05-27 09:24:45 +00:00
this - > stations . ForceRebuild ( ) ;
} else {
this - > stations . ForceResort ( ) ;
}
2008-05-18 16:51:44 +00:00
}
2008-05-11 18:50:12 +00:00
} ;
2008-09-30 20:39:50 +00:00
Listing CompanyStationsWindow : : last_sorting = { false , 0 } ;
byte CompanyStationsWindow : : facilities = FACIL_TRAIN | FACIL_TRUCK_STOP | FACIL_BUS_STOP | FACIL_AIRPORT | FACIL_DOCK ;
bool CompanyStationsWindow : : include_empty = true ;
const uint32 CompanyStationsWindow : : cargo_filter_max = UINT32_MAX ;
uint32 CompanyStationsWindow : : cargo_filter = UINT32_MAX ;
const Station * CompanyStationsWindow : : last_station = NULL ;
2008-05-27 09:57:29 +00:00
/* Availible station sorting functions */
2009-03-15 16:04:39 +00:00
GUIStationList : : SortFunction * const CompanyStationsWindow : : sorter_funcs [ ] = {
2008-05-27 09:57:29 +00:00
& StationNameSorter ,
& StationTypeSorter ,
2013-06-15 15:26:24 +00:00
& StationWaitingTotalSorter ,
& StationWaitingAvailableSorter ,
2009-04-12 19:15:53 +00:00
& StationRatingMaxSorter ,
& StationRatingMinSorter
2008-05-27 09:57:29 +00:00
} ;
/* Names of the sorting functions */
2008-09-30 20:39:50 +00:00
const StringID CompanyStationsWindow : : sorter_names [ ] = {
2009-07-23 19:31:50 +00:00
STR_SORT_BY_NAME ,
2008-05-27 09:57:29 +00:00
STR_SORT_BY_FACILITY ,
2013-06-15 15:26:24 +00:00
STR_SORT_BY_WAITING_TOTAL ,
STR_SORT_BY_WAITING_AVAILABLE ,
2008-05-27 09:57:29 +00:00
STR_SORT_BY_RATING_MAX ,
2009-04-12 19:15:53 +00:00
STR_SORT_BY_RATING_MIN ,
2008-05-27 09:57:29 +00:00
INVALID_STRING_ID
} ;
2008-05-11 18:50:12 +00:00
2010-08-01 19:22:34 +00:00
/**
2011-12-16 18:33:02 +00:00
* Make a horizontal row of cargo buttons , starting at widget # WID_STL_CARGOSTART .
2009-11-08 19:31:57 +00:00
* @ param biggest_index Pointer to store biggest used widget number of the buttons .
* @ return Horizontal row .
*/
static NWidgetBase * CargoWidgets ( int * biggest_index )
{
NWidgetHorizontal * container = new NWidgetHorizontal ( ) ;
2012-10-20 08:44:07 +00:00
for ( uint i = 0 ; i < _sorted_standard_cargo_specs_size ; i + + ) {
NWidgetBackground * panel = new NWidgetBackground ( WWT_PANEL , COLOUR_GREY , WID_STL_CARGOSTART + i ) ;
panel - > SetMinimalSize ( 14 , 11 ) ;
panel - > SetResize ( 0 , 0 ) ;
panel - > SetFill ( 0 , 1 ) ;
panel - > SetDataTip ( 0 , STR_STATION_LIST_USE_CTRL_TO_SELECT_MORE ) ;
container - > Add ( panel ) ;
2009-11-08 19:31:57 +00:00
}
2012-10-20 08:44:07 +00:00
* biggest_index = WID_STL_CARGOSTART + _sorted_standard_cargo_specs_size ;
2009-11-08 19:31:57 +00:00
return container ;
}
2004-08-09 17:04:08 +00:00
2009-05-03 10:46:24 +00:00
static const NWidgetPart _nested_company_stations_widgets [ ] = {
NWidget ( NWID_HORIZONTAL ) ,
2009-11-24 18:05:55 +00:00
NWidget ( WWT_CLOSEBOX , COLOUR_GREY ) ,
2011-12-16 18:33:02 +00:00
NWidget ( WWT_CAPTION , COLOUR_GREY , WID_STL_CAPTION ) , SetDataTip ( STR_STATION_LIST_CAPTION , STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS ) ,
2009-12-21 16:24:29 +00:00
NWidget ( WWT_SHADEBOX , COLOUR_GREY ) ,
2013-05-26 19:30:07 +00:00
NWidget ( WWT_DEFSIZEBOX , COLOUR_GREY ) ,
2009-11-24 18:05:55 +00:00
NWidget ( WWT_STICKYBOX , COLOUR_GREY ) ,
2009-05-03 10:46:24 +00:00
EndContainer ( ) ,
NWidget ( NWID_HORIZONTAL ) ,
2011-12-16 18:33:02 +00:00
NWidget ( WWT_TEXTBTN , COLOUR_GREY , WID_STL_TRAIN ) , SetMinimalSize ( 14 , 11 ) , SetDataTip ( STR_TRAIN , STR_STATION_LIST_USE_CTRL_TO_SELECT_MORE ) , SetFill ( 0 , 1 ) ,
NWidget ( WWT_TEXTBTN , COLOUR_GREY , WID_STL_TRUCK ) , SetMinimalSize ( 14 , 11 ) , SetDataTip ( STR_LORRY , STR_STATION_LIST_USE_CTRL_TO_SELECT_MORE ) , SetFill ( 0 , 1 ) ,
NWidget ( WWT_TEXTBTN , COLOUR_GREY , WID_STL_BUS ) , SetMinimalSize ( 14 , 11 ) , SetDataTip ( STR_BUS , STR_STATION_LIST_USE_CTRL_TO_SELECT_MORE ) , SetFill ( 0 , 1 ) ,
NWidget ( WWT_TEXTBTN , COLOUR_GREY , WID_STL_SHIP ) , SetMinimalSize ( 14 , 11 ) , SetDataTip ( STR_SHIP , STR_STATION_LIST_USE_CTRL_TO_SELECT_MORE ) , SetFill ( 0 , 1 ) ,
NWidget ( WWT_TEXTBTN , COLOUR_GREY , WID_STL_AIRPLANE ) , SetMinimalSize ( 14 , 11 ) , SetDataTip ( STR_PLANE , STR_STATION_LIST_USE_CTRL_TO_SELECT_MORE ) , SetFill ( 0 , 1 ) ,
NWidget ( WWT_PUSHBTN , COLOUR_GREY , WID_STL_FACILALL ) , SetMinimalSize ( 14 , 11 ) , SetDataTip ( 0x0 , STR_STATION_LIST_SELECT_ALL_FACILITIES ) , SetFill ( 0 , 1 ) ,
2009-11-24 21:13:36 +00:00
NWidget ( WWT_PANEL , COLOUR_GREY ) , SetMinimalSize ( 5 , 11 ) , SetFill ( 0 , 1 ) , EndContainer ( ) ,
2009-11-08 19:31:57 +00:00
NWidgetFunction ( CargoWidgets ) ,
2011-12-16 18:33:02 +00:00
NWidget ( WWT_PANEL , COLOUR_GREY , WID_STL_NOCARGOWAITING ) , SetMinimalSize ( 14 , 11 ) , SetDataTip ( 0x0 , STR_STATION_LIST_NO_WAITING_CARGO ) , SetFill ( 0 , 1 ) , EndContainer ( ) ,
NWidget ( WWT_PUSHBTN , COLOUR_GREY , WID_STL_CARGOALL ) , SetMinimalSize ( 14 , 11 ) , SetDataTip ( 0x0 , STR_STATION_LIST_SELECT_ALL_TYPES ) , SetFill ( 0 , 1 ) ,
2009-11-24 21:13:36 +00:00
NWidget ( WWT_PANEL , COLOUR_GREY ) , SetDataTip ( 0x0 , STR_NULL ) , SetResize ( 1 , 0 ) , SetFill ( 1 , 1 ) , EndContainer ( ) ,
2009-05-03 10:46:24 +00:00
EndContainer ( ) ,
NWidget ( NWID_HORIZONTAL ) ,
2012-11-11 16:07:46 +00:00
NWidget ( WWT_PUSHTXTBTN , COLOUR_GREY , WID_STL_SORTBY ) , SetMinimalSize ( 81 , 12 ) , SetDataTip ( STR_BUTTON_SORT_BY , STR_TOOLTIP_SORT_ORDER ) ,
2011-12-16 18:33:02 +00:00
NWidget ( WWT_DROPDOWN , COLOUR_GREY , WID_STL_SORTDROPBTN ) , SetMinimalSize ( 163 , 12 ) , SetDataTip ( STR_SORT_BY_NAME , STR_TOOLTIP_SORT_CRITERIA ) , // widget_data gets overwritten.
2009-11-24 21:13:36 +00:00
NWidget ( WWT_PANEL , COLOUR_GREY ) , SetDataTip ( 0x0 , STR_NULL ) , SetResize ( 1 , 0 ) , SetFill ( 1 , 1 ) , EndContainer ( ) ,
2009-05-03 10:46:24 +00:00
EndContainer ( ) ,
NWidget ( NWID_HORIZONTAL ) ,
2011-12-16 18:33:02 +00:00
NWidget ( WWT_PANEL , COLOUR_GREY , WID_STL_LIST ) , SetMinimalSize ( 346 , 125 ) , SetResize ( 1 , 10 ) , SetDataTip ( 0x0 , STR_STATION_LIST_TOOLTIP ) , SetScrollbar ( WID_STL_SCROLLBAR ) , EndContainer ( ) ,
2009-05-03 10:46:24 +00:00
NWidget ( NWID_VERTICAL ) ,
2011-12-16 18:33:02 +00:00
NWidget ( NWID_VSCROLLBAR , COLOUR_GREY , WID_STL_SCROLLBAR ) ,
2009-11-24 18:05:55 +00:00
NWidget ( WWT_RESIZEBOX , COLOUR_GREY ) ,
2009-05-03 10:46:24 +00:00
EndContainer ( ) ,
EndContainer ( ) ,
} ;
2013-05-26 19:23:42 +00:00
static WindowDesc _company_stations_desc (
2013-05-26 19:25:01 +00:00
WDP_AUTO , " list_stations " , 358 , 162 ,
2007-02-01 15:49:12 +00:00
WC_STATION_LIST , WC_NONE ,
2012-11-11 16:10:43 +00:00
0 ,
2009-11-15 10:26:01 +00:00
_nested_company_stations_widgets , lengthof ( _nested_company_stations_widgets )
2009-03-15 15:12:06 +00:00
) ;
2004-08-09 17:04:08 +00:00
2007-12-05 17:08:10 +00:00
/**
2008-09-30 20:39:50 +00:00
* Opens window with list of company ' s stations
2007-12-05 17:08:10 +00:00
*
2008-09-30 20:39:50 +00:00
* @ param company whose stations ' list show
2007-12-05 17:08:10 +00:00
*/
2008-09-30 20:39:50 +00:00
void ShowCompanyStations ( CompanyID company )
2004-08-09 17:04:08 +00:00
{
2009-05-17 01:00:56 +00:00
if ( ! Company : : IsValidID ( company ) ) return ;
2006-10-31 21:15:56 +00:00
2008-09-30 20:39:50 +00:00
AllocateWindowDescFront < CompanyStationsWindow > ( & _company_stations_desc , company ) ;
2004-08-09 17:04:08 +00:00
}
2009-05-03 10:46:24 +00:00
static const NWidgetPart _nested_station_view_widgets [ ] = {
NWidget ( NWID_HORIZONTAL ) ,
2009-11-24 18:05:55 +00:00
NWidget ( WWT_CLOSEBOX , COLOUR_GREY ) ,
2011-12-16 18:14:11 +00:00
NWidget ( WWT_CAPTION , COLOUR_GREY , WID_SV_CAPTION ) , SetDataTip ( STR_STATION_VIEW_CAPTION , STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS ) ,
2009-12-21 16:24:29 +00:00
NWidget ( WWT_SHADEBOX , COLOUR_GREY ) ,
2013-05-26 19:30:07 +00:00
NWidget ( WWT_DEFSIZEBOX , COLOUR_GREY ) ,
2009-11-24 18:05:55 +00:00
NWidget ( WWT_STICKYBOX , COLOUR_GREY ) ,
2009-05-03 10:46:24 +00:00
EndContainer ( ) ,
NWidget ( NWID_HORIZONTAL ) ,
2013-06-09 13:08:52 +00:00
NWidget ( WWT_PUSHTXTBTN , COLOUR_GREY , WID_SV_SORT_ORDER ) , SetMinimalSize ( 81 , 12 ) , SetFill ( 1 , 1 ) , SetDataTip ( STR_BUTTON_SORT_BY , STR_TOOLTIP_SORT_ORDER ) ,
NWidget ( WWT_DROPDOWN , COLOUR_GREY , WID_SV_SORT_BY ) , SetMinimalSize ( 168 , 12 ) , SetResize ( 1 , 0 ) , SetFill ( 0 , 1 ) , SetDataTip ( 0x0 , STR_TOOLTIP_SORT_CRITERIA ) ,
EndContainer ( ) ,
NWidget ( NWID_HORIZONTAL ) ,
NWidget ( WWT_TEXTBTN , COLOUR_GREY , WID_SV_GROUP ) , SetMinimalSize ( 81 , 12 ) , SetFill ( 1 , 1 ) , SetDataTip ( STR_STATION_VIEW_GROUP , 0x0 ) ,
NWidget ( WWT_DROPDOWN , COLOUR_GREY , WID_SV_GROUP_BY ) , SetMinimalSize ( 168 , 12 ) , SetResize ( 1 , 0 ) , SetFill ( 0 , 1 ) , SetDataTip ( 0x0 , STR_TOOLTIP_GROUP_ORDER ) ,
EndContainer ( ) ,
NWidget ( NWID_HORIZONTAL ) ,
NWidget ( WWT_PANEL , COLOUR_GREY , WID_SV_WAITING ) , SetMinimalSize ( 237 , 44 ) , SetResize ( 1 , 10 ) , SetScrollbar ( WID_SV_SCROLLBAR ) , EndContainer ( ) ,
2011-12-16 18:14:11 +00:00
NWidget ( NWID_VSCROLLBAR , COLOUR_GREY , WID_SV_SCROLLBAR ) ,
2009-05-03 10:46:24 +00:00
EndContainer ( ) ,
2013-06-09 13:08:52 +00:00
NWidget ( WWT_PANEL , COLOUR_GREY , WID_SV_ACCEPT_RATING_LIST ) , SetMinimalSize ( 249 , 23 ) , SetResize ( 1 , 0 ) , EndContainer ( ) ,
2012-04-17 19:43:18 +00:00
NWidget ( NWID_HORIZONTAL ) ,
NWidget ( NWID_HORIZONTAL , NC_EQUALSIZE ) ,
NWidget ( WWT_PUSHTXTBTN , COLOUR_GREY , WID_SV_LOCATION ) , SetMinimalSize ( 45 , 12 ) , SetResize ( 1 , 0 ) , SetFill ( 1 , 1 ) ,
SetDataTip ( STR_BUTTON_LOCATION , STR_STATION_VIEW_CENTER_TOOLTIP ) ,
NWidget ( WWT_PUSHTXTBTN , COLOUR_GREY , WID_SV_ACCEPTS_RATINGS ) , SetMinimalSize ( 46 , 12 ) , SetResize ( 1 , 0 ) , SetFill ( 1 , 1 ) ,
SetDataTip ( STR_STATION_VIEW_RATINGS_BUTTON , STR_STATION_VIEW_RATINGS_TOOLTIP ) ,
NWidget ( WWT_PUSHTXTBTN , COLOUR_GREY , WID_SV_RENAME ) , SetMinimalSize ( 45 , 12 ) , SetResize ( 1 , 0 ) , SetFill ( 1 , 1 ) ,
SetDataTip ( STR_BUTTON_RENAME , STR_STATION_VIEW_RENAME_TOOLTIP ) ,
EndContainer ( ) ,
NWidget ( WWT_TEXTBTN , COLOUR_GREY , WID_SV_CLOSE_AIRPORT ) , SetMinimalSize ( 45 , 12 ) , SetResize ( 1 , 0 ) , SetFill ( 1 , 1 ) ,
SetDataTip ( STR_STATION_VIEW_CLOSE_AIRPORT , STR_STATION_VIEW_CLOSE_AIRPORT_TOOLTIP ) ,
2011-12-16 18:14:11 +00:00
NWidget ( WWT_PUSHTXTBTN , COLOUR_GREY , WID_SV_TRAINS ) , SetMinimalSize ( 14 , 12 ) , SetFill ( 0 , 1 ) , SetDataTip ( STR_TRAIN , STR_STATION_VIEW_SCHEDULED_TRAINS_TOOLTIP ) ,
NWidget ( WWT_PUSHTXTBTN , COLOUR_GREY , WID_SV_ROADVEHS ) , SetMinimalSize ( 14 , 12 ) , SetFill ( 0 , 1 ) , SetDataTip ( STR_LORRY , STR_STATION_VIEW_SCHEDULED_ROAD_VEHICLES_TOOLTIP ) ,
NWidget ( WWT_PUSHTXTBTN , COLOUR_GREY , WID_SV_SHIPS ) , SetMinimalSize ( 14 , 12 ) , SetFill ( 0 , 1 ) , SetDataTip ( STR_SHIP , STR_STATION_VIEW_SCHEDULED_SHIPS_TOOLTIP ) ,
NWidget ( WWT_PUSHTXTBTN , COLOUR_GREY , WID_SV_PLANES ) , SetMinimalSize ( 14 , 12 ) , SetFill ( 0 , 1 ) , SetDataTip ( STR_PLANE , STR_STATION_VIEW_SCHEDULED_AIRCRAFT_TOOLTIP ) ,
2009-11-24 18:05:55 +00:00
NWidget ( WWT_RESIZEBOX , COLOUR_GREY ) ,
2009-05-03 10:46:24 +00:00
EndContainer ( ) ,
} ;
2008-03-28 04:57:32 +00:00
/**
* Draws icons of waiting cargo in the StationView window
*
* @ param i type of cargo
* @ param waiting number of waiting units
2009-11-18 20:22:39 +00:00
* @ param left left most coordinate to draw on
* @ param right right most coordinate to draw on
2008-03-28 04:57:32 +00:00
* @ param y y coordinate
2009-09-19 09:51:14 +00:00
* @ param width the width of the view
2008-03-28 04:57:32 +00:00
*/
2009-11-18 20:22:39 +00:00
static void DrawCargoIcons ( CargoID i , uint waiting , int left , int right , int y )
2008-03-28 04:57:32 +00:00
{
2015-02-01 20:54:24 +00:00
int width = ScaleGUITrad ( 10 ) ;
2014-10-04 20:18:25 +00:00
uint num = min ( ( waiting + ( width / 2 ) ) / width , ( right - left ) / width ) ; // maximum is width / 10 icons so it won't overflow
2008-03-28 04:57:32 +00:00
if ( num = = 0 ) return ;
2009-12-05 16:00:58 +00:00
SpriteID sprite = CargoSpec : : Get ( i ) - > GetCargoIcon ( ) ;
2008-03-28 04:57:32 +00:00
2014-10-04 20:18:25 +00:00
int x = _current_text_dir = = TD_RTL ? left : right - num * width ;
2007-03-23 20:51:42 +00:00
do {
DrawSprite ( sprite , PAL_NONE , x , y ) ;
2014-10-04 20:18:25 +00:00
x + = width ;
2007-03-23 20:51:42 +00:00
} while ( - - num ) ;
}
2013-06-09 13:08:52 +00:00
enum SortOrder {
SO_DESCENDING ,
SO_ASCENDING
} ;
2008-01-26 22:15:39 +00:00
2013-06-09 13:08:52 +00:00
class CargoDataEntry ;
enum CargoSortType {
ST_AS_GROUPING , ///< by the same principle the entries are being grouped
ST_COUNT , ///< by amount of cargo
ST_STATION_STRING , ///< by station name
ST_STATION_ID , ///< by station id
ST_CARGO_ID , ///< by cargo id
2008-01-26 22:15:39 +00:00
} ;
2013-06-09 13:08:52 +00:00
class CargoSorter {
public :
CargoSorter ( CargoSortType t = ST_STATION_ID , SortOrder o = SO_ASCENDING ) : type ( t ) , order ( o ) { }
CargoSortType GetSortType ( ) { return this - > type ; }
bool operator ( ) ( const CargoDataEntry * cd1 , const CargoDataEntry * cd2 ) const ;
private :
CargoSortType type ;
SortOrder order ;
template < class Tid >
bool SortId ( Tid st1 , Tid st2 ) const ;
bool SortCount ( const CargoDataEntry * cd1 , const CargoDataEntry * cd2 ) const ;
bool SortStation ( StationID st1 , StationID st2 ) const ;
} ;
typedef std : : set < CargoDataEntry * , CargoSorter > CargoDataSet ;
/**
* A cargo data entry representing one possible row in the station view window ' s
* top part . Cargo data entries form a tree where each entry can have several
* children . Parents keep track of the sums of their childrens ' cargo counts .
*/
class CargoDataEntry {
public :
CargoDataEntry ( ) ;
~ CargoDataEntry ( ) ;
/**
* Insert a new child or retrieve an existing child using a station ID as ID .
* @ param station ID of the station for which an entry shall be created or retrieved
* @ return a child entry associated with the given station .
*/
CargoDataEntry * InsertOrRetrieve ( StationID station )
{
return this - > InsertOrRetrieve < StationID > ( station ) ;
}
/**
* Insert a new child or retrieve an existing child using a cargo ID as ID .
* @ param cargo ID of the cargo for which an entry shall be created or retrieved
* @ return a child entry associated with the given cargo .
*/
CargoDataEntry * InsertOrRetrieve ( CargoID cargo )
{
return this - > InsertOrRetrieve < CargoID > ( cargo ) ;
}
void Update ( uint count ) ;
/**
* Remove a child associated with the given station .
* @ param station ID of the station for which the child should be removed .
*/
void Remove ( StationID station )
{
CargoDataEntry t ( station ) ;
this - > Remove ( & t ) ;
}
/**
* Remove a child associated with the given cargo .
* @ param cargo ID of the cargo for which the child should be removed .
*/
void Remove ( CargoID cargo )
{
CargoDataEntry t ( cargo ) ;
this - > Remove ( & t ) ;
}
/**
* Retrieve a child for the given station . Return NULL if it doesn ' t exist .
* @ param station ID of the station the child we ' re looking for is associated with .
* @ return a child entry for the given station or NULL .
*/
CargoDataEntry * Retrieve ( StationID station ) const
{
CargoDataEntry t ( station ) ;
return this - > Retrieve ( this - > children - > find ( & t ) ) ;
}
/**
* Retrieve a child for the given cargo . Return NULL if it doesn ' t exist .
* @ param cargo ID of the cargo the child we ' re looking for is associated with .
* @ return a child entry for the given cargo or NULL .
*/
CargoDataEntry * Retrieve ( CargoID cargo ) const
{
CargoDataEntry t ( cargo ) ;
return this - > Retrieve ( this - > children - > find ( & t ) ) ;
}
void Resort ( CargoSortType type , SortOrder order ) ;
/**
* Get the station ID for this entry .
*/
StationID GetStation ( ) const { return this - > station ; }
/**
* Get the cargo ID for this entry .
*/
CargoID GetCargo ( ) const { return this - > cargo ; }
/**
* Get the cargo count for this entry .
*/
uint GetCount ( ) const { return this - > count ; }
/**
* Get the parent entry for this entry .
*/
CargoDataEntry * GetParent ( ) const { return this - > parent ; }
/**
* Get the number of children for this entry .
*/
uint GetNumChildren ( ) const { return this - > num_children ; }
/**
* Get an iterator pointing to the begin of the set of children .
*/
CargoDataSet : : iterator Begin ( ) const { return this - > children - > begin ( ) ; }
/**
* Get an iterator pointing to the end of the set of children .
*/
CargoDataSet : : iterator End ( ) const { return this - > children - > end ( ) ; }
2013-06-22 07:44:59 +00:00
/**
* Has this entry transfers .
*/
bool HasTransfers ( ) const { return this - > transfers ; }
/**
* Set the transfers state .
*/
void SetTransfers ( bool value ) { this - > transfers = value ; }
2013-06-09 13:08:52 +00:00
void Clear ( ) ;
private :
CargoDataEntry ( StationID st , uint c , CargoDataEntry * p ) ;
CargoDataEntry ( CargoID car , uint c , CargoDataEntry * p ) ;
CargoDataEntry ( StationID st ) ;
CargoDataEntry ( CargoID car ) ;
CargoDataEntry * Retrieve ( CargoDataSet : : iterator i ) const ;
template < class Tid >
CargoDataEntry * InsertOrRetrieve ( Tid s ) ;
void Remove ( CargoDataEntry * comp ) ;
void IncrementSize ( ) ;
CargoDataEntry * parent ; ///< the parent of this entry.
const union {
StationID station ; ///< ID of the station this entry is associated with.
struct {
CargoID cargo ; ///< ID of the cargo this entry is associated with.
bool transfers ; ///< If there are transfers for this cargo.
} ;
} ;
uint num_children ; ///< the number of subentries belonging to this entry.
uint count ; ///< sum of counts of all children or amount of cargo for this entry.
CargoDataSet * children ; ///< the children of this entry.
} ;
CargoDataEntry : : CargoDataEntry ( ) :
parent ( NULL ) ,
station ( INVALID_STATION ) ,
num_children ( 0 ) ,
count ( 0 ) ,
children ( new CargoDataSet ( CargoSorter ( ST_CARGO_ID ) ) )
{ }
CargoDataEntry : : CargoDataEntry ( CargoID cargo , uint count , CargoDataEntry * parent ) :
parent ( parent ) ,
cargo ( cargo ) ,
num_children ( 0 ) ,
count ( count ) ,
children ( new CargoDataSet )
{ }
CargoDataEntry : : CargoDataEntry ( StationID station , uint count , CargoDataEntry * parent ) :
parent ( parent ) ,
station ( station ) ,
num_children ( 0 ) ,
count ( count ) ,
children ( new CargoDataSet )
{ }
CargoDataEntry : : CargoDataEntry ( StationID station ) :
parent ( NULL ) ,
station ( station ) ,
num_children ( 0 ) ,
count ( 0 ) ,
children ( NULL )
{ }
CargoDataEntry : : CargoDataEntry ( CargoID cargo ) :
parent ( NULL ) ,
cargo ( cargo ) ,
num_children ( 0 ) ,
count ( 0 ) ,
children ( NULL )
{ }
CargoDataEntry : : ~ CargoDataEntry ( )
{
this - > Clear ( ) ;
delete this - > children ;
}
/**
* Delete all subentries , reset count and num_children and adapt parent ' s count .
*/
void CargoDataEntry : : Clear ( )
{
if ( this - > children ! = NULL ) {
for ( CargoDataSet : : iterator i = this - > children - > begin ( ) ; i ! = this - > children - > end ( ) ; + + i ) {
assert ( * i ! = this ) ;
delete * i ;
}
this - > children - > clear ( ) ;
}
if ( this - > parent ! = NULL ) this - > parent - > count - = this - > count ;
this - > count = 0 ;
this - > num_children = 0 ;
}
/**
* Remove a subentry from this one and delete it .
* @ param child the entry to be removed . This may also be a synthetic entry
* which only contains the ID of the entry to be removed . In this case child is
* not deleted .
*/
void CargoDataEntry : : Remove ( CargoDataEntry * child )
{
CargoDataSet : : iterator i = this - > children - > find ( child ) ;
if ( i ! = this - > children - > end ( ) ) {
delete * i ;
this - > children - > erase ( i ) ;
}
}
/**
* Retrieve a subentry or insert it if it doesn ' t exist , yet .
* @ tparam ID type of ID : either StationID or CargoID
* @ param child_id ID of the child to be inserted or retrieved .
* @ return the new or retrieved subentry
*/
template < class Tid >
CargoDataEntry * CargoDataEntry : : InsertOrRetrieve ( Tid child_id )
{
CargoDataEntry tmp ( child_id ) ;
CargoDataSet : : iterator i = this - > children - > find ( & tmp ) ;
if ( i = = this - > children - > end ( ) ) {
IncrementSize ( ) ;
return * ( this - > children - > insert ( new CargoDataEntry ( child_id , 0 , this ) ) . first ) ;
} else {
CargoDataEntry * ret = * i ;
assert ( this - > children - > value_comp ( ) . GetSortType ( ) ! = ST_COUNT ) ;
return ret ;
}
}
/**
* Update the count for this entry and propagate the change to the parent entry
* if there is one .
* @ param count the amount to be added to this entry
*/
void CargoDataEntry : : Update ( uint count )
{
this - > count + = count ;
if ( this - > parent ! = NULL ) this - > parent - > Update ( count ) ;
}
/**
* Increment
*/
void CargoDataEntry : : IncrementSize ( )
{
+ + this - > num_children ;
if ( this - > parent ! = NULL ) this - > parent - > IncrementSize ( ) ;
}
void CargoDataEntry : : Resort ( CargoSortType type , SortOrder order )
{
CargoDataSet * new_subs = new CargoDataSet ( this - > children - > begin ( ) , this - > children - > end ( ) , CargoSorter ( type , order ) ) ;
delete this - > children ;
this - > children = new_subs ;
}
CargoDataEntry * CargoDataEntry : : Retrieve ( CargoDataSet : : iterator i ) const
{
if ( i = = this - > children - > end ( ) ) {
return NULL ;
} else {
assert ( this - > children - > value_comp ( ) . GetSortType ( ) ! = ST_COUNT ) ;
return * i ;
}
}
bool CargoSorter : : operator ( ) ( const CargoDataEntry * cd1 , const CargoDataEntry * cd2 ) const
{
switch ( this - > type ) {
case ST_STATION_ID :
return this - > SortId < StationID > ( cd1 - > GetStation ( ) , cd2 - > GetStation ( ) ) ;
case ST_CARGO_ID :
return this - > SortId < CargoID > ( cd1 - > GetCargo ( ) , cd2 - > GetCargo ( ) ) ;
case ST_COUNT :
return this - > SortCount ( cd1 , cd2 ) ;
case ST_STATION_STRING :
return this - > SortStation ( cd1 - > GetStation ( ) , cd2 - > GetStation ( ) ) ;
default :
NOT_REACHED ( ) ;
}
}
template < class Tid >
bool CargoSorter : : SortId ( Tid st1 , Tid st2 ) const
{
return ( this - > order = = SO_ASCENDING ) ? st1 < st2 : st2 < st1 ;
}
bool CargoSorter : : SortCount ( const CargoDataEntry * cd1 , const CargoDataEntry * cd2 ) const
{
uint c1 = cd1 - > GetCount ( ) ;
uint c2 = cd2 - > GetCount ( ) ;
if ( c1 = = c2 ) {
return this - > SortStation ( cd1 - > GetStation ( ) , cd2 - > GetStation ( ) ) ;
} else if ( this - > order = = SO_ASCENDING ) {
return c1 < c2 ;
} else {
return c2 < c1 ;
}
}
bool CargoSorter : : SortStation ( StationID st1 , StationID st2 ) const
{
static char buf1 [ MAX_LENGTH_STATION_NAME_CHARS ] ;
static char buf2 [ MAX_LENGTH_STATION_NAME_CHARS ] ;
if ( ! Station : : IsValidID ( st1 ) ) {
return Station : : IsValidID ( st2 ) ? this - > order = = SO_ASCENDING : this - > SortId ( st1 , st2 ) ;
} else if ( ! Station : : IsValidID ( st2 ) ) {
return order = = SO_DESCENDING ;
}
SetDParam ( 0 , st1 ) ;
GetString ( buf1 , STR_STATION_NAME , lastof ( buf1 ) ) ;
SetDParam ( 0 , st2 ) ;
GetString ( buf2 , STR_STATION_NAME , lastof ( buf2 ) ) ;
2014-11-18 20:12:42 +00:00
int res = strnatcmp ( buf1 , buf2 ) ; // Sort by name (natural sorting).
2013-06-09 13:08:52 +00:00
if ( res = = 0 ) {
return this - > SortId ( st1 , st2 ) ;
} else {
return ( this - > order = = SO_ASCENDING ) ? res < 0 : res > 0 ;
}
}
2008-01-26 22:15:39 +00:00
2007-12-05 17:08:10 +00:00
/**
2008-05-11 17:24:52 +00:00
* The StationView window
2007-12-05 17:08:10 +00:00
*/
2008-05-11 17:24:52 +00:00
struct StationViewWindow : public Window {
2013-06-09 13:08:52 +00:00
/**
* A row being displayed in the cargo view ( as opposed to being " hidden " behind a plus sign ) .
*/
struct RowDisplay {
RowDisplay ( CargoDataEntry * f , StationID n ) : filter ( f ) , next_station ( n ) { }
RowDisplay ( CargoDataEntry * f , CargoID n ) : filter ( f ) , next_cargo ( n ) { }
/**
* Parent of the cargo entry belonging to the row .
*/
CargoDataEntry * filter ;
union {
/**
* ID of the station belonging to the entry actually displayed if it ' s to / from / via .
*/
StationID next_station ;
/**
* ID of the cargo belonging to the entry actually displayed if it ' s cargo .
*/
CargoID next_cargo ;
} ;
} ;
typedef std : : vector < RowDisplay > CargoDataVector ;
static const int NUM_COLUMNS = 4 ; ///< Number of "columns" in the cargo view: cargo, from, via, to
/**
* Type of data invalidation .
*/
enum Invalidation {
INV_FLOWS = 0x100 , ///< The planned flows have been recalculated and everything has to be updated.
INV_CARGO = 0x200 ///< Some cargo has been added or removed.
} ;
/**
* Type of grouping used in each of the " columns " .
*/
enum Grouping {
GR_SOURCE , ///< Group by source of cargo ("from").
GR_NEXT , ///< Group by next station ("via").
GR_DESTINATION , ///< Group by estimated final destination ("to").
GR_CARGO , ///< Group by cargo type.
} ;
/**
* Display mode of the cargo view .
*/
enum Mode {
MODE_WAITING , ///< Show cargo waiting at the station.
MODE_PLANNED ///< Show cargo planned to pass through the station.
} ;
2009-11-18 20:22:39 +00:00
uint expand_shrink_width ; ///< The width allocated to the expand/shrink 'button'
2010-02-13 18:39:00 +00:00
int rating_lines ; ///< Number of lines in the cargo ratings view.
int accepts_lines ; ///< Number of lines in the accepted cargo view.
2010-08-12 08:37:01 +00:00
Scrollbar * vscroll ;
2008-05-11 17:24:52 +00:00
2011-12-16 18:14:11 +00:00
/** Height of the #WID_SV_ACCEPT_RATING_LIST widget for different views. */
2009-11-08 15:26:20 +00:00
enum AcceptListHeight {
2009-11-16 20:40:35 +00:00
ALH_RATING = 13 , ///< Height of the cargo ratings view.
ALH_ACCEPTS = 3 , ///< Height of the accepted cargo view.
2009-11-08 15:26:20 +00:00
} ;
2013-06-09 13:08:52 +00:00
static const StringID _sort_names [ ] ; ///< Names of the sorting options in the dropdown.
static const StringID _group_names [ ] ; ///< Names of the grouping options in the dropdown.
/**
* Sort types of the different ' columns ' .
* In fact only ST_COUNT and ST_AS_GROUPING are active and you can only
* sort all the columns in the same way . The other options haven ' t been
* included in the GUI due to lack of space .
*/
CargoSortType sortings [ NUM_COLUMNS ] ;
/** Sort order (ascending/descending) for the 'columns'. */
SortOrder sort_orders [ NUM_COLUMNS ] ;
int scroll_to_row ; ///< If set, scroll the main viewport to the station pointed to by this row.
int grouping_index ; ///< Currently selected entry in the grouping drop down.
Mode current_mode ; ///< Currently selected display mode of cargo view.
Grouping groupings [ NUM_COLUMNS ] ; ///< Grouping modes for the different columns.
CargoDataEntry expanded_rows ; ///< Parent entry of currently expanded rows.
CargoDataEntry cached_destinations ; ///< Cache for the flows passing through this station.
CargoDataVector displayed_rows ; ///< Parent entry of currently displayed rows (including collapsed ones).
StationViewWindow ( WindowDesc * desc , WindowNumber window_number ) : Window ( desc ) ,
scroll_to_row ( INT_MAX ) , grouping_index ( 0 )
2008-05-11 17:24:52 +00:00
{
2010-02-13 18:39:00 +00:00
this - > rating_lines = ALH_RATING ;
this - > accepts_lines = ALH_ACCEPTS ;
2013-05-26 19:23:42 +00:00
this - > CreateNestedTree ( ) ;
2011-12-16 18:14:11 +00:00
this - > vscroll = this - > GetScrollbar ( WID_SV_SCROLLBAR ) ;
/* Nested widget tree creation is done in two steps to ensure that this->GetWidget<NWidgetCore>(WID_SV_ACCEPTS_RATINGS) exists in UpdateWidgetSize(). */
2013-05-26 19:23:42 +00:00
this - > FinishInitNested ( window_number ) ;
2009-11-08 15:26:20 +00:00
2013-06-09 13:08:52 +00:00
this - > groupings [ 0 ] = GR_CARGO ;
this - > sortings [ 0 ] = ST_AS_GROUPING ;
this - > SelectGroupBy ( _settings_client . gui . station_gui_group_order ) ;
this - > SelectSortBy ( _settings_client . gui . station_gui_sort_by ) ;
this - > sort_orders [ 0 ] = SO_ASCENDING ;
this - > SelectSortOrder ( ( SortOrder ) _settings_client . gui . station_gui_sort_order ) ;
2014-10-21 19:16:47 +00:00
this - > owner = Station : : Get ( window_number ) - > owner ;
2008-05-11 17:24:52 +00:00
}
~ StationViewWindow ( )
{
2014-10-21 19:16:47 +00:00
DeleteWindowById ( WC_TRAINS_LIST , VehicleListIdentifier ( VL_STATION_LIST , VEH_TRAIN , this - > owner , this - > window_number ) . Pack ( ) , false ) ;
DeleteWindowById ( WC_ROADVEH_LIST , VehicleListIdentifier ( VL_STATION_LIST , VEH_ROAD , this - > owner , this - > window_number ) . Pack ( ) , false ) ;
DeleteWindowById ( WC_SHIPS_LIST , VehicleListIdentifier ( VL_STATION_LIST , VEH_SHIP , this - > owner , this - > window_number ) . Pack ( ) , false ) ;
DeleteWindowById ( WC_AIRCRAFT_LIST , VehicleListIdentifier ( VL_STATION_LIST , VEH_AIRCRAFT , this - > owner , this - > window_number ) . Pack ( ) , false ) ;
2008-05-11 17:24:52 +00:00
}
2013-06-09 13:08:52 +00:00
/**
* Show a certain cargo entry characterized by source / next / dest station , cargo ID and amount of cargo at the
* right place in the cargo view . I . e . update as many rows as are expanded following that characterization .
* @ param data Root entry of the tree .
* @ param cargo Cargo ID of the entry to be shown .
* @ param source Source station of the entry to be shown .
* @ param next Next station the cargo to be shown will visit .
* @ param dest Final destination of the cargo to be shown .
* @ param count Amount of cargo to be shown .
*/
void ShowCargo ( CargoDataEntry * data , CargoID cargo , StationID source , StationID next , StationID dest , uint count )
{
if ( count = = 0 ) return ;
bool auto_distributed = _settings_game . linkgraph . GetDistributionType ( cargo ) ! = DT_MANUAL ;
const CargoDataEntry * expand = & this - > expanded_rows ;
for ( int i = 0 ; i < NUM_COLUMNS & & expand ! = NULL ; + + i ) {
switch ( groupings [ i ] ) {
case GR_CARGO :
assert ( i = = 0 ) ;
data = data - > InsertOrRetrieve ( cargo ) ;
2013-06-22 07:44:59 +00:00
data - > SetTransfers ( source ! = this - > window_number ) ;
2013-06-09 13:08:52 +00:00
expand = expand - > Retrieve ( cargo ) ;
break ;
case GR_SOURCE :
if ( auto_distributed | | source ! = this - > window_number ) {
data = data - > InsertOrRetrieve ( source ) ;
expand = expand - > Retrieve ( source ) ;
}
break ;
case GR_NEXT :
if ( auto_distributed ) {
data = data - > InsertOrRetrieve ( next ) ;
expand = expand - > Retrieve ( next ) ;
}
break ;
case GR_DESTINATION :
if ( auto_distributed ) {
data = data - > InsertOrRetrieve ( dest ) ;
expand = expand - > Retrieve ( dest ) ;
}
break ;
}
}
data - > Update ( count ) ;
}
2009-11-22 18:28:14 +00:00
virtual void UpdateWidgetSize ( int widget , Dimension * size , const Dimension & padding , Dimension * fill , Dimension * resize )
2009-11-08 15:26:20 +00:00
{
switch ( widget ) {
2011-12-16 18:14:11 +00:00
case WID_SV_WAITING :
2009-11-08 15:26:20 +00:00
resize - > height = FONT_HEIGHT_NORMAL ;
2013-06-09 13:08:52 +00:00
size - > height = WD_FRAMERECT_TOP + 4 * resize - > height + WD_FRAMERECT_BOTTOM ;
2009-11-18 20:22:39 +00:00
this - > expand_shrink_width = max ( GetStringBoundingBox ( " - " ) . width , GetStringBoundingBox ( " + " ) . width ) + WD_FRAMERECT_LEFT + WD_FRAMERECT_RIGHT ;
2009-11-08 15:26:20 +00:00
break ;
2011-12-16 18:14:11 +00:00
case WID_SV_ACCEPT_RATING_LIST :
size - > height = WD_FRAMERECT_TOP + ( ( this - > GetWidget < NWidgetCore > ( WID_SV_ACCEPTS_RATINGS ) - > widget_data = = STR_STATION_VIEW_RATINGS_BUTTON ) ? this - > accepts_lines : this - > rating_lines ) * FONT_HEIGHT_NORMAL + WD_FRAMERECT_BOTTOM ;
2009-11-08 15:26:20 +00:00
break ;
2012-04-17 19:43:18 +00:00
case WID_SV_CLOSE_AIRPORT :
if ( ! ( Station : : Get ( this - > window_number ) - > facilities & FACIL_AIRPORT ) ) {
/* Hide 'Close Airport' button if no airport present. */
size - > width = 0 ;
resize - > width = 0 ;
fill - > width = 0 ;
}
break ;
2009-11-08 15:26:20 +00:00
}
}
2008-05-11 17:24:52 +00:00
virtual void OnPaint ( )
{
2013-06-09 13:08:52 +00:00
const Station * st = Station : : Get ( this - > window_number ) ;
CargoDataEntry cargo ;
BuildCargoList ( & cargo , st ) ;
2009-11-08 12:45:16 +00:00
2013-06-09 13:08:52 +00:00
this - > vscroll - > SetCount ( cargo . GetNumChildren ( ) ) ; // update scrollbar
2009-11-08 12:45:16 +00:00
/* disable some buttons */
2011-12-16 18:14:11 +00:00
this - > SetWidgetDisabledState ( WID_SV_RENAME , st - > owner ! = _local_company ) ;
this - > SetWidgetDisabledState ( WID_SV_TRAINS , ! ( st - > facilities & FACIL_TRAIN ) ) ;
this - > SetWidgetDisabledState ( WID_SV_ROADVEHS , ! ( st - > facilities & FACIL_TRUCK_STOP ) & & ! ( st - > facilities & FACIL_BUS_STOP ) ) ;
this - > SetWidgetDisabledState ( WID_SV_SHIPS , ! ( st - > facilities & FACIL_DOCK ) ) ;
this - > SetWidgetDisabledState ( WID_SV_PLANES , ! ( st - > facilities & FACIL_AIRPORT ) ) ;
2012-11-12 18:09:33 +00:00
this - > SetWidgetDisabledState ( WID_SV_CLOSE_AIRPORT , ! ( st - > facilities & FACIL_AIRPORT ) | | st - > owner ! = _local_company | | st - > owner = = OWNER_NONE ) ; // Also consider SE, where _local_company == OWNER_NONE
2012-04-17 19:43:18 +00:00
this - > SetWidgetLoweredState ( WID_SV_CLOSE_AIRPORT , ( st - > facilities & FACIL_AIRPORT ) & & ( st - > airport . flags & AIRPORT_CLOSED_block ) ! = 0 ) ;
2009-11-08 12:45:16 +00:00
this - > DrawWidgets ( ) ;
2010-02-14 15:35:44 +00:00
if ( ! this - > IsShaded ( ) ) {
/* Draw 'accepted cargo' or 'cargo ratings'. */
2011-12-16 18:14:11 +00:00
const NWidgetBase * wid = this - > GetWidget < NWidgetBase > ( WID_SV_ACCEPT_RATING_LIST ) ;
2015-08-10 20:24:13 +00:00
const Rect r = { ( int ) wid - > pos_x , ( int ) wid - > pos_y , ( int ) ( wid - > pos_x + wid - > current_x - 1 ) , ( int ) ( wid - > pos_y + wid - > current_y - 1 ) } ;
2011-12-16 18:14:11 +00:00
if ( this - > GetWidget < NWidgetCore > ( WID_SV_ACCEPTS_RATINGS ) - > widget_data = = STR_STATION_VIEW_RATINGS_BUTTON ) {
2010-02-14 15:35:44 +00:00
int lines = this - > DrawAcceptedCargo ( r ) ;
if ( lines > this - > accepts_lines ) { // Resize the widget, and perform re-initialization of the window.
this - > accepts_lines = lines ;
this - > ReInit ( ) ;
return ;
}
} else {
int lines = this - > DrawCargoRatings ( r ) ;
if ( lines > this - > rating_lines ) { // Resize the widget, and perform re-initialization of the window.
this - > rating_lines = lines ;
this - > ReInit ( ) ;
return ;
}
2010-02-13 18:44:03 +00:00
}
2010-02-13 18:41:31 +00:00
2013-06-09 13:08:52 +00:00
/* Draw arrow pointing up/down for ascending/descending sorting */
this - > DrawSortButtonState ( WID_SV_SORT_ORDER , sort_orders [ 1 ] = = SO_ASCENDING ? SBS_UP : SBS_DOWN ) ;
int pos = this - > vscroll - > GetPosition ( ) ;
int maxrows = this - > vscroll - > GetCapacity ( ) ;
displayed_rows . clear ( ) ;
2010-02-14 15:35:44 +00:00
/* Draw waiting cargo. */
2011-12-16 18:14:11 +00:00
NWidgetBase * nwi = this - > GetWidget < NWidgetBase > ( WID_SV_WAITING ) ;
2015-08-10 20:24:13 +00:00
Rect waiting_rect = { ( int ) nwi - > pos_x , ( int ) nwi - > pos_y , ( int ) ( nwi - > pos_x + nwi - > current_x - 1 ) , ( int ) ( nwi - > pos_y + nwi - > current_y - 1 ) } ;
2013-06-09 13:08:52 +00:00
this - > DrawEntries ( & cargo , waiting_rect , pos , maxrows , 0 ) ;
scroll_to_row = INT_MAX ;
2010-02-13 18:41:31 +00:00
}
2009-11-08 15:26:20 +00:00
}
virtual void SetStringParameters ( int widget ) const
{
2013-06-09 13:08:52 +00:00
const Station * st = Station : : Get ( this - > window_number ) ;
SetDParam ( 0 , st - > index ) ;
SetDParam ( 1 , st - > facilities ) ;
2009-11-08 12:45:16 +00:00
}
2010-08-01 19:22:34 +00:00
/**
2013-06-09 13:08:52 +00:00
* Rebuild the cache for estimated destinations which is used to quickly show the " destination " entries
* even if we actually don ' t know the destination of a certain packet from just looking at it .
* @ param i Cargo to recalculate the cache for .
2009-11-08 12:45:16 +00:00
*/
2013-06-09 13:08:52 +00:00
void RecalcDestinations ( CargoID i )
2009-11-08 12:45:16 +00:00
{
2013-06-09 13:08:52 +00:00
const Station * st = Station : : Get ( this - > window_number ) ;
CargoDataEntry * cargo_entry = cached_destinations . InsertOrRetrieve ( i ) ;
cargo_entry - > Clear ( ) ;
const FlowStatMap & flows = st - > goods [ i ] . flows ;
for ( FlowStatMap : : const_iterator it = flows . begin ( ) ; it ! = flows . end ( ) ; + + it ) {
StationID from = it - > first ;
CargoDataEntry * source_entry = cargo_entry - > InsertOrRetrieve ( from ) ;
const FlowStat : : SharesMap * shares = it - > second . GetShares ( ) ;
uint32 prev_count = 0 ;
for ( FlowStat : : SharesMap : : const_iterator flow_it = shares - > begin ( ) ; flow_it ! = shares - > end ( ) ; + + flow_it ) {
StationID via = flow_it - > second ;
CargoDataEntry * via_entry = source_entry - > InsertOrRetrieve ( via ) ;
if ( via = = this - > window_number ) {
via_entry - > InsertOrRetrieve ( via ) - > Update ( flow_it - > first - prev_count ) ;
} else {
EstimateDestinations ( i , from , via , flow_it - > first - prev_count , via_entry ) ;
}
prev_count = flow_it - > first ;
}
}
}
2009-11-08 12:45:16 +00:00
2013-06-09 13:08:52 +00:00
/**
* Estimate the amounts of cargo per final destination for a given cargo , source station and next hop and
* save the result as children of the given CargoDataEntry .
* @ param cargo ID of the cargo to estimate destinations for .
* @ param source Source station of the given batch of cargo .
* @ param next Intermediate hop to start the calculation at ( " next hop " ) .
* @ param count Size of the batch of cargo .
* @ param dest CargoDataEntry to save the results in .
*/
void EstimateDestinations ( CargoID cargo , StationID source , StationID next , uint count , CargoDataEntry * dest )
{
if ( Station : : IsValidID ( next ) & & Station : : IsValidID ( source ) ) {
CargoDataEntry tmp ;
const FlowStatMap & flowmap = Station : : Get ( next ) - > goods [ cargo ] . flows ;
FlowStatMap : : const_iterator map_it = flowmap . find ( source ) ;
if ( map_it ! = flowmap . end ( ) ) {
const FlowStat : : SharesMap * shares = map_it - > second . GetShares ( ) ;
uint32 prev_count = 0 ;
for ( FlowStat : : SharesMap : : const_iterator i = shares - > begin ( ) ; i ! = shares - > end ( ) ; + + i ) {
tmp . InsertOrRetrieve ( i - > second ) - > Update ( i - > first - prev_count ) ;
prev_count = i - > first ;
}
}
2008-05-11 17:24:52 +00:00
2013-06-09 13:08:52 +00:00
if ( tmp . GetCount ( ) = = 0 ) {
dest - > InsertOrRetrieve ( INVALID_STATION ) - > Update ( count ) ;
2008-05-11 17:24:52 +00:00
} else {
2013-06-09 13:08:52 +00:00
uint sum_estimated = 0 ;
while ( sum_estimated < count ) {
for ( CargoDataSet : : iterator i = tmp . Begin ( ) ; i ! = tmp . End ( ) & & sum_estimated < count ; + + i ) {
CargoDataEntry * child = * i ;
uint estimate = DivideApprox ( child - > GetCount ( ) * count , tmp . GetCount ( ) ) ;
if ( estimate = = 0 ) estimate = 1 ;
sum_estimated + = estimate ;
if ( sum_estimated > count ) {
estimate - = sum_estimated - count ;
sum_estimated = count ;
2008-01-26 22:15:39 +00:00
}
2013-06-09 13:08:52 +00:00
if ( estimate > 0 ) {
if ( child - > GetStation ( ) = = next ) {
dest - > InsertOrRetrieve ( next ) - > Update ( estimate ) ;
} else {
EstimateDestinations ( cargo , source , child - > GetStation ( ) , estimate , dest ) ;
}
}
2008-05-11 17:24:52 +00:00
}
2013-06-09 13:08:52 +00:00
2008-01-26 22:15:39 +00:00
}
2013-06-09 13:08:52 +00:00
}
} else {
dest - > InsertOrRetrieve ( INVALID_STATION ) - > Update ( count ) ;
}
}
/**
* Build up the cargo view for PLANNED mode and a specific cargo .
* @ param i Cargo to show .
* @ param flows The current station ' s flows for that cargo .
* @ param cargo The CargoDataEntry to save the results in .
*/
void BuildFlowList ( CargoID i , const FlowStatMap & flows , CargoDataEntry * cargo )
{
const CargoDataEntry * source_dest = this - > cached_destinations . Retrieve ( i ) ;
for ( FlowStatMap : : const_iterator it = flows . begin ( ) ; it ! = flows . end ( ) ; + + it ) {
StationID from = it - > first ;
const CargoDataEntry * source_entry = source_dest - > Retrieve ( from ) ;
const FlowStat : : SharesMap * shares = it - > second . GetShares ( ) ;
for ( FlowStat : : SharesMap : : const_iterator flow_it = shares - > begin ( ) ; flow_it ! = shares - > end ( ) ; + + flow_it ) {
const CargoDataEntry * via_entry = source_entry - > Retrieve ( flow_it - > second ) ;
for ( CargoDataSet : : iterator dest_it = via_entry - > Begin ( ) ; dest_it ! = via_entry - > End ( ) ; + + dest_it ) {
CargoDataEntry * dest_entry = * dest_it ;
ShowCargo ( cargo , i , from , flow_it - > second , dest_entry - > GetStation ( ) , dest_entry - > GetCount ( ) ) ;
2013-02-17 14:59:27 +00:00
}
2008-01-26 22:15:39 +00:00
}
2004-08-09 17:04:08 +00:00
}
2009-11-08 12:45:16 +00:00
}
2004-08-09 17:04:08 +00:00
2010-08-01 19:22:34 +00:00
/**
2013-06-09 13:08:52 +00:00
* Build up the cargo view for WAITING mode and a specific cargo .
* @ param i Cargo to show .
* @ param packets The current station ' s cargo list for that cargo .
* @ param cargo The CargoDataEntry to save the result in .
2009-11-08 12:45:16 +00:00
*/
2013-06-09 13:08:52 +00:00
void BuildCargoList ( CargoID i , const StationCargoList & packets , CargoDataEntry * cargo )
2009-11-08 12:45:16 +00:00
{
2013-06-09 13:08:52 +00:00
const CargoDataEntry * source_dest = this - > cached_destinations . Retrieve ( i ) ;
for ( StationCargoList : : ConstIterator it = packets . Packets ( ) - > begin ( ) ; it ! = packets . Packets ( ) - > end ( ) ; it + + ) {
const CargoPacket * cp = * it ;
StationID next = it . GetKey ( ) ;
const CargoDataEntry * source_entry = source_dest - > Retrieve ( cp - > SourceStation ( ) ) ;
if ( source_entry = = NULL ) {
this - > ShowCargo ( cargo , i , cp - > SourceStation ( ) , next , INVALID_STATION , cp - > Count ( ) ) ;
continue ;
}
2004-08-09 17:04:08 +00:00
2013-06-09 13:08:52 +00:00
const CargoDataEntry * via_entry = source_entry - > Retrieve ( next ) ;
if ( via_entry = = NULL ) {
this - > ShowCargo ( cargo , i , cp - > SourceStation ( ) , next , INVALID_STATION , cp - > Count ( ) ) ;
continue ;
}
for ( CargoDataSet : : iterator dest_it = via_entry - > Begin ( ) ; dest_it ! = via_entry - > End ( ) ; + + dest_it ) {
CargoDataEntry * dest_entry = * dest_it ;
uint val = DivideApprox ( cp - > Count ( ) * dest_entry - > GetCount ( ) , via_entry - > GetCount ( ) ) ;
this - > ShowCargo ( cargo , i , cp - > SourceStation ( ) , next , dest_entry - > GetStation ( ) , val ) ;
}
}
this - > ShowCargo ( cargo , i , NEW_STATION , NEW_STATION , NEW_STATION , packets . ReservedCount ( ) ) ;
}
/**
* Build up the cargo view for all cargoes .
* @ param cargo The root cargo entry to save all results in .
* @ param st The station to calculate the cargo view from .
*/
void BuildCargoList ( CargoDataEntry * cargo , const Station * st )
{
for ( CargoID i = 0 ; i < NUM_CARGO ; i + + ) {
if ( this - > cached_destinations . Retrieve ( i ) = = NULL ) {
this - > RecalcDestinations ( i ) ;
}
if ( this - > current_mode = = MODE_WAITING ) {
this - > BuildCargoList ( i , st - > goods [ i ] . cargo , cargo ) ;
} else {
this - > BuildFlowList ( i , st - > goods [ i ] . flows , cargo ) ;
2008-05-11 17:24:52 +00:00
}
2005-11-14 19:48:04 +00:00
}
2013-06-09 13:08:52 +00:00
}
2004-08-09 17:04:08 +00:00
2013-06-09 13:08:52 +00:00
/**
* Mark a specific row , characterized by its CargoDataEntry , as expanded .
* @ param data The row to be marked as expanded .
*/
void SetDisplayedRow ( const CargoDataEntry * data )
{
std : : list < StationID > stations ;
const CargoDataEntry * parent = data - > GetParent ( ) ;
if ( parent - > GetParent ( ) = = NULL ) {
this - > displayed_rows . push_back ( RowDisplay ( & this - > expanded_rows , data - > GetCargo ( ) ) ) ;
return ;
}
StationID next = data - > GetStation ( ) ;
while ( parent - > GetParent ( ) - > GetParent ( ) ! = NULL ) {
stations . push_back ( parent - > GetStation ( ) ) ;
parent = parent - > GetParent ( ) ;
}
CargoID cargo = parent - > GetCargo ( ) ;
CargoDataEntry * filter = this - > expanded_rows . Retrieve ( cargo ) ;
while ( ! stations . empty ( ) ) {
filter = filter - > Retrieve ( stations . back ( ) ) ;
stations . pop_back ( ) ;
}
this - > displayed_rows . push_back ( RowDisplay ( filter , next ) ) ;
}
/**
* Select the correct string for an entry referring to the specified station .
* @ param station Station the entry is showing cargo for .
* @ param here String to be shown if the entry refers to the same station as this station GUI belongs to .
* @ param other_station String to be shown if the entry refers to a specific other station .
* @ param any String to be shown if the entry refers to " any station " .
* @ return One of the three given strings or STR_STATION_VIEW_RESERVED , depending on what station the entry refers to .
*/
StringID GetEntryString ( StationID station , StringID here , StringID other_station , StringID any )
{
if ( station = = this - > window_number ) {
return here ;
} else if ( station = = INVALID_STATION ) {
return any ;
} else if ( station = = NEW_STATION ) {
return STR_STATION_VIEW_RESERVED ;
} else {
SetDParam ( 2 , station ) ;
return other_station ;
}
}
/**
* Determine if we need to show the special " non-stop " string .
* @ param cd Entry we are going to show .
* @ param station Station the entry refers to .
* @ param column The " column " the entry will be shown in .
* @ return either STR_STATION_VIEW_VIA or STR_STATION_VIEW_NONSTOP .
*/
StringID SearchNonStop ( CargoDataEntry * cd , StationID station , int column )
{
CargoDataEntry * parent = cd - > GetParent ( ) ;
for ( int i = column - 1 ; i > 0 ; - - i ) {
if ( this - > groupings [ i ] = = GR_DESTINATION ) {
if ( parent - > GetStation ( ) = = station ) {
return STR_STATION_VIEW_NONSTOP ;
} else {
return STR_STATION_VIEW_VIA ;
}
}
parent = parent - > GetParent ( ) ;
}
if ( this - > groupings [ column + 1 ] = = GR_DESTINATION ) {
CargoDataSet : : iterator begin = cd - > Begin ( ) ;
CargoDataSet : : iterator end = cd - > End ( ) ;
if ( begin ! = end & & + + ( cd - > Begin ( ) ) = = end & & ( * ( begin ) ) - > GetStation ( ) = = station ) {
return STR_STATION_VIEW_NONSTOP ;
} else {
return STR_STATION_VIEW_VIA ;
}
}
return STR_STATION_VIEW_VIA ;
}
/**
* Draw the given cargo entries in the station GUI .
* @ param entry Root entry for all cargo to be drawn .
* @ param r Screen rectangle to draw into .
* @ param pos Current row to be drawn to ( counted down from 0 to - maxrows , same as vscroll - > GetPosition ( ) ) .
* @ param maxrows Maximum row to be drawn .
* @ param column Current " column " being drawn .
* @ param cargo Current cargo being drawn ( if cargo column has been passed ) .
* @ return row ( in " pos " counting ) after the one we have last drawn to .
*/
int DrawEntries ( CargoDataEntry * entry , Rect & r , int pos , int maxrows , int column , CargoID cargo = CT_INVALID )
{
if ( this - > sortings [ column ] = = ST_AS_GROUPING ) {
if ( this - > groupings [ column ] ! = GR_CARGO ) {
entry - > Resort ( ST_STATION_STRING , this - > sort_orders [ column ] ) ;
}
} else {
entry - > Resort ( ST_COUNT , this - > sort_orders [ column ] ) ;
}
for ( CargoDataSet : : iterator i = entry - > Begin ( ) ; i ! = entry - > End ( ) ; + + i ) {
CargoDataEntry * cd = * i ;
Grouping grouping = this - > groupings [ column ] ;
if ( grouping = = GR_CARGO ) cargo = cd - > GetCargo ( ) ;
bool auto_distributed = _settings_game . linkgraph . GetDistributionType ( cargo ) ! = DT_MANUAL ;
if ( pos > - maxrows & & pos < = 0 ) {
StringID str = STR_EMPTY ;
int y = r . top + WD_FRAMERECT_TOP - pos * FONT_HEIGHT_NORMAL ;
SetDParam ( 0 , cargo ) ;
SetDParam ( 1 , cd - > GetCount ( ) ) ;
if ( this - > groupings [ column ] = = GR_CARGO ) {
str = STR_STATION_VIEW_WAITING_CARGO ;
DrawCargoIcons ( cd - > GetCargo ( ) , cd - > GetCount ( ) , r . left + WD_FRAMERECT_LEFT + this - > expand_shrink_width , r . right - WD_FRAMERECT_RIGHT - this - > expand_shrink_width , y ) ;
2008-03-27 15:51:11 +00:00
} else {
2013-06-09 13:08:52 +00:00
if ( ! auto_distributed ) grouping = GR_SOURCE ;
StationID station = cd - > GetStation ( ) ;
switch ( grouping ) {
case GR_SOURCE :
str = this - > GetEntryString ( station , STR_STATION_VIEW_FROM_HERE , STR_STATION_VIEW_FROM , STR_STATION_VIEW_FROM_ANY ) ;
break ;
case GR_NEXT :
str = this - > GetEntryString ( station , STR_STATION_VIEW_VIA_HERE , STR_STATION_VIEW_VIA , STR_STATION_VIEW_VIA_ANY ) ;
if ( str = = STR_STATION_VIEW_VIA ) str = this - > SearchNonStop ( cd , station , column ) ;
break ;
case GR_DESTINATION :
str = this - > GetEntryString ( station , STR_STATION_VIEW_TO_HERE , STR_STATION_VIEW_TO , STR_STATION_VIEW_TO_ANY ) ;
break ;
default :
NOT_REACHED ( ) ;
}
if ( pos = = - this - > scroll_to_row & & Station : : IsValidID ( station ) ) {
ScrollMainWindowToTile ( Station : : Get ( station ) - > xy ) ;
}
2008-03-27 15:51:11 +00:00
}
2004-08-09 17:04:08 +00:00
2013-06-09 13:08:52 +00:00
bool rtl = _current_text_dir = = TD_RTL ;
int text_left = rtl ? r . left + this - > expand_shrink_width : r . left + WD_FRAMERECT_LEFT + column * this - > expand_shrink_width ;
int text_right = rtl ? r . right - WD_FRAMERECT_LEFT - column * this - > expand_shrink_width : r . right - this - > expand_shrink_width ;
int shrink_left = rtl ? r . left + WD_FRAMERECT_LEFT : r . right - this - > expand_shrink_width + WD_FRAMERECT_LEFT ;
int shrink_right = rtl ? r . left + this - > expand_shrink_width - WD_FRAMERECT_RIGHT : r . right - WD_FRAMERECT_RIGHT ;
DrawString ( text_left , text_right , y , str ) ;
if ( column < NUM_COLUMNS - 1 ) {
const char * sym = NULL ;
if ( cd - > GetNumChildren ( ) > 0 ) {
sym = " - " ;
} else if ( auto_distributed & & str ! = STR_STATION_VIEW_RESERVED ) {
sym = " + " ;
} else {
/* Only draw '+' if there is something to be shown. */
const StationCargoList & list = Station : : Get ( this - > window_number ) - > goods [ cargo ] . cargo ;
2013-06-22 07:44:59 +00:00
if ( grouping = = GR_CARGO & & ( list . ReservedCount ( ) > 0 | | cd - > HasTransfers ( ) ) ) {
2013-06-09 13:08:52 +00:00
sym = " + " ;
}
}
if ( sym ) DrawString ( shrink_left , shrink_right , y , sym , TC_YELLOW ) ;
}
this - > SetDisplayedRow ( cd ) ;
}
- - pos ;
if ( auto_distributed | | column = = 0 ) {
pos = this - > DrawEntries ( cd , r , pos , maxrows , column + 1 , cargo ) ;
2008-05-11 17:24:52 +00:00
}
2004-08-09 17:04:08 +00:00
}
2013-06-09 13:08:52 +00:00
return pos ;
2009-11-08 12:45:16 +00:00
}
2004-09-10 19:02:27 +00:00
2010-08-01 19:22:34 +00:00
/**
2011-12-16 18:14:11 +00:00
* Draw accepted cargo in the # WID_SV_ACCEPT_RATING_LIST widget .
2009-11-08 12:45:16 +00:00
* @ param r Rectangle of the widget .
2010-02-13 18:44:03 +00:00
* @ return Number of lines needed for drawing the accepted cargo .
2009-11-08 12:45:16 +00:00
*/
2010-02-13 18:44:03 +00:00
int DrawAcceptedCargo ( const Rect & r ) const
2009-11-08 12:45:16 +00:00
{
const Station * st = Station : : Get ( this - > window_number ) ;
2009-12-19 16:02:29 +00:00
uint32 cargo_mask = 0 ;
2009-11-08 12:45:16 +00:00
for ( CargoID i = 0 ; i < NUM_CARGO ; i + + ) {
2014-05-11 18:02:11 +00:00
if ( HasBit ( st - > goods [ i ] . status , GoodsEntry : : GES_ACCEPTANCE ) ) SetBit ( cargo_mask , i ) ;
2009-11-08 12:45:16 +00:00
}
2012-03-10 19:18:04 +00:00
SetDParam ( 0 , cargo_mask ) ;
int bottom = DrawStringMultiLine ( r . left + WD_FRAMERECT_LEFT , r . right - WD_FRAMERECT_RIGHT , r . top + WD_FRAMERECT_TOP , INT32_MAX , STR_STATION_VIEW_ACCEPTS_CARGO ) ;
2010-04-18 14:56:05 +00:00
return CeilDiv ( bottom - r . top - WD_FRAMERECT_TOP , FONT_HEIGHT_NORMAL ) ;
2009-11-08 12:45:16 +00:00
}
2008-01-26 22:15:39 +00:00
2010-08-01 19:22:34 +00:00
/**
2011-12-16 18:14:11 +00:00
* Draw cargo ratings in the # WID_SV_ACCEPT_RATING_LIST widget .
2009-11-08 12:45:16 +00:00
* @ param r Rectangle of the widget .
2010-02-13 18:44:03 +00:00
* @ return Number of lines needed for drawing the cargo ratings .
2009-11-08 12:45:16 +00:00
*/
2010-02-13 18:44:03 +00:00
int DrawCargoRatings ( const Rect & r ) const
2009-11-08 12:45:16 +00:00
{
const Station * st = Station : : Get ( this - > window_number ) ;
int y = r . top + WD_FRAMERECT_TOP ;
2004-08-09 17:04:08 +00:00
2012-05-06 11:38:52 +00:00
if ( st - > town - > exclusive_counter > 0 ) {
SetDParam ( 0 , st - > town - > exclusivity ) ;
y = DrawStringMultiLine ( r . left + WD_FRAMERECT_LEFT , r . right - WD_FRAMERECT_RIGHT , y , r . bottom , st - > town - > exclusivity = = st - > owner ? STR_STATIOV_VIEW_EXCLUSIVE_RIGHTS_SELF : STR_STATIOV_VIEW_EXCLUSIVE_RIGHTS_COMPANY ) ;
y + = WD_PAR_VSEP_WIDE ;
}
2013-05-20 19:57:38 +00:00
DrawString ( r . left + WD_FRAMERECT_LEFT , r . right - WD_FRAMERECT_RIGHT , y , STR_STATION_VIEW_SUPPLY_RATINGS_TITLE ) ;
2009-11-08 12:45:16 +00:00
y + = FONT_HEIGHT_NORMAL ;
2007-03-11 22:29:37 +00:00
2009-11-08 12:45:16 +00:00
const CargoSpec * cs ;
2010-04-07 14:17:29 +00:00
FOR_ALL_SORTED_STANDARD_CARGOSPECS ( cs ) {
2009-11-08 12:45:16 +00:00
const GoodsEntry * ge = & st - > goods [ cs - > Index ( ) ] ;
2013-04-06 12:10:16 +00:00
if ( ! ge - > HasRating ( ) ) continue ;
2009-11-08 12:45:16 +00:00
2013-05-20 19:57:38 +00:00
const LinkGraph * lg = LinkGraph : : GetIfValid ( ge - > link_graph ) ;
2009-11-08 12:45:16 +00:00
SetDParam ( 0 , cs - > name ) ;
2013-05-20 19:57:38 +00:00
SetDParam ( 1 , lg ! = NULL ? lg - > Monthly ( ( * lg ) [ ge - > node ] . Supply ( ) ) : 0 ) ;
SetDParam ( 2 , STR_CARGO_RATING_APPALLING + ( ge - > rating > > 5 ) ) ;
SetDParam ( 3 , ToPercent8 ( ge - > rating ) ) ;
DrawString ( r . left + WD_FRAMERECT_LEFT + 6 , r . right - WD_FRAMERECT_RIGHT - 6 , y , STR_STATION_VIEW_CARGO_SUPPLY_RATING ) ;
2009-11-08 12:45:16 +00:00
y + = FONT_HEIGHT_NORMAL ;
2004-08-09 17:04:08 +00:00
}
2010-04-18 14:56:05 +00:00
return CeilDiv ( y - r . top - WD_FRAMERECT_TOP , FONT_HEIGHT_NORMAL ) ;
2004-08-09 17:04:08 +00:00
}
2013-06-09 13:08:52 +00:00
/**
* Expand or collapse a specific row .
* @ param filter Parent of the row .
* @ param next ID pointing to the row .
*/
template < class Tid >
void HandleCargoWaitingClick ( CargoDataEntry * filter , Tid next )
2008-05-11 17:24:52 +00:00
{
2013-06-09 13:08:52 +00:00
if ( filter - > Retrieve ( next ) ! = NULL ) {
filter - > Remove ( next ) ;
} else {
filter - > InsertOrRetrieve ( next ) ;
}
}
2008-03-27 15:51:11 +00:00
2013-06-09 13:08:52 +00:00
/**
* Handle a click on a specific row in the cargo view .
* @ param row Row being clicked .
*/
void HandleCargoWaitingClick ( int row )
{
if ( row < 0 | | ( uint ) row > = this - > displayed_rows . size ( ) ) return ;
if ( _ctrl_pressed ) {
this - > scroll_to_row = row ;
} else {
RowDisplay & display = this - > displayed_rows [ row ] ;
if ( display . filter = = & this - > expanded_rows ) {
this - > HandleCargoWaitingClick < CargoID > ( display . filter , display . next_cargo ) ;
} else {
this - > HandleCargoWaitingClick < StationID > ( display . filter , display . next_station ) ;
2008-05-11 17:24:52 +00:00
}
2008-03-27 15:51:11 +00:00
}
2013-06-09 13:08:52 +00:00
this - > SetWidgetDirty ( WID_SV_WAITING ) ;
2008-03-27 15:51:11 +00:00
}
2010-01-30 18:34:48 +00:00
virtual void OnClick ( Point pt , int widget , int click_count )
2008-05-11 17:24:52 +00:00
{
switch ( widget ) {
2011-12-16 18:14:11 +00:00
case WID_SV_WAITING :
2013-06-09 13:08:52 +00:00
this - > HandleCargoWaitingClick ( this - > vscroll - > GetScrolledRowFromWidget ( pt . y , this , WID_SV_WAITING , WD_FRAMERECT_TOP , FONT_HEIGHT_NORMAL ) - this - > vscroll - > GetPosition ( ) ) ;
2008-05-11 17:24:52 +00:00
break ;
2007-03-03 09:40:34 +00:00
2011-12-16 18:14:11 +00:00
case WID_SV_LOCATION :
2008-05-11 17:24:52 +00:00
if ( _ctrl_pressed ) {
2009-05-16 23:34:14 +00:00
ShowExtraViewPortWindow ( Station : : Get ( this - > window_number ) - > xy ) ;
2008-05-11 17:24:52 +00:00
} else {
2009-05-16 23:34:14 +00:00
ScrollMainWindowToTile ( Station : : Get ( this - > window_number ) - > xy ) ;
2008-05-11 17:24:52 +00:00
}
break ;
2004-08-09 17:04:08 +00:00
2011-12-16 18:14:11 +00:00
case WID_SV_ACCEPTS_RATINGS : {
2009-11-08 15:26:20 +00:00
/* Swap between 'accepts' and 'ratings' view. */
int height_change ;
2011-12-16 18:14:11 +00:00
NWidgetCore * nwi = this - > GetWidget < NWidgetCore > ( WID_SV_ACCEPTS_RATINGS ) ;
if ( this - > GetWidget < NWidgetCore > ( WID_SV_ACCEPTS_RATINGS ) - > widget_data = = STR_STATION_VIEW_RATINGS_BUTTON ) {
2009-11-08 15:26:20 +00:00
nwi - > SetDataTip ( STR_STATION_VIEW_ACCEPTS_BUTTON , STR_STATION_VIEW_ACCEPTS_TOOLTIP ) ; // Switch to accepts view.
2010-02-13 18:39:00 +00:00
height_change = this - > rating_lines - this - > accepts_lines ;
2008-05-11 17:24:52 +00:00
} else {
2009-11-08 15:26:20 +00:00
nwi - > SetDataTip ( STR_STATION_VIEW_RATINGS_BUTTON , STR_STATION_VIEW_RATINGS_TOOLTIP ) ; // Switch to ratings view.
2010-02-13 18:39:00 +00:00
height_change = this - > accepts_lines - this - > rating_lines ;
2007-03-03 09:40:34 +00:00
}
2009-11-29 09:01:03 +00:00
this - > ReInit ( 0 , height_change * FONT_HEIGHT_NORMAL ) ;
2008-05-11 17:24:52 +00:00
break ;
2009-11-08 15:26:20 +00:00
}
2004-12-10 18:16:08 +00:00
2011-12-16 18:14:11 +00:00
case WID_SV_RENAME :
2008-05-11 17:24:52 +00:00
SetDParam ( 0 , this - > window_number ) ;
2011-04-17 18:42:17 +00:00
ShowQueryString ( STR_STATION_NAME , STR_STATION_VIEW_RENAME_STATION_CAPTION , MAX_LENGTH_STATION_NAME_CHARS ,
2010-12-05 22:25:36 +00:00
this , CS_ALPHANUMERAL , QSF_ENABLE_DEFAULT | QSF_LEN_IN_CHARS ) ;
2008-05-11 17:24:52 +00:00
break ;
2004-12-10 18:16:08 +00:00
2012-04-17 19:43:18 +00:00
case WID_SV_CLOSE_AIRPORT :
DoCommandP ( 0 , this - > window_number , 0 , CMD_OPEN_CLOSE_AIRPORT ) ;
break ;
2011-12-16 18:14:11 +00:00
case WID_SV_TRAINS : // Show list of scheduled trains to this station
case WID_SV_ROADVEHS : // Show list of scheduled road-vehicles to this station
case WID_SV_SHIPS : // Show list of scheduled ships to this station
2012-05-16 22:08:46 +00:00
case WID_SV_PLANES : { // Show list of scheduled aircraft to this station
Owner owner = Station : : Get ( this - > window_number ) - > owner ;
ShowVehicleListWindow ( owner , ( VehicleType ) ( widget - WID_SV_TRAINS ) , ( StationID ) this - > window_number ) ;
2008-05-11 17:24:52 +00:00
break ;
2012-05-16 22:08:46 +00:00
}
2013-06-09 13:08:52 +00:00
case WID_SV_SORT_BY : {
2013-06-18 19:32:58 +00:00
/* The initial selection is composed of current mode and
* sorting criteria for columns 1 , 2 , and 3. Column 0 is always
* sorted by cargo ID . The others can theoretically be sorted
* by different things but there is no UI for that . */
ShowDropDownMenu ( this , _sort_names ,
this - > current_mode * 2 + ( this - > sortings [ 1 ] = = ST_COUNT ? 1 : 0 ) ,
WID_SV_SORT_BY , 0 , 0 ) ;
2013-06-09 13:08:52 +00:00
break ;
}
case WID_SV_GROUP_BY : {
ShowDropDownMenu ( this , _group_names , this - > grouping_index , WID_SV_GROUP_BY , 0 , 0 ) ;
break ;
}
case WID_SV_SORT_ORDER : { // flip sorting method asc/desc
this - > SelectSortOrder ( this - > sort_orders [ 1 ] = = SO_ASCENDING ? SO_DESCENDING : SO_ASCENDING ) ;
this - > SetTimeout ( ) ;
this - > LowerWidget ( WID_SV_SORT_ORDER ) ;
break ;
}
}
}
/**
* Select a new sort order for the cargo view .
* @ param order New sort order .
*/
void SelectSortOrder ( SortOrder order )
{
this - > sort_orders [ 1 ] = this - > sort_orders [ 2 ] = this - > sort_orders [ 3 ] = order ;
_settings_client . gui . station_gui_sort_order = this - > sort_orders [ 1 ] ;
this - > SetDirty ( ) ;
}
/**
* Select a new sort criterium for the cargo view .
* @ param index Row being selected in the sort criteria drop down .
*/
void SelectSortBy ( int index )
{
_settings_client . gui . station_gui_sort_by = index ;
switch ( _sort_names [ index ] ) {
case STR_STATION_VIEW_WAITING_STATION :
this - > current_mode = MODE_WAITING ;
this - > sortings [ 1 ] = this - > sortings [ 2 ] = this - > sortings [ 3 ] = ST_AS_GROUPING ;
break ;
case STR_STATION_VIEW_WAITING_AMOUNT :
this - > current_mode = MODE_WAITING ;
this - > sortings [ 1 ] = this - > sortings [ 2 ] = this - > sortings [ 3 ] = ST_COUNT ;
break ;
case STR_STATION_VIEW_PLANNED_STATION :
this - > current_mode = MODE_PLANNED ;
this - > sortings [ 1 ] = this - > sortings [ 2 ] = this - > sortings [ 3 ] = ST_AS_GROUPING ;
break ;
case STR_STATION_VIEW_PLANNED_AMOUNT :
this - > current_mode = MODE_PLANNED ;
this - > sortings [ 1 ] = this - > sortings [ 2 ] = this - > sortings [ 3 ] = ST_COUNT ;
break ;
default :
NOT_REACHED ( ) ;
}
/* Display the current sort variant */
this - > GetWidget < NWidgetCore > ( WID_SV_SORT_BY ) - > widget_data = _sort_names [ index ] ;
this - > SetDirty ( ) ;
}
/**
* Select a new grouping mode for the cargo view .
* @ param index Row being selected in the grouping drop down .
*/
void SelectGroupBy ( int index )
{
this - > grouping_index = index ;
_settings_client . gui . station_gui_group_order = index ;
this - > GetWidget < NWidgetCore > ( WID_SV_GROUP_BY ) - > widget_data = _group_names [ index ] ;
switch ( _group_names [ index ] ) {
case STR_STATION_VIEW_GROUP_S_V_D :
this - > groupings [ 1 ] = GR_SOURCE ;
this - > groupings [ 2 ] = GR_NEXT ;
this - > groupings [ 3 ] = GR_DESTINATION ;
break ;
case STR_STATION_VIEW_GROUP_S_D_V :
this - > groupings [ 1 ] = GR_SOURCE ;
this - > groupings [ 2 ] = GR_DESTINATION ;
this - > groupings [ 3 ] = GR_NEXT ;
break ;
case STR_STATION_VIEW_GROUP_V_S_D :
this - > groupings [ 1 ] = GR_NEXT ;
this - > groupings [ 2 ] = GR_SOURCE ;
this - > groupings [ 3 ] = GR_DESTINATION ;
break ;
case STR_STATION_VIEW_GROUP_V_D_S :
this - > groupings [ 1 ] = GR_NEXT ;
this - > groupings [ 2 ] = GR_DESTINATION ;
this - > groupings [ 3 ] = GR_SOURCE ;
break ;
case STR_STATION_VIEW_GROUP_D_S_V :
this - > groupings [ 1 ] = GR_DESTINATION ;
this - > groupings [ 2 ] = GR_SOURCE ;
this - > groupings [ 3 ] = GR_NEXT ;
break ;
case STR_STATION_VIEW_GROUP_D_V_S :
this - > groupings [ 1 ] = GR_DESTINATION ;
this - > groupings [ 2 ] = GR_NEXT ;
this - > groupings [ 3 ] = GR_SOURCE ;
break ;
}
this - > SetDirty ( ) ;
}
virtual void OnDropdownSelect ( int widget , int index )
{
if ( widget = = WID_SV_SORT_BY ) {
this - > SelectSortBy ( index ) ;
} else {
this - > SelectGroupBy ( index ) ;
2008-05-11 17:24:52 +00:00
}
}
2004-12-10 18:16:08 +00:00
2008-05-11 17:24:52 +00:00
virtual void OnQueryTextFinished ( char * str )
{
2008-09-15 19:02:50 +00:00
if ( str = = NULL ) return ;
2009-04-21 23:40:56 +00:00
DoCommandP ( 0 , this - > window_number , 0 , CMD_RENAME_STATION | CMD_MSG ( STR_ERROR_CAN_T_RENAME_STATION ) , NULL , str ) ;
2008-05-11 17:24:52 +00:00
}
2008-01-26 22:15:39 +00:00
2009-10-24 14:53:55 +00:00
virtual void OnResize ( )
2008-05-11 17:24:52 +00:00
{
2011-12-16 18:14:11 +00:00
this - > vscroll - > SetCapacityFromWidget ( this , WID_SV_WAITING , WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM ) ;
2004-08-09 17:04:08 +00:00
}
2012-04-17 19:43:18 +00:00
/**
2013-06-09 13:08:52 +00:00
* Some data on this window has become invalid . Invalidate the cache for the given cargo if necessary .
* @ param data Information about the changed data . If it ' s a valid cargo ID , invalidate the cargo data .
2012-04-17 19:43:18 +00:00
* @ param gui_scope Whether the call is done from GUI scope . You may not do everything when not in GUI scope . See # InvalidateWindowData ( ) for details .
*/
virtual void OnInvalidateData ( int data = 0 , bool gui_scope = true )
{
2013-06-09 13:08:52 +00:00
if ( gui_scope ) {
if ( data > = 0 & & data < NUM_CARGO ) {
this - > cached_destinations . Remove ( ( CargoID ) data ) ;
} else {
this - > ReInit ( ) ;
}
}
2012-04-17 19:43:18 +00:00
}
2008-05-11 17:24:52 +00:00
} ;
2004-08-09 17:04:08 +00:00
2013-06-09 13:08:52 +00:00
const StringID StationViewWindow : : _sort_names [ ] = {
STR_STATION_VIEW_WAITING_STATION ,
STR_STATION_VIEW_WAITING_AMOUNT ,
STR_STATION_VIEW_PLANNED_STATION ,
STR_STATION_VIEW_PLANNED_AMOUNT ,
INVALID_STRING_ID
} ;
const StringID StationViewWindow : : _group_names [ ] = {
STR_STATION_VIEW_GROUP_S_V_D ,
STR_STATION_VIEW_GROUP_S_D_V ,
STR_STATION_VIEW_GROUP_V_S_D ,
STR_STATION_VIEW_GROUP_V_D_S ,
STR_STATION_VIEW_GROUP_D_S_V ,
STR_STATION_VIEW_GROUP_D_V_S ,
INVALID_STRING_ID
} ;
2004-08-09 17:04:08 +00:00
2013-05-26 19:23:42 +00:00
static WindowDesc _station_view_desc (
2013-06-09 13:08:52 +00:00
WDP_AUTO , " view_station " , 249 , 117 ,
2007-02-01 15:49:12 +00:00
WC_STATION_VIEW , WC_NONE ,
2012-11-11 16:10:43 +00:00
0 ,
2009-11-15 10:26:01 +00:00
_nested_station_view_widgets , lengthof ( _nested_station_view_widgets )
2009-03-15 15:12:06 +00:00
) ;
2004-08-09 17:04:08 +00:00
2007-12-05 17:08:10 +00:00
/**
* Opens StationViewWindow for given station
*
* @ param station station which window should be opened
*/
2005-10-07 07:35:15 +00:00
void ShowStationViewWindow ( StationID station )
2004-08-09 17:04:08 +00:00
{
2008-05-11 17:24:52 +00:00
AllocateWindowDescFront < StationViewWindow > ( & _station_view_desc , station ) ;
2004-08-09 17:04:08 +00:00
}
2009-01-08 16:35:45 +00:00
2009-07-03 13:33:00 +00:00
/** Struct containing TileIndex and StationID */
struct TileAndStation {
TileIndex tile ; ///< TileIndex
StationID station ; ///< StationID
} ;
static SmallVector < TileAndStation , 8 > _deleted_stations_nearby ;
2009-01-08 16:35:45 +00:00
static SmallVector < StationID , 8 > _stations_nearby_list ;
/**
* Add station on this tile to _stations_nearby_list if it ' s fully within the
* station spread .
* @ param tile Tile just being checked
2009-07-26 09:25:00 +00:00
* @ param user_data Pointer to TileArea context
2009-07-31 16:28:28 +00:00
* @ tparam T the type of station to look for
2009-01-08 16:35:45 +00:00
*/
2009-07-31 16:28:28 +00:00
template < class T >
2009-01-08 16:35:45 +00:00
static bool AddNearbyStation ( TileIndex tile , void * user_data )
{
2009-07-26 09:25:00 +00:00
TileArea * ctx = ( TileArea * ) user_data ;
2009-01-08 16:35:45 +00:00
2009-07-03 13:33:00 +00:00
/* First check if there were deleted stations here */
for ( uint i = 0 ; i < _deleted_stations_nearby . Length ( ) ; i + + ) {
TileAndStation * ts = _deleted_stations_nearby . Get ( i ) ;
if ( ts - > tile = = tile ) {
* _stations_nearby_list . Append ( ) = _deleted_stations_nearby [ i ] . station ;
_deleted_stations_nearby . Erase ( ts ) ;
i - - ;
}
2009-01-08 16:35:45 +00:00
}
/* Check if own station and if we stay within station spread */
if ( ! IsTileType ( tile , MP_STATION ) ) return false ;
StationID sid = GetStationIndex ( tile ) ;
2009-07-26 09:25:00 +00:00
/* This station is (likely) a waypoint */
2009-07-31 16:28:28 +00:00
if ( ! T : : IsValidID ( sid ) ) return false ;
2009-07-26 09:25:00 +00:00
2009-07-31 16:28:28 +00:00
T * st = T : : Get ( sid ) ;
2009-01-08 16:35:45 +00:00
if ( st - > owner ! = _local_company | | _stations_nearby_list . Contains ( sid ) ) return false ;
2010-03-06 13:23:33 +00:00
if ( st - > rect . BeforeAddRect ( ctx - > tile , ctx - > w , ctx - > h , StationRect : : ADD_TEST ) . Succeeded ( ) ) {
2009-01-08 16:35:45 +00:00
* _stations_nearby_list . Append ( ) = sid ;
}
return false ; // We want to include *all* nearby stations
}
/**
* Circulate around the to - be - built station to find stations we could join .
* Make sure that only stations are returned where joining wouldn ' t exceed
* station spread and are our own station .
2009-09-19 09:51:14 +00:00
* @ param ta Base tile area of the to - be - built station
2009-01-08 16:35:45 +00:00
* @ param distant_join Search for adjacent stations ( false ) or stations fully
* within station spread
2009-07-31 16:28:28 +00:00
* @ tparam T the type of station to look for
2010-08-01 19:44:49 +00:00
*/
2009-07-31 16:28:28 +00:00
template < class T >
static const T * FindStationsNearby ( TileArea ta , bool distant_join )
2009-01-08 16:35:45 +00:00
{
2009-07-26 21:07:03 +00:00
TileArea ctx = ta ;
2009-01-08 16:35:45 +00:00
_stations_nearby_list . Clear ( ) ;
_deleted_stations_nearby . Clear ( ) ;
/* Check the inside, to return, if we sit on another station */
2010-01-04 18:30:10 +00:00
TILE_AREA_LOOP ( t , ta ) {
2009-07-31 16:28:28 +00:00
if ( t < MapSize ( ) & & IsTileType ( t , MP_STATION ) & & T : : IsValidID ( GetStationIndex ( t ) ) ) return T : : GetByTile ( t ) ;
2009-07-26 21:50:30 +00:00
}
2009-01-08 16:35:45 +00:00
/* Look for deleted stations */
2009-07-26 09:25:00 +00:00
const BaseStation * st ;
FOR_ALL_BASE_STATIONS ( st ) {
2009-07-31 16:28:28 +00:00
if ( T : : IsExpected ( st ) & & ! st - > IsInUse ( ) & & st - > owner = = _local_company ) {
2009-01-08 16:35:45 +00:00
/* Include only within station spread (yes, it is strictly less than) */
2009-07-26 21:07:03 +00:00
if ( max ( DistanceMax ( ta . tile , st - > xy ) , DistanceMax ( TILE_ADDXY ( ta . tile , ta . w - 1 , ta . h - 1 ) , st - > xy ) ) < _settings_game . station . station_spread ) {
2009-07-03 13:33:00 +00:00
TileAndStation * ts = _deleted_stations_nearby . Append ( ) ;
ts - > tile = st - > xy ;
ts - > station = st - > index ;
2009-01-08 16:35:45 +00:00
/* Add the station when it's within where we're going to build */
if ( IsInsideBS ( TileX ( st - > xy ) , TileX ( ctx . tile ) , ctx . w ) & &
IsInsideBS ( TileY ( st - > xy ) , TileY ( ctx . tile ) , ctx . h ) ) {
2009-07-31 16:28:28 +00:00
AddNearbyStation < T > ( st - > xy , & ctx ) ;
2009-01-08 16:35:45 +00:00
}
}
}
}
/* Only search tiles where we have a chance to stay within the station spread.
* The complete check needs to be done in the callback as we don ' t know the
* extent of the found station , yet . */
2009-07-26 21:07:03 +00:00
if ( distant_join & & min ( ta . w , ta . h ) > = _settings_game . station . station_spread ) return NULL ;
uint max_dist = distant_join ? _settings_game . station . station_spread - min ( ta . w , ta . h ) : 1 ;
2009-01-08 16:35:45 +00:00
2009-07-26 21:07:03 +00:00
TileIndex tile = TILE_ADD ( ctx . tile , TileOffsByDir ( DIR_N ) ) ;
2009-07-31 16:28:28 +00:00
CircularTileSearch ( & tile , max_dist , ta . w , ta . h , AddNearbyStation < T > , & ctx ) ;
2009-01-08 16:35:45 +00:00
return NULL ;
}
2009-05-03 10:46:24 +00:00
static const NWidgetPart _nested_select_station_widgets [ ] = {
NWidget ( NWID_HORIZONTAL ) ,
2009-11-24 18:05:55 +00:00
NWidget ( WWT_CLOSEBOX , COLOUR_DARK_GREEN ) ,
2011-12-16 18:14:11 +00:00
NWidget ( WWT_CAPTION , COLOUR_DARK_GREEN , WID_JS_CAPTION ) , SetDataTip ( STR_JOIN_STATION_CAPTION , STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS ) ,
2013-05-26 19:30:07 +00:00
NWidget ( WWT_DEFSIZEBOX , COLOUR_DARK_GREEN ) ,
2009-05-03 10:46:24 +00:00
EndContainer ( ) ,
NWidget ( NWID_HORIZONTAL ) ,
2011-12-16 18:14:11 +00:00
NWidget ( WWT_PANEL , COLOUR_DARK_GREEN , WID_JS_PANEL ) , SetResize ( 1 , 0 ) , SetScrollbar ( WID_JS_SCROLLBAR ) , EndContainer ( ) ,
2009-05-03 10:46:24 +00:00
NWidget ( NWID_VERTICAL ) ,
2011-12-16 18:14:11 +00:00
NWidget ( NWID_VSCROLLBAR , COLOUR_DARK_GREEN , WID_JS_SCROLLBAR ) ,
2009-11-24 18:05:55 +00:00
NWidget ( WWT_RESIZEBOX , COLOUR_DARK_GREEN ) ,
2009-05-03 10:46:24 +00:00
EndContainer ( ) ,
EndContainer ( ) ,
} ;
2009-07-31 16:28:28 +00:00
/**
* Window for selecting stations / waypoints to ( distant ) join to .
* @ tparam T The type of station to join with
*/
template < class T >
2009-01-08 16:35:45 +00:00
struct SelectStationWindow : Window {
CommandContainer select_station_cmd ; ///< Command to build new station
2009-07-26 21:07:03 +00:00
TileArea area ; ///< Location of new station
2010-08-12 08:37:01 +00:00
Scrollbar * vscroll ;
2009-01-08 16:35:45 +00:00
2013-11-24 14:29:32 +00:00
SelectStationWindow ( WindowDesc * desc , const CommandContainer & cmd , TileArea ta ) :
2013-05-26 19:23:42 +00:00
Window ( desc ) ,
2009-01-08 16:35:45 +00:00
select_station_cmd ( cmd ) ,
2009-07-26 21:07:03 +00:00
area ( ta )
2009-01-08 16:35:45 +00:00
{
2013-05-26 19:23:42 +00:00
this - > CreateNestedTree ( ) ;
2011-12-16 18:14:11 +00:00
this - > vscroll = this - > GetScrollbar ( WID_JS_SCROLLBAR ) ;
this - > GetWidget < NWidgetCore > ( WID_JS_CAPTION ) - > widget_data = T : : EXPECTED_FACIL = = FACIL_WAYPOINT ? STR_JOIN_WAYPOINT_CAPTION : STR_JOIN_STATION_CAPTION ;
2013-05-26 19:23:42 +00:00
this - > FinishInitNested ( 0 ) ;
2009-09-23 19:41:25 +00:00
this - > OnInvalidateData ( 0 ) ;
2009-09-23 20:14:59 +00:00
}
2009-01-08 16:35:45 +00:00
2009-11-22 18:28:14 +00:00
virtual void UpdateWidgetSize ( int widget , Dimension * size , const Dimension & padding , Dimension * fill , Dimension * resize )
2009-09-23 20:14:59 +00:00
{
2011-12-16 18:14:11 +00:00
if ( widget ! = WID_JS_PANEL ) return ;
2009-09-23 20:14:59 +00:00
/* Determine the widest string */
Dimension d = GetStringBoundingBox ( T : : EXPECTED_FACIL = = FACIL_WAYPOINT ? STR_JOIN_WAYPOINT_CREATE_SPLITTED_WAYPOINT : STR_JOIN_STATION_CREATE_SPLITTED_STATION ) ;
for ( uint i = 0 ; i < _stations_nearby_list . Length ( ) ; i + + ) {
const T * st = T : : Get ( _stations_nearby_list [ i ] ) ;
SetDParam ( 0 , st - > index ) ;
SetDParam ( 1 , st - > facilities ) ;
d = maxdim ( d , GetStringBoundingBox ( T : : EXPECTED_FACIL = = FACIL_WAYPOINT ? STR_STATION_LIST_WAYPOINT : STR_STATION_LIST_STATION ) ) ;
}
resize - > height = d . height ;
2009-11-22 14:46:14 +00:00
d . height * = 5 ;
2009-09-23 20:14:59 +00:00
d . width + = WD_FRAMERECT_RIGHT + WD_FRAMERECT_LEFT ;
d . height + = WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM ;
2009-11-22 14:46:14 +00:00
* size = d ;
2009-01-08 16:35:45 +00:00
}
2009-09-23 20:14:59 +00:00
virtual void DrawWidget ( const Rect & r , int widget ) const
{
2011-12-16 18:14:11 +00:00
if ( widget ! = WID_JS_PANEL ) return ;
2009-01-08 16:35:45 +00:00
2009-09-23 20:14:59 +00:00
uint y = r . top + WD_FRAMERECT_TOP ;
2010-08-12 08:37:01 +00:00
if ( this - > vscroll - > GetPosition ( ) = = 0 ) {
2009-09-23 20:14:59 +00:00
DrawString ( r . left + WD_FRAMERECT_LEFT , r . right - WD_FRAMERECT_RIGHT , y , T : : EXPECTED_FACIL = = FACIL_WAYPOINT ? STR_JOIN_WAYPOINT_CREATE_SPLITTED_WAYPOINT : STR_JOIN_STATION_CREATE_SPLITTED_STATION ) ;
y + = this - > resize . step_height ;
2009-01-08 16:35:45 +00:00
}
2010-08-12 08:37:01 +00:00
for ( uint i = max < uint > ( 1 , this - > vscroll - > GetPosition ( ) ) ; i < = _stations_nearby_list . Length ( ) ; + + i , y + = this - > resize . step_height ) {
2009-01-08 16:35:45 +00:00
/* Don't draw anything if it extends past the end of the window. */
2010-08-12 08:37:01 +00:00
if ( i - this - > vscroll - > GetPosition ( ) > = this - > vscroll - > GetCapacity ( ) ) break ;
2009-01-08 16:35:45 +00:00
2009-07-31 16:28:28 +00:00
const T * st = T : : Get ( _stations_nearby_list [ i - 1 ] ) ;
2009-01-08 16:35:45 +00:00
SetDParam ( 0 , st - > index ) ;
SetDParam ( 1 , st - > facilities ) ;
2009-09-23 20:14:59 +00:00
DrawString ( r . left + WD_FRAMERECT_LEFT , r . right - WD_FRAMERECT_RIGHT , y , T : : EXPECTED_FACIL = = FACIL_WAYPOINT ? STR_STATION_LIST_WAYPOINT : STR_STATION_LIST_STATION ) ;
2009-01-08 16:35:45 +00:00
}
}
2010-01-30 18:34:48 +00:00
virtual void OnClick ( Point pt , int widget , int click_count )
2009-01-08 16:35:45 +00:00
{
2011-12-16 18:14:11 +00:00
if ( widget ! = WID_JS_PANEL ) return ;
2009-01-08 16:35:45 +00:00
2011-12-16 18:14:11 +00:00
uint st_index = this - > vscroll - > GetScrolledRowFromWidget ( pt . y , this , WID_JS_PANEL , WD_FRAMERECT_TOP ) ;
2009-01-08 16:35:45 +00:00
bool distant_join = ( st_index > 0 ) ;
if ( distant_join ) st_index - - ;
if ( distant_join & & st_index > = _stations_nearby_list . Length ( ) ) return ;
/* Insert station to be joined into stored command */
SB ( this - > select_station_cmd . p2 , 16 , 16 ,
2009-04-10 22:47:19 +00:00
( distant_join ? _stations_nearby_list [ st_index ] : NEW_STATION ) ) ;
2009-01-08 16:35:45 +00:00
/* Execute stored Command */
DoCommandP ( & this - > select_station_cmd ) ;
/* Close Window; this might cause double frees! */
DeleteWindowById ( WC_SELECT_STATION , 0 ) ;
}
virtual void OnTick ( )
{
if ( _thd . dirty & 2 ) {
_thd . dirty & = ~ 2 ;
this - > SetDirty ( ) ;
}
}
2009-10-24 14:53:55 +00:00
virtual void OnResize ( )
2009-01-08 16:35:45 +00:00
{
2011-12-16 18:14:11 +00:00
this - > vscroll - > SetCapacityFromWidget ( this , WID_JS_PANEL , WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM ) ;
2009-01-08 16:35:45 +00:00
}
2011-03-13 21:31:29 +00:00
/**
* Some data on this window has become invalid .
* @ param data Information about the changed data .
* @ param gui_scope Whether the call is done from GUI scope . You may not do everything when not in GUI scope . See # InvalidateWindowData ( ) for details .
*/
virtual void OnInvalidateData ( int data = 0 , bool gui_scope = true )
2009-01-08 16:35:45 +00:00
{
2011-03-13 21:31:29 +00:00
if ( ! gui_scope ) return ;
2009-07-31 16:28:28 +00:00
FindStationsNearby < T > ( this - > area , true ) ;
2010-08-12 08:37:01 +00:00
this - > vscroll - > SetCount ( _stations_nearby_list . Length ( ) + 1 ) ;
2009-01-08 16:35:45 +00:00
this - > SetDirty ( ) ;
}
} ;
2013-05-26 19:23:42 +00:00
static WindowDesc _select_station_desc (
2013-05-26 19:25:01 +00:00
WDP_AUTO , " build_station_join " , 200 , 180 ,
2009-01-08 16:35:45 +00:00
WC_SELECT_STATION , WC_NONE ,
2009-11-24 17:28:29 +00:00
WDF_CONSTRUCTION ,
2009-11-15 10:26:01 +00:00
_nested_select_station_widgets , lengthof ( _nested_select_station_widgets )
2009-03-15 15:12:06 +00:00
) ;
2009-01-08 16:35:45 +00:00
/**
* Check whether we need to show the station selection window .
* @ param cmd Command to build the station .
2009-09-19 09:51:14 +00:00
* @ param ta Tile area of the to - be - built station
2009-07-31 16:28:28 +00:00
* @ tparam T the type of station
2009-01-08 16:35:45 +00:00
* @ return whether we need to show the station selection window .
*/
2009-07-31 16:28:28 +00:00
template < class T >
2013-11-24 14:29:32 +00:00
static bool StationJoinerNeeded ( const CommandContainer & cmd , TileArea ta )
2009-01-08 16:35:45 +00:00
{
/* Only show selection if distant join is enabled in the settings */
if ( ! _settings_game . station . distant_join_stations ) return false ;
2009-01-13 17:28:11 +00:00
/* If a window is already opened and we didn't ctrl-click,
* return true ( i . e . just flash the old window ) */
Window * selection_window = FindWindowById ( WC_SELECT_STATION , 0 ) ;
if ( selection_window ! = NULL ) {
/* Abort current distant-join and start new one */
delete selection_window ;
UpdateTileSelection ( ) ;
}
2009-01-08 16:35:45 +00:00
/* only show the popup, if we press ctrl */
if ( ! _ctrl_pressed ) return false ;
2009-01-13 17:28:11 +00:00
/* Now check if we could build there */
2010-01-18 22:57:21 +00:00
if ( DoCommand ( & cmd , CommandFlagsToDCFlags ( GetCommandFlags ( cmd . cmd ) ) ) . Failed ( ) ) return false ;
2009-01-13 17:28:11 +00:00
2009-01-13 18:41:56 +00:00
/* Test for adjacent station or station below selection.
* If adjacent - stations is disabled and we are building next to a station , do not show the selection window .
2010-08-15 14:06:43 +00:00
* but join the other station immediately . */
2009-07-31 16:28:28 +00:00
const T * st = FindStationsNearby < T > ( ta , false ) ;
2009-01-13 18:41:56 +00:00
return st = = NULL & & ( _settings_game . station . adjacent_stations | | _stations_nearby_list . Length ( ) = = 0 ) ;
2009-01-08 16:35:45 +00:00
}
/**
* Show the station selection window when needed . If not , build the station .
* @ param cmd Command to build the station .
2009-07-31 16:28:28 +00:00
* @ param ta Area to build the station in
* @ tparam the class to find stations for
2009-01-08 16:35:45 +00:00
*/
2009-07-31 16:28:28 +00:00
template < class T >
2013-11-24 14:29:32 +00:00
void ShowSelectBaseStationIfNeeded ( const CommandContainer & cmd , TileArea ta )
2009-01-08 16:35:45 +00:00
{
2009-07-31 16:28:28 +00:00
if ( StationJoinerNeeded < T > ( cmd , ta ) ) {
2009-02-08 15:45:34 +00:00
if ( ! _settings_client . gui . persistent_buildingtools ) ResetObjectToPlace ( ) ;
2009-07-31 16:28:28 +00:00
new SelectStationWindow < T > ( & _select_station_desc , cmd , ta ) ;
2009-01-08 16:35:45 +00:00
} else {
DoCommandP ( & cmd ) ;
}
}
2009-07-31 16:28:28 +00:00
/**
* Show the station selection window when needed . If not , build the station .
* @ param cmd Command to build the station .
* @ param ta Area to build the station in
*/
2013-11-24 14:29:32 +00:00
void ShowSelectStationIfNeeded ( const CommandContainer & cmd , TileArea ta )
2009-07-31 16:28:28 +00:00
{
ShowSelectBaseStationIfNeeded < Station > ( cmd , ta ) ;
}
/**
* Show the waypoint selection window when needed . If not , build the waypoint .
* @ param cmd Command to build the waypoint .
* @ param ta Area to build the waypoint in
*/
2013-11-24 14:29:32 +00:00
void ShowSelectWaypointIfNeeded ( const CommandContainer & cmd , TileArea ta )
2009-07-31 16:28:28 +00:00
{
ShowSelectBaseStationIfNeeded < Waypoint > ( cmd , ta ) ;
}