summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrubidium <rubidium@openttd.org>2008-05-11 17:24:52 +0000
committerrubidium <rubidium@openttd.org>2008-05-11 17:24:52 +0000
commit1be2847668259904fe20b41f890376a78bc49e30 (patch)
tree190da4711e22c0a3f1cce610c807ddbf2c031dbd
parentc708ab3b486a2ecf1f163c900ff71fd46764bdfa (diff)
downloadopenttd-1be2847668259904fe20b41f890376a78bc49e30.tar.xz
(svn r13048) -Codechange: make a class of the StationViewWindow.
-rw-r--r--src/station_gui.cpp468
1 files changed, 228 insertions, 240 deletions
diff --git a/src/station_gui.cpp b/src/station_gui.cpp
index dcf26efcc..a0e4c8937 100644
--- a/src/station_gui.cpp
+++ b/src/station_gui.cpp
@@ -727,12 +727,6 @@ static void DrawCargoIcons(CargoID i, uint waiting, int x, int y, uint width)
} while (--num);
}
-struct stationview_d {
- uint32 cargo; ///< Bitmask of cargo types to expand
- uint16 cargo_rows[NUM_CARGO]; ///< Header row for each cargo type
-};
-assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(stationview_d));
-
struct CargoData {
CargoID cargo;
StationID source;
@@ -748,285 +742,285 @@ struct CargoData {
typedef std::list<CargoData> CargoDataList;
/**
- * Redraws whole StationView window
- *
- * @param w pointer to window
+ * The StationView window
*/
-static void DrawStationViewWindow(Window *w)
-{
- StationID station_id = w->window_number;
- const Station *st = GetStation(station_id);
- CargoDataList cargolist;
- uint32 transfers = 0;
-
- /* count types of cargos waiting in station */
- for (CargoID i = 0; i < NUM_CARGO; i++) {
- if (st->goods[i].cargo.Empty()) {
- WP(w, stationview_d).cargo_rows[i] = 0;
- } else {
- /* Add an entry for total amount of cargo of this type waiting. */
- cargolist.push_back(CargoData(i, INVALID_STATION, st->goods[i].cargo.Count()));
-
- /* Set the row for this cargo entry for the expand/hide button */
- WP(w, stationview_d).cargo_rows[i] = cargolist.size();
-
- /* Add an entry for each distinct cargo source. */
- const CargoList::List *packets = st->goods[i].cargo.Packets();
- for (CargoList::List::const_iterator it = packets->begin(); it != packets->end(); it++) {
- const CargoPacket *cp = *it;
- if (cp->source != station_id) {
- bool added = false;
-
- /* Enable the expand/hide button for this cargo type */
- SetBit(transfers, i);
-
- /* Don't add cargo lines if not expanded */
- if (!HasBit(WP(w, stationview_d).cargo, i)) break;
-
- /* Check if we already have this source in the list */
- for (CargoDataList::iterator jt = cargolist.begin(); jt != cargolist.end(); jt++) {
- CargoData *cd = &(*jt);
- if (cd->cargo == i && cd->source == cp->source) {
- cd->count += cp->count;
- added = true;
- break;
+struct StationViewWindow : public Window {
+ uint32 cargo; ///< Bitmask of cargo types to expand
+ uint16 cargo_rows[NUM_CARGO]; ///< Header row for each cargo type
+
+ StationViewWindow(const WindowDesc *desc, void *data, WindowNumber window_number) : Window(desc, data, window_number)
+ {
+ PlayerID owner = GetStation(window_number)->owner;
+ if (owner != OWNER_NONE) this->caption_color = owner;
+ this->vscroll.cap = 5;
+ this->resize.step_height = 10;
+
+ this->FindWindowPlacementAndResize(desc);
+ }
+
+ ~StationViewWindow()
+ {
+ WindowNumber wno =
+ (this->window_number << 16) | VLW_STATION_LIST | GetStation(this->window_number)->owner;
+
+ DeleteWindowById(WC_TRAINS_LIST, wno);
+ DeleteWindowById(WC_ROADVEH_LIST, wno);
+ DeleteWindowById(WC_SHIPS_LIST, wno);
+ DeleteWindowById(WC_AIRCRAFT_LIST, wno);
+ }
+
+ virtual void OnPaint()
+ {
+ StationID station_id = this->window_number;
+ const Station *st = GetStation(station_id);
+ CargoDataList cargolist;
+ uint32 transfers = 0;
+
+ /* count types of cargos waiting in station */
+ for (CargoID i = 0; i < NUM_CARGO; i++) {
+ if (st->goods[i].cargo.Empty()) {
+ this->cargo_rows[i] = 0;
+ } else {
+ /* Add an entry for total amount of cargo of this type waiting. */
+ cargolist.push_back(CargoData(i, INVALID_STATION, st->goods[i].cargo.Count()));
+
+ /* Set the row for this cargo entry for the expand/hide button */
+ this->cargo_rows[i] = cargolist.size();
+
+ /* Add an entry for each distinct cargo source. */
+ const CargoList::List *packets = st->goods[i].cargo.Packets();
+ for (CargoList::List::const_iterator it = packets->begin(); it != packets->end(); it++) {
+ const CargoPacket *cp = *it;
+ if (cp->source != station_id) {
+ bool added = false;
+
+ /* Enable the expand/hide button for this cargo type */
+ SetBit(transfers, i);
+
+ /* Don't add cargo lines if not expanded */
+ if (!HasBit(this->cargo, i)) break;
+
+ /* Check if we already have this source in the list */
+ for (CargoDataList::iterator jt = cargolist.begin(); jt != cargolist.end(); jt++) {
+ CargoData *cd = &(*jt);
+ if (cd->cargo == i && cd->source == cp->source) {
+ cd->count += cp->count;
+ added = true;
+ break;
+ }
}
- }
- if (!added) cargolist.push_back(CargoData(i, cp->source, cp->count));
+ if (!added) cargolist.push_back(CargoData(i, cp->source, cp->count));
+ }
}
}
}
- }
- SetVScrollCount(w, cargolist.size() + 1); // update scrollbar
+ SetVScrollCount(this, cargolist.size() + 1); // update scrollbar
- /* disable some buttons */
- w->SetWidgetDisabledState(SVW_RENAME, st->owner != _local_player);
- w->SetWidgetDisabledState(SVW_TRAINS, !(st->facilities & FACIL_TRAIN));
- w->SetWidgetDisabledState(SVW_ROADVEHS, !(st->facilities & FACIL_TRUCK_STOP) && !(st->facilities & FACIL_BUS_STOP));
- w->SetWidgetDisabledState(SVW_PLANES, !(st->facilities & FACIL_AIRPORT));
- w->SetWidgetDisabledState(SVW_SHIPS, !(st->facilities & FACIL_DOCK));
+ /* disable some buttons */
+ this->SetWidgetDisabledState(SVW_RENAME, st->owner != _local_player);
+ this->SetWidgetDisabledState(SVW_TRAINS, !(st->facilities & FACIL_TRAIN));
+ this->SetWidgetDisabledState(SVW_ROADVEHS, !(st->facilities & FACIL_TRUCK_STOP) && !(st->facilities & FACIL_BUS_STOP));
+ this->SetWidgetDisabledState(SVW_PLANES, !(st->facilities & FACIL_AIRPORT));
+ this->SetWidgetDisabledState(SVW_SHIPS, !(st->facilities & FACIL_DOCK));
- SetDParam(0, st->index);
- SetDParam(1, st->facilities);
- DrawWindowWidgets(w);
+ SetDParam(0, st->index);
+ SetDParam(1, st->facilities);
+ DrawWindowWidgets(this);
- int x = 2; ///< coordinates used for printing waiting/accepted/rating of cargo
- int y = 15;
- int pos = w->vscroll.pos; ///< = w->vscroll.pos
+ int x = 2; ///< coordinates used for printing waiting/accepted/rating of cargo
+ int y = 15;
+ int pos = this->vscroll.pos; ///< = this->vscroll.pos
- uint width = w->widget[SVW_WAITING].right - w->widget[SVW_WAITING].left - 4;
- int maxrows = w->vscroll.cap;
+ uint width = this->widget[SVW_WAITING].right - this->widget[SVW_WAITING].left - 4;
+ int maxrows = this->vscroll.cap;
- StringID str;
+ StringID str;
- if (--pos < 0) {
- str = STR_00D0_NOTHING;
- for (CargoID i = 0; i < NUM_CARGO; i++) {
- if (!st->goods[i].cargo.Empty()) str = STR_EMPTY;
+ if (--pos < 0) {
+ str = STR_00D0_NOTHING;
+ for (CargoID i = 0; i < NUM_CARGO; i++) {
+ if (!st->goods[i].cargo.Empty()) str = STR_EMPTY;
+ }
+ SetDParam(0, str);
+ DrawString(x, y, STR_0008_WAITING, TC_FROMSTRING);
+ y += 10;
}
- SetDParam(0, str);
- DrawString(x, y, STR_0008_WAITING, TC_FROMSTRING);
- y += 10;
- }
- for (CargoDataList::const_iterator it = cargolist.begin(); it != cargolist.end() && pos > -maxrows; ++it) {
- if (--pos < 0) {
- const CargoData *cd = &(*it);
- if (cd->source == INVALID_STATION) {
- /* Heading */
- DrawCargoIcons(cd->cargo, cd->count, x, y, width);
- SetDParam(0, cd->cargo);
- SetDParam(1, cd->count);
- if (HasBit(transfers, cd->cargo)) {
- /* This cargo has transfers waiting so show the expand or shrink 'button' */
- const char *sym = HasBit(WP(w, stationview_d).cargo, cd->cargo) ? "-" : "+";
- DrawStringRightAligned(x + width - 8, y, STR_0009, TC_FROMSTRING);
- DoDrawString(sym, x + width - 6, y, TC_YELLOW);
+ for (CargoDataList::const_iterator it = cargolist.begin(); it != cargolist.end() && pos > -maxrows; ++it) {
+ if (--pos < 0) {
+ const CargoData *cd = &(*it);
+ if (cd->source == INVALID_STATION) {
+ /* Heading */
+ DrawCargoIcons(cd->cargo, cd->count, x, y, width);
+ SetDParam(0, cd->cargo);
+ SetDParam(1, cd->count);
+ if (HasBit(transfers, cd->cargo)) {
+ /* This cargo has transfers waiting so show the expand or shrink 'button' */
+ const char *sym = HasBit(this->cargo, cd->cargo) ? "-" : "+";
+ DrawStringRightAligned(x + width - 8, y, STR_0009, TC_FROMSTRING);
+ DoDrawString(sym, x + width - 6, y, TC_YELLOW);
+ } else {
+ DrawStringRightAligned(x + width, y, STR_0009, TC_FROMSTRING);
+ }
} else {
- DrawStringRightAligned(x + width, y, STR_0009, TC_FROMSTRING);
+ SetDParam(0, cd->cargo);
+ SetDParam(1, cd->count);
+ SetDParam(2, cd->source);
+ DrawStringRightAlignedTruncated(x + width, y, STR_EN_ROUTE_FROM, TC_FROMSTRING, width);
}
- } else {
- SetDParam(0, cd->cargo);
- SetDParam(1, cd->count);
- SetDParam(2, cd->source);
- DrawStringRightAlignedTruncated(x + width, y, STR_EN_ROUTE_FROM, TC_FROMSTRING, width);
- }
- y += 10;
+ y += 10;
+ }
}
- }
- if (w->widget[SVW_ACCEPTS].data == STR_3032_RATINGS) { // small window with list of accepted cargo
- char *b = _userstring;
- bool first = true;
+ if (this->widget[SVW_ACCEPTS].data == STR_3032_RATINGS) { // small window with list of accepted cargo
+ char *b = _userstring;
+ bool first = true;
- b = InlineString(b, STR_000C_ACCEPTS);
+ b = InlineString(b, STR_000C_ACCEPTS);
- for (CargoID i = 0; i < NUM_CARGO; i++) {
- if (b >= lastof(_userstring) - (1 + 2 * 4)) break; // ',' or ' ' and two calls to Utf8Encode()
- if (HasBit(st->goods[i].acceptance_pickup, GoodsEntry::ACCEPTANCE)) {
- if (first) {
- first = false;
- } else {
- /* Add a comma if this is not the first item */
- *b++ = ',';
- *b++ = ' ';
+ for (CargoID i = 0; i < NUM_CARGO; i++) {
+ if (b >= lastof(_userstring) - (1 + 2 * 4)) break; // ',' or ' ' and two calls to Utf8Encode()
+ if (HasBit(st->goods[i].acceptance_pickup, GoodsEntry::ACCEPTANCE)) {
+ if (first) {
+ first = false;
+ } else {
+ /* Add a comma if this is not the first item */
+ *b++ = ',';
+ *b++ = ' ';
+ }
+ b = InlineString(b, GetCargo(i)->name);
}
- b = InlineString(b, GetCargo(i)->name);
}
- }
- /* If first is still true then no cargo is accepted */
- if (first) b = InlineString(b, STR_00D0_NOTHING);
+ /* If first is still true then no cargo is accepted */
+ if (first) b = InlineString(b, STR_00D0_NOTHING);
- *b = '\0';
+ *b = '\0';
- /* Make sure we detect any buffer overflow */
- assert(b < endof(_userstring));
+ /* Make sure we detect any buffer overflow */
+ assert(b < endof(_userstring));
- DrawStringMultiLine(2, w->widget[SVW_ACCEPTLIST].top + 1, STR_SPEC_USERSTRING, w->widget[SVW_ACCEPTLIST].right - w->widget[SVW_ACCEPTLIST].left);
- } else { // extended window with list of cargo ratings
- y = w->widget[SVW_RATINGLIST].top + 1;
+ DrawStringMultiLine(2, this->widget[SVW_ACCEPTLIST].top + 1, STR_SPEC_USERSTRING, this->widget[SVW_ACCEPTLIST].right - this->widget[SVW_ACCEPTLIST].left);
+ } else { // extended window with list of cargo ratings
+ y = this->widget[SVW_RATINGLIST].top + 1;
- DrawString(2, y, STR_3034_LOCAL_RATING_OF_TRANSPORT, TC_FROMSTRING);
- y += 10;
+ DrawString(2, y, STR_3034_LOCAL_RATING_OF_TRANSPORT, TC_FROMSTRING);
+ y += 10;
- for (CargoID i = 0; i < NUM_CARGO; i++) {
- const CargoSpec *cs = GetCargo(i);
- if (!cs->IsValid()) continue;
+ for (CargoID i = 0; i < NUM_CARGO; i++) {
+ const CargoSpec *cs = GetCargo(i);
+ if (!cs->IsValid()) continue;
- const GoodsEntry *ge = &st->goods[i];
- if (!HasBit(ge->acceptance_pickup, GoodsEntry::PICKUP)) continue;
+ const GoodsEntry *ge = &st->goods[i];
+ if (!HasBit(ge->acceptance_pickup, GoodsEntry::PICKUP)) continue;
- SetDParam(0, cs->name);
- SetDParam(2, ge->rating * 101 >> 8);
- SetDParam(1, STR_3035_APPALLING + (ge->rating >> 5));
- DrawString(8, y, STR_303D, TC_FROMSTRING);
- y += 10;
+ SetDParam(0, cs->name);
+ SetDParam(2, ge->rating * 101 >> 8);
+ SetDParam(1, STR_3035_APPALLING + (ge->rating >> 5));
+ DrawString(8, y, STR_303D, TC_FROMSTRING);
+ y += 10;
+ }
}
}
-}
-static void HandleCargoWaitingClick(Window *w, int row)
-{
- if (row == 0) return;
+ void HandleCargoWaitingClick(int row)
+ {
+ if (row == 0) return;
- for (CargoID c = 0; c < NUM_CARGO; c++) {
- if (WP(w, stationview_d).cargo_rows[c] == row) {
- ToggleBit(WP(w, stationview_d).cargo, c);
- w->InvalidateWidget(SVW_WAITING);
- break;
+ for (CargoID c = 0; c < NUM_CARGO; c++) {
+ if (this->cargo_rows[c] == row) {
+ ToggleBit(this->cargo, c);
+ this->InvalidateWidget(SVW_WAITING);
+ break;
+ }
}
}
-}
-
-
-/**
- * Fuction called when any WindowEvent occurs for any StationView window
- *
- * @param w pointer to the StationView window
- * @param e pointer to window event
- */
-static void StationViewWndProc(Window *w, WindowEvent *e)
-{
- switch (e->event) {
- case WE_PAINT:
- DrawStationViewWindow(w);
- break;
-
- case WE_CLICK:
- switch (e->we.click.widget) {
- case SVW_WAITING:
- HandleCargoWaitingClick(w, (e->we.click.pt.y - w->widget[SVW_WAITING].top) / 10 + w->vscroll.pos);
- break;
- case SVW_LOCATION:
- if (_ctrl_pressed) {
- ShowExtraViewPortWindow(GetStation(w->window_number)->xy);
- } else {
- ScrollMainWindowToTile(GetStation(w->window_number)->xy);
- }
- break;
-
- case SVW_RATINGS:
- w->SetDirty();
+ virtual void OnClick(Point pt, int widget)
+ {
+ switch (widget) {
+ case SVW_WAITING:
+ this->HandleCargoWaitingClick((pt.y - this->widget[SVW_WAITING].top) / 10 + this->vscroll.pos);
+ break;
- if (w->widget[SVW_RATINGS].data == STR_3032_RATINGS) {
- /* Switch to ratings view */
- w->widget[SVW_RATINGS].data = STR_3033_ACCEPTS;
- w->widget[SVW_RATINGS].tooltips = STR_3056_SHOW_LIST_OF_ACCEPTED_CARGO;
- ResizeWindowForWidget(w, SVW_ACCEPTLIST, 0, 100);
- } else {
- /* Switch to accepts view */
- w->widget[SVW_RATINGS].data = STR_3032_RATINGS;
- w->widget[SVW_RATINGS].tooltips = STR_3054_SHOW_STATION_RATINGS;
- ResizeWindowForWidget(w, SVW_ACCEPTLIST, 0, -100);
- }
-
- w->SetDirty();
- break;
+ case SVW_LOCATION:
+ if (_ctrl_pressed) {
+ ShowExtraViewPortWindow(GetStation(this->window_number)->xy);
+ } else {
+ ScrollMainWindowToTile(GetStation(this->window_number)->xy);
+ }
+ break;
- case SVW_RENAME:
- SetDParam(0, w->window_number);
- ShowQueryString(STR_STATION, STR_3030_RENAME_STATION_LOADING, 31, 180, w, CS_ALPHANUMERAL);
- break;
+ case SVW_RATINGS:
+ this->SetDirty();
- case SVW_TRAINS: { // Show a list of scheduled trains to this station
- const Station *st = GetStation(w->window_number);
- ShowVehicleListWindow(st->owner, VEH_TRAIN, (StationID)w->window_number);
- break;
+ if (this->widget[SVW_RATINGS].data == STR_3032_RATINGS) {
+ /* Switch to ratings view */
+ this->widget[SVW_RATINGS].data = STR_3033_ACCEPTS;
+ this->widget[SVW_RATINGS].tooltips = STR_3056_SHOW_LIST_OF_ACCEPTED_CARGO;
+ ResizeWindowForWidget(this, SVW_ACCEPTLIST, 0, 100);
+ } else {
+ /* Switch to accepts view */
+ this->widget[SVW_RATINGS].data = STR_3032_RATINGS;
+ this->widget[SVW_RATINGS].tooltips = STR_3054_SHOW_STATION_RATINGS;
+ ResizeWindowForWidget(this, SVW_ACCEPTLIST, 0, -100);
}
- case SVW_ROADVEHS: { // Show a list of scheduled road-vehicles to this station
- const Station *st = GetStation(w->window_number);
- ShowVehicleListWindow(st->owner, VEH_ROAD, (StationID)w->window_number);
- break;
- }
+ this->SetDirty();
+ break;
- case SVW_PLANES: { // Show a list of scheduled aircraft to this station
- const Station *st = GetStation(w->window_number);
- /* Since oilrigs have no owners, show the scheduled aircraft of current player */
- PlayerID owner = (st->owner == OWNER_NONE) ? _current_player : st->owner;
- ShowVehicleListWindow(owner, VEH_AIRCRAFT, (StationID)w->window_number);
- break;
- }
+ case SVW_RENAME:
+ SetDParam(0, this->window_number);
+ ShowQueryString(STR_STATION, STR_3030_RENAME_STATION_LOADING, 31, 180, this, CS_ALPHANUMERAL);
+ break;
- case SVW_SHIPS: { // Show a list of scheduled ships to this station
- const Station *st = GetStation(w->window_number);
- /* Since oilrigs/bouys have no owners, show the scheduled ships of current player */
- PlayerID owner = (st->owner == OWNER_NONE) ? _current_player : st->owner;
- ShowVehicleListWindow(owner, VEH_SHIP, (StationID)w->window_number);
- break;
- }
+ case SVW_TRAINS: { // Show a list of scheduled trains to this station
+ const Station *st = GetStation(this->window_number);
+ ShowVehicleListWindow(st->owner, VEH_TRAIN, (StationID)this->window_number);
+ break;
}
- break;
- case WE_ON_EDIT_TEXT:
- if (!StrEmpty(e->we.edittext.str)) {
- _cmd_text = e->we.edittext.str;
- DoCommandP(0, w->window_number, 0, NULL,
- CMD_RENAME_STATION | CMD_MSG(STR_3031_CAN_T_RENAME_STATION));
+ case SVW_ROADVEHS: { // Show a list of scheduled road-vehicles to this station
+ const Station *st = GetStation(this->window_number);
+ ShowVehicleListWindow(st->owner, VEH_ROAD, (StationID)this->window_number);
+ break;
+ }
+
+ case SVW_PLANES: { // Show a list of scheduled aircraft to this station
+ const Station *st = GetStation(this->window_number);
+ /* Since oilrigs have no owners, show the scheduled aircraft of current player */
+ PlayerID owner = (st->owner == OWNER_NONE) ? _current_player : st->owner;
+ ShowVehicleListWindow(owner, VEH_AIRCRAFT, (StationID)this->window_number);
+ break;
}
- break;
- case WE_DESTROY: {
- WindowNumber wno =
- (w->window_number << 16) | VLW_STATION_LIST | GetStation(w->window_number)->owner;
+ case SVW_SHIPS: { // Show a list of scheduled ships to this station
+ const Station *st = GetStation(this->window_number);
+ /* Since oilrigs/bouys have no owners, show the scheduled ships of current player */
+ PlayerID owner = (st->owner == OWNER_NONE) ? _current_player : st->owner;
+ ShowVehicleListWindow(owner, VEH_SHIP, (StationID)this->window_number);
+ break;
+ }
+ }
+ }
- DeleteWindowById(WC_TRAINS_LIST, wno);
- DeleteWindowById(WC_ROADVEH_LIST, wno);
- DeleteWindowById(WC_SHIPS_LIST, wno);
- DeleteWindowById(WC_AIRCRAFT_LIST, wno);
- break;
+ virtual void OnQueryTextFinished(char *str)
+ {
+ if (!StrEmpty(str)) {
+ _cmd_text = str;
+ DoCommandP(0, this->window_number, 0, NULL,
+ CMD_RENAME_STATION | CMD_MSG(STR_3031_CAN_T_RENAME_STATION));
}
+ }
- case WE_RESIZE:
- if (e->we.sizing.diff.x != 0) ResizeButtons(w, SVW_LOCATION, SVW_RENAME);
- w->vscroll.cap += e->we.sizing.diff.y / (int)w->resize.step_height;
- break;
+ virtual void OnResize(Point new_size, Point delta)
+ {
+ if (delta.x != 0) ResizeButtons(this, SVW_LOCATION, SVW_RENAME);
+ this->vscroll.cap += delta.y / (int)this->resize.step_height;
}
-}
+};
static const WindowDesc _station_view_desc = {
@@ -1034,7 +1028,7 @@ static const WindowDesc _station_view_desc = {
WC_STATION_VIEW, WC_NONE,
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON | WDF_RESIZABLE,
_station_view_widgets,
- StationViewWndProc
+ NULL
};
/**
@@ -1044,11 +1038,5 @@ static const WindowDesc _station_view_desc = {
*/
void ShowStationViewWindow(StationID station)
{
- Window *w = AllocateWindowDescFront<Window>(&_station_view_desc, station);
- if (w == NULL) return;
-
- PlayerID owner = GetStation(w->window_number)->owner;
- if (owner != OWNER_NONE) w->caption_color = owner;
- w->vscroll.cap = 5;
- w->resize.step_height = 10;
+ AllocateWindowDescFront<StationViewWindow>(&_station_view_desc, station);
}