(svn r13056) [NoAI] -Sync: with trunk r12996:13055.
--- a/config.lib Wed May 07 21:09:51 2008 +0000
+++ b/config.lib Sun May 11 20:09:34 2008 +0000
@@ -921,7 +921,7 @@
if [ $cc_version -ge 29 ]; then
CFLAGS="$CFLAGS -Wall -Wno-multichar -Wsign-compare -Wundef"
CFLAGS="$CFLAGS -Wwrite-strings -Wpointer-arith"
- CFLAGS="$CFLAGS -Wno-uninitialized -Wredundant-decls"
+ CFLAGS="$CFLAGS -Wno-uninitialized"
CC_CFLAGS="$CC_CFLAGS -Wstrict-prototypes"
fi
@@ -935,6 +935,7 @@
if [ $cc_version -ge 30 ]; then
CFLAGS="$CFLAGS -W -Wno-unused-parameter -Wformat=2"
+ CFLAGS="$CFLAGS -Wredundant-decls"
fi
if [ $cc_version -ge 34 ]; then
--- a/projects/openttd_vs80.vcproj Wed May 07 21:09:51 2008 +0000
+++ b/projects/openttd_vs80.vcproj Sun May 11 20:09:34 2008 +0000
@@ -468,10 +468,6 @@
>
</File>
<File
- RelativePath=".\..\src\autoreplace_cmd.cpp"
- >
- </File>
- <File
RelativePath=".\..\src\aystar.cpp"
>
</File>
@@ -500,10 +496,6 @@
>
</File>
<File
- RelativePath=".\..\src\cheat_gui.cpp"
- >
- </File>
- <File
RelativePath=".\..\src\command.cpp"
>
</File>
@@ -732,10 +724,6 @@
>
</File>
<File
- RelativePath=".\..\src\statusbar_gui.cpp"
- >
- </File>
- <File
RelativePath=".\..\src\string.cpp"
>
</File>
@@ -980,6 +968,10 @@
>
</File>
<File
+ RelativePath=".\..\src\elrail_func.h"
+ >
+ </File>
+ <File
RelativePath=".\..\src\core\endian_func.hpp"
>
</File>
@@ -1664,6 +1656,10 @@
>
</File>
<File
+ RelativePath=".\..\src\cheat_gui.cpp"
+ >
+ </File>
+ <File
RelativePath=".\..\src\depot_gui.cpp"
>
</File>
@@ -1764,6 +1760,10 @@
>
</File>
<File
+ RelativePath=".\..\src\statusbar_gui.cpp"
+ >
+ </File>
+ <File
RelativePath=".\..\src\subsidy_gui.cpp"
>
</File>
@@ -1792,18 +1792,26 @@
>
</File>
<File
+ RelativePath=".\..\src\tree_gui.cpp"
+ >
+ </File>
+ <File
RelativePath=".\..\src\vehicle_gui.cpp"
>
</File>
</Filter>
<Filter
- Name="Landscape"
+ Name="Command handlers"
>
<File
RelativePath=".\..\src\aircraft_cmd.cpp"
>
</File>
<File
+ RelativePath=".\..\src\autoreplace_cmd.cpp"
+ >
+ </File>
+ <File
RelativePath=".\..\src\clear_cmd.cpp"
>
</File>
--- a/projects/openttd_vs90.vcproj Wed May 07 21:09:51 2008 +0000
+++ b/projects/openttd_vs90.vcproj Sun May 11 20:09:34 2008 +0000
@@ -465,10 +465,6 @@
>
</File>
<File
- RelativePath=".\..\src\autoreplace_cmd.cpp"
- >
- </File>
- <File
RelativePath=".\..\src\aystar.cpp"
>
</File>
@@ -497,10 +493,6 @@
>
</File>
<File
- RelativePath=".\..\src\cheat_gui.cpp"
- >
- </File>
- <File
RelativePath=".\..\src\command.cpp"
>
</File>
@@ -729,10 +721,6 @@
>
</File>
<File
- RelativePath=".\..\src\statusbar_gui.cpp"
- >
- </File>
- <File
RelativePath=".\..\src\string.cpp"
>
</File>
@@ -977,6 +965,10 @@
>
</File>
<File
+ RelativePath=".\..\src\elrail_func.h"
+ >
+ </File>
+ <File
RelativePath=".\..\src\core\endian_func.hpp"
>
</File>
@@ -1661,6 +1653,10 @@
>
</File>
<File
+ RelativePath=".\..\src\cheat_gui.cpp"
+ >
+ </File>
+ <File
RelativePath=".\..\src\depot_gui.cpp"
>
</File>
@@ -1761,6 +1757,10 @@
>
</File>
<File
+ RelativePath=".\..\src\statusbar_gui.cpp"
+ >
+ </File>
+ <File
RelativePath=".\..\src\subsidy_gui.cpp"
>
</File>
@@ -1789,18 +1789,26 @@
>
</File>
<File
+ RelativePath=".\..\src\tree_gui.cpp"
+ >
+ </File>
+ <File
RelativePath=".\..\src\vehicle_gui.cpp"
>
</File>
</Filter>
<Filter
- Name="Landscape"
+ Name="Command handlers"
>
<File
RelativePath=".\..\src\aircraft_cmd.cpp"
>
</File>
<File
+ RelativePath=".\..\src\autoreplace_cmd.cpp"
+ >
+ </File>
+ <File
RelativePath=".\..\src\clear_cmd.cpp"
>
</File>
--- a/source.list Wed May 07 21:09:51 2008 +0000
+++ b/source.list Sun May 11 20:09:34 2008 +0000
@@ -3,7 +3,6 @@
core/alloc_func.cpp
animated_tile.cpp
articulated_vehicles.cpp
-autoreplace_cmd.cpp
aystar.cpp
core/bitmath_func.cpp
bmp.cpp
@@ -11,7 +10,6 @@
cargopacket.cpp
cargotype.cpp
cheat.cpp
-cheat_gui.cpp
command.cpp
console.cpp
console_cmds.cpp
@@ -76,7 +74,6 @@
sound.cpp
spritecache.cpp
station.cpp
-statusbar_gui.cpp
string.cpp
strings.cpp
squirrel.cpp
@@ -170,6 +167,7 @@
economy_type.h
effectvehicle_func.h
effectvehicle_base.h
+elrail_func.h
core/endian_func.hpp
engine_base.h
engine_func.h
@@ -356,6 +354,7 @@
autoreplace_gui.cpp
bridge_gui.cpp
build_vehicle_gui.cpp
+cheat_gui.cpp
depot_gui.cpp
dock_gui.cpp
engine_gui.cpp
@@ -381,6 +380,7 @@
signs_gui.cpp
smallmap_gui.cpp
station_gui.cpp
+statusbar_gui.cpp
subsidy_gui.cpp
terraform_gui.cpp
timetable_gui.cpp
@@ -388,10 +388,12 @@
town_gui.cpp
train_gui.cpp
transparency_gui.cpp
+tree_gui.cpp
vehicle_gui.cpp
-# Landscape
+# Command handlers
aircraft_cmd.cpp
+autoreplace_cmd.cpp
clear_cmd.cpp
disaster_cmd.cpp
dummy_land.cpp
--- a/src/ai/ai_gui.cpp Wed May 07 21:09:51 2008 +0000
+++ b/src/ai/ai_gui.cpp Sun May 11 20:09:34 2008 +0000
@@ -254,5 +254,5 @@
void ShowAIDebugWindow()
{
- AllocateWindowDescFront(&_ai_debug_desc, 0);
+ AllocateWindowDescFront<Window>(&_ai_debug_desc, 0);
}
--- a/src/ai/api/ai_airport.cpp Wed May 07 21:09:51 2008 +0000
+++ b/src/ai/api/ai_airport.cpp Sun May 11 20:09:34 2008 +0000
@@ -9,6 +9,7 @@
#include "../../station_map.h"
#include "../../player_func.h"
#include "../../settings_type.h"
+#include "../../command_type.h"
/* static */ bool AIAirport::IsHangarTile(TileIndex tile)
{
--- a/src/ai/api/ai_road.cpp Wed May 07 21:09:51 2008 +0000
+++ b/src/ai/api/ai_road.cpp Sun May 11 20:09:34 2008 +0000
@@ -6,6 +6,7 @@
#include "../../openttd.h"
#include "../../road_map.h"
#include "../../station_map.h"
+#include "../../command_type.h"
/* static */ bool AIRoad::IsRoadTile(TileIndex tile)
{
--- a/src/airport_gui.cpp Wed May 07 21:09:51 2008 +0000
+++ b/src/airport_gui.cpp Sun May 11 20:09:34 2008 +0000
@@ -95,7 +95,7 @@
case WE_PLACE_MOUSEUP:
if (e->we.place.pt.x != -1 && e->we.place.select_proc == DDSP_DEMOLISH_AREA) {
- DoCommandP(e->we.place.tile, e->we.place.starttile, 0, CcPlaySound10, CMD_CLEAR_AREA | CMD_MSG(STR_00B5_CAN_T_CLEAR_THIS_AREA));
+ GUIPlaceProcDragXY(e);
}
break;
@@ -136,7 +136,7 @@
if (!IsValidPlayer(_current_player)) return;
DeleteWindowByClass(WC_BUILD_TOOLBAR);
- Window *w = AllocateWindowDescFront(&_air_toolbar_desc, TRANSPORT_AIR);
+ Window *w = AllocateWindowDescFront<Window>(&_air_toolbar_desc, TRANSPORT_AIR);
if (_patches.link_terraform_toolbar) ShowTerraformToolbar(w);
}
@@ -230,7 +230,7 @@
}
} break;
- case WE_MOUSELOOP: {
+ case WE_TICK: {
if (WP(w, def_d).close) {
delete w;
return;
@@ -282,7 +282,7 @@
static void ShowBuildAirportPicker()
{
- AllocateWindowDesc(&_build_airport_desc);
+ new Window(&_build_airport_desc);
}
void InitializeAirportGui()
--- a/src/autoreplace_cmd.cpp Wed May 07 21:09:51 2008 +0000
+++ b/src/autoreplace_cmd.cpp Sun May 11 20:09:34 2008 +0000
@@ -244,11 +244,13 @@
}
}
}
- /* We are done setting up the new vehicle. Now we move the cargo from the old one to the new one */
- MoveVehicleCargo(new_v->type == VEH_TRAIN ? new_v->First() : new_v, old_v);
+ if (CmdSucceeded(cost)) {
+ /* We are done setting up the new vehicle. Now we move the cargo from the old one to the new one */
+ MoveVehicleCargo(new_v->type == VEH_TRAIN ? new_v->First() : new_v, old_v);
- // Get the name of the old vehicle if it has a custom name.
- if (old_v->name != NULL) vehicle_name = strdup(old_v->name);
+ /* Get the name of the old vehicle if it has a custom name. */
+ if (old_v->name != NULL) vehicle_name = strdup(old_v->name);
+ }
} else { // flags & DC_EXEC not set
CommandCost tmp_move;
@@ -282,6 +284,8 @@
/* sell the engine/ find out how much you get for the old engine (income is returned as negative cost) */
cost.AddCost(DoCommand(0, old_v->index, 0, flags, GetCmdSellVeh(old_v)));
+ if (CmdFailed(cost)) return cost;
+
if (new_front) {
/* now we assign the old unitnumber to the new vehicle */
new_v->unitnumber = cached_unitnumber;
@@ -423,19 +427,23 @@
/* We are going to try to replace a vehicle but we don't have any backup so we will make one. */
backup.Backup(v, p);
}
- /* Now replace the vehicle */
+ /* Now replace the vehicle.
+ * First we need to cache if it's the front vehicle as we need to update the v pointer if it is.
+ * If the replacement fails then we can't trust the data in the vehicle hence the reason to cache the result. */
+ bool IsFront = w->type != VEH_TRAIN || w->u.rail.first_engine == INVALID_ENGINE;
+
cost.AddCost(ReplaceVehicle(&w, DC_EXEC, cost.GetCost(), p, new_engine));
- if (w->type != VEH_TRAIN || w->u.rail.first_engine == INVALID_ENGINE) {
+ if (IsFront) {
/* now we bought a new engine and sold the old one. We need to fix the
* pointers in order to avoid pointing to the old one for trains: these
* pointers should point to the front engine and not the cars
*/
v = w;
}
- } while (w->type == VEH_TRAIN && (w = GetNextVehicle(w)) != NULL);
+ } while (CmdSucceeded(cost) && w->type == VEH_TRAIN && (w = GetNextVehicle(w)) != NULL);
- if (v->type == VEH_TRAIN && p->renew_keep_length) {
+ if (CmdSucceeded(cost) && v->type == VEH_TRAIN && p->renew_keep_length) {
/* Remove wagons until the wanted length is reached */
cost.AddCost(WagonRemoval(v, old_total_length));
}
--- a/src/autoreplace_gui.cpp Wed May 07 21:09:51 2008 +0000
+++ b/src/autoreplace_gui.cpp Sun May 11 20:09:34 2008 +0000
@@ -25,23 +25,7 @@
#include "table/sprites.h"
#include "table/strings.h"
-struct replaceveh_d {
- byte sel_index[2];
- EngineID sel_engine[2];
- uint16 count[2];
- bool wagon_btnstate; ///< true means engine is selected
- EngineList list[2];
- bool update_left;
- bool update_right;
- bool init_lists;
- GroupID sel_group;
-};
-assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(replaceveh_d));
-
-static RailType _railtype_selected_in_replace_gui;
-
-static bool _rebuild_left_list;
-static bool _rebuild_right_list;
+void DrawEngineList(VehicleType type, int x, int y, const EngineList eng_list, uint16 min, uint16 max, EngineID selected_id, int count_location, GroupID selected_group);
static const StringID _rail_types_list[] = {
STR_RAIL_VEHICLES,
@@ -82,12 +66,6 @@
return r;
}
-/* General Vehicle GUI based procedures that are independent of vehicle types */
-void InitializeVehiclesGuiList()
-{
- _railtype_selected_in_replace_gui = RAILTYPE_RAIL;
-}
-
/** Rebuild the left autoreplace list if an engine is removed or added
* @param e Engine to check if it is removed or added
* @param id_g The group the engine belongs to
@@ -99,19 +77,14 @@
void InvalidateAutoreplaceWindow(EngineID e, GroupID id_g)
{
Player *p = GetPlayer(_local_player);
- VehicleType type = GetEngine(e)->type;
uint num_engines = GetGroupNumEngines(_local_player, id_g, e);
if (num_engines == 0 || p->num_engines[e] == 0) {
/* We don't have any of this engine type.
* Either we just sold the last one, we build a new one or we stopped replacing it.
* In all cases, we need to update the left list */
- _rebuild_left_list = true;
- } else {
- _rebuild_left_list = false;
+ InvalidateWindowData(WC_REPLACE_VEHICLE, GetEngine(e)->type, true);
}
- _rebuild_right_list = false;
- InvalidateWindowData(WC_REPLACE_VEHICLE, type);
}
/** When an engine is made buildable or is removed from being buildable, add/remove it from the build/autoreplace lists
@@ -119,9 +92,7 @@
*/
void AddRemoveEngineFromAutoreplaceAndBuildWindows(VehicleType type)
{
- _rebuild_left_list = false; // left list is only for the vehicles the player owns and is not related to being buildable
- _rebuild_right_list = true;
- InvalidateWindowData(WC_REPLACE_VEHICLE, type); // Update the autoreplace window
+ InvalidateWindowData(WC_REPLACE_VEHICLE, type, false); // Update the autoreplace window
InvalidateWindowClassesData(WC_BUILD_VEHICLE); // The build windows needs updating as well
}
@@ -144,30 +115,6 @@
}
}
-/** Figure out if an engine should be added to a list
- * @param e The EngineID
- * @param draw_left If true, then the left list is drawn (the engines specific to the railtype you selected)
- * @param show_engines if truem then locomotives are drawn, else wagons (never both)
- * @return true if the engine should be in the list (based on this check)
- */
-static bool GenerateReplaceRailList(EngineID e, bool draw_left, bool show_engines)
-{
- const RailVehicleInfo *rvi = RailVehInfo(e);
-
- /* Ensure that the wagon/engine selection fits the engine. */
- if ((rvi->railveh_type == RAILVEH_WAGON) == show_engines) return false;
-
- if (draw_left && show_engines) {
- /* Ensure that the railtype is specific to the selected one */
- if (rvi->railtype != _railtype_selected_in_replace_gui) return false;
- } else {
- /* Ensure that it's a compatible railtype to the selected one (like electric <-> diesel)
- * The vehicle do not have to have power on the railtype in question, only able to drive (pulled if needed) */
- if (!IsCompatibleRail(rvi->railtype, _railtype_selected_in_replace_gui)) return false;
- }
- return true;
-}
-
/** Figure out if two engines got at least one type of cargo in common (refitting if needed)
* @param engine_a one of the EngineIDs
* @param engine_b the other EngineID
@@ -186,301 +133,374 @@
return false;
}
-/** Generate a list
- * @param w Window, that contains the list
- * @param draw_left true if generating the left list, otherwise false
+/**
+ * Window for the autoreplacing of vehicles.
*/
-static void GenerateReplaceVehList(Window *w, bool draw_left)
-{
- EngineID selected_engine = INVALID_ENGINE;
- VehicleType type = (VehicleType)w->window_number;
- byte i = draw_left ? 0 : 1;
-
- EngineList *list = &WP(w, replaceveh_d).list[i];
- list->clear();
+class ReplaceVehicleWindow : public Window {
+ byte sel_index[2];
+ EngineID sel_engine[2];
+ uint16 count[2];
+ bool wagon_btnstate; ///< true means engine is selected
+ EngineList list[2];
+ bool update_left;
+ bool update_right;
+ bool init_lists;
+ GroupID sel_group;
+ static RailType sel_railtype;
- const Engine *e;
- FOR_ALL_ENGINES_OF_TYPE(e, type) {
- EngineID eid = e->index;
- if (type == VEH_TRAIN && !GenerateReplaceRailList(eid, draw_left, WP(w, replaceveh_d).wagon_btnstate)) continue; // special rules for trains
-
- if (draw_left) {
- const GroupID selected_group = WP(w, replaceveh_d).sel_group;
- const uint num_engines = GetGroupNumEngines(_local_player, selected_group, eid);
+ /** Figure out if an engine should be added to a list
+ * @param e The EngineID
+ * @param draw_left If true, then the left list is drawn (the engines specific to the railtype you selected)
+ * @param show_engines if truem then locomotives are drawn, else wagons (never both)
+ * @return true if the engine should be in the list (based on this check)
+ */
+ bool GenerateReplaceRailList(EngineID e, bool draw_left, bool show_engines)
+ {
+ const RailVehicleInfo *rvi = RailVehInfo(e);
- /* Skip drawing the engines we don't have any of and haven't set for replacement */
- if (num_engines == 0 && EngineReplacementForPlayer(GetPlayer(_local_player), eid, selected_group) == INVALID_ENGINE) continue;
+ /* Ensure that the wagon/engine selection fits the engine. */
+ if ((rvi->railveh_type == RAILVEH_WAGON) == show_engines) return false;
+
+ if (draw_left && show_engines) {
+ /* Ensure that the railtype is specific to the selected one */
+ if (rvi->railtype != this->sel_railtype) return false;
} else {
- /* This is for engines we can replace to and they should depend on what we selected to replace from */
- if (!IsEngineBuildable(eid, type, _local_player)) continue; // we need to be able to build the engine
- if (!EnginesGotCargoInCommon(eid, WP(w, replaceveh_d).sel_engine[0])) continue; // the engines needs to be able to carry the same cargo
+ /* Ensure that it's a compatible railtype to the selected one (like electric <-> diesel)
+ * The vehicle do not have to have power on the railtype in question, only able to drive (pulled if needed) */
+ if (!IsCompatibleRail(rvi->railtype, this->sel_railtype)) return false;
+ }
+ return true;
+ }
- /* Road vehicles can't be replaced by trams and vice-versa */
- if (type == VEH_ROAD && HasBit(EngInfo(WP(w, replaceveh_d).sel_engine[0])->misc_flags, EF_ROAD_TRAM) != HasBit(e->info.misc_flags, EF_ROAD_TRAM)) continue;
- if (eid == WP(w, replaceveh_d).sel_engine[0]) continue; // we can't replace an engine into itself (that would be autorenew)
+
+ /** Generate a list
+ * @param w Window, that contains the list
+ * @param draw_left true if generating the left list, otherwise false
+ */
+ void GenerateReplaceVehList(Window *w, bool draw_left)
+ {
+ EngineID selected_engine = INVALID_ENGINE;
+ VehicleType type = (VehicleType)this->window_number;
+ byte i = draw_left ? 0 : 1;
+
+ EngineList *list = &this->list[i];
+ list->clear();
+
+ const Engine *e;
+ FOR_ALL_ENGINES_OF_TYPE(e, type) {
+ EngineID eid = e->index;
+ if (type == VEH_TRAIN && !GenerateReplaceRailList(eid, draw_left, this->wagon_btnstate)) continue; // special rules for trains
+
+ if (draw_left) {
+ const GroupID selected_group = this->sel_group;
+ const uint num_engines = GetGroupNumEngines(_local_player, selected_group, eid);
+
+ /* Skip drawing the engines we don't have any of and haven't set for replacement */
+ if (num_engines == 0 && EngineReplacementForPlayer(GetPlayer(_local_player), eid, selected_group) == INVALID_ENGINE) continue;
+ } else {
+ /* This is for engines we can replace to and they should depend on what we selected to replace from */
+ if (!IsEngineBuildable(eid, type, _local_player)) continue; // we need to be able to build the engine
+ if (!EnginesGotCargoInCommon(eid, this->sel_engine[0])) continue; // the engines needs to be able to carry the same cargo
+
+ /* Road vehicles can't be replaced by trams and vice-versa */
+ if (type == VEH_ROAD && HasBit(EngInfo(this->sel_engine[0])->misc_flags, EF_ROAD_TRAM) != HasBit(e->info.misc_flags, EF_ROAD_TRAM)) continue;
+ if (eid == this->sel_engine[0]) continue; // we can't replace an engine into itself (that would be autorenew)
+ }
+
+ list->push_back(eid);
+ if (eid == this->sel_engine[i]) selected_engine = eid; // The selected engine is still in the list
+ }
+ this->sel_engine[i] = selected_engine; // update which engine we selected (the same or none, if it's not in the list anymore)
+ if (type == VEH_TRAIN) EngList_Sort(list, &TrainEngineNumberSorter);
+ }
+
+ /** Generate the lists */
+ void GenerateLists()
+ {
+ EngineID e = this->sel_engine[0];
+
+ if (this->update_left == true) {
+ /* We need to rebuild the left list */
+ GenerateReplaceVehList(this, true);
+ SetVScrollCount(this, this->list[0].size());
+ if (this->init_lists && this->sel_engine[0] == INVALID_ENGINE && this->list[0].size() != 0) {
+ this->sel_engine[0] = this->list[0][0];
+ }
}
- list->push_back(eid);
- if (eid == WP(w, replaceveh_d).sel_engine[i]) selected_engine = eid; // The selected engine is still in the list
- }
- WP(w, replaceveh_d).sel_engine[i] = selected_engine; // update which engine we selected (the same or none, if it's not in the list anymore)
- if (type == VEH_TRAIN) EngList_Sort(list, &TrainEngineNumberSorter);
-}
-
-/** Generate the lists
- * @param w Window containing the lists
- */
-static void GenerateLists(Window *w)
-{
- EngineID e = WP(w, replaceveh_d).sel_engine[0];
-
- if (WP(w, replaceveh_d).update_left == true) {
- /* We need to rebuild the left list */
- GenerateReplaceVehList(w, true);
- SetVScrollCount(w, WP(w, replaceveh_d).list[0].size());
- if (WP(w, replaceveh_d).init_lists && WP(w, replaceveh_d).sel_engine[0] == INVALID_ENGINE && WP(w, replaceveh_d).list[0].size() != 0) {
- WP(w, replaceveh_d).sel_engine[0] = WP(w, replaceveh_d).list[0][0];
+ if (this->update_right || e != this->sel_engine[0]) {
+ /* Either we got a request to rebuild the right list or the left list selected a different engine */
+ if (this->sel_engine[0] == INVALID_ENGINE) {
+ /* Always empty the right list when nothing is selected in the left list */
+ this->list[1].clear();
+ this->sel_engine[1] = INVALID_ENGINE;
+ } else {
+ GenerateReplaceVehList(this, false);
+ SetVScroll2Count(this, this->list[1].size());
+ if (this->init_lists && this->sel_engine[1] == INVALID_ENGINE && this->list[1].size() != 0) {
+ this->sel_engine[1] = this->list[1][0];
+ }
+ }
}
+ /* Reset the flags about needed updates */
+ this->update_left = false;
+ this->update_right = false;
+ this->init_lists = false;
}
- if (WP(w, replaceveh_d).update_right || e != WP(w, replaceveh_d).sel_engine[0]) {
- /* Either we got a request to rebuild the right list or the left list selected a different engine */
- if (WP(w, replaceveh_d).sel_engine[0] == INVALID_ENGINE) {
- /* Always empty the right list when nothing is selected in the left list */
- WP(w, replaceveh_d).list[1].clear();
- WP(w, replaceveh_d).sel_engine[1] = INVALID_ENGINE;
+public:
+ ReplaceVehicleWindow(const WindowDesc *desc, VehicleType vehicletype, GroupID id_g) : Window(desc, NULL, window_number)
+ {
+ this->wagon_btnstate = true; // start with locomotives (all other vehicles will not read this bool)
+ new (&this->list[0]) EngineList();
+ new (&this->list[1]) EngineList();
+ this->update_left = true;
+ this->update_right = true;
+ this->init_lists = true;
+ this->sel_engine[0] = INVALID_ENGINE;
+ this->sel_engine[1] = INVALID_ENGINE;
+
+ this->resize.step_height = GetVehicleListHeight(vehicletype);
+ this->vscroll.cap = this->resize.step_height == 14 ? 8 : 4;
+
+ Widget *widget = this->widget;
+ widget[RVW_WIDGET_LEFT_MATRIX].data = widget[RVW_WIDGET_RIGHT_MATRIX].data = (this->vscroll.cap << 8) + 1;
+
+ if (vehicletype == VEH_TRAIN) {
+ this->wagon_btnstate = true;
+ /* The train window is bigger so we will move some of the widgets to fit the new size.
+ * We will start by moving the resize button to the lower right corner. */
+ widget[RVW_WIDGET_RESIZE].top = widget[RVW_WIDGET_TRAIN_ENGINEWAGON_TOGGLE].top;
+ widget[RVW_WIDGET_RESIZE].bottom = widget[RVW_WIDGET_TRAIN_ENGINEWAGON_TOGGLE].bottom;
+ widget[RVW_WIDGET_STOP_REPLACE].right = widget[RVW_WIDGET_RESIZE].right;
+
+ /* The detail panel is one line taller for trains so we will move some of the widgets one line (10 pixels) down. */
+ widget[RVW_WIDGET_LEFT_DETAILS].bottom += 10;
+ widget[RVW_WIDGET_RIGHT_DETAILS].bottom += 10;
+ for (int i = RVW_WIDGET_START_REPLACE; i < RVW_WIDGET_RESIZE; i++) {
+ widget[i].top += 10;
+ widget[i].bottom += 10;
+ }
} else {
- GenerateReplaceVehList(w, false);
- SetVScroll2Count(w, WP(w, replaceveh_d).list[1].size());
- if (WP(w, replaceveh_d).init_lists && WP(w, replaceveh_d).sel_engine[1] == INVALID_ENGINE && WP(w, replaceveh_d).list[1].size() != 0) {
- WP(w, replaceveh_d).sel_engine[1] = WP(w, replaceveh_d).list[1][0];
+ /* Since it's not a train we will hide the train only widgets. */
+ this->SetWidgetsHiddenState(true,
+ RVW_WIDGET_TRAIN_ENGINEWAGON_TOGGLE,
+ RVW_WIDGET_TRAIN_FLUFF_LEFT,
+ RVW_WIDGET_TRAIN_RAILTYPE_DROPDOWN,
+ RVW_WIDGET_TRAIN_FLUFF_RIGHT,
+ RVW_WIDGET_TRAIN_WAGONREMOVE_TOGGLE,
+ WIDGET_LIST_END);
+ }
+
+ ResizeWindow(this, 0, this->resize.step_height * this->vscroll.cap);
+
+ /* Set the minimum window size to the current window size */
+ this->resize.width = this->width;
+ this->resize.height = this->height;
+
+ this->caption_color = _local_player;
+ this->sel_group = id_g;
+ this->vscroll2.cap = this->vscroll.cap; // these two are always the same
+
+ this->FindWindowPlacementAndResize(desc);
+ }
+
+ virtual void OnPaint()
+ {
+ static const StringID _vehicle_type_names[] = {
+ STR_019F_TRAIN,
+ STR_019C_ROAD_VEHICLE,
+ STR_019E_SHIP,
+ STR_019D_AIRCRAFT
+ };
+
+ if (this->update_left || this->update_right) this->GenerateLists();
+
+ Player *p = GetPlayer(_local_player);
+ EngineID selected_id[2];
+ const GroupID selected_group = this->sel_group;
+
+ selected_id[0] = this->sel_engine[0];
+ selected_id[1] = this->sel_engine[1];
+
+ /* Disable the "Start Replacing" button if:
+ * Either list is empty
+ * or The selected replacement engine has a replacement (to prevent loops)
+ * or The right list (new replacement) has the existing replacement vehicle selected */
+ this->SetWidgetDisabledState(RVW_WIDGET_START_REPLACE,
+ selected_id[0] == INVALID_ENGINE ||
+ selected_id[1] == INVALID_ENGINE ||
+ EngineReplacementForPlayer(p, selected_id[1], selected_group) != INVALID_ENGINE ||
+ EngineReplacementForPlayer(p, selected_id[0], selected_group) == selected_id[1]);
+
+ /* Disable the "Stop Replacing" button if:
+ * The left list (existing vehicle) is empty
+ * or The selected vehicle has no replacement set up */
+ this->SetWidgetDisabledState(RVW_WIDGET_STOP_REPLACE,
+ selected_id[0] == INVALID_ENGINE ||
+ !EngineHasReplacementForPlayer(p, selected_id[0], selected_group));
+
+ /* now the actual drawing of the window itself takes place */
+ SetDParam(0, _vehicle_type_names[this->window_number]);
+
+ if (this->window_number == VEH_TRAIN) {
+ /* set on/off for renew_keep_length */
+ SetDParam(1, p->renew_keep_length ? STR_CONFIG_PATCHES_ON : STR_CONFIG_PATCHES_OFF);
+
+ /* set wagon/engine button */
+ SetDParam(2, this->wagon_btnstate ? STR_ENGINES : STR_WAGONS);
+
+ /* sets the colour of that art thing */
+ this->widget[RVW_WIDGET_TRAIN_FLUFF_LEFT].color = _player_colors[_local_player];
+ this->widget[RVW_WIDGET_TRAIN_FLUFF_RIGHT].color = _player_colors[_local_player];
+ }
+
+ if (this->window_number == VEH_TRAIN) {
+ /* Show the selected railtype in the pulldown menu */
+ this->widget[RVW_WIDGET_TRAIN_RAILTYPE_DROPDOWN].data = _rail_types_list[sel_railtype];
+ }
+
+ DrawWindowWidgets(this);
+
+ /* sets up the string for the vehicle that is being replaced to */
+ if (selected_id[0] != INVALID_ENGINE) {
+ if (!EngineHasReplacementForPlayer(p, selected_id[0], selected_group)) {
+ SetDParam(0, STR_NOT_REPLACING);
+ } else {
+ SetDParam(0, STR_ENGINE_NAME);
+ SetDParam(1, EngineReplacementForPlayer(p, selected_id[0], selected_group));
+ }
+ } else {
+ SetDParam(0, STR_NOT_REPLACING_VEHICLE_SELECTED);
+ }
+
+ DrawString(145, this->widget[RVW_WIDGET_INFO_TAB].top + 1, STR_02BD, TC_BLACK);
+
+ /* Draw the lists */
+ for (byte i = 0; i < 2; i++) {
+ uint widget = (i == 0) ? RVW_WIDGET_LEFT_MATRIX : RVW_WIDGET_RIGHT_MATRIX;
+ EngineList list = this->list[i]; // which list to draw
+ EngineID start = i == 0 ? this->vscroll.pos : this->vscroll2.pos; // what is the offset for the start (scrolling)
+ EngineID end = min((i == 0 ? this->vscroll.cap : this->vscroll2.cap) + start, list.size());
+
+ /* Do the actual drawing */
+ DrawEngineList((VehicleType)this->window_number, this->widget[widget].left + 2, this->widget[widget].top + 1, list, start, end, this->sel_engine[i], i == 0 ? this->widget[RVW_WIDGET_LEFT_MATRIX].right - 2 : 0, selected_group);
+
+ /* Also draw the details if an engine is selected */
+ if (this->sel_engine[i] != INVALID_ENGINE) {
+ const Widget *wi = &this->widget[i == 0 ? RVW_WIDGET_LEFT_DETAILS : RVW_WIDGET_RIGHT_DETAILS];
+ int text_end = DrawVehiclePurchaseInfo(wi->left + 2, wi->top + 1, wi->right - wi->left - 2, this->sel_engine[i]);
+
+ if (text_end > wi->bottom) {
+ this->SetDirty();
+ ResizeWindowForWidget(this, i == 0 ? RVW_WIDGET_LEFT_DETAILS : RVW_WIDGET_RIGHT_DETAILS, 0, text_end - wi->bottom);
+ this->SetDirty();
+ }
}
}
}
- /* Reset the flags about needed updates */
- WP(w, replaceveh_d).update_left = false;
- WP(w, replaceveh_d).update_right = false;
- WP(w, replaceveh_d).init_lists = false;
-}
-
-
-void DrawEngineList(VehicleType type, int x, int y, const EngineList eng_list, uint16 min, uint16 max, EngineID selected_id, int count_location, GroupID selected_group);
-
-static void ReplaceVehicleWndProc(Window *w, WindowEvent *e)
-{
- /* Strings for the pulldown menu */
- static const StringID _vehicle_type_names[] = {
- STR_019F_TRAIN,
- STR_019C_ROAD_VEHICLE,
- STR_019E_SHIP,
- STR_019D_AIRCRAFT
- };
-
- switch (e->event) {
- case WE_CREATE:
- WP(w, replaceveh_d).wagon_btnstate = true; // start with locomotives (all other vehicles will not read this bool)
- new (&WP(w, replaceveh_d).list[0]) EngineList();
- new (&WP(w, replaceveh_d).list[1]) EngineList();
- WP(w, replaceveh_d).update_left = true;
- WP(w, replaceveh_d).update_right = true;
- WP(w, replaceveh_d).init_lists = true;
- WP(w, replaceveh_d).sel_engine[0] = INVALID_ENGINE;
- WP(w, replaceveh_d).sel_engine[1] = INVALID_ENGINE;
- break;
-
- case WE_PAINT: {
- if (WP(w, replaceveh_d).update_left || WP(w, replaceveh_d).update_right) GenerateLists(w);
-
- Player *p = GetPlayer(_local_player);
- EngineID selected_id[2];
- const GroupID selected_group = WP(w, replaceveh_d).sel_group;
-
- selected_id[0] = WP(w, replaceveh_d).sel_engine[0];
- selected_id[1] = WP(w, replaceveh_d).sel_engine[1];
-
- /* Disable the "Start Replacing" button if:
- * Either list is empty
- * or The selected replacement engine has a replacement (to prevent loops)
- * or The right list (new replacement) has the existing replacement vehicle selected */
- w->SetWidgetDisabledState(RVW_WIDGET_START_REPLACE,
- selected_id[0] == INVALID_ENGINE ||
- selected_id[1] == INVALID_ENGINE ||
- EngineReplacementForPlayer(p, selected_id[1], selected_group) != INVALID_ENGINE ||
- EngineReplacementForPlayer(p, selected_id[0], selected_group) == selected_id[1]);
-
- /* Disable the "Stop Replacing" button if:
- * The left list (existing vehicle) is empty
- * or The selected vehicle has no replacement set up */
- w->SetWidgetDisabledState(RVW_WIDGET_STOP_REPLACE,
- selected_id[0] == INVALID_ENGINE ||
- !EngineHasReplacementForPlayer(p, selected_id[0], selected_group));
-
- /* now the actual drawing of the window itself takes place */
- SetDParam(0, _vehicle_type_names[w->window_number]);
-
- if (w->window_number == VEH_TRAIN) {
- /* set on/off for renew_keep_length */
- SetDParam(1, p->renew_keep_length ? STR_CONFIG_PATCHES_ON : STR_CONFIG_PATCHES_OFF);
-
- /* set wagon/engine button */
- SetDParam(2, WP(w, replaceveh_d).wagon_btnstate ? STR_ENGINES : STR_WAGONS);
-
- /* sets the colour of that art thing */
- w->widget[RVW_WIDGET_TRAIN_FLUFF_LEFT].color = _player_colors[_local_player];
- w->widget[RVW_WIDGET_TRAIN_FLUFF_RIGHT].color = _player_colors[_local_player];
- }
-
- if (w->window_number == VEH_TRAIN) {
- /* Show the selected railtype in the pulldown menu */
- RailType railtype = _railtype_selected_in_replace_gui;
- w->widget[RVW_WIDGET_TRAIN_RAILTYPE_DROPDOWN].data = _rail_types_list[railtype];
- }
-
- DrawWindowWidgets(w);
-
- /* sets up the string for the vehicle that is being replaced to */
- if (selected_id[0] != INVALID_ENGINE) {
- if (!EngineHasReplacementForPlayer(p, selected_id[0], selected_group)) {
- SetDParam(0, STR_NOT_REPLACING);
- } else {
- SetDParam(0, STR_ENGINE_NAME);
- SetDParam(1, EngineReplacementForPlayer(p, selected_id[0], selected_group));
- }
- } else {
- SetDParam(0, STR_NOT_REPLACING_VEHICLE_SELECTED);
- }
-
- DrawString(145, w->widget[RVW_WIDGET_INFO_TAB].top + 1, STR_02BD, TC_BLACK);
-
- /* Draw the lists */
- for(byte i = 0; i < 2; i++) {
- uint widget = (i == 0) ? RVW_WIDGET_LEFT_MATRIX : RVW_WIDGET_RIGHT_MATRIX;
- EngineList list = WP(w, replaceveh_d).list[i]; // which list to draw
- EngineID start = i == 0 ? w->vscroll.pos : w->vscroll2.pos; // what is the offset for the start (scrolling)
- EngineID end = min((i == 0 ? w->vscroll.cap : w->vscroll2.cap) + start, list.size());
-
- /* Do the actual drawing */
- DrawEngineList((VehicleType)w->window_number, w->widget[widget].left + 2, w->widget[widget].top + 1, list, start, end, WP(w, replaceveh_d).sel_engine[i], i == 0 ? w->widget[RVW_WIDGET_LEFT_MATRIX].right - 2 : 0, selected_group);
-
- /* Also draw the details if an engine is selected */
- if (WP(w, replaceveh_d).sel_engine[i] != INVALID_ENGINE) {
- const Widget *wi = &w->widget[i == 0 ? RVW_WIDGET_LEFT_DETAILS : RVW_WIDGET_RIGHT_DETAILS];
- int text_end = DrawVehiclePurchaseInfo(wi->left + 2, wi->top + 1, wi->right - wi->left - 2, WP(w, replaceveh_d).sel_engine[i]);
- if (text_end > wi->bottom) {
- w->SetDirty();
- ResizeWindowForWidget(w, i == 0 ? RVW_WIDGET_LEFT_DETAILS : RVW_WIDGET_RIGHT_DETAILS, 0, text_end - wi->bottom);
- w->SetDirty();
- }
- }
- }
-
- } break; // end of paint
-
- case WE_CLICK: {
- switch (e->we.click.widget) {
- case RVW_WIDGET_TRAIN_ENGINEWAGON_TOGGLE:
- WP(w, replaceveh_d).wagon_btnstate = !(WP(w, replaceveh_d).wagon_btnstate);
- WP(w, replaceveh_d).update_left = true;
- WP(w, replaceveh_d).init_lists = true;
- w->SetDirty();
- break;
-
- case RVW_WIDGET_TRAIN_RAILTYPE_DROPDOWN: /* Railtype selection dropdown menu */
- ShowDropDownMenu(w, _rail_types_list, _railtype_selected_in_replace_gui, RVW_WIDGET_TRAIN_RAILTYPE_DROPDOWN, 0, ~GetPlayer(_local_player)->avail_railtypes);
- break;
-
- case RVW_WIDGET_TRAIN_WAGONREMOVE_TOGGLE: /* toggle renew_keep_length */
- DoCommandP(0, 5, GetPlayer(_local_player)->renew_keep_length ? 0 : 1, NULL, CMD_SET_AUTOREPLACE);
- break;
-
- case RVW_WIDGET_START_REPLACE: { /* Start replacing */
- EngineID veh_from = WP(w, replaceveh_d).sel_engine[0];
- EngineID veh_to = WP(w, replaceveh_d).sel_engine[1];
- DoCommandP(0, 3 + (WP(w, replaceveh_d).sel_group << 16) , veh_from + (veh_to << 16), NULL, CMD_SET_AUTOREPLACE);
- } break;
-
- case RVW_WIDGET_STOP_REPLACE: { /* Stop replacing */
- EngineID veh_from = WP(w, replaceveh_d).sel_engine[0];
- DoCommandP(0, 3 + (WP(w, replaceveh_d).sel_group << 16), veh_from + (INVALID_ENGINE << 16), NULL, CMD_SET_AUTOREPLACE);
- } break;
-
- case RVW_WIDGET_LEFT_MATRIX:
- case RVW_WIDGET_RIGHT_MATRIX: {
- uint i = (e->we.click.pt.y - 14) / w->resize.step_height;
- uint16 click_scroll_pos = e->we.click.widget == RVW_WIDGET_LEFT_MATRIX ? w->vscroll.pos : w->vscroll2.pos;
- uint16 click_scroll_cap = e->we.click.widget == RVW_WIDGET_LEFT_MATRIX ? w->vscroll.cap : w->vscroll2.cap;
- byte click_side = e->we.click.widget == RVW_WIDGET_LEFT_MATRIX ? 0 : 1;
- uint16 engine_count = WP(w, replaceveh_d).list[click_side].size();
+ virtual void OnClick(Point pt, int widget)
+ {
+ switch (widget) {
+ case RVW_WIDGET_TRAIN_ENGINEWAGON_TOGGLE:
+ this->wagon_btnstate = !(this->wagon_btnstate);
+ this->update_left = true;
+ this->init_lists = true;
+ this->SetDirty();
+ break;
- if (i < click_scroll_cap) {
- i += click_scroll_pos;
- EngineID e = engine_count > i ? WP(w, replaceveh_d).list[click_side][i] : INVALID_ENGINE;
- if (e == WP(w, replaceveh_d).sel_engine[click_side]) break; // we clicked the one we already selected
- WP(w, replaceveh_d).sel_engine[click_side] = e;
- if (click_side == 0) {
- WP(w, replaceveh_d).update_right = true;
- WP(w, replaceveh_d).init_lists = true;
- }
- w->SetDirty();
- }
- break;
- }
- }
- break;
- }
-
- case WE_DROPDOWN_SELECT: { /* we have selected a dropdown item in the list */
- RailType temp = (RailType)e->we.dropdown.index;
- if (temp == _railtype_selected_in_replace_gui) break; // we didn't select a new one. No need to change anything
- _railtype_selected_in_replace_gui = temp;
- /* Reset scrollbar positions */
- w->vscroll.pos = 0;
- w->vscroll2.pos = 0;
- /* Rebuild the lists */
- WP(w, replaceveh_d).update_left = true;
- WP(w, replaceveh_d).update_right = true;
- WP(w, replaceveh_d).init_lists = true;
- w->SetDirty();
- } break;
+ case RVW_WIDGET_TRAIN_RAILTYPE_DROPDOWN: /* Railtype selection dropdown menu */
+ ShowDropDownMenu(this, _rail_types_list, sel_railtype, RVW_WIDGET_TRAIN_RAILTYPE_DROPDOWN, 0, ~GetPlayer(_local_player)->avail_railtypes);
+ break;
- case WE_RESIZE:
- {
- w->vscroll.cap += e->we.sizing.diff.y / (int)w->resize.step_height;
- w->vscroll2.cap += e->we.sizing.diff.y / (int)w->resize.step_height;
-
- Widget *widget = w->widget;
-
- widget[RVW_WIDGET_LEFT_MATRIX].data = widget[RVW_WIDGET_RIGHT_MATRIX].data = (w->vscroll2.cap << 8) + 1;
+ case RVW_WIDGET_TRAIN_WAGONREMOVE_TOGGLE: /* toggle renew_keep_length */
+ DoCommandP(0, 5, GetPlayer(_local_player)->renew_keep_length ? 0 : 1, NULL, CMD_SET_AUTOREPLACE);
+ break;
- if (e->we.sizing.diff.x != 0) {
- /* We changed the width of the window so we have to resize the lists.
- * Because ResizeButtons() makes each widget the same size it can't be used on the lists
- * because then the lists would have the same size as the scrollbars.
- * Instead we use it on the detail panels.
- * Afterwards we use the new location of the detail panels (the middle of the window)
- * to place the lists.
- * This way the lists will have equal size while keeping the width of the scrollbars unchanged. */
- ResizeButtons(w, RVW_WIDGET_LEFT_DETAILS, RVW_WIDGET_RIGHT_DETAILS);
- widget[RVW_WIDGET_RIGHT_MATRIX].left = widget[RVW_WIDGET_RIGHT_DETAILS].left;
- widget[RVW_WIDGET_LEFT_SCROLLBAR].right = widget[RVW_WIDGET_LEFT_DETAILS].right;
- widget[RVW_WIDGET_LEFT_SCROLLBAR].left = widget[RVW_WIDGET_LEFT_SCROLLBAR].right - 11;
- widget[RVW_WIDGET_LEFT_MATRIX].right = widget[RVW_WIDGET_LEFT_SCROLLBAR].left - 1;
- }
- } break;
+ case RVW_WIDGET_START_REPLACE: { /* Start replacing */
+ EngineID veh_from = this->sel_engine[0];
+ EngineID veh_to = this->sel_engine[1];
+ DoCommandP(0, 3 + (this->sel_group << 16) , veh_from + (veh_to << 16), NULL, CMD_SET_AUTOREPLACE);
+ } break;
- case WE_INVALIDATE_DATA:
- if (_rebuild_left_list) WP(w, replaceveh_d).update_left = true;
- if (_rebuild_right_list) WP(w, replaceveh_d).update_right = true;
- w->SetDirty();
- break;
+ case RVW_WIDGET_STOP_REPLACE: { /* Stop replacing */
+ EngineID veh_from = this->sel_engine[0];
+ DoCommandP(0, 3 + (this->sel_group << 16), veh_from + (INVALID_ENGINE << 16), NULL, CMD_SET_AUTOREPLACE);
+ } break;
- case WE_DESTROY:
- WP(w, replaceveh_d).list[0].~EngineList(); // call destructor explicitly
- WP(w, replaceveh_d).list[1].~EngineList();
- break;
+ case RVW_WIDGET_LEFT_MATRIX:
+ case RVW_WIDGET_RIGHT_MATRIX: {
+ uint i = (pt.y - 14) / this->resize.step_height;
+ uint16 click_scroll_pos = widget == RVW_WIDGET_LEFT_MATRIX ? this->vscroll.pos : this->vscroll2.pos;
+ uint16 click_scroll_cap = widget == RVW_WIDGET_LEFT_MATRIX ? this->vscroll.cap : this->vscroll2.cap;
+ byte click_side = widget == RVW_WIDGET_LEFT_MATRIX ? 0 : 1;
+ size_t engine_count = this->list[click_side].size();
+
+ if (i < click_scroll_cap) {
+ i += click_scroll_pos;
+ EngineID e = engine_count > i ? this->list[click_side][i] : INVALID_ENGINE;
+ if (e == this->sel_engine[click_side]) break; // we clicked the one we already selected
+ this->sel_engine[click_side] = e;
+ if (click_side == 0) {
+ this->update_right = true;
+ this->init_lists = true;
+ }
+ this->SetDirty();
+ }
+ break;
+ }
+ }
}
-}
+
+ virtual void OnDropdownSelect(int widget, int index)
+ {
+ RailType temp = (RailType)index;
+ if (temp == sel_railtype) return; // we didn't select a new one. No need to change anything
+ sel_railtype = temp;
+ /* Reset scrollbar positions */
+ this->vscroll.pos = 0;
+ this->vscroll2.pos = 0;
+ /* Rebuild the lists */
+ this->update_left = true;
+ this->update_right = true;
+ this->init_lists = true;
+ this->SetDirty();
+ }
+
+ virtual void OnResize(Point new_size, Point delta) {
+ this->vscroll.cap += delta.y / (int)this->resize.step_height;
+ this->vscroll2.cap += delta.y / (int)this->resize.step_height;
+
+ Widget *widget = this->widget;
+
+ widget[RVW_WIDGET_LEFT_MATRIX].data = widget[RVW_WIDGET_RIGHT_MATRIX].data = (this->vscroll2.cap << 8) + 1;
+
+ if (delta.x != 0) {
+ /* We changed the width of the window so we have to resize the lists.
+ * Because ResizeButtons() makes each widget the same size it can't be used on the lists
+ * because then the lists would have the same size as the scrollbars.
+ * Instead we use it on the detail panels.
+ * Afterwards we use the new location of the detail panels (the middle of the window)
+ * to place the lists.
+ * This way the lists will have equal size while keeping the width of the scrollbars unchanged. */
+ ResizeButtons(this, RVW_WIDGET_LEFT_DETAILS, RVW_WIDGET_RIGHT_DETAILS);
+ widget[RVW_WIDGET_RIGHT_MATRIX].left = widget[RVW_WIDGET_RIGHT_DETAILS].left;
+ widget[RVW_WIDGET_LEFT_SCROLLBAR].right = widget[RVW_WIDGET_LEFT_DETAILS].right;
+ widget[RVW_WIDGET_LEFT_SCROLLBAR].left = widget[RVW_WIDGET_LEFT_SCROLLBAR].right - 11;
+ widget[RVW_WIDGET_LEFT_MATRIX].right = widget[RVW_WIDGET_LEFT_SCROLLBAR].left - 1;
+ }
+ }
+
+ virtual void OnInvalidateData(int data)
+ {
+ if (data != 0) {
+ this->update_left = true;
+ } else {
+ this->update_right = true;
+ }
+ }
+};
static const Widget _replace_vehicle_widgets[] = {
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
@@ -512,7 +532,7 @@
WC_REPLACE_VEHICLE, WC_NONE,
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON | WDF_RESIZABLE,
_replace_vehicle_widgets,
- ReplaceVehicleWndProc
+ NULL
};
static const WindowDesc _replace_vehicle_desc = {
@@ -520,55 +540,13 @@
WC_REPLACE_VEHICLE, WC_NONE,
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON | WDF_RESIZABLE,
_replace_vehicle_widgets,
- ReplaceVehicleWndProc
+ NULL
};
+RailType ReplaceVehicleWindow::sel_railtype = RAILTYPE_RAIL;
void ShowReplaceGroupVehicleWindow(GroupID id_g, VehicleType vehicletype)
{
DeleteWindowById(WC_REPLACE_VEHICLE, vehicletype);
- Window *w = vehicletype == VEH_TRAIN ? AllocateWindowDescFront(&_replace_rail_vehicle_desc, VEH_TRAIN)
- : AllocateWindowDescFront(&_replace_vehicle_desc, vehicletype);
-
- w->resize.step_height = GetVehicleListHeight(vehicletype);
- w->vscroll.cap = w->resize.step_height == 14 ? 8 : 4;
-
- Widget *widget = w->widget;
- widget[RVW_WIDGET_LEFT_MATRIX].data = widget[RVW_WIDGET_RIGHT_MATRIX].data = (w->vscroll.cap << 8) + 1;
-
- if (vehicletype == VEH_TRAIN) {
- WP(w, replaceveh_d).wagon_btnstate = true;
- /* The train window is bigger so we will move some of the widgets to fit the new size.
- * We will start by moving the resize button to the lower right corner. */
- widget[RVW_WIDGET_RESIZE].top = widget[RVW_WIDGET_TRAIN_ENGINEWAGON_TOGGLE].top;
- widget[RVW_WIDGET_RESIZE].bottom = widget[RVW_WIDGET_TRAIN_ENGINEWAGON_TOGGLE].bottom;
- widget[RVW_WIDGET_STOP_REPLACE].right = widget[RVW_WIDGET_RESIZE].right;
-
- /* The detail panel is one line taller for trains so we will move some of the widgets one line (10 pixels) down. */
- widget[RVW_WIDGET_LEFT_DETAILS].bottom += 10;
- widget[RVW_WIDGET_RIGHT_DETAILS].bottom += 10;
- for (int i = RVW_WIDGET_START_REPLACE; i < RVW_WIDGET_RESIZE; i++) {
- widget[i].top += 10;
- widget[i].bottom += 10;
- }
- } else {
- /* Since it's not a train we will hide the train only widgets. */
- w->SetWidgetsHiddenState(true,
- RVW_WIDGET_TRAIN_ENGINEWAGON_TOGGLE,
- RVW_WIDGET_TRAIN_FLUFF_LEFT,
- RVW_WIDGET_TRAIN_RAILTYPE_DROPDOWN,
- RVW_WIDGET_TRAIN_FLUFF_RIGHT,
- RVW_WIDGET_TRAIN_WAGONREMOVE_TOGGLE,
- WIDGET_LIST_END);
- }
-
- ResizeWindow(w, 0, w->resize.step_height * w->vscroll.cap);
-
- /* Set the minimum window size to the current window size */
- w->resize.width = w->width;
- w->resize.height = w->height;
-
- w->caption_color = _local_player;
- WP(w, replaceveh_d).sel_group = id_g;
- w->vscroll2.cap = w->vscroll.cap; // these two are always the same
+ new ReplaceVehicleWindow(vehicletype == VEH_TRAIN ? &_replace_rail_vehicle_desc : &_replace_vehicle_desc, vehicletype, id_g);
}
--- a/src/bridge_gui.cpp Wed May 07 21:09:51 2008 +0000
+++ b/src/bridge_gui.cpp Sun May 11 20:09:34 2008 +0000
@@ -184,7 +184,7 @@
}
if (j != 0) {
- Window *w = AllocateWindowDesc(&_build_bridge_desc);
+ Window *w = new Window(&_build_bridge_desc);
/* Change the data, or the caption of the gui. Set it to road or rail, accordingly */
w->widget[BBSW_CAPTION].data = (transport_type == TRANSPORT_ROAD) ? STR_1803_SELECT_ROAD_BRIDGE : STR_100D_SELECT_RAIL_BRIDGE;
} else {
--- a/src/build_vehicle_gui.cpp Wed May 07 21:09:51 2008 +0000
+++ b/src/build_vehicle_gui.cpp Sun May 11 20:09:34 2008 +0000
@@ -27,6 +27,7 @@
#include "settings_type.h"
#include "gfx_func.h"
#include "widgets/dropdown_func.h"
+#include "string_func.h"
#include "table/sprites.h"
#include "table/strings.h"
@@ -1034,7 +1035,7 @@
case BUILD_VEHICLE_WIDGET_LIST: {
uint i = (e->we.click.pt.y - w->widget[BUILD_VEHICLE_WIDGET_LIST].top) / GetVehicleListHeight(bv->vehicle_type) + w->vscroll.pos;
- uint num_items = bv->eng_list.size();
+ size_t num_items = bv->eng_list.size();
bv->sel_engine = (i < num_items) ? bv->eng_list[i] : INVALID_ENGINE;
w->SetDirty();
break;
@@ -1136,7 +1137,7 @@
break;
case WE_ON_EDIT_TEXT: {
- if (e->we.edittext.str[0] != '\0') {
+ if (!StrEmpty(e->we.edittext.str)) {
StringID str = STR_NULL;
_cmd_text = e->we.edittext.str;
switch (bv->vehicle_type) {
@@ -1192,7 +1193,7 @@
DeleteWindowById(WC_BUILD_VEHICLE, num);
- w = AllocateWindowDescFront(&_build_vehicle_desc, num, &type);
+ w = AllocateWindowDescFront<Window>(&_build_vehicle_desc, num, &type);
if (w == NULL) return;
--- a/src/cheat_gui.cpp Wed May 07 21:09:51 2008 +0000
+++ b/src/cheat_gui.cpp Sun May 11 20:09:34 2008 +0000
@@ -229,5 +229,5 @@
void ShowCheatWindow()
{
DeleteWindowById(WC_CHEATS, 0);
- AllocateWindowDesc(&_cheats_desc);
+ new Window(&_cheats_desc);
}
--- a/src/console.cpp Wed May 07 21:09:51 2008 +0000
+++ b/src/console.cpp Sun May 11 20:09:34 2008 +0000
@@ -318,7 +318,7 @@
{
switch (_iconsole_mode) {
case ICONSOLE_CLOSED: {
- Window *w = AllocateWindowDesc(&_iconsole_window_desc);
+ Window *w = new Window(&_iconsole_window_desc);
w->height = _screen.height / 3;
w->width = _screen.width;
_iconsole_mode = ICONSOLE_OPENED;
--- a/src/depot_gui.cpp Wed May 07 21:09:51 2008 +0000
+++ b/src/depot_gui.cpp Sun May 11 20:09:34 2008 +0000
@@ -100,6 +100,20 @@
{ WIDGETS_END},
};
+
+struct depot_d {
+ VehicleID sel;
+ VehicleType type;
+ bool generate_list;
+ uint16 engine_list_length;
+ uint16 wagon_list_length;
+ uint16 engine_count;
+ uint16 wagon_count;
+ Vehicle **vehicle_list;
+ Vehicle **wagon_list;
+};
+assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(depot_d));
+
static void DepotWndProc(Window *w, WindowEvent *e);
static const WindowDesc _train_depot_desc = {
@@ -997,13 +1011,13 @@
switch (type) {
default: NOT_REACHED();
case VEH_TRAIN:
- w = AllocateWindowDescFront(&_train_depot_desc, tile); break;
+ w = AllocateWindowDescFront<Window>(&_train_depot_desc, tile); break;
case VEH_ROAD:
- w = AllocateWindowDescFront(&_road_depot_desc, tile); break;
+ w = AllocateWindowDescFront<Window>(&_road_depot_desc, tile); break;
case VEH_SHIP:
- w = AllocateWindowDescFront(&_ship_depot_desc, tile); break;
+ w = AllocateWindowDescFront<Window>(&_ship_depot_desc, tile); break;
case VEH_AIRCRAFT:
- w = AllocateWindowDescFront(&_aircraft_depot_desc, tile); break;
+ w = AllocateWindowDescFront<Window>(&_aircraft_depot_desc, tile); break;
}
if (w != NULL) {
--- a/src/dock_gui.cpp Wed May 07 21:09:51 2008 +0000
+++ b/src/dock_gui.cpp Sun May 11 20:09:34 2008 +0000
@@ -229,7 +229,7 @@
if (!IsValidPlayer(_current_player)) return;
DeleteWindowByClass(WC_BUILD_TOOLBAR);
- Window *w = AllocateWindowDescFront(&_build_docks_toolbar_desc, TRANSPORT_WATER);
+ Window *w = AllocateWindowDescFront<Window>(&_build_docks_toolbar_desc, TRANSPORT_WATER);
if (_patches.link_terraform_toolbar) ShowTerraformToolbar(w);
}
@@ -274,7 +274,7 @@
}
break;
- case WE_MOUSELOOP:
+ case WE_TICK:
if (WP(w, def_d).close) {
delete w;
return;
@@ -309,7 +309,7 @@
static void ShowBuildDockStationPicker()
{
- AllocateWindowDesc(&_build_dock_station_desc);
+ new Window(&_build_dock_station_desc);
}
static void UpdateDocksDirection()
@@ -349,7 +349,7 @@
}
} break;
- case WE_MOUSELOOP:
+ case WE_TICK:
if (WP(w, def_d).close) delete w;
break;
@@ -379,7 +379,7 @@
static void ShowBuildDocksDepotPicker()
{
- AllocateWindowDesc(&_build_docks_depot_desc);
+ new Window(&_build_docks_depot_desc);
UpdateDocksDirection();
}
--- a/src/driver.h Wed May 07 21:09:51 2008 +0000
+++ b/src/driver.h Sun May 11 20:09:34 2008 +0000
@@ -43,7 +43,7 @@
static Drivers &GetDrivers()
{
- static Drivers &s_drivers = *new Drivers();
+ static Drivers s_drivers;
return s_drivers;
}
@@ -67,7 +67,23 @@
name(NULL)
{}
- virtual ~DriverFactoryBase() { if (this->name != NULL) GetDrivers().erase(this->name); free(this->name); }
+ /** Frees memory used for this->name
+ */
+ virtual ~DriverFactoryBase() {
+ if (this->name == NULL) return;
+ GetDrivers().erase(this->name);
+ free(this->name);
+ }
+
+ /** Shuts down all active drivers
+ */
+ static void ShutdownDrivers()
+ {
+ for (Driver::Type dt = Driver::DT_BEGIN; dt < Driver::DT_END; dt++) {
+ Driver *driver = *GetActiveDriver(dt);
+ if (driver != NULL) driver->Stop();
+ }
+ }
static const Driver *SelectDriver(const char *name, Driver::Type type);
static char *GetDriversInfo(char *p, const char *last);
--- a/src/economy.cpp Wed May 07 21:09:51 2008 +0000
+++ b/src/economy.cpp Sun May 11 20:09:34 2008 +0000
@@ -1151,7 +1151,7 @@
if (s->age == 12-1) {
pair = SetupSubsidyDecodeParam(s, 1);
- AddNewsItem(STR_202E_OFFER_OF_SUBSIDY_EXPIRED, NM_NORMAL, NF_TILE, NT_SUBSIDIES, DNC_NONE, pair.a, pair.b);
+ AddNewsItem(STR_202E_OFFER_OF_SUBSIDY_EXPIRED, NM_NORMAL, NF_TILE | NF_TILE2, NT_SUBSIDIES, DNC_NONE, pair.a, pair.b);
s->cargo_type = CT_INVALID;
modified = true;
for (PlayerID i = PLAYER_FIRST; i != MAX_PLAYERS; i++) {
@@ -1161,7 +1161,7 @@
st = GetStation(s->to);
if (st->owner == _local_player) {
pair = SetupSubsidyDecodeParam(s, 1);
- AddNewsItem(STR_202F_SUBSIDY_WITHDRAWN_SERVICE, NM_NORMAL, NF_TILE, NT_SUBSIDIES, DNC_NONE, pair.a, pair.b);
+ AddNewsItem(STR_202F_SUBSIDY_WITHDRAWN_SERVICE, NM_NORMAL, NF_TILE | NF_TILE2, NT_SUBSIDIES, DNC_NONE, pair.a, pair.b);
}
s->cargo_type = CT_INVALID;
modified = true;
@@ -1203,7 +1203,7 @@
if (!CheckSubsidyDuplicate(s)) {
s->age = 0;
pair = SetupSubsidyDecodeParam(s, 0);
- AddNewsItem(STR_2030_SERVICE_SUBSIDY_OFFERED, NM_NORMAL, NF_TILE, NT_SUBSIDIES, DNC_NONE, pair.a, pair.b);
+ AddNewsItem(STR_2030_SERVICE_SUBSIDY_OFFERED, NM_NORMAL, NF_TILE | NF_TILE2, NT_SUBSIDIES, DNC_NONE, pair.a, pair.b);
for (PlayerID i = PLAYER_FIRST; i != MAX_PLAYERS; i++) {
AI_Event(i, new AIEventSubsidyOffer(s - _subsidies));
}
@@ -1423,7 +1423,7 @@
SetDParam(0, _current_player);
AddNewsItem(
STR_2031_SERVICE_SUBSIDY_AWARDED + _opt.diff.subsidy_multiplier,
- NM_NORMAL, NF_TILE, NT_SUBSIDIES, DNC_NONE,
+ NM_NORMAL, NF_TILE | NF_TILE2, NT_SUBSIDIES, DNC_NONE,
pair.a, pair.b
);
for (PlayerID i = PLAYER_FIRST; i != MAX_PLAYERS; i++) {
--- a/src/elrail.cpp Wed May 07 21:09:51 2008 +0000
+++ b/src/elrail.cpp Sun May 11 20:09:34 2008 +0000
@@ -67,6 +67,7 @@
#include "player_base.h"
#include "tunnelbridge.h"
#include "engine_func.h"
+#include "elrail_func.h"
#include "engine_base.h"
#include "table/sprites.h"
@@ -182,8 +183,6 @@
{ 1, 0, 15, 16 }, // NW
};
- if (!HasCatenary(GetRailType(ti->tile)) || _patches.disable_elrails) return;
-
DiagDirection dir = GetTunnelBridgeDirection(ti->tile);
const SortableSpriteStruct *sss = &CatenarySpriteData_Tunnel[dir];
@@ -382,11 +381,6 @@
void DrawCatenaryOnBridge(const TileInfo *ti)
{
- if (_patches.disable_elrails) return;
-
- /* Do not draw catenary if it is invisible */
- if (IsInvisibilitySet(TO_CATENARY)) return;
-
TileIndex end = GetSouthernBridgeEnd(ti->tile);
TileIndex start = GetOtherBridgeEnd(end);
@@ -440,11 +434,6 @@
void DrawCatenary(const TileInfo *ti)
{
- if (_patches.disable_elrails) return;
-
- /* Do not draw catenary if it is invisible */
- if (IsInvisibilitySet(TO_CATENARY)) return;
-
switch (GetTileType(ti->tile)) {
case MP_RAILWAY:
if (IsRailDepot(ti->tile)) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/elrail_func.h Sun May 11 20:09:34 2008 +0000
@@ -0,0 +1,42 @@
+/* $Id$ */
+
+/** @file elrail_func.h header file for electrified rail specific functions */
+
+#ifndef ELRAIL_FUNC_H
+#define ELRAIL_FUNC_H
+
+#include "rail.h"
+#include "transparency.h"
+#include "tile_cmd.h"
+#include "settings_type.h"
+
+/**
+ * Test if a rail type has catenary
+ * @param rt Rail type to test
+ */
+static inline bool HasCatenary(RailType rt)
+{
+ return HasBit(GetRailTypeInfo(rt)->flags, RTF_CATENARY);
+}
+
+/**
+ * Test if we should draw rail catenary
+ * @param rt Rail type to test
+ */
+static inline bool HasCatenaryDrawn(RailType rt)
+{
+ return HasCatenary(rt) && !IsInvisibilitySet(TO_CATENARY) && !_patches.disable_elrails;
+}
+
+/**
+ * Draws overhead wires and pylons for electric railways.
+ * @param ti The TileInfo struct of the tile being drawn
+ * @see DrawCatenaryRailway
+ */
+void DrawCatenary(const TileInfo *ti);
+void DrawCatenaryOnTunnel(const TileInfo *ti);
+void DrawCatenaryOnBridge(const TileInfo *ti);
+
+int32 SettingsDisableElrail(int32 p1); ///< _patches.disable_elrail callback
+
+#endif /* ELRAIL_FUNC_H */
--- a/src/engine_gui.cpp Wed May 07 21:09:51 2008 +0000
+++ b/src/engine_gui.cpp Sun May 11 20:09:34 2008 +0000
@@ -114,7 +114,7 @@
void ShowEnginePreviewWindow(EngineID engine)
{
- AllocateWindowDescFront(&_engine_preview_desc, engine);
+ AllocateWindowDescFront<Window>(&_engine_preview_desc, engine);
}
static void DrawTrainEngineInfo(EngineID engine, int x, int y, int maxw)
--- a/src/fileio.cpp Wed May 07 21:09:51 2008 +0000
+++ b/src/fileio.cpp Sun May 11 20:09:34 2008 +0000
@@ -27,7 +27,7 @@
struct Fio {
byte *buffer, *buffer_end; ///< position pointer in local buffer and last valid byte of buffer
- uint32 pos; ///< current (system) position in file
+ size_t pos; ///< current (system) position in file
FILE *cur_fh; ///< current file handle
const char *filename; ///< current filename
FILE *handles[MAX_FILE_SLOTS]; ///< array of file handles we can have open
@@ -125,7 +125,7 @@
return (FioReadWord() << 16) | b;
}
-void FioReadBlock(void *ptr, uint size)
+void FioReadBlock(void *ptr, size_t size)
{
FioSeekTo(FioGetPos(), SEEK_SET);
_fio.pos += fread(ptr, 1, size, _fio.cur_fh);
@@ -480,7 +480,7 @@
TarHeader th;
char buf[sizeof(th.name) + 1], *end;
char name[sizeof(th.prefix) + 1 + sizeof(th.name) + 1];
- int num = 0, pos = 0;
+ size_t num = 0, pos = 0;
/* Make a char of 512 empty bytes */
char empty[512];
@@ -499,7 +499,7 @@
}
name[0] = '\0';
- int len = 0;
+ size_t len = 0;
/* The prefix contains the directory-name */
if (th.prefix[0] != '\0') {
@@ -550,7 +550,7 @@
return true;
}
-static int ScanPathForTarFiles(const char *path, int basepath_length)
+static int ScanPathForTarFiles(const char *path, size_t basepath_length)
{
extern bool FiosIsValidFile(const char *path, const struct dirent *ent, struct stat *sb);
--- a/src/fileio.h Wed May 07 21:09:51 2008 +0000
+++ b/src/fileio.h Sun May 11 20:09:34 2008 +0000
@@ -18,7 +18,7 @@
uint32 FioReadDword();
void FioCloseAll();
void FioOpenFile(int slot, const char *filename);
-void FioReadBlock(void *ptr, uint size);
+void FioReadBlock(void *ptr, size_t size);
void FioSkipBytes(int n);
void FioCreateDirectory(const char *filename);
@@ -70,8 +70,8 @@
};
struct TarFileListEntry {
TarListEntry *tar;
- int size;
- int position;
+ size_t size;
+ size_t position;
};
typedef std::map<std::string, TarListEntry *> TarList;
typedef std::map<std::string, TarFileListEntry> TarFileList;
--- a/src/fios.cpp Wed May 07 21:09:51 2008 +0000
+++ b/src/fios.cpp Sun May 11 20:09:34 2008 +0000
@@ -18,6 +18,9 @@
#ifdef WIN32
# include <tchar.h>
+# ifndef UNICODE
+# include <io.h>
+# endif
# define access _taccess
# define unlink _tunlink
#else
--- a/src/functions.h Wed May 07 21:09:51 2008 +0000
+++ b/src/functions.h Sun May 11 20:09:34 2008 +0000
@@ -23,9 +23,6 @@
bool CheckOwnership(Owner owner);
bool CheckTileOwnership(TileIndex tile);
-/* misc_cmd.cpp */
-void PlaceTreesRandomly();
-
void InitializeLandscapeVariables(bool only_constants);
/* misc functions */
--- a/src/genworld_gui.cpp Wed May 07 21:09:51 2008 +0000
+++ b/src/genworld_gui.cpp Sun May 11 20:09:34 2008 +0000
@@ -29,6 +29,7 @@
#include "widgets/dropdown_func.h"
#include "core/random_func.hpp"
#include "landscape_type.h"
+#include "querystring_gui.h"
#include "table/strings.h"
#include "table/sprites.h"
@@ -43,14 +44,6 @@
GLWP_END
};
-struct generate_d {
- uint widget_id;
- uint x;
- uint y;
- char name[64];
-};
-assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(generate_d));
-
extern void SwitchMode(int new_mode);
static inline void SetNewLandscapeType(byte landscape)
@@ -244,314 +237,324 @@
return list;
}
-static void GenerateLandscapeWndProc(Window *w, WindowEvent *e)
-{
- static const StringID elevations[] = {STR_682A_VERY_FLAT, STR_682B_FLAT, STR_682C_HILLY, STR_682D_MOUNTAINOUS, INVALID_STRING_ID};
- static const StringID sea_lakes[] = {STR_VERY_LOW, STR_6820_LOW, STR_6821_MEDIUM, STR_6822_HIGH, INVALID_STRING_ID};
- static const StringID smoothness[] = {STR_CONFIG_PATCHES_ROUGHNESS_OF_TERRAIN_VERY_SMOOTH, STR_CONFIG_PATCHES_ROUGHNESS_OF_TERRAIN_SMOOTH, STR_CONFIG_PATCHES_ROUGHNESS_OF_TERRAIN_ROUGH, STR_CONFIG_PATCHES_ROUGHNESS_OF_TERRAIN_VERY_ROUGH, INVALID_STRING_ID};
- static const StringID tree_placer[] = {STR_CONFIG_PATCHES_TREE_PLACER_NONE, STR_CONFIG_PATCHES_TREE_PLACER_ORIGINAL, STR_CONFIG_PATCHES_TREE_PLACER_IMPROVED, INVALID_STRING_ID};
- static const StringID rotation[] = {STR_CONFIG_PATCHES_HEIGHTMAP_ROTATION_COUNTER_CLOCKWISE, STR_CONFIG_PATCHES_HEIGHTMAP_ROTATION_CLOCKWISE, INVALID_STRING_ID};
- static const StringID landscape[] = {STR_CONFIG_PATCHES_LAND_GENERATOR_ORIGINAL, STR_CONFIG_PATCHES_LAND_GENERATOR_TERRA_GENESIS, INVALID_STRING_ID};
- static const StringID num_towns[] = {STR_NUM_VERY_LOW, STR_6816_LOW, STR_6817_NORMAL, STR_6818_HIGH, INVALID_STRING_ID};
- static const StringID num_inds[] = {STR_NONE, STR_NUM_VERY_LOW, STR_6816_LOW, STR_6817_NORMAL, STR_6818_HIGH, INVALID_STRING_ID};
-
- /* Data used for the generate seed edit box */
- static querystr_d _genseed_query;
- static char _genseed_buffer[11];
-
- glwp_modes mode = (glwp_modes)w->window_number;
-
- switch (e->event) {
- case WE_CREATE:
- w->LowerWidget(_opt_newgame.landscape + GLAND_TEMPERATE);
-
- snprintf(_genseed_buffer, sizeof(_genseed_buffer), "%u", _patches_newgame.generation_seed);
- InitializeTextBuffer(&_genseed_query.text, _genseed_buffer, lengthof(_genseed_buffer), 120);
- _genseed_query.caption = STR_NULL;
- _genseed_query.afilter = CS_NUMERAL;
- break;
+static const StringID _elevations[] = {STR_682A_VERY_FLAT, STR_682B_FLAT, STR_682C_HILLY, STR_682D_MOUNTAINOUS, INVALID_STRING_ID};
+static const StringID _sea_lakes[] = {STR_VERY_LOW, STR_6820_LOW, STR_6821_MEDIUM, STR_6822_HIGH, INVALID_STRING_ID};
+static const StringID _smoothness[] = {STR_CONFIG_PATCHES_ROUGHNESS_OF_TERRAIN_VERY_SMOOTH, STR_CONFIG_PATCHES_ROUGHNESS_OF_TERRAIN_SMOOTH, STR_CONFIG_PATCHES_ROUGHNESS_OF_TERRAIN_ROUGH, STR_CONFIG_PATCHES_ROUGHNESS_OF_TERRAIN_VERY_ROUGH, INVALID_STRING_ID};
+static const StringID _tree_placer[] = {STR_CONFIG_PATCHES_TREE_PLACER_NONE, STR_CONFIG_PATCHES_TREE_PLACER_ORIGINAL, STR_CONFIG_PATCHES_TREE_PLACER_IMPROVED, INVALID_STRING_ID};
+static const StringID _rotation[] = {STR_CONFIG_PATCHES_HEIGHTMAP_ROTATION_COUNTER_CLOCKWISE, STR_CONFIG_PATCHES_HEIGHTMAP_ROTATION_CLOCKWISE, INVALID_STRING_ID};
+static const StringID _landscape[] = {STR_CONFIG_PATCHES_LAND_GENERATOR_ORIGINAL, STR_CONFIG_PATCHES_LAND_GENERATOR_TERRA_GENESIS, INVALID_STRING_ID};
+static const StringID _num_towns[] = {STR_NUM_VERY_LOW, STR_6816_LOW, STR_6817_NORMAL, STR_6818_HIGH, INVALID_STRING_ID};
+static const StringID _num_inds[] = {STR_NONE, STR_NUM_VERY_LOW, STR_6816_LOW, STR_6817_NORMAL, STR_6818_HIGH, INVALID_STRING_ID};
- case WE_PAINT:
- /* You can't select smoothness if not terragenesis */
- if (mode == GLWP_GENERATE) {
- w->SetWidgetDisabledState(GLAND_SMOOTHNESS_PULLDOWN, _patches_newgame.land_generator == 0);
- }
- /* Disable snowline if not hilly */
- w->SetWidgetDisabledState(GLAND_SNOW_LEVEL_TEXT, _opt_newgame.landscape != LT_ARCTIC);
- /* Disable town, industry and trees in SE */
- w->SetWidgetDisabledState(GLAND_TOWN_PULLDOWN, _game_mode == GM_EDITOR);
- w->SetWidgetDisabledState(GLAND_INDUSTRY_PULLDOWN, _game_mode == GM_EDITOR);
- w->SetWidgetDisabledState(GLAND_TREE_PULLDOWN, _game_mode == GM_EDITOR);
-
- w->SetWidgetDisabledState(GLAND_START_DATE_DOWN, _patches_newgame.starting_year <= MIN_YEAR);
- w->SetWidgetDisabledState(GLAND_START_DATE_UP, _patches_newgame.starting_year >= MAX_YEAR);
- w->SetWidgetDisabledState(GLAND_SNOW_LEVEL_DOWN, _patches_newgame.snow_line_height <= 2 || _opt_newgame.landscape != LT_ARCTIC);
- w->SetWidgetDisabledState(GLAND_SNOW_LEVEL_UP, _patches_newgame.snow_line_height >= MAX_SNOWLINE_HEIGHT || _opt_newgame.landscape != LT_ARCTIC);
+struct GenerateLandscapeWindow : public QueryStringBaseWindow {
+ uint widget_id;
+ uint x;
+ uint y;
+ char name[64];
+ glwp_modes mode;
- w->SetWidgetLoweredState(GLAND_TEMPERATE, _opt_newgame.landscape == LT_TEMPERATE);
- w->SetWidgetLoweredState(GLAND_ARCTIC, _opt_newgame.landscape == LT_ARCTIC);
- w->SetWidgetLoweredState(GLAND_TROPICAL, _opt_newgame.landscape == LT_TROPIC);
- w->SetWidgetLoweredState(GLAND_TOYLAND, _opt_newgame.landscape == LT_TOYLAND);
+ GenerateLandscapeWindow(const WindowDesc *desc, void *data = NULL, WindowNumber number = 0) : QueryStringBaseWindow(desc, NULL, number)
+ {
+ this->LowerWidget(_opt_newgame.landscape + GLAND_TEMPERATE);
- if (_game_mode == GM_EDITOR) {
- w->widget[GLAND_TOWN_PULLDOWN].data = STR_6836_OFF;
- w->widget[GLAND_INDUSTRY_PULLDOWN].data = STR_6836_OFF;
+ snprintf(this->edit_str_buf, sizeof(this->edit_str_buf), "%u", _patches_newgame.generation_seed);
+ InitializeTextBuffer(&this->text, this->edit_str_buf, lengthof(this->edit_str_buf), 120);
+ this->caption = STR_NULL;
+ this->afilter = CS_NUMERAL;
+
+ this->mode = (glwp_modes)this->window_number;
+
+ this->FindWindowPlacementAndResize(desc);
+ }
+
+ virtual void OnPaint()
+ {
+ /* You can't select smoothness if not terragenesis */
+ if (mode == GLWP_GENERATE) {
+ this->SetWidgetDisabledState(GLAND_SMOOTHNESS_PULLDOWN, _patches_newgame.land_generator == 0);
+ }
+ /* Disable snowline if not hilly */
+ this->SetWidgetDisabledState(GLAND_SNOW_LEVEL_TEXT, _opt_newgame.landscape != LT_ARCTIC);
+ /* Disable town, industry and trees in SE */
+ this->SetWidgetDisabledState(GLAND_TOWN_PULLDOWN, _game_mode == GM_EDITOR);
+ this->SetWidgetDisabledState(GLAND_INDUSTRY_PULLDOWN, _game_mode == GM_EDITOR);
+ this->SetWidgetDisabledState(GLAND_TREE_PULLDOWN, _game_mode == GM_EDITOR);
+
+ this->SetWidgetDisabledState(GLAND_START_DATE_DOWN, _patches_newgame.starting_year <= MIN_YEAR);
+ this->SetWidgetDisabledState(GLAND_START_DATE_UP, _patches_newgame.starting_year >= MAX_YEAR);
+ this->SetWidgetDisabledState(GLAND_SNOW_LEVEL_DOWN, _patches_newgame.snow_line_height <= 2 || _opt_newgame.landscape != LT_ARCTIC);
+ this->SetWidgetDisabledState(GLAND_SNOW_LEVEL_UP, _patches_newgame.snow_line_height >= MAX_SNOWLINE_HEIGHT || _opt_newgame.landscape != LT_ARCTIC);
+
+ this->SetWidgetLoweredState(GLAND_TEMPERATE, _opt_newgame.landscape == LT_TEMPERATE);
+ this->SetWidgetLoweredState(GLAND_ARCTIC, _opt_newgame.landscape == LT_ARCTIC);
+ this->SetWidgetLoweredState(GLAND_TROPICAL, _opt_newgame.landscape == LT_TROPIC);
+ this->SetWidgetLoweredState(GLAND_TOYLAND, _opt_newgame.landscape == LT_TOYLAND);
+
+ if (_game_mode == GM_EDITOR) {
+ this->widget[GLAND_TOWN_PULLDOWN].data = STR_6836_OFF;
+ this->widget[GLAND_INDUSTRY_PULLDOWN].data = STR_6836_OFF;
+ } else {
+ this->widget[GLAND_TOWN_PULLDOWN].data = _num_towns[_opt_newgame.diff.number_towns];
+ this->widget[GLAND_INDUSTRY_PULLDOWN].data = _num_inds[_opt_newgame.diff.number_industries];
+ }
+
+ if (mode == GLWP_GENERATE) {
+ this->widget[GLAND_LANDSCAPE_PULLDOWN].data = _landscape[_patches_newgame.land_generator];
+ this->widget[GLAND_TREE_PULLDOWN].data = _tree_placer[_patches_newgame.tree_placer];
+ this->widget[GLAND_TERRAIN_PULLDOWN].data = _elevations[_opt_newgame.diff.terrain_type];
+ this->widget[GLAND_WATER_PULLDOWN].data = _sea_lakes[_opt_newgame.diff.quantity_sea_lakes];
+ this->widget[GLAND_SMOOTHNESS_PULLDOWN].data = _smoothness[_patches_newgame.tgen_smoothness];
+ } else {
+ this->widget[GLAND_TREE_PULLDOWN].data = _tree_placer[_patches_newgame.tree_placer];
+ this->widget[GLAND_HEIGHTMAP_ROTATION_PULLDOWN].data = _rotation[_patches_newgame.heightmap_rotation];
+ }
+
+ /* Set parameters for widget text that requires them. */
+ SetDParam(0, ConvertYMDToDate(_patches_newgame.starting_year, 0, 1)); // GLAND_START_DATE_TEXT
+ SetDParam(1, 1 << _patches_newgame.map_x); // GLAND_MAPSIZE_X_PULLDOWN
+ SetDParam(2, 1 << _patches_newgame.map_y); // GLAND_MAPSIZE_Y_PULLDOWN
+ SetDParam(3, _patches_newgame.snow_line_height); // GLAND_SNOW_LEVEL_TEXT
+
+ DrawWindowWidgets(this);
+
+ this->DrawEditBox(GLAND_RANDOM_EDITBOX);
+
+ if (mode != GLWP_GENERATE) {
+ char buffer[512];
+
+ if (_patches_newgame.heightmap_rotation == HM_CLOCKWISE) {
+ SetDParam(0, this->y);
+ SetDParam(1, this->x);
} else {
- w->widget[GLAND_TOWN_PULLDOWN].data = num_towns[_opt_newgame.diff.number_towns];
- w->widget[GLAND_INDUSTRY_PULLDOWN].data = num_inds[_opt_newgame.diff.number_industries];
- }
-
- if (mode == GLWP_GENERATE) {
- w->widget[GLAND_LANDSCAPE_PULLDOWN].data = landscape[_patches_newgame.land_generator];
- w->widget[GLAND_TREE_PULLDOWN].data = tree_placer[_patches_newgame.tree_placer];
- w->widget[GLAND_TERRAIN_PULLDOWN].data = elevations[_opt_newgame.diff.terrain_type];
- w->widget[GLAND_WATER_PULLDOWN].data = sea_lakes[_opt_newgame.diff.quantity_sea_lakes];
- w->widget[GLAND_SMOOTHNESS_PULLDOWN].data = smoothness[_patches_newgame.tgen_smoothness];
- } else {
- w->widget[GLAND_TREE_PULLDOWN].data = tree_placer[_patches_newgame.tree_placer];
- w->widget[GLAND_HEIGHTMAP_ROTATION_PULLDOWN].data = rotation[_patches_newgame.heightmap_rotation];
+ SetDParam(0, this->x);
+ SetDParam(1, this->y);
}
-
- /* Set parameters for widget text that requires them. */
- SetDParam(0, ConvertYMDToDate(_patches_newgame.starting_year, 0, 1)); // GLAND_START_DATE_TEXT
- SetDParam(1, 1 << _patches_newgame.map_x); // GLAND_MAPSIZE_X_PULLDOWN
- SetDParam(2, 1 << _patches_newgame.map_y); // GLAND_MAPSIZE_Y_PULLDOWN
- SetDParam(3, _patches_newgame.snow_line_height); // GLAND_SNOW_LEVEL_TEXT
-
- DrawWindowWidgets(w);
-
- DrawEditBox(w, &_genseed_query, GLAND_RANDOM_EDITBOX);
-
- if (mode != GLWP_GENERATE) {
- char buffer[512];
-
- if (_patches_newgame.heightmap_rotation == HM_CLOCKWISE) {
- SetDParam(0, WP(w, generate_d).y);
- SetDParam(1, WP(w, generate_d).x);
- } else {
- SetDParam(0, WP(w, generate_d).x);
- SetDParam(1, WP(w, generate_d).y);
- }
- GetString(buffer, STR_HEIGHTMAP_SIZE, lastof(buffer));
- DrawStringRightAligned(326, 91, STR_HEIGHTMAP_SIZE, TC_BLACK);
-
- DrawString( 12, 91, STR_HEIGHTMAP_NAME, TC_BLACK);
- SetDParamStr(0, WP(w, generate_d).name);
- DrawStringTruncated(114, 91, STR_ORANGE, TC_BLACK, 326 - 114 - GetStringBoundingBox(buffer).width - 5);
- }
- break;
+ GetString(buffer, STR_HEIGHTMAP_SIZE, lastof(buffer));
+ DrawStringRightAligned(326, 91, STR_HEIGHTMAP_SIZE, TC_BLACK);
- case WE_CLICK:
- switch (e->we.click.widget) {
- case 0: delete w; break;
-
- case GLAND_TEMPERATE:
- case GLAND_ARCTIC:
- case GLAND_TROPICAL:
- case GLAND_TOYLAND:
- w->RaiseWidget(_opt_newgame.landscape + GLAND_TEMPERATE);
- SetNewLandscapeType(e->we.click.widget - GLAND_TEMPERATE);
- break;
-
- case GLAND_MAPSIZE_X_PULLDOWN: // Mapsize X
- ShowDropDownList(w, BuildMapsizeDropDown(), _patches_newgame.map_x, GLAND_MAPSIZE_X_PULLDOWN);
- break;
+ DrawString( 12, 91, STR_HEIGHTMAP_NAME, TC_BLACK);
+ SetDParamStr(0, this->name);
+ DrawStringTruncated(114, 91, STR_ORANGE, TC_BLACK, 326 - 114 - GetStringBoundingBox(buffer).width - 5);
+ }
+ }
- case GLAND_MAPSIZE_Y_PULLDOWN: // Mapsize Y
- ShowDropDownList(w, BuildMapsizeDropDown(), _patches_newgame.map_y, GLAND_MAPSIZE_Y_PULLDOWN);
- break;
-
- case GLAND_TOWN_PULLDOWN: // Number of towns
- ShowDropDownMenu(w, num_towns, _opt_newgame.diff.number_towns, GLAND_TOWN_PULLDOWN, 0, 0);
- break;
+ virtual void OnClick(Point pt, int widget)
+ {
+ switch (widget) {
+ case 0: delete this; break;
- case GLAND_INDUSTRY_PULLDOWN: // Number of industries
- ShowDropDownMenu(w, num_inds, _opt_newgame.diff.number_industries, GLAND_INDUSTRY_PULLDOWN, 0, 0);
- break;
+ case GLAND_TEMPERATE:
+ case GLAND_ARCTIC:
+ case GLAND_TROPICAL:
+ case GLAND_TOYLAND:
+ this->RaiseWidget(_opt_newgame.landscape + GLAND_TEMPERATE);
+ SetNewLandscapeType(widget - GLAND_TEMPERATE);
+ break;
- case GLAND_RANDOM_BUTTON: // Random seed
- _patches_newgame.generation_seed = InteractiveRandom();
- snprintf(_genseed_buffer, lengthof(_genseed_buffer), "%u", _patches_newgame.generation_seed);
- UpdateTextBufferSize(&_genseed_query.text);
- w->SetDirty();
- break;
+ case GLAND_MAPSIZE_X_PULLDOWN: // Mapsize X
+ ShowDropDownList(this, BuildMapsizeDropDown(), _patches_newgame.map_x, GLAND_MAPSIZE_X_PULLDOWN);
+ break;
- case GLAND_RANDOM_EDITBOX: // edit box for random seed
- ShowOnScreenKeyboard(w, & _genseed_query, GLAND_RANDOM_EDITBOX, 0, 0);
+ case GLAND_MAPSIZE_Y_PULLDOWN: // Mapsize Y
+ ShowDropDownList(this, BuildMapsizeDropDown(), _patches_newgame.map_y, GLAND_MAPSIZE_Y_PULLDOWN);
+ break;
+
+ case GLAND_TOWN_PULLDOWN: // Number of towns
+ ShowDropDownMenu(this, _num_towns, _opt_newgame.diff.number_towns, GLAND_TOWN_PULLDOWN, 0, 0);
+ break;
+
+ case GLAND_INDUSTRY_PULLDOWN: // Number of industries
+ ShowDropDownMenu(this, _num_inds, _opt_newgame.diff.number_industries, GLAND_INDUSTRY_PULLDOWN, 0, 0);
+ break;
+
+ case GLAND_RANDOM_BUTTON: // Random seed
+ _patches_newgame.generation_seed = InteractiveRandom();
+ snprintf(this->edit_str_buf, lengthof(this->edit_str_buf), "%u", _patches_newgame.generation_seed);
+ UpdateTextBufferSize(&this->text);
+ this->SetDirty();
+ break;
+
+ case GLAND_RANDOM_EDITBOX: // edit box for random seed
+ ShowOnScreenKeyboard(this, GLAND_RANDOM_EDITBOX, 0, 0);
+ break;
+
+ case GLAND_GENERATE_BUTTON: // Generate
+ UpdatePatches();
+
+ if (_patches.town_layout == TL_NO_ROADS) {
+ ShowQuery(
+ STR_TOWN_LAYOUT_WARNING_CAPTION,
+ STR_TOWN_LAYOUT_WARNING_MESSAGE,
+ this,
+ LandscapeGenerationCallback);
+ } else if (mode == GLWP_HEIGHTMAP &&
+ (this->x * 2 < (1U << _patches_newgame.map_x) ||
+ this->x / 2 > (1U << _patches_newgame.map_x) ||
+ this->y * 2 < (1U << _patches_newgame.map_y) ||
+ this->y / 2 > (1U << _patches_newgame.map_y))) {
+ ShowQuery(
+ STR_HEIGHTMAP_SCALE_WARNING_CAPTION,
+ STR_HEIGHTMAP_SCALE_WARNING_MESSAGE,
+ this,
+ LandscapeGenerationCallback);
+ } else {
+ StartGeneratingLandscape(mode);
+ }
+ break;
+
+ case GLAND_START_DATE_DOWN:
+ case GLAND_START_DATE_UP: // Year buttons
+ /* Don't allow too fast scrolling */
+ if ((this->flags4 & WF_TIMEOUT_MASK) <= 2 << WF_TIMEOUT_SHL) {
+ this->HandleButtonClick(widget);
+ this->SetDirty();
+
+ _patches_newgame.starting_year = Clamp(_patches_newgame.starting_year + widget - GLAND_START_DATE_TEXT, MIN_YEAR, MAX_YEAR);
+ }
+ _left_button_clicked = false;
+ break;
+
+ case GLAND_START_DATE_TEXT: // Year text
+ this->widget_id = GLAND_START_DATE_TEXT;
+ SetDParam(0, _patches_newgame.starting_year);
+ ShowQueryString(STR_CONFIG_PATCHES_INT32, STR_START_DATE_QUERY_CAPT, 8, 100, this, CS_NUMERAL);
+ break;
+
+ case GLAND_SNOW_LEVEL_DOWN:
+ case GLAND_SNOW_LEVEL_UP: // Snow line buttons
+ /* Don't allow too fast scrolling */
+ if ((this->flags4 & WF_TIMEOUT_MASK) <= 2 << WF_TIMEOUT_SHL) {
+ this->HandleButtonClick(widget);
+ this->SetDirty();
+
+ _patches_newgame.snow_line_height = Clamp(_patches_newgame.snow_line_height + widget - GLAND_SNOW_LEVEL_TEXT, 2, MAX_SNOWLINE_HEIGHT);
+ }
+ _left_button_clicked = false;
+ break;
+
+ case GLAND_SNOW_LEVEL_TEXT: // Snow line text
+ this->widget_id = GLAND_SNOW_LEVEL_TEXT;
+ SetDParam(0, _patches_newgame.snow_line_height);
+ ShowQueryString(STR_CONFIG_PATCHES_INT32, STR_SNOW_LINE_QUERY_CAPT, 3, 100, this, CS_NUMERAL);
+ break;
+
+ case GLAND_TREE_PULLDOWN: // Tree placer
+ ShowDropDownMenu(this, _tree_placer, _patches_newgame.tree_placer, GLAND_TREE_PULLDOWN, 0, 0);
+ break;
+
+ case GLAND_LANDSCAPE_PULLDOWN: // Landscape generator OR Heightmap rotation
+ /* case GLAND_HEIGHTMAP_ROTATION_TEXT: case GLAND_HEIGHTMAP_ROTATION_PULLDOWN:*/
+ if (mode == GLWP_HEIGHTMAP) {
+ ShowDropDownMenu(this, _rotation, _patches_newgame.heightmap_rotation, GLAND_HEIGHTMAP_ROTATION_PULLDOWN, 0, 0);
+ } else {
+ ShowDropDownMenu(this, _landscape, _patches_newgame.land_generator, GLAND_LANDSCAPE_PULLDOWN, 0, 0);
+ }
+ break;
+
+ case GLAND_TERRAIN_PULLDOWN: // Terrain type
+ ShowDropDownMenu(this, _elevations, _opt_newgame.diff.terrain_type, GLAND_TERRAIN_PULLDOWN, 0, 0);
+ break;
+
+ case GLAND_WATER_PULLDOWN: // Water quantity
+ ShowDropDownMenu(this, _sea_lakes, _opt_newgame.diff.quantity_sea_lakes, GLAND_WATER_PULLDOWN, 0, 0);
+ break;
+
+ case GLAND_SMOOTHNESS_PULLDOWN: // Map smoothness
+ ShowDropDownMenu(this, _smoothness, _patches_newgame.tgen_smoothness, GLAND_SMOOTHNESS_PULLDOWN, 0, 0);
+ break;
+ }
+ }
+
+ virtual void OnMouseLoop()
+ {
+ this->HandleEditBox(GLAND_RANDOM_EDITBOX);
+ }
+
+ virtual bool OnKeyPress(uint16 key, uint16 keycode)
+ {
+ bool cont;
+ this->HandleEditBoxKey(GLAND_RANDOM_EDITBOX, key, keycode, cont);
+ /* the seed is unsigned, therefore atoi cannot be used.
+ * As 2^32 - 1 (MAX_UVALUE(uint32)) is a 'magic' value
+ * (use random seed) it should not be possible to be
+ * entered into the input field; the generate seed
+ * button can be used instead. */
+ _patches_newgame.generation_seed = minu(strtoul(this->edit_str_buf, NULL, sizeof(this->edit_str_buf) - 1), MAX_UVALUE(uint32) - 1);
+ return cont;
+ }
+
+ virtual void OnDropdownSelect(int widget, int index)
+ {
+ switch (widget) {
+ case GLAND_MAPSIZE_X_PULLDOWN: _patches_newgame.map_x = index; break;
+ case GLAND_MAPSIZE_Y_PULLDOWN: _patches_newgame.map_y = index; break;
+ case GLAND_TREE_PULLDOWN: _patches_newgame.tree_placer = index; break;
+ case GLAND_SMOOTHNESS_PULLDOWN: _patches_newgame.tgen_smoothness = index; break;
+
+ case GLAND_TOWN_PULLDOWN:
+ _opt_newgame.diff.number_towns = index;
+ if (_opt_newgame.diff_level != 3) ShowErrorMessage(INVALID_STRING_ID, STR_DIFFICULTY_TO_CUSTOM, 0, 0);
+ DoCommandP(0, 2, _opt_newgame.diff.number_towns, NULL, CMD_CHANGE_DIFFICULTY_LEVEL);
+ break;
+
+ case GLAND_INDUSTRY_PULLDOWN:
+ _opt_newgame.diff.number_industries = index;
+ if (_opt_newgame.diff_level != 3) ShowErrorMessage(INVALID_STRING_ID, STR_DIFFICULTY_TO_CUSTOM, 0, 0);
+ DoCommandP(0, 3, _opt_newgame.diff.number_industries, NULL, CMD_CHANGE_DIFFICULTY_LEVEL);
+ break;
+
+ case GLAND_LANDSCAPE_PULLDOWN:
+ /* case GLAND_HEIGHTMAP_PULLDOWN: */
+ if (mode == GLWP_HEIGHTMAP) {
+ _patches_newgame.heightmap_rotation = index;
+ } else {
+ _patches_newgame.land_generator = index;
+ }
+ break;
+
+ case GLAND_TERRAIN_PULLDOWN:
+ _opt_newgame.diff.terrain_type = index;
+ if (_opt_newgame.diff_level != 3) ShowErrorMessage(INVALID_STRING_ID, STR_DIFFICULTY_TO_CUSTOM, 0, 0);
+ DoCommandP(0, 12, _opt_newgame.diff.terrain_type, NULL, CMD_CHANGE_DIFFICULTY_LEVEL);
+ break;
+
+ case GLAND_WATER_PULLDOWN:
+ _opt_newgame.diff.quantity_sea_lakes = index;
+ if (_opt_newgame.diff_level != 3) ShowErrorMessage(INVALID_STRING_ID, STR_DIFFICULTY_TO_CUSTOM, 0, 0);
+ DoCommandP(0, 13, _opt_newgame.diff.quantity_sea_lakes, NULL, CMD_CHANGE_DIFFICULTY_LEVEL);
+ break;
+ }
+ this->SetDirty();
+ }
+
+ virtual void OnQueryTextFinished(char *str)
+ {
+ if (!StrEmpty(str)) {
+ int32 value = atoi(str);
+
+ switch (this->widget_id) {
+ case GLAND_START_DATE_TEXT:
+ this->InvalidateWidget(GLAND_START_DATE_TEXT);
+ _patches_newgame.starting_year = Clamp(value, MIN_YEAR, MAX_YEAR);
break;
- case GLAND_GENERATE_BUTTON: // Generate
- UpdatePatches();
-
- if (_patches.town_layout == TL_NO_ROADS) {
- ShowQuery(
- STR_TOWN_LAYOUT_WARNING_CAPTION,
- STR_TOWN_LAYOUT_WARNING_MESSAGE,
- w,
- LandscapeGenerationCallback);
- } else if (mode == GLWP_HEIGHTMAP &&
- (WP(w, generate_d).x * 2 < (1U << _patches_newgame.map_x) ||
- WP(w, generate_d).x / 2 > (1U << _patches_newgame.map_x) ||
- WP(w, generate_d).y * 2 < (1U << _patches_newgame.map_y) ||
- WP(w, generate_d).y / 2 > (1U << _patches_newgame.map_y))) {
- ShowQuery(
- STR_HEIGHTMAP_SCALE_WARNING_CAPTION,
- STR_HEIGHTMAP_SCALE_WARNING_MESSAGE,
- w,
- LandscapeGenerationCallback);
- } else {
- StartGeneratingLandscape(mode);
- }
- break;
-
- case GLAND_START_DATE_DOWN:
- case GLAND_START_DATE_UP: // Year buttons
- /* Don't allow too fast scrolling */
- if ((w->flags4 & WF_TIMEOUT_MASK) <= 2 << WF_TIMEOUT_SHL) {
- w->HandleButtonClick(e->we.click.widget);
- w->SetDirty();
-
- _patches_newgame.starting_year = Clamp(_patches_newgame.starting_year + e->we.click.widget - GLAND_START_DATE_TEXT, MIN_YEAR, MAX_YEAR);
- }
- _left_button_clicked = false;
- break;
-
- case GLAND_START_DATE_TEXT: // Year text
- WP(w, generate_d).widget_id = GLAND_START_DATE_TEXT;
- SetDParam(0, _patches_newgame.starting_year);
- ShowQueryString(STR_CONFIG_PATCHES_INT32, STR_START_DATE_QUERY_CAPT, 8, 100, w, CS_NUMERAL);
- break;
-
- case GLAND_SNOW_LEVEL_DOWN:
- case GLAND_SNOW_LEVEL_UP: // Snow line buttons
- /* Don't allow too fast scrolling */
- if ((w->flags4 & WF_TIMEOUT_MASK) <= 2 << WF_TIMEOUT_SHL) {
- w->HandleButtonClick(e->we.click.widget);
- w->SetDirty();
-
- _patches_newgame.snow_line_height = Clamp(_patches_newgame.snow_line_height + e->we.click.widget - GLAND_SNOW_LEVEL_TEXT, 2, MAX_SNOWLINE_HEIGHT);
- }
- _left_button_clicked = false;
- break;
-
- case GLAND_SNOW_LEVEL_TEXT: // Snow line text
- WP(w, generate_d).widget_id = GLAND_SNOW_LEVEL_TEXT;
- SetDParam(0, _patches_newgame.snow_line_height);
- ShowQueryString(STR_CONFIG_PATCHES_INT32, STR_SNOW_LINE_QUERY_CAPT, 3, 100, w, CS_NUMERAL);
- break;
-
- case GLAND_TREE_PULLDOWN: // Tree placer
- ShowDropDownMenu(w, tree_placer, _patches_newgame.tree_placer, GLAND_TREE_PULLDOWN, 0, 0);
- break;
-
- case GLAND_LANDSCAPE_PULLDOWN: // Landscape generator OR Heightmap rotation
- /* case GLAND_HEIGHTMAP_ROTATION_TEXT: case GLAND_HEIGHTMAP_ROTATION_PULLDOWN:*/
- if (mode == GLWP_HEIGHTMAP) {
- ShowDropDownMenu(w, rotation, _patches_newgame.heightmap_rotation, GLAND_HEIGHTMAP_ROTATION_PULLDOWN, 0, 0);
- } else {
- ShowDropDownMenu(w, landscape, _patches_newgame.land_generator, GLAND_LANDSCAPE_PULLDOWN, 0, 0);
- }
- break;
-
- case GLAND_TERRAIN_PULLDOWN: // Terrain type
- ShowDropDownMenu(w, elevations, _opt_newgame.diff.terrain_type, GLAND_TERRAIN_PULLDOWN, 0, 0);
- break;
-
- case GLAND_WATER_PULLDOWN: // Water quantity
- ShowDropDownMenu(w, sea_lakes, _opt_newgame.diff.quantity_sea_lakes, GLAND_WATER_PULLDOWN, 0, 0);
- break;
-
- case GLAND_SMOOTHNESS_PULLDOWN: // Map smoothness
- ShowDropDownMenu(w, smoothness, _patches_newgame.tgen_smoothness, GLAND_SMOOTHNESS_PULLDOWN, 0, 0);
+ case GLAND_SNOW_LEVEL_TEXT:
+ this->InvalidateWidget(GLAND_SNOW_LEVEL_TEXT);
+ _patches_newgame.snow_line_height = Clamp(value, 2, MAX_SNOWLINE_HEIGHT);
break;
}
- break;
-
- case WE_MOUSELOOP:
- HandleEditBox(w, &_genseed_query, GLAND_RANDOM_EDITBOX);
- break;
-
- case WE_KEYPRESS:
- HandleEditBoxKey(w, &_genseed_query, GLAND_RANDOM_EDITBOX, e);
- /* the seed is unsigned, therefore atoi cannot be used.
- * As 2^32 - 1 (MAX_UVALUE(uint32)) is a 'magic' value
- * (use random seed) it should not be possible to be
- * entered into the input field; the generate seed
- * button can be used instead. */
- _patches_newgame.generation_seed = minu(strtoul(_genseed_buffer, NULL, sizeof(_genseed_buffer) - 1), MAX_UVALUE(uint32) - 1);
- break;
-
- case WE_DROPDOWN_SELECT:
- switch (e->we.dropdown.button) {
- case GLAND_MAPSIZE_X_PULLDOWN: _patches_newgame.map_x = e->we.dropdown.index; break;
- case GLAND_MAPSIZE_Y_PULLDOWN: _patches_newgame.map_y = e->we.dropdown.index; break;
- case GLAND_TREE_PULLDOWN: _patches_newgame.tree_placer = e->we.dropdown.index; break;
- case GLAND_SMOOTHNESS_PULLDOWN: _patches_newgame.tgen_smoothness = e->we.dropdown.index; break;
-
- case GLAND_TOWN_PULLDOWN:
- _opt_newgame.diff.number_towns = e->we.dropdown.index;
- if (_opt_newgame.diff_level != 3) ShowErrorMessage(INVALID_STRING_ID, STR_DIFFICULTY_TO_CUSTOM, 0, 0);
- DoCommandP(0, 2, _opt_newgame.diff.number_towns, NULL, CMD_CHANGE_DIFFICULTY_LEVEL);
- break;
-
- case GLAND_INDUSTRY_PULLDOWN:
- _opt_newgame.diff.number_industries = e->we.dropdown.index;
- if (_opt_newgame.diff_level != 3) ShowErrorMessage(INVALID_STRING_ID, STR_DIFFICULTY_TO_CUSTOM, 0, 0);
- DoCommandP(0, 3, _opt_newgame.diff.number_industries, NULL, CMD_CHANGE_DIFFICULTY_LEVEL);
- break;
- case GLAND_LANDSCAPE_PULLDOWN:
- /* case GLAND_HEIGHTMAP_PULLDOWN: */
- if (mode == GLWP_HEIGHTMAP) {
- _patches_newgame.heightmap_rotation = e->we.dropdown.index;
- } else {
- _patches_newgame.land_generator = e->we.dropdown.index;
- }
- break;
-
- case GLAND_TERRAIN_PULLDOWN:
- _opt_newgame.diff.terrain_type = e->we.dropdown.index;
- if (_opt_newgame.diff_level != 3) ShowErrorMessage(INVALID_STRING_ID, STR_DIFFICULTY_TO_CUSTOM, 0, 0);
- DoCommandP(0, 12, _opt_newgame.diff.terrain_type, NULL, CMD_CHANGE_DIFFICULTY_LEVEL);
- break;
-
- case GLAND_WATER_PULLDOWN:
- _opt_newgame.diff.quantity_sea_lakes = e->we.dropdown.index;
- if (_opt_newgame.diff_level != 3) ShowErrorMessage(INVALID_STRING_ID, STR_DIFFICULTY_TO_CUSTOM, 0, 0);
- DoCommandP(0, 13, _opt_newgame.diff.quantity_sea_lakes, NULL, CMD_CHANGE_DIFFICULTY_LEVEL);
- break;
- }
- w->SetDirty();
- break;
-
- case WE_ON_EDIT_TEXT:
- if (e->we.edittext.str != NULL) {
- int32 value = atoi(e->we.edittext.str);
-
- switch (WP(w, generate_d).widget_id) {
- case GLAND_START_DATE_TEXT:
- w->InvalidateWidget(GLAND_START_DATE_TEXT);
- _patches_newgame.starting_year = Clamp(value, MIN_YEAR, MAX_YEAR);
- break;
-
- case GLAND_SNOW_LEVEL_TEXT:
- w->InvalidateWidget(GLAND_SNOW_LEVEL_TEXT);
- _patches_newgame.snow_line_height = Clamp(value, 2, MAX_SNOWLINE_HEIGHT);
- break;
- }
-
- w->SetDirty();
- }
- break;
+ this->SetDirty();
+ }
}
-}
+};
static const WindowDesc _generate_landscape_desc = {
WDP_CENTER, WDP_CENTER, 338, 268, 338, 268,
WC_GENERATE_LANDSCAPE, WC_NONE,
WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
_generate_landscape_widgets,
- GenerateLandscapeWndProc,
+ NULL,
};
static const WindowDesc _heightmap_load_desc = {
@@ -559,7 +562,7 @@
WC_GENERATE_LANDSCAPE, WC_NONE,
WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_STD_BTN | WDF_UNCLICK_BUTTONS,
_heightmap_load_widgets,
- GenerateLandscapeWndProc,
+ NULL,
};
static void _ShowGenerateLandscape(glwp_modes mode)
@@ -577,14 +580,12 @@
if (!GetHeightmapDimensions(_file_to_saveload.name, &x, &y)) return;
}
- Window *w = AllocateWindowDescFront((mode == GLWP_HEIGHTMAP) ? &_heightmap_load_desc : &_generate_landscape_desc, mode);
-
- if (w == NULL) return;
+ GenerateLandscapeWindow *w = AllocateWindowDescFront<GenerateLandscapeWindow>((mode == GLWP_HEIGHTMAP) ? &_heightmap_load_desc : &_generate_landscape_desc, mode);
if (mode == GLWP_HEIGHTMAP) {
- WP(w, generate_d).x = x;
- WP(w, generate_d).y = y;
- strecpy(WP(w, generate_d).name, _file_to_saveload.title, lastof(WP(w, generate_d).name));
+ w->x = x;
+ w->y = y;
+ strecpy(w->name, _file_to_saveload.title, lastof(w->name));
}
InvalidateWindow(WC_GENERATE_LANDSCAPE, mode);
@@ -639,127 +640,131 @@
};
-static void CreateScenarioWndProc(Window *w, WindowEvent *e)
+struct CreateScenarioWindow : public Window
{
- switch (e->event) {
- case WE_CREATE:
- w->LowerWidget(_opt_newgame.landscape + CSCEN_TEMPERATE);
- break;
-
- case WE_PAINT:
- w->SetWidgetDisabledState(CSCEN_START_DATE_DOWN, _patches_newgame.starting_year <= MIN_YEAR);
- w->SetWidgetDisabledState(CSCEN_START_DATE_UP, _patches_newgame.starting_year >= MAX_YEAR);
- w->SetWidgetDisabledState(CSCEN_FLAT_LAND_HEIGHT_DOWN, _patches_newgame.se_flat_world_height <= 0);
- w->SetWidgetDisabledState(CSCEN_FLAT_LAND_HEIGHT_UP, _patches_newgame.se_flat_world_height >= MAX_TILE_HEIGHT);
-
- w->SetWidgetLoweredState(CSCEN_TEMPERATE, _opt_newgame.landscape == LT_TEMPERATE);
- w->SetWidgetLoweredState(CSCEN_ARCTIC, _opt_newgame.landscape == LT_ARCTIC);
- w->SetWidgetLoweredState(CSCEN_TROPICAL, _opt_newgame.landscape == LT_TROPIC);
- w->SetWidgetLoweredState(CSCEN_TOYLAND, _opt_newgame.landscape == LT_TOYLAND);
-
- /* Set parameters for widget text that requires them */
- SetDParam(0, ConvertYMDToDate(_patches_newgame.starting_year, 0, 1)); // CSCEN_START_DATE_TEXT
- SetDParam(1, 1 << _patches_newgame.map_x); // CSCEN_MAPSIZE_X_PULLDOWN
- SetDParam(2, 1 << _patches_newgame.map_y); // CSCEN_MAPSIZE_Y_PULLDOWN
- SetDParam(3, _patches_newgame.se_flat_world_height); // CSCEN_FLAT_LAND_HEIGHT_TEXT
-
- DrawWindowWidgets(w);
+ uint widget_id;
- break;
-
- case WE_CLICK:
- switch (e->we.click.widget) {
- case CSCEN_TEMPERATE:
- case CSCEN_ARCTIC:
- case CSCEN_TROPICAL:
- case CSCEN_TOYLAND:
- w->RaiseWidget(_opt_newgame.landscape + CSCEN_TEMPERATE);
- SetNewLandscapeType(e->we.click.widget - CSCEN_TEMPERATE);
- break;
+ CreateScenarioWindow(const WindowDesc *desc, WindowNumber window_number) : Window(desc, NULL, window_number)
+ {
+ this->LowerWidget(_opt_newgame.landscape + CSCEN_TEMPERATE);
+ }
- case CSCEN_MAPSIZE_X_PULLDOWN: // Mapsize X
- ShowDropDownList(w, BuildMapsizeDropDown(), _patches_newgame.map_x, CSCEN_MAPSIZE_X_PULLDOWN);
- break;
+ virtual void OnPaint()
+ {
+ this->SetWidgetDisabledState(CSCEN_START_DATE_DOWN, _patches_newgame.starting_year <= MIN_YEAR);
+ this->SetWidgetDisabledState(CSCEN_START_DATE_UP, _patches_newgame.starting_year >= MAX_YEAR);
+ this->SetWidgetDisabledState(CSCEN_FLAT_LAND_HEIGHT_DOWN, _patches_newgame.se_flat_world_height <= 0);
+ this->SetWidgetDisabledState(CSCEN_FLAT_LAND_HEIGHT_UP, _patches_newgame.se_flat_world_height >= MAX_TILE_HEIGHT);
- case CSCEN_MAPSIZE_Y_PULLDOWN: // Mapsize Y
- ShowDropDownList(w, BuildMapsizeDropDown(), _patches_newgame.map_y, CSCEN_MAPSIZE_Y_PULLDOWN);
- break;
+ this->SetWidgetLoweredState(CSCEN_TEMPERATE, _opt_newgame.landscape == LT_TEMPERATE);
+ this->SetWidgetLoweredState(CSCEN_ARCTIC, _opt_newgame.landscape == LT_ARCTIC);
+ this->SetWidgetLoweredState(CSCEN_TROPICAL, _opt_newgame.landscape == LT_TROPIC);
+ this->SetWidgetLoweredState(CSCEN_TOYLAND, _opt_newgame.landscape == LT_TOYLAND);
- case CSCEN_EMPTY_WORLD: // Empty world / flat world
- StartGeneratingLandscape(GLWP_SCENARIO);
- break;
+ /* Set parameters for widget text that requires them */
+ SetDParam(0, ConvertYMDToDate(_patches_newgame.starting_year, 0, 1)); // CSCEN_START_DATE_TEXT
+ SetDParam(1, 1 << _patches_newgame.map_x); // CSCEN_MAPSIZE_X_PULLDOWN
+ SetDParam(2, 1 << _patches_newgame.map_y); // CSCEN_MAPSIZE_Y_PULLDOWN
+ SetDParam(3, _patches_newgame.se_flat_world_height); // CSCEN_FLAT_LAND_HEIGHT_TEXT
- case CSCEN_RANDOM_WORLD: // Generate
- ShowGenerateLandscape();
+ DrawWindowWidgets(this);
+ }
+
+ virtual void OnClick(Point pt, int widget)
+ {
+ switch (widget) {
+ case CSCEN_TEMPERATE:
+ case CSCEN_ARCTIC:
+ case CSCEN_TROPICAL:
+ case CSCEN_TOYLAND:
+ this->RaiseWidget(_opt_newgame.landscape + CSCEN_TEMPERATE);
+ SetNewLandscapeType(widget - CSCEN_TEMPERATE);
+ break;
+
+ case CSCEN_MAPSIZE_X_PULLDOWN: // Mapsize X
+ ShowDropDownList(this, BuildMapsizeDropDown(), _patches_newgame.map_x, CSCEN_MAPSIZE_X_PULLDOWN);
+ break;
+
+ case CSCEN_MAPSIZE_Y_PULLDOWN: // Mapsize Y
+ ShowDropDownList(this, BuildMapsizeDropDown(), _patches_newgame.map_y, CSCEN_MAPSIZE_Y_PULLDOWN);
+ break;
+
+ case CSCEN_EMPTY_WORLD: // Empty world / flat world
+ StartGeneratingLandscape(GLWP_SCENARIO);
+ break;
+
+ case CSCEN_RANDOM_WORLD: // Generate
+ ShowGenerateLandscape();
+ break;
+
+ case CSCEN_START_DATE_DOWN:
+ case CSCEN_START_DATE_UP: // Year buttons
+ /* Don't allow too fast scrolling */
+ if ((this->flags4 & WF_TIMEOUT_MASK) <= 2 << WF_TIMEOUT_SHL) {
+ this->HandleButtonClick(widget);
+ this->SetDirty();
+
+ _patches_newgame.starting_year = Clamp(_patches_newgame.starting_year + widget - CSCEN_START_DATE_TEXT, MIN_YEAR, MAX_YEAR);
+ }
+ _left_button_clicked = false;
+ break;
+
+ case CSCEN_START_DATE_TEXT: // Year text
+ this->widget_id = CSCEN_START_DATE_TEXT;
+ SetDParam(0, _patches_newgame.starting_year);
+ ShowQueryString(STR_CONFIG_PATCHES_INT32, STR_START_DATE_QUERY_CAPT, 8, 100, this, CS_NUMERAL);
+ break;
+
+ case CSCEN_FLAT_LAND_HEIGHT_DOWN:
+ case CSCEN_FLAT_LAND_HEIGHT_UP: // Height level buttons
+ /* Don't allow too fast scrolling */
+ if ((this->flags4 & WF_TIMEOUT_MASK) <= 2 << WF_TIMEOUT_SHL) {
+ this->HandleButtonClick(widget);
+ this->SetDirty();
+
+ _patches_newgame.se_flat_world_height = Clamp(_patches_newgame.se_flat_world_height + widget - CSCEN_FLAT_LAND_HEIGHT_TEXT, 0, MAX_TILE_HEIGHT);
+ }
+ _left_button_clicked = false;
+ break;
+
+ case CSCEN_FLAT_LAND_HEIGHT_TEXT: // Height level text
+ this->widget_id = CSCEN_FLAT_LAND_HEIGHT_TEXT;
+ SetDParam(0, _patches_newgame.se_flat_world_height);
+ ShowQueryString(STR_CONFIG_PATCHES_INT32, STR_FLAT_WORLD_HEIGHT_QUERY_CAPT, 3, 100, this, CS_NUMERAL);
+ break;
+ }
+ }
+
+ virtual void OnDropdownSelect(int widget, int index)
+ {
+ switch (widget) {
+ case CSCEN_MAPSIZE_X_PULLDOWN: _patches_newgame.map_x = index; break;
+ case CSCEN_MAPSIZE_Y_PULLDOWN: _patches_newgame.map_y = index; break;
+ }
+ this->SetDirty();
+ }
+
+ virtual void OnQueryTextFinished(char *str)
+ {
+ if (!StrEmpty(str)) {
+ int32 value = atoi(str);
+
+ switch (this->widget_id) {
+ case CSCEN_START_DATE_TEXT:
+ this->InvalidateWidget(CSCEN_START_DATE_TEXT);
+ _patches_newgame.starting_year = Clamp(value, MIN_YEAR, MAX_YEAR);
break;
- case CSCEN_START_DATE_DOWN:
- case CSCEN_START_DATE_UP: // Year buttons
- /* Don't allow too fast scrolling */
- if ((w->flags4 & WF_TIMEOUT_MASK) <= 2 << WF_TIMEOUT_SHL) {
- w->HandleButtonClick(e->we.click.widget);
- w->SetDirty();
-
- _patches_newgame.starting_year = Clamp(_patches_newgame.starting_year + e->we.click.widget - CSCEN_START_DATE_TEXT, MIN_YEAR, MAX_YEAR);
- }
- _left_button_clicked = false;
- break;
-
- case CSCEN_START_DATE_TEXT: // Year text
- WP(w, generate_d).widget_id = CSCEN_START_DATE_TEXT;
- SetDParam(0, _patches_newgame.starting_year);
- ShowQueryString(STR_CONFIG_PATCHES_INT32, STR_START_DATE_QUERY_CAPT, 8, 100, w, CS_NUMERAL);
- break;
-
- case CSCEN_FLAT_LAND_HEIGHT_DOWN:
- case CSCEN_FLAT_LAND_HEIGHT_UP: // Height level buttons
- /* Don't allow too fast scrolling */
- if ((w->flags4 & WF_TIMEOUT_MASK) <= 2 << WF_TIMEOUT_SHL) {
- w->HandleButtonClick(e->we.click.widget);
- w->SetDirty();
-
- _patches_newgame.se_flat_world_height = Clamp(_patches_newgame.se_flat_world_height + e->we.click.widget - CSCEN_FLAT_LAND_HEIGHT_TEXT, 0, MAX_TILE_HEIGHT);
- }
- _left_button_clicked = false;
- break;
-
- case CSCEN_FLAT_LAND_HEIGHT_TEXT: // Height level text
- WP(w, generate_d).widget_id = CSCEN_FLAT_LAND_HEIGHT_TEXT;
- SetDParam(0, _patches_newgame.se_flat_world_height);
- ShowQueryString(STR_CONFIG_PATCHES_INT32, STR_FLAT_WORLD_HEIGHT_QUERY_CAPT, 3, 100, w, CS_NUMERAL);
+ case CSCEN_FLAT_LAND_HEIGHT_TEXT:
+ this->InvalidateWidget(CSCEN_FLAT_LAND_HEIGHT_TEXT);
+ _patches_newgame.se_flat_world_height = Clamp(value, 0, MAX_TILE_HEIGHT);
break;
}
- break;
-
- case WE_DROPDOWN_SELECT:
- switch (e->we.dropdown.button) {
- case CSCEN_MAPSIZE_X_PULLDOWN: _patches_newgame.map_x = e->we.dropdown.index; break;
- case CSCEN_MAPSIZE_Y_PULLDOWN: _patches_newgame.map_y = e->we.dropdown.index; break;
- }
- w->SetDirty();
- break;
-
- case WE_ON_EDIT_TEXT:
- if (e->we.edittext.str != NULL) {
- int32 value = atoi(e->we.edittext.str);
- switch (WP(w, generate_d).widget_id) {
- case CSCEN_START_DATE_TEXT:
- w->InvalidateWidget(CSCEN_START_DATE_TEXT);
- _patches_newgame.starting_year = Clamp(value, MIN_YEAR, MAX_YEAR);
- break;
-
- case CSCEN_FLAT_LAND_HEIGHT_TEXT:
- w->InvalidateWidget(CSCEN_FLAT_LAND_HEIGHT_TEXT);
- _patches_newgame.se_flat_world_height = Clamp(value, 0, MAX_TILE_HEIGHT);
- break;
- }
-
- w->SetDirty();
- }
- break;
+ this->SetDirty();
+ }
}
-}
+};
static const Widget _create_scenario_widgets[] = {
{ WWT_CLOSEBOX, RESIZE_NONE, 13, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
@@ -796,13 +801,13 @@
WC_GENERATE_LANDSCAPE, WC_NONE,
WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_STD_BTN | WDF_UNCLICK_BUTTONS,
_create_scenario_widgets,
- CreateScenarioWndProc,
+ NULL,
};
void ShowCreateScenario()
{
DeleteWindowByClass(WC_GENERATE_LANDSCAPE);
- AllocateWindowDescFront(&_create_scenario_desc, GLWP_SCENARIO);
+ new CreateScenarioWindow(&_create_scenario_desc, GLWP_SCENARIO);
}
@@ -896,7 +901,7 @@
*/
void ShowGenerateWorldProgress()
{
- AllocateWindowDescFront(&_show_terrain_progress_desc, 0);
+ AllocateWindowDescFront<Window>(&_show_terrain_progress_desc, 0);
}
static void _SetGeneratingWorldProgress(gwp_class cls, uint progress, uint total)
--- a/src/graph_gui.cpp Wed May 07 21:09:51 2008 +0000
+++ b/src/graph_gui.cpp Sun May 11 20:09:34 2008 +0000
@@ -339,7 +339,7 @@
static void ShowGraphLegend()
{
- AllocateWindowDescFront(&_graph_legend_desc, 0);
+ AllocateWindowDescFront<Window>(&_graph_legend_desc, 0);
}
/********************/
@@ -438,7 +438,7 @@
void ShowOperatingProfitGraph()
{
- if (AllocateWindowDescFront(&_operating_profit_desc, 0)) {
+ if (AllocateWindowDescFront<Window>(&_operating_profit_desc, 0)) {
InvalidateWindow(WC_GRAPH_LEGEND, 0);
}
}
@@ -506,7 +506,7 @@
void ShowIncomeGraph()
{
- if (AllocateWindowDescFront(&_income_graph_desc, 0)) {
+ if (AllocateWindowDescFront<Window>(&_income_graph_desc, 0)) {
InvalidateWindow(WC_GRAPH_LEGEND, 0);
}
}
@@ -573,7 +573,7 @@
void ShowDeliveredCargoGraph()
{
- if (AllocateWindowDescFront(&_delivered_cargo_graph_desc, 0)) {
+ if (AllocateWindowDescFront<Window>(&_delivered_cargo_graph_desc, 0)) {
InvalidateWindow(WC_GRAPH_LEGEND, 0);
}
}
@@ -642,7 +642,7 @@
void ShowPerformanceHistoryGraph()
{
- if (AllocateWindowDescFront(&_performance_history_desc, 0)) {
+ if (AllocateWindowDescFront<Window>(&_performance_history_desc, 0)) {
InvalidateWindow(WC_GRAPH_LEGEND, 0);
}
}
@@ -709,7 +709,7 @@
void ShowCompanyValueGraph()
{
- if (AllocateWindowDescFront(&_company_value_graph_desc, 0)) {
+ if (AllocateWindowDescFront<Window>(&_company_value_graph_desc, 0)) {
InvalidateWindow(WC_GRAPH_LEGEND, 0);
}
}
@@ -807,7 +807,7 @@
void ShowCargoPaymentRates()
{
- Window *w = AllocateWindowDescFront(&_cargo_payment_rates_desc, 0);
+ Window *w = AllocateWindowDescFront<Window>(&_cargo_payment_rates_desc, 0);
if (w == NULL) return;
/* Count the number of active cargo types */
@@ -928,7 +928,7 @@
void ShowCompanyLeagueTable()
{
- AllocateWindowDescFront(&_company_league_desc, 0);
+ AllocateWindowDescFront<Window>(&_company_league_desc, 0);
}
/*****************************/
@@ -1163,5 +1163,5 @@
void ShowPerformanceRatingDetail()
{
- AllocateWindowDescFront(&_performance_rating_detail_desc, 0);
+ AllocateWindowDescFront<Window>(&_performance_rating_detail_desc, 0);
}
--- a/src/group_gui.cpp Wed May 07 21:09:51 2008 +0000
+++ b/src/group_gui.cpp Sun May 11 20:09:34 2008 +0000
@@ -28,53 +28,29 @@
#include "table/strings.h"
#include "table/sprites.h"
-struct grouplist_d {
- const Group **sort_list;
- list_d l; // General list struct
-};
-assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(grouplist_d));
-
-struct groupveh_d : vehiclelist_d {
- GroupID group_sel;
- VehicleID vehicle_sel;
-
- grouplist_d gl;
-};
-assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(groupveh_d));
+typedef GUIList<const Group*> GUIGroupList;
-struct Sorting {
- Listing aircraft;
- Listing roadveh;
- Listing ship;
- Listing train;
-};
-
-static Sorting _sorting;
-
-
-static void BuildGroupList(grouplist_d* gl, PlayerID owner, VehicleType vehicle_type)
+static void BuildGroupList(GUIGroupList *gl, PlayerID owner, VehicleType vehicle_type)
{
- const Group** list;
- const Group *g;
uint n = 0;
- if (!(gl->l.flags & VL_REBUILD)) return;
+ if (!(gl->flags & VL_REBUILD)) return;
- list = MallocT<const Group*>(GetGroupArraySize());
+ const Group **list = MallocT<const Group*>(GetGroupArraySize());
+ const Group *g;
FOR_ALL_GROUPS(g) {
if (g->owner == owner && g->vehicle_type == vehicle_type) list[n++] = g;
}
- free((void*)gl->sort_list);
- gl->sort_list = MallocT<const Group *>(n);
- gl->l.list_length = n;
+ gl->sort_list = ReallocT(gl->sort_list, n);
+ gl->list_length = n;
for (uint i = 0; i < n; ++i) gl->sort_list[i] = list[i];
- free((void*)list);
+ free(list);
- gl->l.flags &= ~VL_REBUILD;
- gl->l.flags |= VL_RESORT;
+ gl->flags &= ~VL_REBUILD;
+ gl->flags |= VL_RESORT;
}
@@ -107,14 +83,14 @@
}
-static void SortGroupList(grouplist_d *gl)
+static void SortGroupList(GUIGroupList *gl)
{
- if (!(gl->l.flags & VL_RESORT)) return;
+ if (!(gl->flags & VL_RESORT)) return;
- qsort((void*)gl->sort_list, gl->l.list_length, sizeof(gl->sort_list[0]), GroupNameSorter);
+ qsort((void*)gl->sort_list, gl->list_length, sizeof(gl->sort_list[0]), GroupNameSorter);
- gl->l.resort_timer = DAY_TICKS * PERIODIC_RESORT_DAYS;
- gl->l.flags &= ~VL_RESORT;
+ gl->resort_timer = DAY_TICKS * PERIODIC_RESORT_DAYS;
+ gl->flags &= ~VL_RESORT;
}
@@ -146,6 +122,35 @@
GRP_WIDGET_RESIZE,
};
+enum GroupActionListFunction {
+ GALF_REPLACE,
+ GALF_SERVICE,
+ GALF_DEPOT,
+ GALF_ADD_SHARED,
+ GALF_REMOVE_ALL,
+};
+
+/**
+ * Update/redraw the group action dropdown
+ * @param w the window the dropdown belongs to
+ * @param gid the currently selected group in the window
+ */
+static void ShowGroupActionDropdown(Window *w, GroupID gid)
+{
+ DropDownList *list = new DropDownList();
+
+ list->push_back(new DropDownListStringItem(STR_REPLACE_VEHICLES, GALF_REPLACE, false));
+ list->push_back(new DropDownListStringItem(STR_SEND_FOR_SERVICING, GALF_SERVICE, false));
+ list->push_back(new DropDownListStringItem(STR_SEND_TRAIN_TO_DEPOT, GALF_DEPOT, false));
+
+ if (IsValidGroupID(gid)) {
+ list->push_back(new DropDownListStringItem(STR_GROUP_ADD_SHARED_VEHICLE, GALF_ADD_SHARED, false));
+ list->push_back(new DropDownListStringItem(STR_GROUP_REMOVE_ALL_VEHICLES, GALF_REMOVE_ALL, false));
+ }
+
+ ShowDropDownList(w, list, 0, GRP_WIDGET_MANAGE_VEHICLES_DROPDOWN);
+}
+
static const Widget _group_widgets[] = {
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
@@ -177,614 +182,575 @@
};
-static void CreateVehicleGroupWindow(Window *w)
-{
- const PlayerID owner = (PlayerID)GB(w->window_number, 0, 8);
- groupveh_d *gv = &WP(w, groupveh_d);
- grouplist_d *gl = &WP(w, groupveh_d).gl;
-
- w->caption_color = owner;
- w->hscroll.cap = 224;
- w->resize.step_width = 1;
-
- switch (gv->vehicle_type) {
- default: NOT_REACHED();
- case VEH_TRAIN:
- case VEH_ROAD:
- w->vscroll.cap = 9;
- w->vscroll2.cap = 6;
- w->resize.step_height = PLY_WND_PRC__SIZE_OF_ROW_SMALL;
- break;
- case VEH_SHIP:
- case VEH_AIRCRAFT:
- w->vscroll.cap = 9;
- w->vscroll2.cap = 4;
- w->resize.step_height = PLY_WND_PRC__SIZE_OF_ROW_BIG2;
- break;
- }
-
- w->widget[GRP_WIDGET_LIST_GROUP].data = (w->vscroll.cap << 8) + 1;
- w->widget[GRP_WIDGET_LIST_VEHICLE].data = (w->vscroll2.cap << 8) + 1;
-
- switch (gv->vehicle_type) {
- default: NOT_REACHED();
- case VEH_TRAIN: gv->_sorting = &_sorting.train; break;
- case VEH_ROAD: gv->_sorting = &_sorting.roadveh; break;
- case VEH_SHIP: gv->_sorting = &_sorting.ship; break;
- case VEH_AIRCRAFT: gv->_sorting = &_sorting.aircraft; break;
- }
-
- gv->sort_list = NULL;
- gv->vehicle_type = (VehicleType)GB(w->window_number, 11, 5);
- gv->l.sort_type = gv->_sorting->criteria;
- gv->l.flags = VL_REBUILD | (gv->_sorting->order ? VL_DESC : VL_NONE);
- gv->l.resort_timer = DAY_TICKS * PERIODIC_RESORT_DAYS; // Set up resort timer
-
- gl->sort_list = NULL;
- gl->l.flags = VL_REBUILD | VL_NONE;
- gl->l.resort_timer = DAY_TICKS * PERIODIC_RESORT_DAYS; // Set up resort timer
-
- gv->group_sel = ALL_GROUP;
- gv->vehicle_sel = INVALID_VEHICLE;
-
- switch (gv->vehicle_type) {
- case VEH_TRAIN:
- w->widget[GRP_WIDGET_LIST_VEHICLE].tooltips = STR_883D_TRAINS_CLICK_ON_TRAIN_FOR;
- w->widget[GRP_WIDGET_AVAILABLE_VEHICLES].data = STR_AVAILABLE_TRAINS;
+struct VehicleGroupWindow : public Window, public VehicleListBase {
+ GroupID group_sel;
+ VehicleID vehicle_sel;
+ GUIGroupList groups;
- w->widget[GRP_WIDGET_CREATE_GROUP].data = SPR_GROUP_CREATE_TRAIN;
- w->widget[GRP_WIDGET_RENAME_GROUP].data = SPR_GROUP_RENAME_TRAIN;
- w->widget[GRP_WIDGET_DELETE_GROUP].data = SPR_GROUP_DELETE_TRAIN;
- break;
-
- case VEH_ROAD:
- w->widget[GRP_WIDGET_LIST_VEHICLE].tooltips = STR_901A_ROAD_VEHICLES_CLICK_ON;
- w->widget[GRP_WIDGET_AVAILABLE_VEHICLES].data = STR_AVAILABLE_ROAD_VEHICLES;
-
- w->widget[GRP_WIDGET_CREATE_GROUP].data = SPR_GROUP_CREATE_ROADVEH;
- w->widget[GRP_WIDGET_RENAME_GROUP].data = SPR_GROUP_RENAME_ROADVEH;
- w->widget[GRP_WIDGET_DELETE_GROUP].data = SPR_GROUP_DELETE_ROADVEH;
- break;
-
- case VEH_SHIP:
- w->widget[GRP_WIDGET_LIST_VEHICLE].tooltips = STR_9823_SHIPS_CLICK_ON_SHIP_FOR;
- w->widget[GRP_WIDGET_AVAILABLE_VEHICLES].data = STR_AVAILABLE_SHIPS;
-
- w->widget[GRP_WIDGET_CREATE_GROUP].data = SPR_GROUP_CREATE_SHIP;
- w->widget[GRP_WIDGET_RENAME_GROUP].data = SPR_GROUP_RENAME_SHIP;
- w->widget[GRP_WIDGET_DELETE_GROUP].data = SPR_GROUP_DELETE_SHIP;
- break;
-
- case VEH_AIRCRAFT:
- w->widget[GRP_WIDGET_LIST_VEHICLE].tooltips = STR_A01F_AIRCRAFT_CLICK_ON_AIRCRAFT;
- w->widget[GRP_WIDGET_AVAILABLE_VEHICLES].data = STR_AVAILABLE_AIRCRAFT;
+ VehicleGroupWindow(const WindowDesc *desc, WindowNumber window_number) : Window(desc, NULL, window_number)
+ {
+ const PlayerID owner = (PlayerID)GB(this->window_number, 0, 8);
- w->widget[GRP_WIDGET_CREATE_GROUP].data = SPR_GROUP_CREATE_AIRCRAFT;
- w->widget[GRP_WIDGET_RENAME_GROUP].data = SPR_GROUP_RENAME_AIRCRAFT;
- w->widget[GRP_WIDGET_DELETE_GROUP].data = SPR_GROUP_DELETE_AIRCRAFT;
- break;
-
- default: NOT_REACHED();
- }
-}
+ this->caption_color = owner;
+ this->hscroll.cap = 224;
+ this->resize.step_width = 1;
-enum GroupActionListFunction {
- GALF_REPLACE,
- GALF_SERVICE,
- GALF_DEPOT,
- GALF_ADD_SHARED,
- GALF_REMOVE_ALL,
-};
+ switch (this->vehicle_type) {
+ default: NOT_REACHED();
+ case VEH_TRAIN:
+ case VEH_ROAD:
+ this->vscroll.cap = 9;
+ this->vscroll2.cap = 6;
+ this->resize.step_height = PLY_WND_PRC__SIZE_OF_ROW_SMALL;
+ break;
+ case VEH_SHIP:
+ case VEH_AIRCRAFT:
+ this->vscroll.cap = 9;
+ this->vscroll2.cap = 4;
+ this->resize.step_height = PLY_WND_PRC__SIZE_OF_ROW_BIG2;
+ break;
+ }
-/**
- * Update/redraw the group action dropdown
- * @param w the window the dropdown belongs to
- * @param gid the currently selected group in the window
- */
-static void ShowGroupActionDropdown(Window *w, GroupID gid)
-{
- DropDownList *list = new DropDownList();
+ this->widget[GRP_WIDGET_LIST_GROUP].data = (this->vscroll.cap << 8) + 1;
+ this->widget[GRP_WIDGET_LIST_VEHICLE].data = (this->vscroll2.cap << 8) + 1;
- list->push_back(new DropDownListStringItem(STR_REPLACE_VEHICLES, GALF_REPLACE, false));
- list->push_back(new DropDownListStringItem(STR_SEND_FOR_SERVICING, GALF_SERVICE, false));
- list->push_back(new DropDownListStringItem(STR_SEND_TRAIN_TO_DEPOT, GALF_DEPOT, false));
+ switch (this->vehicle_type) {
+ default: NOT_REACHED();
+ case VEH_TRAIN: this->sorting = &_sorting.train; break;
+ case VEH_ROAD: this->sorting = &_sorting.roadveh; break;
+ case VEH_SHIP: this->sorting = &_sorting.ship; break;
+ case VEH_AIRCRAFT: this->sorting = &_sorting.aircraft; break;
+ }
- if (IsValidGroupID(gid)) {
- list->push_back(new DropDownListStringItem(STR_GROUP_ADD_SHARED_VEHICLE, GALF_ADD_SHARED, false));
- list->push_back(new DropDownListStringItem(STR_GROUP_REMOVE_ALL_VEHICLES, GALF_REMOVE_ALL, false));
+ this->vehicle_type = (VehicleType)GB(this->window_number, 11, 5);
+
+ this->vehicles.sort_list = NULL;
+ this->vehicles.sort_type = this->sorting->criteria;
+ this->vehicles.flags = VL_REBUILD | (this->sorting->order ? VL_DESC : VL_NONE);
+ this->vehicles.resort_timer = DAY_TICKS * PERIODIC_RESORT_DAYS; // Set up resort timer
+
+ this->groups.sort_list = NULL;
+ this->groups.flags = VL_REBUILD | VL_NONE;
+ this->groups.resort_timer = DAY_TICKS * PERIODIC_RESORT_DAYS; // Set up resort timer
+
+ this->group_sel = ALL_GROUP;
+ this->vehicle_sel = INVALID_VEHICLE;
+
+ switch (this->vehicle_type) {
+ case VEH_TRAIN:
+ this->widget[GRP_WIDGET_LIST_VEHICLE].tooltips = STR_883D_TRAINS_CLICK_ON_TRAIN_FOR;
+ this->widget[GRP_WIDGET_AVAILABLE_VEHICLES].data = STR_AVAILABLE_TRAINS;
+
+ this->widget[GRP_WIDGET_CREATE_GROUP].data = SPR_GROUP_CREATE_TRAIN;
+ this->widget[GRP_WIDGET_RENAME_GROUP].data = SPR_GROUP_RENAME_TRAIN;
+ this->widget[GRP_WIDGET_DELETE_GROUP].data = SPR_GROUP_DELETE_TRAIN;
+ break;
+
+ case VEH_ROAD:
+ this->widget[GRP_WIDGET_LIST_VEHICLE].tooltips = STR_901A_ROAD_VEHICLES_CLICK_ON;
+ this->widget[GRP_WIDGET_AVAILABLE_VEHICLES].data = STR_AVAILABLE_ROAD_VEHICLES;
+
+ this->widget[GRP_WIDGET_CREATE_GROUP].data = SPR_GROUP_CREATE_ROADVEH;
+ this->widget[GRP_WIDGET_RENAME_GROUP].data = SPR_GROUP_RENAME_ROADVEH;
+ this->widget[GRP_WIDGET_DELETE_GROUP].data = SPR_GROUP_DELETE_ROADVEH;
+ break;
+
+ case VEH_SHIP:
+ this->widget[GRP_WIDGET_LIST_VEHICLE].tooltips = STR_9823_SHIPS_CLICK_ON_SHIP_FOR;
+ this->widget[GRP_WIDGET_AVAILABLE_VEHICLES].data = STR_AVAILABLE_SHIPS;
+
+ this->widget[GRP_WIDGET_CREATE_GROUP].data = SPR_GROUP_CREATE_SHIP;
+ this->widget[GRP_WIDGET_RENAME_GROUP].data = SPR_GROUP_RENAME_SHIP;
+ this->widget[GRP_WIDGET_DELETE_GROUP].data = SPR_GROUP_DELETE_SHIP;
+ break;
+
+ case VEH_AIRCRAFT:
+ this->widget[GRP_WIDGET_LIST_VEHICLE].tooltips = STR_A01F_AIRCRAFT_CLICK_ON_AIRCRAFT;
+ this->widget[GRP_WIDGET_AVAILABLE_VEHICLES].data = STR_AVAILABLE_AIRCRAFT;
+
+ this->widget[GRP_WIDGET_CREATE_GROUP].data = SPR_GROUP_CREATE_AIRCRAFT;
+ this->widget[GRP_WIDGET_RENAME_GROUP].data = SPR_GROUP_RENAME_AIRCRAFT;
+ this->widget[GRP_WIDGET_DELETE_GROUP].data = SPR_GROUP_DELETE_AIRCRAFT;
+ break;
+
+ default: NOT_REACHED();
+ }
+
+ this->FindWindowPlacementAndResize(desc);
}
- ShowDropDownList(w, list, 0, GRP_WIDGET_MANAGE_VEHICLES_DROPDOWN);
-}
-
-/**
- * bitmask for w->window_number
- * 0-7 PlayerID (owner)
- * 11-15 vehicle type
- **/
-static void GroupWndProc(Window *w, WindowEvent *e)
-{
- const PlayerID owner = (PlayerID)GB(w->window_number, 0, 8);
- groupveh_d *gv = &WP(w, groupveh_d);
- grouplist_d *gl = &WP(w, groupveh_d).gl;
-
- gv->vehicle_type = (VehicleType)GB(w->window_number, 11, 5);
+ ~VehicleGroupWindow()
+ {
+ free((void*)this->vehicles.sort_list);
+ free((void*)this->groups.sort_list);
+ }
- switch(e->event) {
- case WE_INVALIDATE_DATA:
- gv->l.flags |= VL_REBUILD;
- gl->l.flags |= VL_REBUILD;
- if (!(IsAllGroupID(gv->group_sel) || IsDefaultGroupID(gv->group_sel) || IsValidGroupID(gv->group_sel))) {
- gv->group_sel = ALL_GROUP;
- HideDropDownMenu(w);
- }
- w->SetDirty();
- break;
+ virtual void OnInvalidateData(int data)
+ {
+ this->vehicles.flags |= VL_REBUILD;
+ this->groups.flags |= VL_REBUILD;
+ if (!(IsAllGroupID(this->group_sel) || IsDefaultGroupID(this->group_sel) || IsValidGroupID(this->group_sel))) {
+ this->group_sel = ALL_GROUP;
+ HideDropDownMenu(this);
+ }
+ this->SetDirty();
+ }
- case WE_CREATE:
- CreateVehicleGroupWindow(w);
- break;
+ virtual void OnPaint()
+ {
+ const PlayerID owner = (PlayerID)GB(this->window_number, 0, 8);
+ int x = 203;
+ int y2 = PLY_WND_PRC__OFFSET_TOP_WIDGET;
+ int y1 = PLY_WND_PRC__OFFSET_TOP_WIDGET + 2;
+ int max;
+ int i;
- case WE_PAINT: {
- int x = 203;
- int y2 = PLY_WND_PRC__OFFSET_TOP_WIDGET;
- int y1 = PLY_WND_PRC__OFFSET_TOP_WIDGET + 2;
- int max;
- int i;
-
- /* If we select the all vehicles, gv->list will contain all vehicles of the player
- * else gv->list will contain all vehicles which belong to the selected group */
- BuildVehicleList(gv, owner, gv->group_sel, IsAllGroupID(gv->group_sel) ? VLW_STANDARD : VLW_GROUP_LIST);
- SortVehicleList(gv);
+ /* If we select the all vehicles, this->list will contain all vehicles of the player
+ * else this->list will contain all vehicles which belong to the selected group */
+ BuildVehicleList(this, owner, this->group_sel, IsAllGroupID(this->group_sel) ? VLW_STANDARD : VLW_GROUP_LIST);
+ SortVehicleList(this);
- BuildGroupList(gl, owner, gv->vehicle_type);
- SortGroupList(gl);
-
- SetVScrollCount(w, gl->l.list_length);
- SetVScroll2Count(w, gv->l.list_length);
-
- /* The drop down menu is out, *but* it may not be used, retract it. */
- if (gv->l.list_length == 0 && w->IsWidgetLowered(GRP_WIDGET_MANAGE_VEHICLES_DROPDOWN)) {
- w->RaiseWidget(GRP_WIDGET_MANAGE_VEHICLES_DROPDOWN);
- HideDropDownMenu(w);
- }
+ BuildGroupList(&this->groups, owner, this->vehicle_type);
+ SortGroupList(&this->groups);
- /* Disable all lists management button when the list is empty */
- w->SetWidgetsDisabledState(gv->l.list_length == 0 || _local_player != owner,
- GRP_WIDGET_STOP_ALL,
- GRP_WIDGET_START_ALL,
- GRP_WIDGET_MANAGE_VEHICLES_DROPDOWN,
- WIDGET_LIST_END);
+ SetVScrollCount(this, this->groups.list_length);
+ SetVScroll2Count(this, this->vehicles.list_length);
- /* Disable the group specific function when we select the default group or all vehicles */
- w->SetWidgetsDisabledState(IsDefaultGroupID(gv->group_sel) || IsAllGroupID(gv->group_sel) || _local_player != owner,
- GRP_WIDGET_DELETE_GROUP,
- GRP_WIDGET_RENAME_GROUP,
- GRP_WIDGET_REPLACE_PROTECTION,
- WIDGET_LIST_END);
+ /* The drop down menu is out, *but* it may not be used, retract it. */
+ if (this->vehicles.list_length == 0 && this->IsWidgetLowered(GRP_WIDGET_MANAGE_VEHICLES_DROPDOWN)) {
+ this->RaiseWidget(GRP_WIDGET_MANAGE_VEHICLES_DROPDOWN);
+ HideDropDownMenu(this);
+ }
- /* Disable remaining buttons for non-local player
- * Needed while changing _local_player, eg. by cheats
- * All procedures (eg. move vehicle to another group)
- * verify, whether you are the owner of the vehicle,
- * so it doesn't have to be disabled
- */
- w->SetWidgetsDisabledState(_local_player != owner,
- GRP_WIDGET_CREATE_GROUP,
- GRP_WIDGET_AVAILABLE_VEHICLES,
- WIDGET_LIST_END);
+ /* Disable all lists management button when the list is empty */
+ this->SetWidgetsDisabledState(this->vehicles.list_length == 0 || _local_player != owner,
+ GRP_WIDGET_STOP_ALL,
+ GRP_WIDGET_START_ALL,
+ GRP_WIDGET_MANAGE_VEHICLES_DROPDOWN,
+ WIDGET_LIST_END);
+
+ /* Disable the group specific function when we select the default group or all vehicles */
+ this->SetWidgetsDisabledState(IsDefaultGroupID(this->group_sel) || IsAllGroupID(this->group_sel) || _local_player != owner,
+ GRP_WIDGET_DELETE_GROUP,
+ GRP_WIDGET_RENAME_GROUP,
+ GRP_WIDGET_REPLACE_PROTECTION,
+ WIDGET_LIST_END);
+
+ /* Disable remaining buttons for non-local player
+ * Needed while changing _local_player, eg. by cheats
+ * All procedures (eg. move vehicle to another group)
+ * verify, whether you are the owner of the vehicle,
+ * so it doesn't have to be disabled
+ */
+ this->SetWidgetsDisabledState(_local_player != owner,
+ GRP_WIDGET_CREATE_GROUP,
+ GRP_WIDGET_AVAILABLE_VEHICLES,
+ WIDGET_LIST_END);
- /* If selected_group == DEFAULT_GROUP || ALL_GROUP, draw the standard caption
- We list all vehicles or ungrouped vehicles */
- if (IsDefaultGroupID(gv->group_sel) || IsAllGroupID(gv->group_sel)) {
- SetDParam(0, owner);
- SetDParam(1, gv->l.list_length);
-
- switch (gv->vehicle_type) {
- case VEH_TRAIN:
- w->widget[GRP_WIDGET_CAPTION].data = STR_881B_TRAINS;
- w->widget[GRP_WIDGET_REPLACE_PROTECTION].data = SPR_GROUP_REPLACE_OFF_TRAIN;
- break;
- case VEH_ROAD:
- w->widget[GRP_WIDGET_CAPTION].data = STR_9001_ROAD_VEHICLES;
- w->widget[GRP_WIDGET_REPLACE_PROTECTION].data = SPR_GROUP_REPLACE_OFF_ROADVEH;
- break;
- case VEH_SHIP:
- w->widget[GRP_WIDGET_CAPTION].data = STR_9805_SHIPS;
- w->widget[GRP_WIDGET_REPLACE_PROTECTION].data = SPR_GROUP_REPLACE_OFF_SHIP;
- break;
- case VEH_AIRCRAFT:
- w->widget[GRP_WIDGET_CAPTION].data = STR_A009_AIRCRAFT;
- w->widget[GRP_WIDGET_REPLACE_PROTECTION].data = SPR_GROUP_REPLACE_OFF_AIRCRAFT;
- break;
- default: NOT_REACHED();
- }
- } else {
- const Group *g = GetGroup(gv->group_sel);
-
- SetDParam(0, g->index);
- SetDParam(1, g->num_vehicle);
+ /* If selected_group == DEFAULT_GROUP || ALL_GROUP, draw the standard caption
+ We list all vehicles or ungrouped vehicles */
+ if (IsDefaultGroupID(this->group_sel) || IsAllGroupID(this->group_sel)) {
+ SetDParam(0, owner);
+ SetDParam(1, this->vehicles.list_length);
- switch (gv->vehicle_type) {
- case VEH_TRAIN:
- w->widget[GRP_WIDGET_CAPTION].data = STR_GROUP_TRAINS_CAPTION;
- w->widget[GRP_WIDGET_REPLACE_PROTECTION].data = (g->replace_protection) ? SPR_GROUP_REPLACE_ON_TRAIN : SPR_GROUP_REPLACE_OFF_TRAIN;
- break;
- case VEH_ROAD:
- w->widget[GRP_WIDGET_CAPTION].data = STR_GROUP_ROADVEH_CAPTION;
- w->widget[GRP_WIDGET_REPLACE_PROTECTION].data = (g->replace_protection) ? SPR_GROUP_REPLACE_ON_ROADVEH : SPR_GROUP_REPLACE_OFF_ROADVEH;
- break;
- case VEH_SHIP:
- w->widget[GRP_WIDGET_CAPTION].data = STR_GROUP_SHIPS_CAPTION;
- w->widget[GRP_WIDGET_REPLACE_PROTECTION].data = (g->replace_protection) ? SPR_GROUP_REPLACE_ON_SHIP : SPR_GROUP_REPLACE_OFF_SHIP;
- break;
- case VEH_AIRCRAFT:
- w->widget[GRP_WIDGET_CAPTION].data = STR_GROUP_AIRCRAFTS_CAPTION;
- w->widget[GRP_WIDGET_REPLACE_PROTECTION].data = (g->replace_protection) ? SPR_GROUP_REPLACE_ON_AIRCRAFT : SPR_GROUP_REPLACE_OFF_AIRCRAFT;
- break;
- default: NOT_REACHED();
- }
- }
-
- /* Set text of sort by dropdown */
- w->widget[GRP_WIDGET_SORT_BY_DROPDOWN].data = _vehicle_sort_listing[gv->l.sort_type];
-
- DrawWindowWidgets(w);
-
- /* Draw Matrix Group
- * The selected group is drawn in white */
- StringID str_all_veh, str_no_group_veh;
-
- switch (gv->vehicle_type) {
+ switch (this->vehicle_type) {
case VEH_TRAIN:
- str_all_veh = STR_GROUP_ALL_TRAINS;
- str_no_group_veh = STR_GROUP_DEFAULT_TRAINS;
+ this->widget[GRP_WIDGET_CAPTION].data = STR_881B_TRAINS;
+ this->widget[GRP_WIDGET_REPLACE_PROTECTION].data = SPR_GROUP_REPLACE_OFF_TRAIN;
break;
case VEH_ROAD:
- str_all_veh = STR_GROUP_ALL_ROADS;
- str_no_group_veh = STR_GROUP_DEFAULT_ROADS;
+ this->widget[GRP_WIDGET_CAPTION].data = STR_9001_ROAD_VEHICLES;
+ this->widget[GRP_WIDGET_REPLACE_PROTECTION].data = SPR_GROUP_REPLACE_OFF_ROADVEH;
break;
case VEH_SHIP:
- str_all_veh = STR_GROUP_ALL_SHIPS;
- str_no_group_veh = STR_GROUP_DEFAULT_SHIPS;
+ this->widget[GRP_WIDGET_CAPTION].data = STR_9805_SHIPS;
+ this->widget[GRP_WIDGET_REPLACE_PROTECTION].data = SPR_GROUP_REPLACE_OFF_SHIP;
break;
case VEH_AIRCRAFT:
- str_all_veh = STR_GROUP_ALL_AIRCRAFTS;
- str_no_group_veh = STR_GROUP_DEFAULT_AIRCRAFTS;
+ this->widget[GRP_WIDGET_CAPTION].data = STR_A009_AIRCRAFT;
+ this->widget[GRP_WIDGET_REPLACE_PROTECTION].data = SPR_GROUP_REPLACE_OFF_AIRCRAFT;
break;
default: NOT_REACHED();
}
- DrawString(10, y1, str_all_veh, IsAllGroupID(gv->group_sel) ? TC_WHITE : TC_BLACK);
-
- y1 += 13;
-
- DrawString(10, y1, str_no_group_veh, IsDefaultGroupID(gv->group_sel) ? TC_WHITE : TC_BLACK);
-
- max = min(w->vscroll.pos + w->vscroll.cap, gl->l.list_length);
- for (i = w->vscroll.pos ; i < max ; ++i) {
- const Group *g = gl->sort_list[i];
-
- assert(g->owner == owner);
-
- y1 += PLY_WND_PRC__SIZE_OF_ROW_TINY;
-
- /* draw the selected group in white, else we draw it in black */
- SetDParam(0, g->index);
- DrawString(10, y1, STR_GROUP_NAME, (gv->group_sel == g->index) ? TC_WHITE : TC_BLACK);
-
- /* draw the number of vehicles of the group */
- SetDParam(0, g->num_vehicle);
- DrawStringRightAligned(187, y1 + 1, STR_GROUP_TINY_NUM, (gv->group_sel == g->index) ? TC_WHITE : TC_BLACK);
- }
-
- DrawSortButtonState(w, GRP_WIDGET_SORT_BY_ORDER, gv->l.flags & VL_DESC ? SBS_DOWN : SBS_UP);
+ } else {
+ const Group *g = GetGroup(this->group_sel);
- /* Draw Matrix Vehicle according to the vehicle list built before */
- max = min(w->vscroll2.pos + w->vscroll2.cap, gv->l.list_length);
- for (i = w->vscroll2.pos ; i < max ; ++i) {
- const Vehicle* v = gv->sort_list[i];
-
- assert(v->type == gv->vehicle_type && v->owner == owner);
-
- DrawVehicleImage(v, x + 19, y2 + 6, gv->vehicle_sel, w->hscroll.cap, 0);
- DrawVehicleProfitButton(v, x, y2 + 13);
-
- SetDParam(0, v->unitnumber);
- DrawString(x, y2 + 2, v->IsInDepot() ? STR_021F : (v->age > v->max_age - 366 ? STR_00E3 : STR_00E2), TC_FROMSTRING);
+ SetDParam(0, g->index);
+ SetDParam(1, g->num_vehicle);
- if (w->resize.step_height == PLY_WND_PRC__SIZE_OF_ROW_BIG2) DrawSmallOrderList(v, x + 138, y2);
-
- SetDParam(0, v->GetDisplayProfitThisYear());
- SetDParam(1, v->GetDisplayProfitLastYear());
- DrawString(x + 19, y2 + w->resize.step_height - 8, STR_0198_PROFIT_THIS_YEAR_LAST_YEAR, TC_FROMSTRING);
-
- if (IsValidGroupID(v->group_id)) {
- SetDParam(0, v->group_id);
- DrawString(x + 19, y2, STR_GROUP_TINY_NAME, TC_BLACK);
- }
-
- y2 += w->resize.step_height;
+ switch (this->vehicle_type) {
+ case VEH_TRAIN:
+ this->widget[GRP_WIDGET_CAPTION].data = STR_GROUP_TRAINS_CAPTION;
+ this->widget[GRP_WIDGET_REPLACE_PROTECTION].data = (g->replace_protection) ? SPR_GROUP_REPLACE_ON_TRAIN : SPR_GROUP_REPLACE_OFF_TRAIN;
+ break;
+ case VEH_ROAD:
+ this->widget[GRP_WIDGET_CAPTION].data = STR_GROUP_ROADVEH_CAPTION;
+ this->widget[GRP_WIDGET_REPLACE_PROTECTION].data = (g->replace_protection) ? SPR_GROUP_REPLACE_ON_ROADVEH : SPR_GROUP_REPLACE_OFF_ROADVEH;
+ break;
+ case VEH_SHIP:
+ this->widget[GRP_WIDGET_CAPTION].data = STR_GROUP_SHIPS_CAPTION;
+ this->widget[GRP_WIDGET_REPLACE_PROTECTION].data = (g->replace_protection) ? SPR_GROUP_REPLACE_ON_SHIP : SPR_GROUP_REPLACE_OFF_SHIP;
+ break;
+ case VEH_AIRCRAFT:
+ this->widget[GRP_WIDGET_CAPTION].data = STR_GROUP_AIRCRAFTS_CAPTION;
+ this->widget[GRP_WIDGET_REPLACE_PROTECTION].data = (g->replace_protection) ? SPR_GROUP_REPLACE_ON_AIRCRAFT : SPR_GROUP_REPLACE_OFF_AIRCRAFT;
+ break;
+ default: NOT_REACHED();
}
-
- break;
}
- case WE_CLICK:
- if (e->we.click.widget != GRP_WIDGET_SORT_BY_DROPDOWN && e->we.click.widget != GRP_WIDGET_MANAGE_VEHICLES_DROPDOWN) HideDropDownMenu(w);
-
- switch(e->we.click.widget) {
- case GRP_WIDGET_SORT_BY_ORDER: // Flip sorting method ascending/descending
- gv->l.flags ^= VL_DESC;
- gv->l.flags |= VL_RESORT;
-
- gv->_sorting->order = !!(gv->l.flags & VL_DESC);
- w->SetDirty();
- break;
-
- case GRP_WIDGET_SORT_BY_DROPDOWN: // Select sorting criteria dropdown menu
- ShowDropDownMenu(w, _vehicle_sort_listing, gv->l.sort_type, GRP_WIDGET_SORT_BY_DROPDOWN, 0, (gv->vehicle_type == VEH_TRAIN || gv->vehicle_type == VEH_ROAD) ? 0 : (1 << 10));
- return;
+ /* Set text of sort by dropdown */
+ this->widget[GRP_WIDGET_SORT_BY_DROPDOWN].data = _vehicle_sort_listing[this->vehicles.sort_type];
- case GRP_WIDGET_ALL_VEHICLES: // All vehicles button
- if (!IsAllGroupID(gv->group_sel)) {
- gv->group_sel = ALL_GROUP;
- gv->l.flags |= VL_REBUILD;
- w->SetDirty();
- }
- break;
+ DrawWindowWidgets(this);
- case GRP_WIDGET_DEFAULT_VEHICLES: // Ungrouped vehicles button
- if (!IsDefaultGroupID(gv->group_sel)) {
- gv->group_sel = DEFAULT_GROUP;
- gv->l.flags |= VL_REBUILD;
- w->SetDirty();
- }
- break;
-
- case GRP_WIDGET_LIST_GROUP: { // Matrix Group
- uint16 id_g = (e->we.click.pt.y - PLY_WND_PRC__OFFSET_TOP_WIDGET - 26) / PLY_WND_PRC__SIZE_OF_ROW_TINY;
+ /* Draw Matrix Group
+ * The selected group is drawn in white */
+ StringID str_all_veh, str_no_group_veh;
- if (id_g >= w->vscroll.cap) return;
-
- id_g += w->vscroll.pos;
+ switch (this->vehicle_type) {
+ case VEH_TRAIN:
+ str_all_veh = STR_GROUP_ALL_TRAINS;
+ str_no_group_veh = STR_GROUP_DEFAULT_TRAINS;
+ break;
+ case VEH_ROAD:
+ str_all_veh = STR_GROUP_ALL_ROADS;
+ str_no_group_veh = STR_GROUP_DEFAULT_ROADS;
+ break;
+ case VEH_SHIP:
+ str_all_veh = STR_GROUP_ALL_SHIPS;
+ str_no_group_veh = STR_GROUP_DEFAULT_SHIPS;
+ break;
+ case VEH_AIRCRAFT:
+ str_all_veh = STR_GROUP_ALL_AIRCRAFTS;
+ str_no_group_veh = STR_GROUP_DEFAULT_AIRCRAFTS;
+ break;
+ default: NOT_REACHED();
+ }
+ DrawString(10, y1, str_all_veh, IsAllGroupID(this->group_sel) ? TC_WHITE : TC_BLACK);
- if (id_g >= gl->l.list_length) return;
+ y1 += 13;
- gv->group_sel = gl->sort_list[id_g]->index;;
+ DrawString(10, y1, str_no_group_veh, IsDefaultGroupID(this->group_sel) ? TC_WHITE : TC_BLACK);
- gv->l.flags |= VL_REBUILD;
- w->SetDirty();
- break;
+ max = min(this->vscroll.pos + this->vscroll.cap, this->groups.list_length);
+ for (i = this->vscroll.pos ; i < max ; ++i) {
+ const Group *g = this->groups.sort_list[i];
+
+ assert(g->owner == owner);
+
+ y1 += PLY_WND_PRC__SIZE_OF_ROW_TINY;
+
+ /* draw the selected group in white, else we draw it in black */
+ SetDParam(0, g->index);
+ DrawString(10, y1, STR_GROUP_NAME, (this->group_sel == g->index) ? TC_WHITE : TC_BLACK);
+
+ /* draw the number of vehicles of the group */
+ SetDParam(0, g->num_vehicle);
+ DrawStringRightAligned(187, y1 + 1, STR_GROUP_TINY_NUM, (this->group_sel == g->index) ? TC_WHITE : TC_BLACK);
+ }
+
+ DrawSortButtonState(this, GRP_WIDGET_SORT_BY_ORDER, this->vehicles.flags & VL_DESC ? SBS_DOWN : SBS_UP);
+
+ /* Draw Matrix Vehicle according to the vehicle list built before */
+ max = min(this->vscroll2.pos + this->vscroll2.cap, this->vehicles.list_length);
+ for (i = this->vscroll2.pos ; i < max ; ++i) {
+ const Vehicle* v = this->vehicles.sort_list[i];
+
+ assert(v->type == this->vehicle_type && v->owner == owner);
+
+ DrawVehicleImage(v, x + 19, y2 + 6, this->vehicle_sel, this->hscroll.cap, 0);
+ DrawVehicleProfitButton(v, x, y2 + 13);
+
+ SetDParam(0, v->unitnumber);
+ DrawString(x, y2 + 2, v->IsInDepot() ? STR_021F : (v->age > v->max_age - 366 ? STR_00E3 : STR_00E2), TC_FROMSTRING);
+
+ if (this->resize.step_height == PLY_WND_PRC__SIZE_OF_ROW_BIG2) DrawSmallOrderList(v, x + 138, y2);
+
+ SetDParam(0, v->GetDisplayProfitThisYear());
+ SetDParam(1, v->GetDisplayProfitLastYear());
+ DrawString(x + 19, y2 + this->resize.step_height - 8, STR_0198_PROFIT_THIS_YEAR_LAST_YEAR, TC_FROMSTRING);
+
+ if (IsValidGroupID(v->group_id)) {
+ SetDParam(0, v->group_id);
+ DrawString(x + 19, y2, STR_GROUP_TINY_NAME, TC_BLACK);
+ }
+
+ y2 += this->resize.step_height;
+ }
+ }
+
+ virtual void OnClick(Point pt, int widget)
+ {
+ if (widget != GRP_WIDGET_SORT_BY_DROPDOWN && widget != GRP_WIDGET_MANAGE_VEHICLES_DROPDOWN) HideDropDownMenu(this);
+
+ switch(widget) {
+ case GRP_WIDGET_SORT_BY_ORDER: // Flip sorting method ascending/descending
+ this->vehicles.flags ^= VL_DESC;
+ this->vehicles.flags |= VL_RESORT;
+
+ this->sorting->order = !!(this->vehicles.flags & VL_DESC);
+ this->SetDirty();
+ break;
+
+ case GRP_WIDGET_SORT_BY_DROPDOWN: // Select sorting criteria dropdown menu
+ ShowDropDownMenu(this, _vehicle_sort_listing, this->vehicles.sort_type, GRP_WIDGET_SORT_BY_DROPDOWN, 0, (this->vehicle_type == VEH_TRAIN || this->vehicle_type == VEH_ROAD) ? 0 : (1 << 10));
+ return;
+
+ case GRP_WIDGET_ALL_VEHICLES: // All vehicles button
+ if (!IsAllGroupID(this->group_sel)) {
+ this->group_sel = ALL_GROUP;
+ this->vehicles.flags |= VL_REBUILD;
+ this->SetDirty();
+ }
+ break;
+
+ case GRP_WIDGET_DEFAULT_VEHICLES: // Ungrouped vehicles button
+ if (!IsDefaultGroupID(this->group_sel)) {
+ this->group_sel = DEFAULT_GROUP;
+ this->vehicles.flags |= VL_REBUILD;
+ this->SetDirty();
+ }
+ break;
+
+ case GRP_WIDGET_LIST_GROUP: { // Matrix Group
+ uint16 id_g = (pt.y - PLY_WND_PRC__OFFSET_TOP_WIDGET - 26) / PLY_WND_PRC__SIZE_OF_ROW_TINY;
+
+ if (id_g >= this->vscroll.cap) return;
+
+ id_g += this->vscroll.pos;
+
+ if (id_g >= this->groups.list_length) return;
+
+ this->group_sel = this->groups.sort_list[id_g]->index;;
+
+ this->vehicles.flags |= VL_REBUILD;
+ this->SetDirty();
+ break;
+ }
+
+ case GRP_WIDGET_LIST_VEHICLE: { // Matrix Vehicle
+ uint32 id_v = (pt.y - PLY_WND_PRC__OFFSET_TOP_WIDGET) / (int)this->resize.step_height;
+ const Vehicle *v;
+
+ if (id_v >= this->vscroll2.cap) return; // click out of bounds
+
+ id_v += this->vscroll2.pos;
+
+ if (id_v >= this->vehicles.list_length) return; // click out of list bound
+
+ v = this->vehicles.sort_list[id_v];
+
+ this->vehicle_sel = v->index;
+
+ if (v->IsValid()) {
+ SetObjectToPlaceWnd(v->GetImage(DIR_W), GetVehiclePalette(v), VHM_DRAG, this);
+ _cursor.vehchain = true;
}
- case GRP_WIDGET_LIST_VEHICLE: { // Matrix Vehicle
- uint32 id_v = (e->we.click.pt.y - PLY_WND_PRC__OFFSET_TOP_WIDGET) / (int)w->resize.step_height;
- const Vehicle *v;
-
- if (id_v >= w->vscroll2.cap) return; // click out of bounds
-
- id_v += w->vscroll2.pos;
-
- if (id_v >= gv->l.list_length) return; // click out of list bound
-
- v = gv->sort_list[id_v];
-
- gv->vehicle_sel = v->index;
-
- if (v->IsValid()) {
- SetObjectToPlaceWnd(v->GetImage(DIR_W), GetVehiclePalette(v), VHM_DRAG, w);
- _cursor.vehchain = true;
- }
+ this->SetDirty();
+ break;
+ }
- w->SetDirty();
- break;
- }
-
- case GRP_WIDGET_CREATE_GROUP: // Create a new group
- DoCommandP(0, gv->vehicle_type, 0, NULL, CMD_CREATE_GROUP | CMD_MSG(STR_GROUP_CAN_T_CREATE));
- break;
-
- case GRP_WIDGET_DELETE_GROUP: { // Delete the selected group
- GroupID group = gv->group_sel;
- gv->group_sel = ALL_GROUP;
+ case GRP_WIDGET_CREATE_GROUP: // Create a new group
+ DoCommandP(0, this->vehicle_type, 0, NULL, CMD_CREATE_GROUP | CMD_MSG(STR_GROUP_CAN_T_CREATE));
+ break;
- DoCommandP(0, group, 0, NULL, CMD_DELETE_GROUP | CMD_MSG(STR_GROUP_CAN_T_DELETE));
- break;
- }
+ case GRP_WIDGET_DELETE_GROUP: { // Delete the selected group
+ GroupID group = this->group_sel;
+ this->group_sel = ALL_GROUP;
- case GRP_WIDGET_RENAME_GROUP: { // Rename the selected roup
- assert(IsValidGroupID(gv->group_sel));
+ DoCommandP(0, group, 0, NULL, CMD_DELETE_GROUP | CMD_MSG(STR_GROUP_CAN_T_DELETE));
+ break;
+ }
- const Group *g = GetGroup(gv->group_sel);
+ case GRP_WIDGET_RENAME_GROUP: { // Rename the selected roup
+ assert(IsValidGroupID(this->group_sel));
- SetDParam(0, g->index);
- ShowQueryString(STR_GROUP_NAME, STR_GROUP_RENAME_CAPTION, 31, 150, w, CS_ALPHANUMERAL);
- } break;
+ const Group *g = GetGroup(this->group_sel);
+
+ SetDParam(0, g->index);
+ ShowQueryString(STR_GROUP_NAME, STR_GROUP_RENAME_CAPTION, 31, 150, this, CS_ALPHANUMERAL);
+ } break;
- case GRP_WIDGET_AVAILABLE_VEHICLES:
- ShowBuildVehicleWindow(0, gv->vehicle_type);
- break;
-
- case GRP_WIDGET_MANAGE_VEHICLES_DROPDOWN:
- ShowGroupActionDropdown(w, gv->group_sel);
- break;
+ case GRP_WIDGET_AVAILABLE_VEHICLES:
+ ShowBuildVehicleWindow(0, this->vehicle_type);
+ break;
- case GRP_WIDGET_START_ALL:
- case GRP_WIDGET_STOP_ALL: { // Start/stop all vehicles of the list
- DoCommandP(0, gv->group_sel, ((IsAllGroupID(gv->group_sel) ? VLW_STANDARD : VLW_GROUP_LIST) & VLW_MASK)
- | (1 << 6)
- | (e->we.click.widget == GRP_WIDGET_START_ALL ? (1 << 5) : 0)
- | gv->vehicle_type, NULL, CMD_MASS_START_STOP);
+ case GRP_WIDGET_MANAGE_VEHICLES_DROPDOWN:
+ ShowGroupActionDropdown(this, this->group_sel);
+ break;
- break;
- }
+ case GRP_WIDGET_START_ALL:
+ case GRP_WIDGET_STOP_ALL: { // Start/stop all vehicles of the list
+ DoCommandP(0, this->group_sel, ((IsAllGroupID(this->group_sel) ? VLW_STANDARD : VLW_GROUP_LIST) & VLW_MASK)
+ | (1 << 6)
+ | (widget == GRP_WIDGET_START_ALL ? (1 << 5) : 0)
+ | this->vehicle_type, NULL, CMD_MASS_START_STOP);
- case GRP_WIDGET_REPLACE_PROTECTION:
- if (IsValidGroupID(gv->group_sel)) {
- const Group *g = GetGroup(gv->group_sel);
-
- DoCommandP(0, gv->group_sel, !g->replace_protection, NULL, CMD_SET_GROUP_REPLACE_PROTECTION);
- }
- break;
+ break;
}
- break;
-
- case WE_DRAGDROP: {
- switch (e->we.click.widget) {
- case GRP_WIDGET_ALL_VEHICLES: // All vehicles
- case GRP_WIDGET_DEFAULT_VEHICLES: // Ungrouped vehicles
- DoCommandP(0, DEFAULT_GROUP, gv->vehicle_sel, NULL, CMD_ADD_VEHICLE_GROUP | CMD_MSG(STR_GROUP_CAN_T_ADD_VEHICLE));
-
- gv->vehicle_sel = INVALID_VEHICLE;
-
- w->SetDirty();
-
- break;
+ case GRP_WIDGET_REPLACE_PROTECTION:
+ if (IsValidGroupID(this->group_sel)) {
+ const Group *g = GetGroup(this->group_sel);
- case GRP_WIDGET_LIST_GROUP: { // Maxtrix group
- uint16 id_g = (e->we.click.pt.y - PLY_WND_PRC__OFFSET_TOP_WIDGET - 26) / PLY_WND_PRC__SIZE_OF_ROW_TINY;
- const VehicleID vindex = gv->vehicle_sel;
-
- gv->vehicle_sel = INVALID_VEHICLE;
-
- w->SetDirty();
+ DoCommandP(0, this->group_sel, !g->replace_protection, NULL, CMD_SET_GROUP_REPLACE_PROTECTION);
+ }
+ break;
+ }
+ }
- if (id_g >= w->vscroll.cap) return;
-
- id_g += w->vscroll.pos;
+ virtual void OnDragDrop(Point pt, int widget)
+ {
+ switch (widget) {
+ case GRP_WIDGET_ALL_VEHICLES: // All vehicles
+ case GRP_WIDGET_DEFAULT_VEHICLES: // Ungrouped vehicles
+ DoCommandP(0, DEFAULT_GROUP, this->vehicle_sel, NULL, CMD_ADD_VEHICLE_GROUP | CMD_MSG(STR_GROUP_CAN_T_ADD_VEHICLE));
- if (id_g >= gl->l.list_length) return;
+ this->vehicle_sel = INVALID_VEHICLE;
- DoCommandP(0, gl->sort_list[id_g]->index, vindex, NULL, CMD_ADD_VEHICLE_GROUP | CMD_MSG(STR_GROUP_CAN_T_ADD_VEHICLE));
+ this->SetDirty();
- break;
+ break;
+
+ case GRP_WIDGET_LIST_GROUP: { // Maxtrix group
+ uint16 id_g = (pt.y - PLY_WND_PRC__OFFSET_TOP_WIDGET - 26) / PLY_WND_PRC__SIZE_OF_ROW_TINY;
+ const VehicleID vindex = this->vehicle_sel;
+
+ this->vehicle_sel = INVALID_VEHICLE;
+
+ this->SetDirty();
+
+ if (id_g >= this->vscroll.cap) return;
+
+ id_g += this->vscroll.pos;
+
+ if (id_g >= this->groups.list_length) return;
+
+ DoCommandP(0, this->groups.sort_list[id_g]->index, vindex, NULL, CMD_ADD_VEHICLE_GROUP | CMD_MSG(STR_GROUP_CAN_T_ADD_VEHICLE));
+
+ break;
+ }
+
+ case GRP_WIDGET_LIST_VEHICLE: { // Maxtrix vehicle
+ uint32 id_v = (pt.y - PLY_WND_PRC__OFFSET_TOP_WIDGET) / (int)this->resize.step_height;
+ const Vehicle *v;
+ const VehicleID vindex = this->vehicle_sel;
+
+ this->vehicle_sel = INVALID_VEHICLE;
+
+ this->SetDirty();
+
+ if (id_v >= this->vscroll2.cap) return; // click out of bounds
+
+ id_v += this->vscroll2.pos;
+
+ if (id_v >= this->vehicles.list_length) return; // click out of list bound
+
+ v = this->vehicles.sort_list[id_v];
+
+ if (vindex == v->index) {
+ ShowVehicleViewWindow(v);
}
- case GRP_WIDGET_LIST_VEHICLE: { // Maxtrix vehicle
- uint32 id_v = (e->we.click.pt.y - PLY_WND_PRC__OFFSET_TOP_WIDGET) / (int)w->resize.step_height;
- const Vehicle *v;
- const VehicleID vindex = gv->vehicle_sel;
-
- gv->vehicle_sel = INVALID_VEHICLE;
-
- w->SetDirty();
-
- if (id_v >= w->vscroll2.cap) return; // click out of bounds
-
- id_v += w->vscroll2.pos;
+ break;
+ }
+ }
+ _cursor.vehchain = false;
+ }
- if (id_v >= gv->l.list_length) return; // click out of list bound
-
- v = gv->sort_list[id_v];
+ virtual void OnQueryTextFinished(char *str)
+ {
+ if (!StrEmpty(str)) {
+ _cmd_text = str;
- if (vindex == v->index) {
- ShowVehicleViewWindow(v);
- }
+ DoCommandP(0, this->group_sel, 0, NULL, CMD_RENAME_GROUP | CMD_MSG(STR_GROUP_CAN_T_RENAME));
+ }
+ }
- break;
+ virtual void OnResize(Point new_size, Point delta)
+ {
+ this->hscroll.cap += delta.x;
+ this->vscroll.cap += delta.y / PLY_WND_PRC__SIZE_OF_ROW_TINY;
+ this->vscroll2.cap += delta.y / (int)this->resize.step_height;
+
+ this->widget[GRP_WIDGET_LIST_GROUP].data = (this->vscroll.cap << 8) + 1;
+ this->widget[GRP_WIDGET_LIST_VEHICLE].data = (this->vscroll2.cap << 8) + 1;
+ }
+
+ virtual void OnDropdownSelect(int widget, int index)
+ {
+ switch (widget) {
+ case GRP_WIDGET_SORT_BY_DROPDOWN:
+ if (this->vehicles.sort_type != index) {
+ this->vehicles.flags |= VL_RESORT;
+ this->vehicles.sort_type = index;
+ this->sorting->criteria = this->vehicles.sort_type;
}
- }
- _cursor.vehchain = false;
- break;
+ break;
+
+ case GRP_WIDGET_MANAGE_VEHICLES_DROPDOWN:
+ assert(this->vehicles.list_length != 0);
+
+ switch (index) {
+ case GALF_REPLACE: // Replace window
+ ShowReplaceGroupVehicleWindow(this->group_sel, this->vehicle_type);
+ break;
+ case GALF_SERVICE: // Send for servicing
+ DoCommandP(0, this->group_sel, ((IsAllGroupID(this->group_sel) ? VLW_STANDARD : VLW_GROUP_LIST) & VLW_MASK)
+ | DEPOT_MASS_SEND
+ | DEPOT_SERVICE, NULL, GetCmdSendToDepot(this->vehicle_type));
+ break;
+ case GALF_DEPOT: // Send to Depots
+ DoCommandP(0, this->group_sel, ((IsAllGroupID(this->group_sel) ? VLW_STANDARD : VLW_GROUP_LIST) & VLW_MASK)
+ | DEPOT_MASS_SEND, NULL, GetCmdSendToDepot(this->vehicle_type));
+ break;
+ case GALF_ADD_SHARED: // Add shared Vehicles
+ assert(IsValidGroupID(this->group_sel));
+
+ DoCommandP(0, this->group_sel, this->vehicle_type, NULL, CMD_ADD_SHARED_VEHICLE_GROUP | CMD_MSG(STR_GROUP_CAN_T_ADD_SHARED_VEHICLE));
+ break;
+ case GALF_REMOVE_ALL: // Remove all Vehicles from the selected group
+ assert(IsValidGroupID(this->group_sel));
+
+ DoCommandP(0, this->group_sel, this->vehicle_type, NULL, CMD_REMOVE_ALL_VEHICLES_GROUP | CMD_MSG(STR_GROUP_CAN_T_REMOVE_ALL_VEHICLES));
+ break;
+ default: NOT_REACHED();
+ }
+ break;
+
+ default: NOT_REACHED();
}
- case WE_ON_EDIT_TEXT:
- if (!StrEmpty(e->we.edittext.str)) {
- _cmd_text = e->we.edittext.str;
-
- DoCommandP(0, gv->group_sel, 0, NULL, CMD_RENAME_GROUP | CMD_MSG(STR_GROUP_CAN_T_RENAME));
- }
- break;
-
- case WE_RESIZE:
- w->hscroll.cap += e->we.sizing.diff.x;
- w->vscroll.cap += e->we.sizing.diff.y / PLY_WND_PRC__SIZE_OF_ROW_TINY;
- w->vscroll2.cap += e->we.sizing.diff.y / (int)w->resize.step_height;
-
- w->widget[GRP_WIDGET_LIST_GROUP].data = (w->vscroll.cap << 8) + 1;
- w->widget[GRP_WIDGET_LIST_VEHICLE].data = (w->vscroll2.cap << 8) + 1;
- break;
-
-
- case WE_DROPDOWN_SELECT: // we have selected a dropdown item in the list
- switch (e->we.dropdown.button) {
- case GRP_WIDGET_SORT_BY_DROPDOWN:
- if (gv->l.sort_type != e->we.dropdown.index) {
- gv->l.flags |= VL_RESORT;
- gv->l.sort_type = e->we.dropdown.index;
- gv->_sorting->criteria = gv->l.sort_type;
- }
- break;
-
- case GRP_WIDGET_MANAGE_VEHICLES_DROPDOWN:
- assert(gv->l.list_length != 0);
+ this->SetDirty();
+ }
- switch (e->we.dropdown.index) {
- case GALF_REPLACE: // Replace window
- ShowReplaceGroupVehicleWindow(gv->group_sel, gv->vehicle_type);
- break;
- case GALF_SERVICE: // Send for servicing
- DoCommandP(0, gv->group_sel, ((IsAllGroupID(gv->group_sel) ? VLW_STANDARD : VLW_GROUP_LIST) & VLW_MASK)
- | DEPOT_MASS_SEND
- | DEPOT_SERVICE, NULL, GetCmdSendToDepot(gv->vehicle_type));
- break;
- case GALF_DEPOT: // Send to Depots
- DoCommandP(0, gv->group_sel, ((IsAllGroupID(gv->group_sel) ? VLW_STANDARD : VLW_GROUP_LIST) & VLW_MASK)
- | DEPOT_MASS_SEND, NULL, GetCmdSendToDepot(gv->vehicle_type));
- break;
- case GALF_ADD_SHARED: // Add shared Vehicles
- assert(IsValidGroupID(gv->group_sel));
-
- DoCommandP(0, gv->group_sel, gv->vehicle_type, NULL, CMD_ADD_SHARED_VEHICLE_GROUP | CMD_MSG(STR_GROUP_CAN_T_ADD_SHARED_VEHICLE));
- break;
- case GALF_REMOVE_ALL: // Remove all Vehicles from the selected group
- assert(IsValidGroupID(gv->group_sel));
-
- DoCommandP(0, gv->group_sel, gv->vehicle_type, NULL, CMD_REMOVE_ALL_VEHICLES_GROUP | CMD_MSG(STR_GROUP_CAN_T_REMOVE_ALL_VEHICLES));
- break;
- default: NOT_REACHED();
- }
- break;
-
- default: NOT_REACHED();
- }
+ virtual void OnTick()
+ {
+ if (_pause_game != 0) return;
+ if (--this->vehicles.resort_timer == 0) {
+ this->vehicles.resort_timer = DAY_TICKS * PERIODIC_RESORT_DAYS;
+ this->vehicles.flags |= VL_RESORT;
+ this->SetDirty();
+ }
+ if (--this->groups.resort_timer == 0) {
+ this->groups.resort_timer = DAY_TICKS * PERIODIC_RESORT_DAYS;
+ this->groups.flags |= VL_RESORT;
+ this->SetDirty();
+ }
+ }
- w->SetDirty();
- break;
-
-
- case WE_DESTROY:
- free((void*)gv->sort_list);
- free((void*)gl->sort_list);
- break;
-
-
- case WE_TICK: // resort the lists every 20 seconds orso (10 days)
- if (_pause_game != 0) break;
- if (--gv->l.resort_timer == 0) {
- gv->l.resort_timer = DAY_TICKS * PERIODIC_RESORT_DAYS;
- gv->l.flags |= VL_RESORT;
- w->SetDirty();
- }
- if (--gl->l.resort_timer == 0) {
- gl->l.resort_timer = DAY_TICKS * PERIODIC_RESORT_DAYS;
- gl->l.flags |= VL_RESORT;
- w->SetDirty();
- }
- break;
-
- case WE_ABORT_PLACE_OBJ: // called when new object to place is selected from keyboard
+ virtual void OnPlaceObjectAbort()
+ {
/* abort drag & drop */
- gv->vehicle_sel = INVALID_VEHICLE;
- w->InvalidateWidget(GRP_WIDGET_LIST_VEHICLE);
- break;
-
+ this->vehicle_sel = INVALID_VEHICLE;
+ this->InvalidateWidget(GRP_WIDGET_LIST_VEHICLE);
}
-}
+};
static const WindowDesc _group_desc = {
@@ -792,7 +758,7 @@
WC_TRAINS_LIST, WC_NONE,
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON | WDF_RESIZABLE,
_group_widgets,
- GroupWndProc
+ NULL
};
void ShowPlayerGroup(PlayerID player, VehicleType vehicle_type)
@@ -811,8 +777,6 @@
WindowNumber num = (vehicle_type << 11) | VLW_GROUP_LIST | player;
DeleteWindowById(wc, num);
- Window *w = AllocateWindowDescFront(&_group_desc, num);
- if (w == NULL) return;
-
+ Window *w = new VehicleGroupWindow(&_group_desc, num);
w->window_class = wc;
}
--- a/src/gui.h Wed May 07 21:09:51 2008 +0000
+++ b/src/gui.h Sun May 11 20:09:34 2008 +0000
@@ -48,35 +48,6 @@
void ShowGenerateLandscape();
void ShowHeightmapLoad();
-/** Drag and drop selection process, or, what to do with an area of land when
- * you've selected it. */
-enum {
- DDSP_DEMOLISH_AREA,
- DDSP_RAISE_AND_LEVEL_AREA,
- DDSP_LOWER_AND_LEVEL_AREA,
- DDSP_LEVEL_AREA,
- DDSP_CREATE_DESERT,
- DDSP_CREATE_ROCKS,
- DDSP_CREATE_WATER,
- DDSP_CREATE_RIVER,
- DDSP_PLANT_TREES,
- DDSP_BUILD_BRIDGE,
-
- /* Rail specific actions */
- DDSP_PLACE_RAIL_NE,
- DDSP_PLACE_RAIL_NW,
- DDSP_PLACE_AUTORAIL,
- DDSP_BUILD_SIGNALS,
- DDSP_BUILD_STATION,
- DDSP_REMOVE_STATION,
- DDSP_CONVERT_RAIL,
-
- /* Road specific actions */
- DDSP_PLACE_ROAD_X_DIR,
- DDSP_PLACE_ROAD_Y_DIR,
- DDSP_PLACE_AUTOROAD,
-};
-
/* misc_gui.cpp */
void PlaceLandBlockInfo();
void ShowAboutWindow();
--- a/src/industry_gui.cpp Wed May 07 21:09:51 2008 +0000
+++ b/src/industry_gui.cpp Sun May 11 20:09:34 2008 +0000
@@ -25,43 +25,13 @@
#include "player_func.h"
#include "settings_type.h"
#include "tilehighlight_func.h"
+#include "string_func.h"
#include "table/strings.h"
#include "table/sprites.h"
bool _ignore_restrictions;
-/** Names of the widgets of the dynamic place industries gui */
-enum DynamicPlaceIndustriesWidgets {
- DPIW_CLOSEBOX = 0,
- DPIW_CAPTION,
- DPIW_MATRIX_WIDGET,
- DPIW_SCROLLBAR,
- DPIW_INFOPANEL,
- DPIW_FUND_WIDGET,
- DPIW_RESIZE_WIDGET,
-};
-
-/** Attached struct to the window extended data */
-struct fnd_d {
- int index; ///< index of the element in the matrix
- IndustryType select; ///< industry corresponding to the above index
- uint16 callback_timer; ///< timer counter for callback eventual verification
- bool timer_enabled; ///< timer can be used
-};
-assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(fnd_d));
-
-/** Helper struct holding the available industries for current situation */
-static struct IndustryData {
- uint16 count; ///< How many industries are loaded
- IndustryType index[NUM_INDUSTRYTYPES + 1]; ///< Type of industry, in the order it was loaded
- StringID text[NUM_INDUSTRYTYPES + 1]; ///< Text coming from CBM_IND_FUND_MORE_TEXT (if ever)
- bool enabled[NUM_INDUSTRYTYPES + 1]; ///< availability state, coming from CBID_INDUSTRY_AVAILABLE (if ever)
-} _fund_gui;
-
-assert_compile(lengthof(_fund_gui.index) == lengthof(_fund_gui.text));
-assert_compile(lengthof(_fund_gui.index) == lengthof(_fund_gui.enabled));
-
enum CargoSuffixType {
CST_FUND,
CST_VIEW,
@@ -91,288 +61,19 @@
return STR_EMPTY;
}
-static void BuildDynamicIndustryWndProc(Window *w, WindowEvent *e)
-{
- switch (e->event) {
- case WE_CREATE: {
- IndustryType ind;
- const IndustrySpec *indsp;
-
- /* Shorten the window to the equivalant of the additionnal purchase
- * info coming from the callback. SO it will only be available to tis full
- * height when newindistries are loaded */
- if (!_loaded_newgrf_features.has_newindustries) {
- w->widget[DPIW_INFOPANEL].bottom -= 44;
- w->widget[DPIW_FUND_WIDGET].bottom -= 44;
- w->widget[DPIW_FUND_WIDGET].top -= 44;
- w->widget[DPIW_RESIZE_WIDGET].bottom -= 44;
- w->widget[DPIW_RESIZE_WIDGET].top -= 44;
- w->resize.height = w->height -= 44;
- }
-
- WP(w, fnd_d).timer_enabled = _loaded_newgrf_features.has_newindustries;
-
- /* Initilialize structures */
- _fund_gui.count = 0;
-
- for (uint i = 0; i < lengthof(_fund_gui.index); i++) {
- _fund_gui.index[i] = 0xFF;
- _fund_gui.text[i] = STR_NULL;
- _fund_gui.enabled[i] = false;
- }
-
- w->vscroll.cap = 8; // rows in grid, same in scroller
- w->resize.step_height = 13;
-
- if (_game_mode == GM_EDITOR) { // give room for the Many Random "button"
- _fund_gui.index[_fund_gui.count] = INVALID_INDUSTRYTYPE;
- _fund_gui.count++;
- WP(w, fnd_d).timer_enabled = false;
- }
-
- /* Fill the _fund_gui structure with industries.
- * The tests performed after the enabled allow to load the industries
- * In the same way they are inserted by grf (if any)
- */
- for (ind = 0; ind < NUM_INDUSTRYTYPES; ind++) {
- indsp = GetIndustrySpec(ind);
- if (indsp->enabled){
- /* Rule is that editor mode loads all industries.
- * In game mode, all non raw industries are loaded too
- * and raw ones are loaded only when setting allows it */
- if (_game_mode != GM_EDITOR && indsp->IsRawIndustry() && _patches.raw_industry_construction == 0) continue;
- _fund_gui.index[_fund_gui.count] = ind;
- _fund_gui.enabled[_fund_gui.count] = (_game_mode == GM_EDITOR) || CheckIfCallBackAllowsAvailability(ind, IACT_USERCREATION);
- _fund_gui.count++;
- }
- }
-
- /* first indutry type is selected.
- * I'll be damned if there are none available ;) */
- WP(w, fnd_d).index = 0;
- WP(w, fnd_d).select = _fund_gui.index[0];
- WP(w, fnd_d).callback_timer = DAY_TICKS;
- } break;
-
- case WE_PAINT: {
- const IndustrySpec *indsp = (WP(w, fnd_d).select == INVALID_INDUSTRYTYPE) ? NULL : GetIndustrySpec(WP(w, fnd_d).select);
- int x_str = w->widget[DPIW_INFOPANEL].left + 3;
- int y_str = w->widget[DPIW_INFOPANEL].top + 3;
- const Widget *wi = &w->widget[DPIW_INFOPANEL];
- int max_width = wi->right - wi->left - 4;
-
- /* Raw industries might be prospected. Show this fact by changing the string
- * In Editor, you just build, while ingame, or you fund or you prospect */
- if (_game_mode == GM_EDITOR) {
- /* We've chosen many random industries but no industries have been specified */
- if (indsp == NULL) _fund_gui.enabled[WP(w, fnd_d).index] = _opt.diff.number_industries != 0;
- w->widget[DPIW_FUND_WIDGET].data = STR_BUILD_NEW_INDUSTRY;
- } else {
- w->widget[DPIW_FUND_WIDGET].data = (_patches.raw_industry_construction == 2 && indsp->IsRawIndustry()) ? STR_PROSPECT_NEW_INDUSTRY : STR_FUND_NEW_INDUSTRY;
- }
- w->SetWidgetDisabledState(DPIW_FUND_WIDGET, !_fund_gui.enabled[WP(w, fnd_d).index]);
-
- SetVScrollCount(w, _fund_gui.count);
-
- DrawWindowWidgets(w);
-
- /* and now with the matrix painting */
- for (byte i = 0; i < w->vscroll.cap && ((i + w->vscroll.pos) < _fund_gui.count); i++) {
- int offset = i * 13;
- int x = 3;
- int y = 16;
- bool selected = WP(w, fnd_d).index == i + w->vscroll.pos;
-
- if (_fund_gui.index[i + w->vscroll.pos] == INVALID_INDUSTRYTYPE) {
- DrawStringTruncated(20, y + offset, STR_MANY_RANDOM_INDUSTRIES, selected ? TC_WHITE : TC_ORANGE, max_width - 25);
- continue;
- }
- const IndustrySpec *indsp = GetIndustrySpec(_fund_gui.index[i + w->vscroll.pos]);
-
- /* Draw the name of the industry in white is selected, otherwise, in orange */
- DrawStringTruncated(20, y + offset, indsp->name, selected ? TC_WHITE : TC_ORANGE, max_width - 25);
- GfxFillRect(x, y + 1 + offset, x + 10, y + 7 + offset, selected ? 15 : 0);
- GfxFillRect(x + 1, y + 2 + offset, x + 9, y + 6 + offset, indsp->map_colour);
- }
-
- if (WP(w, fnd_d).select == INVALID_INDUSTRYTYPE) {
- DrawStringMultiLine(x_str, y_str, STR_RANDOM_INDUSTRIES_TIP, max_width, wi->bottom - wi->top - 40);
- break;
- }
-
- if (_game_mode != GM_EDITOR) {
- SetDParam(0, indsp->GetConstructionCost());
- DrawStringTruncated(x_str, y_str, STR_482F_COST, TC_FROMSTRING, max_width);
- y_str += 11;
- }
-
- /* Draw the accepted cargos, if any. Otherwhise, will print "Nothing" */
- StringID str = STR_4827_REQUIRES;
- byte p = 0;
- SetDParam(0, STR_00D0_NOTHING);
- SetDParam(1, STR_EMPTY);
- for (byte j = 0; j < lengthof(indsp->accepts_cargo); j++) {
- if (indsp->accepts_cargo[j] == CT_INVALID) continue;
- if (p > 0) str++;
- SetDParam(p++, GetCargo(indsp->accepts_cargo[j])->name);
- SetDParam(p++, GetCargoSuffix(j, CST_FUND, NULL, WP(w, fnd_d).select, indsp));
- }
- DrawStringTruncated(x_str, y_str, str, TC_FROMSTRING, max_width);
- y_str += 11;
-
- /* Draw the produced cargos, if any. Otherwhise, will print "Nothing" */
- str = STR_4827_PRODUCES;
- p = 0;
- SetDParam(0, STR_00D0_NOTHING);
- SetDParam(1, STR_EMPTY);
- for (byte j = 0; j < lengthof(indsp->produced_cargo); j++) {
- if (indsp->produced_cargo[j] == CT_INVALID) continue;
- if (p > 0) str++;
- SetDParam(p++, GetCargo(indsp->produced_cargo[j])->name);
- SetDParam(p++, GetCargoSuffix(j + 3, CST_FUND, NULL, WP(w, fnd_d).select, indsp));
- }
- DrawStringTruncated(x_str, y_str, str, TC_FROMSTRING, max_width);
- y_str += 11;
-
- /* Get the additional purchase info text, if it has not already been */
- if (_fund_gui.text[WP(w, fnd_d).index] == STR_NULL) { // Have i been called already?
- if (HasBit(indsp->callback_flags, CBM_IND_FUND_MORE_TEXT)) { // No. Can it be called?
- uint16 callback_res = GetIndustryCallback(CBID_INDUSTRY_FUND_MORE_TEXT, 0, 0, NULL, WP(w, fnd_d).select, INVALID_TILE);
- if (callback_res != CALLBACK_FAILED) { // Did it failed?
- StringID newtxt = GetGRFStringID(indsp->grf_prop.grffile->grfid, 0xD000 + callback_res); // No. here's the new string
- _fund_gui.text[WP(w, fnd_d).index] = newtxt; // Store it for further usage
- }
- }
- }
-
- /* Draw the Additional purchase text, provided by newgrf callback, if any.
- * Otherwhise, will print Nothing */
- str = _fund_gui.text[WP(w, fnd_d).index];
- if (str != STR_NULL && str != STR_UNDEFINED) {
- SetDParam(0, str);
- DrawStringMultiLine(x_str, y_str, STR_JUST_STRING, max_width, wi->bottom - wi->top - 40);
- }
- } break;
-
- case WE_DOUBLE_CLICK:
- if (e->we.click.widget != DPIW_MATRIX_WIDGET) break;
- e->we.click.widget = DPIW_FUND_WIDGET;
- /* Fall through */
-
- case WE_CLICK:
- switch (e->we.click.widget) {
- case DPIW_MATRIX_WIDGET: {
- const IndustrySpec *indsp;
- int y = (e->we.click.pt.y - w->widget[DPIW_MATRIX_WIDGET].top) / 13 + w->vscroll.pos ;
-
- if (y >= 0 && y < _fund_gui.count) { // Is it within the boundaries of available data?
- WP(w, fnd_d).index = y;
- WP(w, fnd_d).select = _fund_gui.index[WP(w, fnd_d).index];
- indsp = (WP(w, fnd_d).select == INVALID_INDUSTRYTYPE) ? NULL : GetIndustrySpec(WP(w, fnd_d).select);
-
- w->SetDirty();
-
- if ((_game_mode != GM_EDITOR && _patches.raw_industry_construction == 2 && indsp != NULL && indsp->IsRawIndustry()) ||
- WP(w, fnd_d).select == INVALID_INDUSTRYTYPE) {
- /* Reset the button state if going to prospecting or "build many industries" */
- w->RaiseButtons();
- ResetObjectToPlace();
- }
- }
- } break;
-
- case DPIW_FUND_WIDGET: {
- if (WP(w, fnd_d).select == INVALID_INDUSTRYTYPE) {
- w->HandleButtonClick(DPIW_FUND_WIDGET);
-
- if (GetNumTowns() == 0) {
- ShowErrorMessage(STR_0286_MUST_BUILD_TOWN_FIRST, STR_CAN_T_GENERATE_INDUSTRIES, 0, 0);
- } else {
- extern void GenerateIndustries();
- _generating_world = true;
- GenerateIndustries();
- _generating_world = false;
- }
- } else if (_game_mode != GM_EDITOR && _patches.raw_industry_construction == 2 && GetIndustrySpec(WP(w, fnd_d).select)->IsRawIndustry()) {
- DoCommandP(0, WP(w, fnd_d).select, InteractiveRandom(), NULL, CMD_BUILD_INDUSTRY | CMD_MSG(STR_4830_CAN_T_CONSTRUCT_THIS_INDUSTRY));
- w->HandleButtonClick(DPIW_FUND_WIDGET);
- } else {
- HandlePlacePushButton(w, DPIW_FUND_WIDGET, SPR_CURSOR_INDUSTRY, VHM_RECT, NULL);
- }
- } break;
- }
- break;
-
- case WE_RESIZE: {
- /* Adjust the number of items in the matrix depending of the rezise */
- w->vscroll.cap += e->we.sizing.diff.y / (int)w->resize.step_height;
- w->widget[DPIW_MATRIX_WIDGET].data = (w->vscroll.cap << 8) + 1;
- } break;
-
- case WE_PLACE_OBJ: {
- bool success = true;
- /* We do not need to protect ourselves against "Random Many Industries" in this mode */
- const IndustrySpec *indsp = GetIndustrySpec(WP(w, fnd_d).select);
- uint32 seed = InteractiveRandom();
-
- if (_game_mode == GM_EDITOR) {
- /* Show error if no town exists at all */
- if (GetNumTowns() == 0) {
- SetDParam(0, indsp->name);
- ShowErrorMessage(STR_0286_MUST_BUILD_TOWN_FIRST, STR_0285_CAN_T_BUILD_HERE, e->we.place.pt.x, e->we.place.pt.y);
- return;
- }
-
- _current_player = OWNER_NONE;
- _generating_world = true;
- _ignore_restrictions = true;
- success = DoCommandP(e->we.place.tile, (InteractiveRandomRange(indsp->num_table) << 16) | WP(w, fnd_d).select, seed, NULL, CMD_BUILD_INDUSTRY | CMD_MSG(STR_4830_CAN_T_CONSTRUCT_THIS_INDUSTRY));
- if (!success) {
- SetDParam(0, indsp->name);
- ShowErrorMessage(_error_message, STR_0285_CAN_T_BUILD_HERE, e->we.place.pt.x, e->we.place.pt.y);
- }
-
- _ignore_restrictions = false;
- _generating_world = false;
- } else {
- success = DoCommandP(e->we.place.tile, (InteractiveRandomRange(indsp->num_table) << 16) | WP(w, fnd_d).select, seed, NULL, CMD_BUILD_INDUSTRY | CMD_MSG(STR_4830_CAN_T_CONSTRUCT_THIS_INDUSTRY));
- }
-
- /* If an industry has been built, just reset the cursor and the system */
- if (success) ResetObjectToPlace();
- } break;
-
- case WE_TICK:
- if (_pause_game != 0) break;
- if (!WP(w, fnd_d).timer_enabled) break;
- if (--WP(w, fnd_d).callback_timer == 0) {
- /* We have just passed another day.
- * See if we need to update availability of currently selected industry */
- WP(w, fnd_d).callback_timer = DAY_TICKS; //restart counter
-
- const IndustrySpec *indsp = GetIndustrySpec(WP(w, fnd_d).select);
-
- if (indsp->enabled) {
- bool call_back_result = CheckIfCallBackAllowsAvailability(WP(w, fnd_d).select, IACT_USERCREATION);
-
- /* Only if result does match the previous state would it require a redraw. */
- if (call_back_result != _fund_gui.enabled[WP(w, fnd_d).index]) {
- _fund_gui.enabled[WP(w, fnd_d).index] = call_back_result;
- w->SetDirty();
- }
- }
- }
- break;
-
- case WE_TIMEOUT:
- case WE_ABORT_PLACE_OBJ:
- w->RaiseButtons();
- break;
- }
-}
+/** Names of the widgets of the dynamic place industries gui */
+enum DynamicPlaceIndustriesWidgets {
+ DPIW_CLOSEBOX = 0,
+ DPIW_CAPTION,
+ DPIW_MATRIX_WIDGET,
+ DPIW_SCROLLBAR,
+ DPIW_INFOPANEL,
+ DPIW_FUND_WIDGET,
+ DPIW_RESIZE_WIDGET,
+};
/** Widget definition of the dynamic place industries gui */
-static const Widget _build_dynamic_industry_widgets[] = {
+static const Widget _build_industry_widgets[] = {
{ WWT_CLOSEBOX, RESIZE_NONE, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, // DPIW_CLOSEBOX
{ WWT_CAPTION, RESIZE_RIGHT, 7, 11, 169, 0, 13, STR_0314_FUND_NEW_INDUSTRY, STR_018C_WINDOW_TITLE_DRAG_THIS}, // DPIW_CAPTION
{ WWT_MATRIX, RESIZE_RB, 7, 0, 157, 14, 118, 0x801, STR_INDUSTRY_SELECTION_HINT}, // DPIW_MATRIX_WIDGET
@@ -384,18 +85,320 @@
};
/** Window definition of the dynamic place industries gui */
-static const WindowDesc _build_industry_dynamic_desc = {
+static const WindowDesc _build_industry_desc = {
WDP_AUTO, WDP_AUTO, 170, 212, 170, 212,
WC_BUILD_INDUSTRY, WC_NONE,
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_RESIZABLE,
- _build_dynamic_industry_widgets,
- BuildDynamicIndustryWndProc,
+ _build_industry_widgets,
+ NULL,
+};
+
+class BuildIndustryWindow : public Window {
+ int selected_index; ///< index of the element in the matrix
+ IndustryType selected_type; ///< industry corresponding to the above index
+ uint16 callback_timer; ///< timer counter for callback eventual verification
+ bool timer_enabled; ///< timer can be used
+ uint16 count; ///< How many industries are loaded
+ IndustryType index[NUM_INDUSTRYTYPES + 1]; ///< Type of industry, in the order it was loaded
+ StringID text[NUM_INDUSTRYTYPES + 1]; ///< Text coming from CBM_IND_FUND_MORE_TEXT (if ever)
+ bool enabled[NUM_INDUSTRYTYPES + 1]; ///< availability state, coming from CBID_INDUSTRY_AVAILABLE (if ever)
+
+public:
+ BuildIndustryWindow() : Window(&_build_industry_desc)
+ {
+ IndustryType ind;
+ const IndustrySpec *indsp;
+
+ /* Shorten the window to the equivalant of the additionnal purchase
+ * info coming from the callback. SO it will only be available to tis full
+ * height when newindistries are loaded */
+ if (!_loaded_newgrf_features.has_newindustries) {
+ this->widget[DPIW_INFOPANEL].bottom -= 44;
+ this->widget[DPIW_FUND_WIDGET].bottom -= 44;
+ this->widget[DPIW_FUND_WIDGET].top -= 44;
+ this->widget[DPIW_RESIZE_WIDGET].bottom -= 44;
+ this->widget[DPIW_RESIZE_WIDGET].top -= 44;
+ this->resize.height = this->height -= 44;
+ }
+
+ this->timer_enabled = _loaded_newgrf_features.has_newindustries;
+
+ /* Initialize structures */
+ this->count = 0;
+
+ for (uint i = 0; i < lengthof(this->index); i++) {
+ this->index[i] = 0xFF;
+ this->text[i] = STR_NULL;
+ this->enabled[i] = false;
+ }
+
+ this->vscroll.cap = 8; // rows in grid, same in scroller
+ this->resize.step_height = 13;
+
+ if (_game_mode == GM_EDITOR) { // give room for the Many Random "button"
+ this->index[this->count] = INVALID_INDUSTRYTYPE;
+ this->count++;
+ this->timer_enabled = false;
+ }
+
+ /* Fill the _fund_gui structure with industries.
+ * The tests performed after the enabled allow to load the industries
+ * In the same way they are inserted by grf (if any)
+ */
+ for (ind = 0; ind < NUM_INDUSTRYTYPES; ind++) {
+ indsp = GetIndustrySpec(ind);
+ if (indsp->enabled){
+ /* Rule is that editor mode loads all industries.
+ * In game mode, all non raw industries are loaded too
+ * and raw ones are loaded only when setting allows it */
+ if (_game_mode != GM_EDITOR && indsp->IsRawIndustry() && _patches.raw_industry_construction == 0) continue;
+ this->index[this->count] = ind;
+ this->enabled[this->count] = (_game_mode == GM_EDITOR) || CheckIfCallBackAllowsAvailability(ind, IACT_USERCREATION);
+ this->count++;
+ }
+ }
+
+ /* first indutry type is selected.
+ * I'll be damned if there are none available ;) */
+ this->selected_index = 0;
+ this->selected_type = this->index[0];
+ this->callback_timer = DAY_TICKS;
+
+ this->FindWindowPlacementAndResize(&_build_industry_desc);
+ }
+
+ virtual void OnPaint()
+ {
+ const IndustrySpec *indsp = (this->selected_type == INVALID_INDUSTRYTYPE) ? NULL : GetIndustrySpec(this->selected_type);
+ int x_str = this->widget[DPIW_INFOPANEL].left + 3;
+ int y_str = this->widget[DPIW_INFOPANEL].top + 3;
+ const Widget *wi = &this->widget[DPIW_INFOPANEL];
+ int max_width = wi->right - wi->left - 4;
+
+ /* Raw industries might be prospected. Show this fact by changing the string
+ * In Editor, you just build, while ingame, or you fund or you prospect */
+ if (_game_mode == GM_EDITOR) {
+ /* We've chosen many random industries but no industries have been specified */
+ if (indsp == NULL) this->enabled[this->selected_index] = _opt.diff.number_industries != 0;
+ this->widget[DPIW_FUND_WIDGET].data = STR_BUILD_NEW_INDUSTRY;
+ } else {
+ this->widget[DPIW_FUND_WIDGET].data = (_patches.raw_industry_construction == 2 && indsp->IsRawIndustry()) ? STR_PROSPECT_NEW_INDUSTRY : STR_FUND_NEW_INDUSTRY;
+ }
+ this->SetWidgetDisabledState(DPIW_FUND_WIDGET, !this->enabled[this->selected_index]);
+
+ SetVScrollCount(this, this->count);
+
+ DrawWindowWidgets(this);
+
+ /* and now with the matrix painting */
+ for (byte i = 0; i < this->vscroll.cap && ((i + this->vscroll.pos) < this->count); i++) {
+ int offset = i * 13;
+ int x = 3;
+ int y = 16;
+ bool selected = this->selected_index == i + this->vscroll.pos;
+
+ if (this->index[i + this->vscroll.pos] == INVALID_INDUSTRYTYPE) {
+ DrawStringTruncated(20, y + offset, STR_MANY_RANDOM_INDUSTRIES, selected ? TC_WHITE : TC_ORANGE, max_width - 25);
+ continue;
+ }
+ const IndustrySpec *indsp = GetIndustrySpec(this->index[i + this->vscroll.pos]);
+
+ /* Draw the name of the industry in white is selected, otherwise, in orange */
+ DrawStringTruncated(20, y + offset, indsp->name, selected ? TC_WHITE : TC_ORANGE, max_width - 25);
+ GfxFillRect(x, y + 1 + offset, x + 10, y + 7 + offset, selected ? 15 : 0);
+ GfxFillRect(x + 1, y + 2 + offset, x + 9, y + 6 + offset, indsp->map_colour);
+ }
+
+ if (this->selected_type == INVALID_INDUSTRYTYPE) {
+ DrawStringMultiLine(x_str, y_str, STR_RANDOM_INDUSTRIES_TIP, max_width, wi->bottom - wi->top - 40);
+ return;
+ }
+
+ if (_game_mode != GM_EDITOR) {
+ SetDParam(0, indsp->GetConstructionCost());
+ DrawStringTruncated(x_str, y_str, STR_482F_COST, TC_FROMSTRING, max_width);
+ y_str += 11;
+ }
+
+ /* Draw the accepted cargos, if any. Otherwhise, will print "Nothing" */
+ StringID str = STR_4827_REQUIRES;
+ byte p = 0;
+ SetDParam(0, STR_00D0_NOTHING);
+ SetDParam(1, STR_EMPTY);
+ for (byte j = 0; j < lengthof(indsp->accepts_cargo); j++) {
+ if (indsp->accepts_cargo[j] == CT_INVALID) continue;
+ if (p > 0) str++;
+ SetDParam(p++, GetCargo(indsp->accepts_cargo[j])->name);
+ SetDParam(p++, GetCargoSuffix(j, CST_FUND, NULL, this->selected_type, indsp));
+ }
+ DrawStringTruncated(x_str, y_str, str, TC_FROMSTRING, max_width);
+ y_str += 11;
+
+ /* Draw the produced cargos, if any. Otherwhise, will print "Nothing" */
+ str = STR_4827_PRODUCES;
+ p = 0;
+ SetDParam(0, STR_00D0_NOTHING);
+ SetDParam(1, STR_EMPTY);
+ for (byte j = 0; j < lengthof(indsp->produced_cargo); j++) {
+ if (indsp->produced_cargo[j] == CT_INVALID) continue;
+ if (p > 0) str++;
+ SetDParam(p++, GetCargo(indsp->produced_cargo[j])->name);
+ SetDParam(p++, GetCargoSuffix(j + 3, CST_FUND, NULL, this->selected_type, indsp));
+ }
+ DrawStringTruncated(x_str, y_str, str, TC_FROMSTRING, max_width);
+ y_str += 11;
+
+ /* Get the additional purchase info text, if it has not already been */
+ if (this->text[this->selected_index] == STR_NULL) { // Have i been called already?
+ if (HasBit(indsp->callback_flags, CBM_IND_FUND_MORE_TEXT)) { // No. Can it be called?
+ uint16 callback_res = GetIndustryCallback(CBID_INDUSTRY_FUND_MORE_TEXT, 0, 0, NULL, this->selected_type, INVALID_TILE);
+ if (callback_res != CALLBACK_FAILED) { // Did it failed?
+ StringID newtxt = GetGRFStringID(indsp->grf_prop.grffile->grfid, 0xD000 + callback_res); // No. here's the new string
+ this->text[this->selected_index] = newtxt; // Store it for further usage
+ }
+ }
+ }
+
+ /* Draw the Additional purchase text, provided by newgrf callback, if any.
+ * Otherwhise, will print Nothing */
+ str = this->text[this->selected_index];
+ if (str != STR_NULL && str != STR_UNDEFINED) {
+ SetDParam(0, str);
+ DrawStringMultiLine(x_str, y_str, STR_JUST_STRING, max_width, wi->bottom - wi->top - 40);
+ }
+ }
+
+ virtual void OnDoubleClick(Point pt, int widget)
+ {
+ if (widget != DPIW_MATRIX_WIDGET) return;
+ this->OnClick(pt, DPIW_FUND_WIDGET);
+ }
+
+ virtual void OnClick(Point pt, int widget)
+ {
+ switch (widget) {
+ case DPIW_MATRIX_WIDGET: {
+ const IndustrySpec *indsp;
+ int y = (pt.y - this->widget[DPIW_MATRIX_WIDGET].top) / 13 + this->vscroll.pos ;
+
+ if (y >= 0 && y < count) { // Is it within the boundaries of available data?
+ this->selected_index = y;
+ this->selected_type = this->index[y];
+ indsp = (this->selected_type == INVALID_INDUSTRYTYPE) ? NULL : GetIndustrySpec(this->selected_type);
+
+ this->SetDirty();
+
+ if ((_game_mode != GM_EDITOR && _patches.raw_industry_construction == 2 && indsp != NULL && indsp->IsRawIndustry()) ||
+ this->selected_type == INVALID_INDUSTRYTYPE) {
+ /* Reset the button state if going to prospecting or "build many industries" */
+ this->RaiseButtons();
+ ResetObjectToPlace();
+ }
+ }
+ } break;
+
+ case DPIW_FUND_WIDGET: {
+ if (this->selected_type == INVALID_INDUSTRYTYPE) {
+ this->HandleButtonClick(DPIW_FUND_WIDGET);
+
+ if (GetNumTowns() == 0) {
+ ShowErrorMessage(STR_0286_MUST_BUILD_TOWN_FIRST, STR_CAN_T_GENERATE_INDUSTRIES, 0, 0);
+ } else {
+ extern void GenerateIndustries();
+ _generating_world = true;
+ GenerateIndustries();
+ _generating_world = false;
+ }
+ } else if (_game_mode != GM_EDITOR && _patches.raw_industry_construction == 2 && GetIndustrySpec(this->selected_type)->IsRawIndustry()) {
+ DoCommandP(0, this->selected_type, InteractiveRandom(), NULL, CMD_BUILD_INDUSTRY | CMD_MSG(STR_4830_CAN_T_CONSTRUCT_THIS_INDUSTRY));
+ this->HandleButtonClick(DPIW_FUND_WIDGET);
+ } else {
+ HandlePlacePushButton(this, DPIW_FUND_WIDGET, SPR_CURSOR_INDUSTRY, VHM_RECT, NULL);
+ }
+ } break;
+ }
+ }
+
+ virtual void OnResize(Point new_size, Point delta)
+ {
+ /* Adjust the number of items in the matrix depending of the rezise */
+ this->vscroll.cap += delta.y / (int)this->resize.step_height;
+ this->widget[DPIW_MATRIX_WIDGET].data = (this->vscroll.cap << 8) + 1;
+ }
+
+ virtual void OnPlaceObject(Point pt, TileIndex tile)
+ {
+ bool success = true;
+ /* We do not need to protect ourselves against "Random Many Industries" in this mode */
+ const IndustrySpec *indsp = GetIndustrySpec(this->selected_type);
+ uint32 seed = InteractiveRandom();
+
+ if (_game_mode == GM_EDITOR) {
+ /* Show error if no town exists at all */
+ if (GetNumTowns() == 0) {
+ SetDParam(0, indsp->name);
+ ShowErrorMessage(STR_0286_MUST_BUILD_TOWN_FIRST, STR_0285_CAN_T_BUILD_HERE, pt.x, pt.y);
+ return;
+ }
+
+ _current_player = OWNER_NONE;
+ _generating_world = true;
+ _ignore_restrictions = true;
+ success = DoCommandP(tile, (InteractiveRandomRange(indsp->num_table) << 16) | this->selected_type, seed, NULL, CMD_BUILD_INDUSTRY | CMD_MSG(STR_4830_CAN_T_CONSTRUCT_THIS_INDUSTRY));
+ if (!success) {
+ SetDParam(0, indsp->name);
+ ShowErrorMessage(_error_message, STR_0285_CAN_T_BUILD_HERE, pt.x, pt.y);
+ }
+
+ _ignore_restrictions = false;
+ _generating_world = false;
+ } else {
+ success = DoCommandP(tile, (InteractiveRandomRange(indsp->num_table) << 16) | this->selected_type, seed, NULL, CMD_BUILD_INDUSTRY | CMD_MSG(STR_4830_CAN_T_CONSTRUCT_THIS_INDUSTRY));
+ }
+
+ /* If an industry has been built, just reset the cursor and the system */
+ if (success) ResetObjectToPlace();
+ }
+
+ virtual void OnTick()
+ {
+ if (_pause_game != 0) return;
+ if (!this->timer_enabled) return;
+ if (--this->callback_timer == 0) {
+ /* We have just passed another day.
+ * See if we need to update availability of currently selected industry */
+ this->callback_timer = DAY_TICKS; //restart counter
+
+ const IndustrySpec *indsp = GetIndustrySpec(this->selected_type);
+
+ if (indsp->enabled) {
+ bool call_back_result = CheckIfCallBackAllowsAvailability(this->selected_type, IACT_USERCREATION);
+
+ /* Only if result does match the previous state would it require a redraw. */
+ if (call_back_result != this->enabled[this->selected_index]) {
+ this->enabled[this->selected_index] = call_back_result;
+ this->SetDirty();
+ }
+ }
+ }
+ }
+
+ virtual void OnTimeout()
+ {
+ this->RaiseButtons();
+ }
+
+ virtual void OnPlaceObjectAbort()
+ {
+ this->RaiseButtons();
+ }
};
void ShowBuildIndustryWindow()
{
if (_game_mode != GM_EDITOR && !IsValidPlayer(_current_player)) return;
- AllocateWindowDescFront(&_build_industry_dynamic_desc, 0);
+ if (BringWindowToFrontById(WC_BUILD_INDUSTRY, 0)) return;
+ new BuildIndustryWindow();
}
static void UpdateIndustryProduction(Industry *i);
@@ -426,182 +429,204 @@
IVW_INFO,
IVW_GOTO,
IVW_SPACER,
+ IVW_RESIZE,
};
-/** Information to store about the industry window */
-struct indview_d : public vp_d {
+class IndustryViewWindow : public Window
+{
byte editbox_line; ///< The line clicked to open the edit box
byte clicked_line; ///< The line of the button that has been clicked
byte clicked_button; ///< The button that has been clicked (to raise)
byte production_offset_y; ///< The offset of the production texts/buttons
-};
-assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(indview_d));
-
-
-static void IndustryViewWndProc(Window *w, WindowEvent *e)
-{
- switch (e->event) {
- case WE_PAINT: {
- Industry *i = GetIndustry(w->window_number);
- const IndustrySpec *ind = GetIndustrySpec(i->type);
- int y = w->widget[IVW_INFO].top + 1;
- bool first = true;
- bool has_accept = false;
-
- SetDParam(0, w->window_number);
- DrawWindowWidgets(w);
- if (HasBit(ind->callback_flags, CBM_IND_PRODUCTION_CARGO_ARRIVAL) || HasBit(ind->callback_flags, CBM_IND_PRODUCTION_256_TICKS)) {
- for (byte j = 0; j < lengthof(i->accepts_cargo); j++) {
- if (i->accepts_cargo[j] == CT_INVALID) continue;
- has_accept = true;
- if (first) {
- DrawString(2, y, STR_INDUSTRY_WINDOW_WAITING_FOR_PROCESSING, TC_FROMSTRING);
- y += 10;
- first = false;
- }
- SetDParam(0, i->accepts_cargo[j]);
- SetDParam(1, i->incoming_cargo_waiting[j]);
- SetDParam(2, GetCargoSuffix(j, CST_VIEW, i, i->type, ind));
- DrawString(4, y, STR_INDUSTRY_WINDOW_WAITING_STOCKPILE_CARGO, TC_FROMSTRING);
+public:
+ IndustryViewWindow(const WindowDesc *desc, void *data, WindowNumber window_number) : Window(desc, data, window_number)
+ {
+ this->flags4 |= WF_DISABLE_VP_SCROLL;
+ this->editbox_line = 0;
+ this->clicked_line = 0;
+ this->clicked_button = 0;
+ InitializeWindowViewport(this, 3, 17, 254, 86, GetIndustry(window_number)->xy + TileDiffXY(1, 1), ZOOM_LVL_INDUSTRY);
+ this->FindWindowPlacementAndResize(desc);
+ }
+
+ virtual void OnPaint()
+ {
+ Industry *i = GetIndustry(this->window_number);
+ const IndustrySpec *ind = GetIndustrySpec(i->type);
+ int y = this->widget[IVW_INFO].top + 1;
+ bool first = true;
+ bool has_accept = false;
+
+ SetDParam(0, this->window_number);
+ DrawWindowWidgets(this);
+
+ if (HasBit(ind->callback_flags, CBM_IND_PRODUCTION_CARGO_ARRIVAL) || HasBit(ind->callback_flags, CBM_IND_PRODUCTION_256_TICKS)) {
+ for (byte j = 0; j < lengthof(i->accepts_cargo); j++) {
+ if (i->accepts_cargo[j] == CT_INVALID) continue;
+ has_accept = true;
+ if (first) {
+ DrawStringTruncated(2, y, STR_INDUSTRY_WINDOW_WAITING_FOR_PROCESSING, TC_FROMSTRING, this->widget[IVW_INFO].right - 2);
y += 10;
- }
- } else {
- StringID str = STR_4827_REQUIRES;
- byte p = 0;
- for (byte j = 0; j < lengthof(i->accepts_cargo); j++) {
- if (i->accepts_cargo[j] == CT_INVALID) continue;
- has_accept = true;
- if (p > 0) str++;
- SetDParam(p++, GetCargo(i->accepts_cargo[j])->name);
- SetDParam(p++, GetCargoSuffix(j, CST_VIEW, i, i->type, ind));
- }
- if (has_accept) {
- DrawString(2, y, str, TC_FROMSTRING);
- y += 10;
- }
- }
-
- first = true;
- for (byte j = 0; j < lengthof(i->produced_cargo); j++) {
- if (i->produced_cargo[j] == CT_INVALID) continue;
- if (first) {
- if (has_accept) y += 10;
- DrawString(2, y, STR_482A_PRODUCTION_LAST_MONTH, TC_FROMSTRING);
- y += 10;
- WP(w, indview_d).production_offset_y = y;
first = false;
}
-
- SetDParam(0, i->produced_cargo[j]);
- SetDParam(1, i->last_month_production[j]);
- SetDParam(2, GetCargoSuffix(j + 3, CST_VIEW, i, i->type, ind));
+ SetDParam(0, i->accepts_cargo[j]);
+ SetDParam(1, i->incoming_cargo_waiting[j]);
+ SetDParam(2, GetCargoSuffix(j, CST_VIEW, i, i->type, ind));
+ DrawStringTruncated(4, y, STR_INDUSTRY_WINDOW_WAITING_STOCKPILE_CARGO, TC_FROMSTRING, this->widget[IVW_INFO].right - 4);
+ y += 10;
+ }
+ } else {
+ StringID str = STR_4827_REQUIRES;
+ byte p = 0;
+ for (byte j = 0; j < lengthof(i->accepts_cargo); j++) {
+ if (i->accepts_cargo[j] == CT_INVALID) continue;
+ has_accept = true;
+ if (p > 0) str++;
+ SetDParam(p++, GetCargo(i->accepts_cargo[j])->name);
+ SetDParam(p++, GetCargoSuffix(j, CST_VIEW, i, i->type, ind));
+ }
+ if (has_accept) {
+ DrawStringTruncated(2, y, str, TC_FROMSTRING, this->widget[IVW_INFO].right - 2);
+ y += 10;
+ }
+ }
- SetDParam(3, i->last_month_pct_transported[j] * 100 >> 8);
- DrawString(4 + (IsProductionAlterable(i) ? 30 : 0), y, STR_482B_TRANSPORTED, TC_FROMSTRING);
- /* Let's put out those buttons.. */
- if (IsProductionAlterable(i)) {
- DrawArrowButtons(5, y, 3, (WP(w, indview_d).clicked_line == j + 1) ? WP(w, indview_d).clicked_button : 0,
- !IsProductionMinimum(i, j), !IsProductionMaximum(i, j));
- }
+ first = true;
+ for (byte j = 0; j < lengthof(i->produced_cargo); j++) {
+ if (i->produced_cargo[j] == CT_INVALID) continue;
+ if (first) {
+ if (has_accept) y += 10;
+ DrawStringTruncated(2, y, STR_482A_PRODUCTION_LAST_MONTH, TC_FROMSTRING, this->widget[IVW_INFO].right - 2);
y += 10;
+ this->production_offset_y = y;
+ first = false;
}
- /* Get the extra message for the GUI */
- if (HasBit(ind->callback_flags, CBM_IND_WINDOW_MORE_TEXT)) {
- uint16 callback_res = GetIndustryCallback(CBID_INDUSTRY_WINDOW_MORE_TEXT, 0, 0, i, i->type, i->xy);
- if (callback_res != CALLBACK_FAILED) {
- StringID message = GetGRFStringID(ind->grf_prop.grffile->grfid, 0xD000 + callback_res);
- if (message != STR_NULL && message != STR_UNDEFINED) {
- const Widget *wi = &w->widget[IVW_INFO];
- y += 10;
+ SetDParam(0, i->produced_cargo[j]);
+ SetDParam(1, i->last_month_production[j]);
+ SetDParam(2, GetCargoSuffix(j + 3, CST_VIEW, i, i->type, ind));
- PrepareTextRefStackUsage(6);
- /* Use all the available space left from where we stand up to the end of the window */
- y += DrawStringMultiLine(2, y, message, wi->right - wi->left - 4, -1);
- StopTextRefStackUsage();
- }
+ SetDParam(3, i->last_month_pct_transported[j] * 100 >> 8);
+ uint x = 4 + (IsProductionAlterable(i) ? 30 : 0);
+ DrawStringTruncated(x, y, STR_482B_TRANSPORTED, TC_FROMSTRING, this->widget[IVW_INFO].right - x);
+ /* Let's put out those buttons.. */
+ if (IsProductionAlterable(i)) {
+ DrawArrowButtons(5, y, 3, (this->clicked_line == j + 1) ? this->clicked_button : 0,
+ !IsProductionMinimum(i, j), !IsProductionMaximum(i, j));
+ }
+ y += 10;
+ }
+
+ /* Get the extra message for the GUI */
+ if (HasBit(ind->callback_flags, CBM_IND_WINDOW_MORE_TEXT)) {
+ uint16 callback_res = GetIndustryCallback(CBID_INDUSTRY_WINDOW_MORE_TEXT, 0, 0, i, i->type, i->xy);
+ if (callback_res != CALLBACK_FAILED) {
+ StringID message = GetGRFStringID(ind->grf_prop.grffile->grfid, 0xD000 + callback_res);
+ if (message != STR_NULL && message != STR_UNDEFINED) {
+ const Widget *wi = &this->widget[IVW_INFO];
+ y += 10;
+
+ PrepareTextRefStackUsage(6);
+ /* Use all the available space left from where we stand up to the end of the window */
+ y += DrawStringMultiLine(2, y, message, wi->right - wi->left - 4, -1);
+ StopTextRefStackUsage();
}
}
-
- if (y > w->widget[IVW_INFO].bottom) {
- w->SetDirty();
- ResizeWindowForWidget(w, IVW_INFO, 0, y - w->widget[IVW_INFO].top);
- w->SetDirty();
- return;
- }
-
- DrawWindowViewport(w);
- } break;
-
- case WE_CLICK: {
- Industry *i;
-
- switch (e->we.click.widget) {
- case IVW_INFO: {
- int line, x;
-
- i = GetIndustry(w->window_number);
-
- /* We should work if needed.. */
- if (!IsProductionAlterable(i)) return;
- x = e->we.click.pt.x;
- line = (e->we.click.pt.y - WP(w, indview_d).production_offset_y) / 10;
- if (e->we.click.pt.y >= WP(w, indview_d).production_offset_y && IsInsideMM(line, 0, 2) && i->produced_cargo[line] != CT_INVALID) {
- if (IsInsideMM(x, 5, 25) ) {
- /* Clicked buttons, decrease or increase production */
- if (x < 15) {
- if (IsProductionMinimum(i, line)) return;
- i->production_rate[line] = max(i->production_rate[line] / 2, 0);
- } else {
- /* a zero production industry is unlikely to give anything but zero, so push it a little bit */
- int new_prod = i->production_rate[line] == 0 ? 1 : i->production_rate[line] * 2;
- if (IsProductionMaximum(i, line)) return;
- i->production_rate[line] = minu(new_prod, 255);
- }
+ }
- UpdateIndustryProduction(i);
- w->SetDirty();
- w->flags4 |= 5 << WF_TIMEOUT_SHL;
- WP(w, indview_d).clicked_line = line + 1;
- WP(w, indview_d).clicked_button = (x < 15 ? 1 : 2);
- } else if (IsInsideMM(x, 34, 160)) {
- /* clicked the text */
- WP(w, indview_d).editbox_line = line;
- SetDParam(0, i->production_rate[line] * 8);
- ShowQueryString(STR_CONFIG_PATCHES_INT32, STR_CONFIG_GAME_PRODUCTION, 10, 100, w, CS_ALPHANUMERAL);
+ if (y > this->widget[IVW_INFO].bottom) {
+ this->SetDirty();
+ ResizeWindowForWidget(this, IVW_INFO, 0, y - this->widget[IVW_INFO].top);
+ this->SetDirty();
+ return;
+ }
+
+ DrawWindowViewport(this);
+ }
+
+ virtual void OnClick(Point pt, int widget)
+ {
+ Industry *i;
+
+ switch (widget) {
+ case IVW_INFO: {
+ int line, x;
+
+ i = GetIndustry(this->window_number);
+
+ /* We should work if needed.. */
+ if (!IsProductionAlterable(i)) return;
+ x = pt.x;
+ line = (pt.y - this->production_offset_y) / 10;
+ if (pt.y >= this->production_offset_y && IsInsideMM(line, 0, 2) && i->produced_cargo[line] != CT_INVALID) {
+ if (IsInsideMM(x, 5, 25) ) {
+ /* Clicked buttons, decrease or increase production */
+ if (x < 15) {
+ if (IsProductionMinimum(i, line)) return;
+ i->production_rate[line] = max(i->production_rate[line] / 2, 0);
+ } else {
+ /* a zero production industry is unlikely to give anything but zero, so push it a little bit */
+ int new_prod = i->production_rate[line] == 0 ? 1 : i->production_rate[line] * 2;
+ if (IsProductionMaximum(i, line)) return;
+ i->production_rate[line] = minu(new_prod, 255);
}
- }
- } break;
- case IVW_GOTO:
- i = GetIndustry(w->window_number);
- if (_ctrl_pressed) {
- ShowExtraViewPortWindow(i->xy + TileDiffXY(1, 1));
- } else {
- ScrollMainWindowToTile(i->xy + TileDiffXY(1, 1));
+ UpdateIndustryProduction(i);
+ this->SetDirty();
+ this->flags4 |= 5 << WF_TIMEOUT_SHL;
+ this->clicked_line = line + 1;
+ this->clicked_button = (x < 15 ? 1 : 2);
+ } else if (IsInsideMM(x, 34, 160)) {
+ /* clicked the text */
+ this->editbox_line = line;
+ SetDParam(0, i->production_rate[line] * 8);
+ ShowQueryString(STR_CONFIG_PATCHES_INT32, STR_CONFIG_GAME_PRODUCTION, 10, 100, this, CS_ALPHANUMERAL);
}
-
+ }
} break;
- } break;
-
- case WE_TIMEOUT:
- WP(w, indview_d).clicked_line = 0;
- WP(w, indview_d).clicked_button = 0;
- w->SetDirty();
- break;
- case WE_ON_EDIT_TEXT:
- if (e->we.edittext.str[0] != '\0') {
- Industry* i = GetIndustry(w->window_number);
- int line = WP(w, indview_d).editbox_line;
+ case IVW_GOTO:
+ i = GetIndustry(this->window_number);
+ if (_ctrl_pressed) {
+ ShowExtraViewPortWindow(i->xy + TileDiffXY(1, 1));
+ } else {
+ ScrollMainWindowToTile(i->xy + TileDiffXY(1, 1));
+ }
+ break;
+ }
+ }
- i->production_rate[line] = ClampU(atoi(e->we.edittext.str), 0, 255);
- UpdateIndustryProduction(i);
- w->SetDirty();
- }
+ virtual void OnTimeout()
+ {
+ this->clicked_line = 0;
+ this->clicked_button = 0;
+ this->SetDirty();
}
-}
+
+ virtual void OnResize(Point new_size, Point delta)
+ {
+ this->viewport->width += delta.x;
+ this->viewport->height += delta.y;
+ this->viewport->virtual_width += delta.x;
+ this->viewport->virtual_height += delta.y;
+ this->viewport->dest_scrollpos_x -= delta.x;
+ this->viewport->dest_scrollpos_y -= delta.y;
+ UpdateViewportPosition(this);
+ }
+
+ virtual void OnQueryTextFinished(char *str)
+ {
+ if (StrEmpty(str)) return;
+
+ Industry* i = GetIndustry(this->window_number);
+ int line = this->editbox_line;
+
+ i->production_rate[line] = ClampU(atoi(str), 0, 255);
+ UpdateIndustryProduction(i);
+ this->SetDirty();
+ }
+};
static void UpdateIndustryProduction(Industry *i)
{
@@ -615,13 +640,14 @@
/** Widget definition of the view industy gui */
static const Widget _industry_view_widgets[] = {
{ WWT_CLOSEBOX, RESIZE_NONE, 9, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, // IVW_CLOSEBOX
-{ WWT_CAPTION, RESIZE_NONE, 9, 11, 247, 0, 13, STR_4801, STR_018C_WINDOW_TITLE_DRAG_THIS}, // IVW_CAPTION
-{ WWT_STICKYBOX, RESIZE_NONE, 9, 248, 259, 0, 13, 0x0, STR_STICKY_BUTTON}, // IVW_STICKY
-{ WWT_PANEL, RESIZE_NONE, 9, 0, 259, 14, 105, 0x0, STR_NULL}, // IVW_BACKGROUND
-{ WWT_INSET, RESIZE_NONE, 9, 2, 257, 16, 103, 0x0, STR_NULL}, // IVW_VIEWPORT
-{ WWT_PANEL, RESIZE_BOTTOM, 9, 0, 259, 106, 107, 0x0, STR_NULL}, // IVW_INFO
+{ WWT_CAPTION, RESIZE_RIGHT, 9, 11, 247, 0, 13, STR_4801, STR_018C_WINDOW_TITLE_DRAG_THIS}, // IVW_CAPTION
+{ WWT_STICKYBOX, RESIZE_LR, 9, 248, 259, 0, 13, 0x0, STR_STICKY_BUTTON}, // IVW_STICKY
+{ WWT_PANEL, RESIZE_RB, 9, 0, 259, 14, 105, 0x0, STR_NULL}, // IVW_BACKGROUND
+{ WWT_INSET, RESIZE_RB, 9, 2, 257, 16, 103, 0x0, STR_NULL}, // IVW_VIEWPORT
+{ WWT_PANEL, RESIZE_RTB, 9, 0, 259, 106, 107, 0x0, STR_NULL}, // IVW_INFO
{ WWT_PUSHTXTBTN, RESIZE_TB, 9, 0, 129, 108, 119, STR_00E4_LOCATION, STR_482C_CENTER_THE_MAIN_VIEW_ON}, // IVW_GOTO
-{ WWT_PANEL, RESIZE_TB, 9, 130, 259, 108, 119, 0x0, STR_NULL}, // IVW_SPACER
+{ WWT_PANEL, RESIZE_RTB, 9, 130, 247, 108, 119, 0x0, STR_NULL}, // IVW_SPACER
+{ WWT_RESIZEBOX, RESIZE_LRTB, 9, 248, 259, 108, 119, 0x0, STR_RESIZE_BUTTON}, // IVW_RESIZE
{ WIDGETS_END},
};
@@ -629,22 +655,14 @@
static const WindowDesc _industry_view_desc = {
WDP_AUTO, WDP_AUTO, 260, 120, 260, 120,
WC_INDUSTRY_VIEW, WC_NONE,
- WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON,
+ WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON | WDF_RESIZABLE,
_industry_view_widgets,
- IndustryViewWndProc
+ NULL
};
void ShowIndustryViewWindow(int industry)
{
- Window *w = AllocateWindowDescFront(&_industry_view_desc, industry);
-
- if (w != NULL) {
- w->flags4 |= WF_DISABLE_VP_SCROLL;
- WP(w, indview_d).editbox_line = 0;
- WP(w, indview_d).clicked_line = 0;
- WP(w, indview_d).clicked_button = 0;
- InitializeWindowViewport(w, 3, 17, 254, 86, GetIndustry(w->window_number)->xy + TileDiffXY(1, 1), ZOOM_LVL_INDUSTRY);
- }
+ AllocateWindowDescFront<IndustryViewWindow>(&_industry_view_desc, industry);
}
/** Names of the widgets of the industry directory gui */
@@ -665,16 +683,16 @@
/** Widget definition of the industy directory gui */
static const Widget _industry_directory_widgets[] = {
{ WWT_CLOSEBOX, RESIZE_NONE, 13, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, // IDW_CLOSEBOX
-{ WWT_CAPTION, RESIZE_NONE, 13, 11, 495, 0, 13, STR_INDUSTRYDIR_CAPTION, STR_018C_WINDOW_TITLE_DRAG_THIS}, // IDW_CAPTION
-{ WWT_STICKYBOX, RESIZE_NONE, 13, 496, 507, 0, 13, 0x0, STR_STICKY_BUTTON}, // IDW_STICKY
+{ WWT_CAPTION, RESIZE_RIGHT, 13, 11, 495, 0, 13, STR_INDUSTRYDIR_CAPTION, STR_018C_WINDOW_TITLE_DRAG_THIS}, // IDW_CAPTION
+{ WWT_STICKYBOX, RESIZE_LR, 13, 496, 507, 0, 13, 0x0, STR_STICKY_BUTTON}, // IDW_STICKY
{ WWT_PUSHTXTBTN, RESIZE_NONE, 13, 0, 100, 14, 25, STR_SORT_BY_NAME, STR_SORT_ORDER_TIP}, // IDW_SORTBYNAME
{ WWT_PUSHTXTBTN, RESIZE_NONE, 13, 101, 200, 14, 25, STR_SORT_BY_TYPE, STR_SORT_ORDER_TIP}, // IDW_SORTBYTYPE
{ WWT_PUSHTXTBTN, RESIZE_NONE, 13, 201, 300, 14, 25, STR_SORT_BY_PRODUCTION, STR_SORT_ORDER_TIP}, // IDW_SORTBYPROD
{ WWT_PUSHTXTBTN, RESIZE_NONE, 13, 301, 400, 14, 25, STR_SORT_BY_TRANSPORTED, STR_SORT_ORDER_TIP}, // IDW_SORTBYTRANSPORT
-{ WWT_PANEL, RESIZE_NONE, 13, 401, 495, 14, 25, 0x0, STR_NULL}, // IDW_SPACER
-{ WWT_PANEL, RESIZE_BOTTOM, 13, 0, 495, 26, 189, 0x0, STR_200A_TOWN_NAMES_CLICK_ON_NAME}, // IDW_INDUSRTY_LIST
-{ WWT_SCROLLBAR, RESIZE_BOTTOM, 13, 496, 507, 14, 177, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST}, // IDW_SCROLLBAR
-{ WWT_RESIZEBOX, RESIZE_TB, 13, 496, 507, 178, 189, 0x0, STR_RESIZE_BUTTON}, // IDW_RESIZE
+{ WWT_PANEL, RESIZE_RIGHT, 13, 401, 495, 14, 25, 0x0, STR_NULL}, // IDW_SPACER
+{ WWT_PANEL, RESIZE_RB, 13, 0, 495, 26, 189, 0x0, STR_200A_TOWN_NAMES_CLICK_ON_NAME}, // IDW_INDUSRTY_LIST
+{ WWT_SCROLLBAR, RESIZE_LRB, 13, 496, 507, 14, 177, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST}, // IDW_SCROLLBAR
+{ WWT_RESIZEBOX, RESIZE_LRTB, 13, 496, 507, 178, 189, 0x0, STR_RESIZE_BUTTON}, // IDW_RESIZE
{ WIDGETS_END},
};
@@ -831,7 +849,7 @@
/* Drawing the right string */
StringID str = STR_INDUSTRYDIR_ITEM_NOPROD;
if (p != 1) str = (p == 5) ? STR_INDUSTRYDIR_ITEM : STR_INDUSTRYDIR_ITEM_TWO;
- DrawString(4, 28 + n * 10, str, TC_FROMSTRING);
+ DrawStringTruncated(4, 28 + n * 10, str, TC_FROMSTRING, w->widget[IDW_INDUSRTY_LIST].right - 4);
pos++;
if (++n == w->vscroll.cap) break;
@@ -881,7 +899,7 @@
}
break;
- case WE_4:
+ case WE_100_TICKS:
w->SetDirty();
break;
@@ -902,7 +920,7 @@
void ShowIndustryDirectory()
{
- Window *w = AllocateWindowDescFront(&_industry_directory_desc, 0);
+ Window *w = AllocateWindowDescFront<Window>(&_industry_directory_desc, 0);
if (w != NULL) {
w->vscroll.cap = 16;
--- a/src/intro_gui.cpp Wed May 07 21:09:51 2008 +0000
+++ b/src/intro_gui.cpp Sun May 11 20:09:34 2008 +0000
@@ -133,7 +133,7 @@
void ShowSelectGameWindow()
{
- AllocateWindowDesc(&_select_game_desc);
+ new Window(&_select_game_desc);
}
static void AskExitGameCallback(Window *w, bool confirmed)
--- a/src/main_gui.cpp Wed May 07 21:09:51 2008 +0000
+++ b/src/main_gui.cpp Sun May 11 20:09:34 2008 +0000
@@ -167,31 +167,31 @@
vp->virtual_width >>= 1;
vp->virtual_height >>= 1;
- WP(w, vp_d).scrollpos_x += vp->virtual_width >> 1;
- WP(w, vp_d).scrollpos_y += vp->virtual_height >> 1;
- WP(w, vp_d).dest_scrollpos_x = WP(w,vp_d).scrollpos_x;
- WP(w, vp_d).dest_scrollpos_y = WP(w,vp_d).scrollpos_y;
+ w->viewport->scrollpos_x += vp->virtual_width >> 1;
+ w->viewport->scrollpos_y += vp->virtual_height >> 1;
+ w->viewport->dest_scrollpos_x = w->viewport->scrollpos_x;
+ w->viewport->dest_scrollpos_y = w->viewport->scrollpos_y;
break;
case ZOOM_OUT:
if (vp->zoom == ZOOM_LVL_MAX) return false;
vp->zoom = (ZoomLevel)((int)vp->zoom + 1);
- WP(w, vp_d).scrollpos_x -= vp->virtual_width >> 1;
- WP(w, vp_d).scrollpos_y -= vp->virtual_height >> 1;
- WP(w, vp_d).dest_scrollpos_x = WP(w,vp_d).scrollpos_x;
- WP(w, vp_d).dest_scrollpos_y = WP(w,vp_d).scrollpos_y;
+ w->viewport->scrollpos_x -= vp->virtual_width >> 1;
+ w->viewport->scrollpos_y -= vp->virtual_height >> 1;
+ w->viewport->dest_scrollpos_x = w->viewport->scrollpos_x;
+ w->viewport->dest_scrollpos_y = w->viewport->scrollpos_y;
vp->virtual_width <<= 1;
vp->virtual_height <<= 1;
break;
}
if (vp != NULL) { // the vp can be null when how == ZOOM_NONE
- vp->virtual_left = WP(w, vp_d).scrollpos_x;
- vp->virtual_top = WP(w, vp_d).scrollpos_y;
+ vp->virtual_left = w->viewport->scrollpos_x;
+ vp->virtual_top = w->viewport->scrollpos_y;
}
w->SetDirty();
/* Update the windows that have zoom-buttons to perhaps disable their buttons */
- SendWindowMessageClass(w->window_class, how, w->window_number, 0);
+ InvalidateThisWindowData(w);
return true;
}
@@ -381,19 +381,19 @@
_scrolling_viewport = false;
}
- WP(w, vp_d).scrollpos_x += ScaleByZoom(e->we.scroll.delta.x, vp->zoom);
- WP(w, vp_d).scrollpos_y += ScaleByZoom(e->we.scroll.delta.y, vp->zoom);
- WP(w, vp_d).dest_scrollpos_x = WP(w, vp_d).scrollpos_x;
- WP(w, vp_d).dest_scrollpos_y = WP(w, vp_d).scrollpos_y;
+ w->viewport->scrollpos_x += ScaleByZoom(e->we.scroll.delta.x, vp->zoom);
+ w->viewport->scrollpos_y += ScaleByZoom(e->we.scroll.delta.y, vp->zoom);
+ w->viewport->dest_scrollpos_x = w->viewport->scrollpos_x;
+ w->viewport->dest_scrollpos_y = w->viewport->scrollpos_y;
} break;
case WE_MOUSEWHEEL:
ZoomInOrOutToCursorWindow(e->we.wheel.wheel < 0, w);
break;
- case WE_MESSAGE:
+ case WE_INVALIDATE_DATA:
/* Forward the message to the appropiate toolbar (ingame or scenario editor) */
- SendWindowMessage(WC_MAIN_TOOLBAR, 0, e->we.message.msg, e->we.message.wparam, e->we.message.lparam);
+ InvalidateWindowData(WC_MAIN_TOOLBAR, 0, e->we.invalidate.data);
break;
}
}
@@ -413,7 +413,7 @@
int width = _screen.width;
int height = _screen.height;
- Window *w = AllocateWindow(0, 0, width, height, MainWindowWndProc, WC_MAIN_WINDOW, NULL);
+ Window *w = new Window(0, 0, width, height, MainWindowWndProc, WC_MAIN_WINDOW, NULL);
InitializeWindowViewport(w, 0, 0, width, height, TileXY(32, 32), ZOOM_LVL_VIEWPORT);
/* XXX: these are not done */
--- a/src/minilzo.cpp Wed May 07 21:09:51 2008 +0000
+++ b/src/minilzo.cpp Sun May 11 20:09:34 2008 +0000
@@ -1029,7 +1029,7 @@
{
register const lzo_byte *m_pos;
lzo_moff_t m_off;
- lzo_uint m_len;
+ lzo_ptrdiff_t m_len;
lzo_uint dindex;
DINDEX1(dindex,ip);
--- a/src/misc.cpp Wed May 07 21:09:51 2008 +0000
+++ b/src/misc.cpp Sun May 11 20:09:34 2008 +0000
@@ -95,7 +95,6 @@
InitializeIndustries();
InitializeBuildingCounts();
- InitializeVehiclesGuiList();
InitializeTrains();
InitializeNPF();
--- a/src/misc/dbg_helpers.cpp Wed May 07 21:09:51 2008 +0000
+++ b/src/misc/dbg_helpers.cpp Sun May 11 20:09:34 2008 +0000
@@ -5,6 +5,7 @@
#include "../stdafx.h"
#include "../openttd.h"
#include "../direction_type.h"
+#include "../strings_type.h"
#include "../rail.h"
#include "../rail_map.h"
#include "dbg_helpers.h"
--- a/src/misc_gui.cpp Wed May 07 21:09:51 2008 +0000
+++ b/src/misc_gui.cpp Sun May 11 20:09:34 2008 +0000
@@ -44,10 +44,10 @@
#include "newgrf_cargo.h"
#include "rail_gui.h"
#include "tilehighlight_func.h"
+#include "querystring_gui.h"
#include "table/sprites.h"
#include "table/strings.h"
-#include "table/tree_land.h"
/* Variables to display file lists */
FiosItem *_fios_list;
@@ -57,28 +57,6 @@
static bool _fios_path_changed;
static bool _savegame_sort_dirty;
-enum {
- LAND_INFO_LINES = 7,
- LAND_INFO_LINE_BUFF_SIZE = 512,
-};
-
-static char _landinfo_data[LAND_INFO_LINES][LAND_INFO_LINE_BUFF_SIZE];
-
-static void LandInfoWndProc(Window *w, WindowEvent *e)
-{
- if (e->event == WE_PAINT) {
- DrawWindowWidgets(w);
-
- DoDrawStringCentered(140, 16, _landinfo_data[0], TC_LIGHT_BLUE);
- DoDrawStringCentered(140, 27, _landinfo_data[1], TC_FROMSTRING);
- DoDrawStringCentered(140, 38, _landinfo_data[2], TC_FROMSTRING);
- DoDrawStringCentered(140, 49, _landinfo_data[3], TC_FROMSTRING);
- DoDrawStringCentered(140, 60, _landinfo_data[4], TC_FROMSTRING);
- if (_landinfo_data[5][0] != '\0') DrawStringMultiCenter(140, 76, BindCString(_landinfo_data[5]), w->width - 4);
- if (_landinfo_data[6][0] != '\0') DoDrawStringCentered(140, 71, _landinfo_data[6], TC_FROMSTRING);
- }
-}
-
static const Widget _land_info_widgets[] = {
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
{ WWT_CAPTION, RESIZE_NONE, 14, 11, 279, 0, 13, STR_01A3_LAND_AREA_INFORMATION, STR_018C_WINDOW_TITLE_DRAG_THIS},
@@ -91,106 +69,131 @@
WC_LAND_INFO, WC_NONE,
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
_land_info_widgets,
- LandInfoWndProc
+ NULL
};
-static void Place_LandInfo(TileIndex tile)
-{
- DeleteWindowById(WC_LAND_INFO, 0);
-
- Window *w = AllocateWindowDesc(&_land_info_desc);
- WP(w, void_d).data = &_landinfo_data;
-
- Player *p = GetPlayer(IsValidPlayer(_local_player) ? _local_player : PLAYER_FIRST);
- Town *t = ClosestTownFromTile(tile, _patches.dist_local_authority);
-
- Money old_money = p->player_money;
- p->player_money = INT64_MAX;
- CommandCost costclear = DoCommand(tile, 0, 0, 0, CMD_LANDSCAPE_CLEAR);
- p->player_money = old_money;
+class LandInfoWindow : public Window {
+ enum {
+ LAND_INFO_LINES = 7,
+ LAND_INFO_LINE_BUFF_SIZE = 512,
+ };
- /* Because build_date is not set yet in every TileDesc, we make sure it is empty */
- TileDesc td;
- AcceptedCargo ac;
-
- td.build_date = 0;
- GetAcceptedCargo(tile, ac);
- GetTileDesc(tile, &td);
+public:
+ char landinfo_data[LAND_INFO_LINES][LAND_INFO_LINE_BUFF_SIZE];
- SetDParam(0, td.dparam[0]);
- GetString(_landinfo_data[0], td.str, lastof(_landinfo_data[0]));
+ virtual void OnPaint()
+ {
+ DrawWindowWidgets(this);
- SetDParam(0, STR_01A6_N_A);
- if (td.owner != OWNER_NONE && td.owner != OWNER_WATER) GetNameOfOwner(td.owner, tile);
- GetString(_landinfo_data[1], STR_01A7_OWNER, lastof(_landinfo_data[1]));
-
- StringID str = STR_01A4_COST_TO_CLEAR_N_A;
- if (CmdSucceeded(costclear)) {
- SetDParam(0, costclear.GetCost());
- str = STR_01A5_COST_TO_CLEAR;
+ DoDrawStringCentered(140, 16, this->landinfo_data[0], TC_LIGHT_BLUE);
+ DoDrawStringCentered(140, 27, this->landinfo_data[1], TC_FROMSTRING);
+ DoDrawStringCentered(140, 38, this->landinfo_data[2], TC_FROMSTRING);
+ DoDrawStringCentered(140, 49, this->landinfo_data[3], TC_FROMSTRING);
+ DoDrawStringCentered(140, 60, this->landinfo_data[4], TC_FROMSTRING);
+ if (!StrEmpty(this->landinfo_data[5])) DrawStringMultiCenter(140, 76, BindCString(this->landinfo_data[5]), this->width - 4);
+ if (!StrEmpty(this->landinfo_data[6])) DoDrawStringCentered(140, 71, this->landinfo_data[6], TC_FROMSTRING);
}
- GetString(_landinfo_data[2], str, lastof(_landinfo_data[2]));
-
- snprintf(_userstring, lengthof(_userstring), "0x%.4X", tile);
- SetDParam(0, TileX(tile));
- SetDParam(1, TileY(tile));
- SetDParam(2, TileHeight(tile));
- SetDParam(3, STR_SPEC_USERSTRING);
- GetString(_landinfo_data[3], STR_LANDINFO_COORDS, lastof(_landinfo_data[3]));
-
- SetDParam(0, STR_01A9_NONE);
- if (t != NULL && t->IsValid()) {
- SetDParam(0, STR_TOWN);
- SetDParam(1, t->index);
- }
- GetString(_landinfo_data[4], STR_01A8_LOCAL_AUTHORITY, lastof(_landinfo_data[4]));
- char *strp = GetString(_landinfo_data[5], STR_01CE_CARGO_ACCEPTED, lastof(_landinfo_data[5]));
- bool found = false;
+ LandInfoWindow(TileIndex tile) : Window(&_land_info_desc) {
+ Player *p = GetPlayer(IsValidPlayer(_local_player) ? _local_player : PLAYER_FIRST);
+ Town *t = ClosestTownFromTile(tile, _patches.dist_local_authority);
- for (CargoID i = 0; i < NUM_CARGO; ++i) {
- if (ac[i] > 0) {
- /* Add a comma between each item. */
- if (found) {
- *strp++ = ',';
- *strp++ = ' ';
- }
- found = true;
+ Money old_money = p->player_money;
+ p->player_money = INT64_MAX;
+ CommandCost costclear = DoCommand(tile, 0, 0, 0, CMD_LANDSCAPE_CLEAR);
+ p->player_money = old_money;
- /* If the accepted value is less than 8, show it in 1/8:ths */
- if (ac[i] < 8) {
- SetDParam(0, ac[i]);
- SetDParam(1, GetCargo(i)->name);
- strp = GetString(strp, STR_01D1_8, lastof(_landinfo_data[5]));
- } else {
- strp = GetString(strp, GetCargo(i)->name, lastof(_landinfo_data[5]));
+ /* Because build_date is not set yet in every TileDesc, we make sure it is empty */
+ TileDesc td;
+ AcceptedCargo ac;
+
+ td.build_date = 0;
+ GetAcceptedCargo(tile, ac);
+ GetTileDesc(tile, &td);
+
+ SetDParam(0, td.dparam[0]);
+ GetString(this->landinfo_data[0], td.str, lastof(this->landinfo_data[0]));
+
+ SetDParam(0, STR_01A6_N_A);
+ if (td.owner != OWNER_NONE && td.owner != OWNER_WATER) GetNameOfOwner(td.owner, tile);
+ GetString(this->landinfo_data[1], STR_01A7_OWNER, lastof(this->landinfo_data[1]));
+
+ StringID str = STR_01A4_COST_TO_CLEAR_N_A;
+ if (CmdSucceeded(costclear)) {
+ SetDParam(0, costclear.GetCost());
+ str = STR_01A5_COST_TO_CLEAR;
+ }
+ GetString(this->landinfo_data[2], str, lastof(this->landinfo_data[2]));
+
+ snprintf(_userstring, lengthof(_userstring), "0x%.4X", tile);
+ SetDParam(0, TileX(tile));
+ SetDParam(1, TileY(tile));
+ SetDParam(2, TileHeight(tile));
+ SetDParam(3, STR_SPEC_USERSTRING);
+ GetString(this->landinfo_data[3], STR_LANDINFO_COORDS, lastof(this->landinfo_data[3]));
+
+ SetDParam(0, STR_01A9_NONE);
+ if (t != NULL && t->IsValid()) {
+ SetDParam(0, STR_TOWN);
+ SetDParam(1, t->index);
+ }
+ GetString(this->landinfo_data[4], STR_01A8_LOCAL_AUTHORITY, lastof(this->landinfo_data[4]));
+
+ char *strp = GetString(this->landinfo_data[5], STR_01CE_CARGO_ACCEPTED, lastof(this->landinfo_data[5]));
+ bool found = false;
+
+ for (CargoID i = 0; i < NUM_CARGO; ++i) {
+ if (ac[i] > 0) {
+ /* Add a comma between each item. */
+ if (found) {
+ *strp++ = ',';
+ *strp++ = ' ';
+ }
+ found = true;
+
+ /* If the accepted value is less than 8, show it in 1/8:ths */
+ if (ac[i] < 8) {
+ SetDParam(0, ac[i]);
+ SetDParam(1, GetCargo(i)->name);
+ strp = GetString(strp, STR_01D1_8, lastof(this->landinfo_data[5]));
+ } else {
+ strp = GetString(strp, GetCargo(i)->name, lastof(this->landinfo_data[5]));
+ }
}
}
- }
- if (!found) _landinfo_data[5][0] = '\0';
+ if (!found) this->landinfo_data[5][0] = '\0';
- if (td.build_date != 0) {
- SetDParam(0, td.build_date);
- GetString(_landinfo_data[6], STR_BUILD_DATE, lastof(_landinfo_data[6]));
- } else {
- _landinfo_data[6][0] = '\0';
- }
+ if (td.build_date != 0) {
+ SetDParam(0, td.build_date);
+ GetString(this->landinfo_data[6], STR_BUILD_DATE, lastof(this->landinfo_data[6]));
+ } else {
+ this->landinfo_data[6][0] = '\0';
+ }
#if defined(_DEBUG)
# define LANDINFOD_LEVEL 0
#else
# define LANDINFOD_LEVEL 1
#endif
- DEBUG(misc, LANDINFOD_LEVEL, "TILE: %#x (%i,%i)", tile, TileX(tile), TileY(tile));
- DEBUG(misc, LANDINFOD_LEVEL, "type_height = %#x", _m[tile].type_height);
- DEBUG(misc, LANDINFOD_LEVEL, "m1 = %#x", _m[tile].m1);
- DEBUG(misc, LANDINFOD_LEVEL, "m2 = %#x", _m[tile].m2);
- DEBUG(misc, LANDINFOD_LEVEL, "m3 = %#x", _m[tile].m3);
- DEBUG(misc, LANDINFOD_LEVEL, "m4 = %#x", _m[tile].m4);
- DEBUG(misc, LANDINFOD_LEVEL, "m5 = %#x", _m[tile].m5);
- DEBUG(misc, LANDINFOD_LEVEL, "m6 = %#x", _m[tile].m6);
- DEBUG(misc, LANDINFOD_LEVEL, "m7 = %#x", _me[tile].m7);
+ DEBUG(misc, LANDINFOD_LEVEL, "TILE: %#x (%i,%i)", tile, TileX(tile), TileY(tile));
+ DEBUG(misc, LANDINFOD_LEVEL, "type_height = %#x", _m[tile].type_height);
+ DEBUG(misc, LANDINFOD_LEVEL, "m1 = %#x", _m[tile].m1);
+ DEBUG(misc, LANDINFOD_LEVEL, "m2 = %#x", _m[tile].m2);
+ DEBUG(misc, LANDINFOD_LEVEL, "m3 = %#x", _m[tile].m3);
+ DEBUG(misc, LANDINFOD_LEVEL, "m4 = %#x", _m[tile].m4);
+ DEBUG(misc, LANDINFOD_LEVEL, "m5 = %#x", _m[tile].m5);
+ DEBUG(misc, LANDINFOD_LEVEL, "m6 = %#x", _m[tile].m6);
+ DEBUG(misc, LANDINFOD_LEVEL, "m7 = %#x", _me[tile].m7);
#undef LANDINFOD_LEVEL
+
+ this->FindWindowPlacementAndResize(&_land_info_desc);
+ }
+};
+
+static void Place_LandInfo(TileIndex tile)
+{
+ DeleteWindowById(WC_LAND_INFO, 0);
+ new LandInfoWindow(tile);
}
void PlaceLandBlockInfo()
@@ -203,6 +206,12 @@
}
}
+struct scroller_d {
+ int height;
+ uint16 counter;
+};
+assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(scroller_d));
+
static const char *credits[] = {
/*************************************************************************
* maximum length of string which fits in window -^*/
@@ -318,176 +327,7 @@
void ShowAboutWindow()
{
DeleteWindowById(WC_GAME_OPTIONS, 0);
- AllocateWindowDesc(&_about_desc);
-}
-
-static int _tree_to_plant;
-
-static const PalSpriteID _tree_sprites[] = {
- { 0x655, PAL_NONE }, { 0x663, PAL_NONE }, { 0x678, PAL_NONE }, { 0x62B, PAL_NONE },
- { 0x647, PAL_NONE }, { 0x639, PAL_NONE }, { 0x64E, PAL_NONE }, { 0x632, PAL_NONE },
- { 0x67F, PAL_NONE }, { 0x68D, PAL_NONE }, { 0x69B, PAL_NONE }, { 0x6A9, PAL_NONE },
- { 0x6AF, PAL_NONE }, { 0x6D2, PAL_NONE }, { 0x6D9, PAL_NONE }, { 0x6C4, PAL_NONE },
- { 0x6CB, PAL_NONE }, { 0x6B6, PAL_NONE }, { 0x6BD, PAL_NONE }, { 0x6E0, PAL_NONE },
- { 0x72E, PAL_NONE }, { 0x734, PAL_NONE }, { 0x74A, PAL_NONE }, { 0x74F, PAL_NONE },
- { 0x76B, PAL_NONE }, { 0x78F, PAL_NONE }, { 0x788, PAL_NONE }, { 0x77B, PAL_NONE },
- { 0x75F, PAL_NONE }, { 0x774, PAL_NONE }, { 0x720, PAL_NONE }, { 0x797, PAL_NONE },
- { 0x79E, PAL_NONE }, { 0x7A5, PALETTE_TO_GREEN }, { 0x7AC, PALETTE_TO_RED }, { 0x7B3, PAL_NONE },
- { 0x7BA, PAL_NONE }, { 0x7C1, PALETTE_TO_RED, }, { 0x7C8, PALETTE_TO_PALE_GREEN }, { 0x7CF, PALETTE_TO_YELLOW }, { 0x7D6, PALETTE_TO_RED }
-};
-
-static void BuildTreesWndProc(Window *w, WindowEvent *e)
-{
- switch (e->event) {
- case WE_CREATE:
- ResetObjectToPlace();
- break;
-
- case WE_PAINT: {
- DrawWindowWidgets(w);
-
- int i = WP(w, tree_d).base = _tree_base_by_landscape[_opt.landscape];
- int count = WP(w, tree_d).count = _tree_count_by_landscape[_opt.landscape];
-
- int x = 18;
- int y = 54;
- do {
- DrawSprite(_tree_sprites[i].sprite, _tree_sprites[i].pal, x, y);
- x += 35;
- if (!(++i & 3)) {
- x -= 35 * 4;
- y += 47;
- }
- } while (--count);
- } break;
-
- case WE_CLICK: {
- int wid = e->we.click.widget;
-
- switch (wid) {
- case 0:
- ResetObjectToPlace();
- break;
-
- case 3: case 4: case 5: case 6:
- case 7: case 8: case 9: case 10:
- case 11:case 12: case 13: case 14:
- if (wid - 3 >= WP(w, tree_d).count) break;
-
- if (HandlePlacePushButton(w, wid, SPR_CURSOR_TREE, VHM_RECT, NULL)) {
- _tree_to_plant = WP(w, tree_d).base + wid - 3;
- }
- break;
-
- case 15: // tree of random type.
- if (HandlePlacePushButton(w, 15, SPR_CURSOR_TREE, VHM_RECT, NULL)) {
- _tree_to_plant = -1;
- }
- break;
-
- case 16: // place trees randomly over the landscape
- w->LowerWidget(16);
- w->flags4 |= 5 << WF_TIMEOUT_SHL;
- SndPlayFx(SND_15_BEEP);
- PlaceTreesRandomly();
- MarkWholeScreenDirty();
- break;
- }
- } break;
-
- case WE_PLACE_OBJ:
- VpStartPlaceSizing(e->we.place.tile, VPM_X_AND_Y_LIMITED, DDSP_PLANT_TREES);
- VpSetPlaceSizingLimit(20);
- break;
-
- case WE_PLACE_DRAG:
- VpSelectTilesWithMethod(e->we.place.pt.x, e->we.place.pt.y, e->we.place.select_method);
- return;
-
- case WE_PLACE_MOUSEUP:
- if (e->we.place.pt.x != -1 && e->we.place.select_proc == DDSP_PLANT_TREES) {
- DoCommandP(e->we.place.tile, _tree_to_plant, e->we.place.starttile, NULL,
- CMD_PLANT_TREE | CMD_MSG(STR_2805_CAN_T_PLANT_TREE_HERE));
- }
- break;
-
- case WE_TIMEOUT:
- w->RaiseWidget(16);
- break;
-
- case WE_ABORT_PLACE_OBJ:
- w->RaiseButtons();
- break;
- }
-}
-
-static const Widget _build_trees_widgets[] = {
-{ WWT_CLOSEBOX, RESIZE_NONE, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
-{ WWT_CAPTION, RESIZE_NONE, 7, 11, 142, 0, 13, STR_2802_TREES, STR_018C_WINDOW_TITLE_DRAG_THIS},
-{ WWT_PANEL, RESIZE_NONE, 7, 0, 142, 14, 170, 0x0, STR_NULL},
-{ WWT_PANEL, RESIZE_NONE, 14, 2, 35, 16, 61, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT},
-{ WWT_PANEL, RESIZE_NONE, 14, 37, 70, 16, 61, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT},
-{ WWT_PANEL, RESIZE_NONE, 14, 72, 105, 16, 61, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT},
-{ WWT_PANEL, RESIZE_NONE, 14, 107, 140, 16, 61, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT},
-{ WWT_PANEL, RESIZE_NONE, 14, 2, 35, 63, 108, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT},
-{ WWT_PANEL, RESIZE_NONE, 14, 37, 70, 63, 108, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT},
-{ WWT_PANEL, RESIZE_NONE, 14, 72, 105, 63, 108, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT},
-{ WWT_PANEL, RESIZE_NONE, 14, 107, 140, 63, 108, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT},
-{ WWT_PANEL, RESIZE_NONE, 14, 2, 35, 110, 155, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT},
-{ WWT_PANEL, RESIZE_NONE, 14, 37, 70, 110, 155, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT},
-{ WWT_PANEL, RESIZE_NONE, 14, 72, 105, 110, 155, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT},
-{ WWT_PANEL, RESIZE_NONE, 14, 107, 140, 110, 155, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT},
-{ WWT_TEXTBTN, RESIZE_NONE, 14, 2, 140, 157, 168, STR_TREES_RANDOM_TYPE, STR_TREES_RANDOM_TYPE_TIP},
-{ WIDGETS_END},
-};
-
-static const WindowDesc _build_trees_desc = {
- 497, 22, 143, 171, 143, 171,
- WC_BUILD_TREES, WC_SCEN_LAND_GEN,
- WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
- _build_trees_widgets,
- BuildTreesWndProc
-};
-
-static const Widget _build_trees_scen_widgets[] = {
-{ WWT_CLOSEBOX, RESIZE_NONE, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
-{ WWT_CAPTION, RESIZE_NONE, 7, 11, 142, 0, 13, STR_2802_TREES, STR_018C_WINDOW_TITLE_DRAG_THIS},
-{ WWT_PANEL, RESIZE_NONE, 7, 0, 142, 14, 183, 0x0, STR_NULL},
-{ WWT_PANEL, RESIZE_NONE, 14, 2, 35, 16, 61, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT},
-{ WWT_PANEL, RESIZE_NONE, 14, 37, 70, 16, 61, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT},
-{ WWT_PANEL, RESIZE_NONE, 14, 72, 105, 16, 61, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT},
-{ WWT_PANEL, RESIZE_NONE, 14, 107, 140, 16, 61, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT},
-{ WWT_PANEL, RESIZE_NONE, 14, 2, 35, 63, 108, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT},
-{ WWT_PANEL, RESIZE_NONE, 14, 37, 70, 63, 108, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT},
-{ WWT_PANEL, RESIZE_NONE, 14, 72, 105, 63, 108, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT},
-{ WWT_PANEL, RESIZE_NONE, 14, 107, 140, 63, 108, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT},
-{ WWT_PANEL, RESIZE_NONE, 14, 2, 35, 110, 155, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT},
-{ WWT_PANEL, RESIZE_NONE, 14, 37, 70, 110, 155, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT},
-{ WWT_PANEL, RESIZE_NONE, 14, 72, 105, 110, 155, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT},
-{ WWT_PANEL, RESIZE_NONE, 14, 107, 140, 110, 155, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT},
-{ WWT_TEXTBTN, RESIZE_NONE, 14, 2, 140, 157, 168, STR_TREES_RANDOM_TYPE, STR_TREES_RANDOM_TYPE_TIP},
-{ WWT_TEXTBTN, RESIZE_NONE, 14, 2, 140, 170, 181, STR_028A_RANDOM_TREES, STR_028B_PLANT_TREES_RANDOMLY_OVER},
-{ WIDGETS_END},
-};
-
-static const WindowDesc _build_trees_scen_desc = {
- WDP_AUTO, WDP_AUTO, 143, 184, 143, 184,
- WC_BUILD_TREES, WC_NONE,
- WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
- _build_trees_scen_widgets,
- BuildTreesWndProc
-};
-
-
-void ShowBuildTreesToolbar()
-{
- if (!IsValidPlayer(_current_player)) return;
- AllocateWindowDescFront(&_build_trees_desc, 0);
-}
-
-void ShowBuildTreesScenToolbar()
-{
- AllocateWindowDescFront(&_build_trees_scen_desc, 0);
+ new Window(&_about_desc);
}
static uint64 _errmsg_decode_params[20];
@@ -562,7 +402,7 @@
if (_right_button_down) delete w;
break;
- case WE_4:
+ case WE_100_TICKS:
if (--_errmsg_duration == 0) delete w;
break;
@@ -615,7 +455,7 @@
pt.x = (_screen.width - 240) >> 1;
pt.y = (_screen.height - 46) >> 1;
}
- w = AllocateWindow(pt.x, pt.y, 240, 46, ErrmsgWndProc, WC_ERRMSG, _errmsg_widgets);
+ w = new Window(pt.x, pt.y, 240, 46, ErrmsgWndProc, WC_ERRMSG, _errmsg_widgets);
} else {
if ((x | y) != 0) {
pt = RemapCoords2(x, y);
@@ -626,7 +466,7 @@
pt.x = (_screen.width - 334) >> 1;
pt.y = (_screen.height - 137) >> 1;
}
- w = AllocateWindow(pt.x, pt.y, 334, 137, ErrmsgWndProc, WC_ERRMSG, _errmsg_face_widgets);
+ w = new Window(pt.x, pt.y, 334, 137, ErrmsgWndProc, WC_ERRMSG, _errmsg_face_widgets);
}
w->desc_flags = WDF_STD_BTN | WDF_DEF_WIDGET;
@@ -694,32 +534,50 @@
{ WIDGETS_END},
};
-
-static void TooltipsWndProc(Window *w, WindowEvent *e)
+struct TooltipsWindow : public Window
{
- switch (e->event) {
- case WE_PAINT:
- GfxFillRect(0, 0, w->width - 1, w->height - 1, 0);
- GfxFillRect(1, 1, w->width - 2, w->height - 2, 0x44);
+ StringID string_id;
+ byte paramcount;
+ uint64 params[5];
- for (uint arg = 0; arg < WP(w, tooltips_d).paramcount; arg++) {
- SetDParam(arg, WP(w, tooltips_d).params[arg]);
- }
- DrawStringMultiCenter((w->width >> 1), (w->height >> 1) - 5, WP(w, tooltips_d).string_id, w->width - 2);
- break;
+ TooltipsWindow(int x, int y, int width, int height, const Widget *widget,
+ StringID str, uint paramcount, const uint64 params[]) :
+ Window(x, y, width, height, NULL, WC_TOOLTIPS, widget)
+ {
+ this->string_id = str;
+ assert(sizeof(this->params[0]) == sizeof(params[0]));
+ memcpy(this->params, params, sizeof(this->params[0]) * paramcount);
+ this->paramcount = paramcount;
- case WE_MOUSELOOP:
- /* We can show tooltips while dragging tools. These are shown as long as
- * we are dragging the tool. Normal tooltips work with rmb */
- if (WP(w, tooltips_d).paramcount == 0 ) {
- if (!_right_button_down) delete w;
- } else {
- if (!_left_button_down) delete w;
- }
+ this->flags4 &= ~WF_WHITE_BORDER_MASK; // remove white-border from tooltip
+ this->widget[0].right = width;
+ this->widget[0].bottom = height;
- break;
+ FindWindowPlacementAndResize(width, height);
}
-}
+
+ virtual void OnPaint()
+ {
+ GfxFillRect(0, 0, this->width - 1, this->height - 1, 0);
+ GfxFillRect(1, 1, this->width - 2, this->height - 2, 0x44);
+
+ for (uint arg = 0; arg < this->paramcount; arg++) {
+ SetDParam(arg, this->params[arg]);
+ }
+ DrawStringMultiCenter((this->width >> 1), (this->height >> 1) - 5, this->string_id, this->width - 2);
+ }
+
+ virtual void OnMouseLoop()
+ {
+ /* We can show tooltips while dragging tools. These are shown as long as
+ * we are dragging the tool. Normal tooltips work with rmb */
+ if (this->paramcount == 0 ) {
+ if (!_right_button_down) delete this;
+ } else {
+ if (!_left_button_down) delete this;
+ }
+ }
+};
/** Shows a tooltip
* @param str String to be displayed
@@ -753,16 +611,7 @@
if (y + br.height > _screen.height - 12) y = _cursor.pos.y + _cursor.offs.y - br.height - 5;
int x = Clamp(_cursor.pos.x - (br.width >> 1), 0, _screen.width - br.width);
- Window *w = AllocateWindow(x, y, br.width, br.height, TooltipsWndProc, WC_TOOLTIPS, _tooltips_widgets);
-
- WP(w, tooltips_d).string_id = str;
- assert(sizeof(WP(w, tooltips_d).params[0]) == sizeof(params[0]));
- memcpy(WP(w, tooltips_d).params, params, sizeof(WP(w, tooltips_d).params[0]) * paramcount);
- WP(w, tooltips_d).paramcount = paramcount;
-
- w->flags4 &= ~WF_WHITE_BORDER_MASK; // remove white-border from tooltip
- w->widget[0].right = br.width;
- w->widget[0].bottom = br.height;
+ new TooltipsWindow(x, y, br.width, br.height, _tooltips_widgets, str, paramcount, params);
}
@@ -1032,43 +881,6 @@
tb->caretxoffs = tb->width;
}
-int HandleEditBoxKey(Window *w, querystr_d *string, int wid, WindowEvent *e)
-{
- e->we.keypress.cont = false;
-
- switch (e->we.keypress.keycode) {
- case WKC_ESC: return 2;
-
- case WKC_RETURN: case WKC_NUM_ENTER: return 1;
-
- case (WKC_CTRL | 'V'):
- if (InsertTextBufferClipboard(&string->text)) w->InvalidateWidget(wid);
- break;
-
- case (WKC_CTRL | 'U'):
- DeleteTextBufferAll(&string->text);
- w->InvalidateWidget(wid);
- break;
-
- case WKC_BACKSPACE: case WKC_DELETE:
- if (DeleteTextBufferChar(&string->text, e->we.keypress.keycode)) w->InvalidateWidget(wid);
- break;
-
- case WKC_LEFT: case WKC_RIGHT: case WKC_END: case WKC_HOME:
- if (MoveTextBufferPos(&string->text, e->we.keypress.keycode)) w->InvalidateWidget(wid);
- break;
-
- default:
- if (IsValidChar(e->we.keypress.key, string->afilter)) {
- if (InsertTextBufferChar(&string->text, e->we.keypress.key)) w->InvalidateWidget(wid);
- } else { // key wasn't caught. Continue only if standard entry specified
- e->we.keypress.cont = (string->afilter == CS_ALPHANUMERAL);
- }
- }
-
- return 0;
-}
-
bool HandleCaret(Textbuf *tb)
{
/* caret changed? */
@@ -1081,12 +893,49 @@
return false;
}
-void HandleEditBox(Window *w, querystr_d *string, int wid)
+int QueryString::HandleEditBoxKey(Window *w, int wid, uint16 key, uint16 keycode, bool &cont)
{
- if (HandleCaret(&string->text)) w->InvalidateWidget(wid);
+ cont = false;
+
+ switch (keycode) {
+ case WKC_ESC: return 2;
+
+ case WKC_RETURN: case WKC_NUM_ENTER: return 1;
+
+ case (WKC_CTRL | 'V'):
+ if (InsertTextBufferClipboard(&this->text)) w->InvalidateWidget(wid);
+ break;
+
+ case (WKC_CTRL | 'U'):
+ DeleteTextBufferAll(&this->text);
+ w->InvalidateWidget(wid);
+ break;
+
+ case WKC_BACKSPACE: case WKC_DELETE:
+ if (DeleteTextBufferChar(&this->text, keycode)) w->InvalidateWidget(wid);
+ break;
+
+ case WKC_LEFT: case WKC_RIGHT: case WKC_END: case WKC_HOME:
+ if (MoveTextBufferPos(&this->text, keycode)) w->InvalidateWidget(wid);
+ break;
+
+ default:
+ if (IsValidChar(key, this->afilter)) {
+ if (InsertTextBufferChar(&this->text, key)) w->InvalidateWidget(wid);
+ } else { // key wasn't caught. Continue only if standard entry specified
+ cont = (this->afilter == CS_ALPHANUMERAL);
+ }
+ }
+
+ return 0;
}
-void DrawEditBox(Window *w, querystr_d *string, int wid)
+void QueryString::HandleEditBox(Window *w, int wid)
+{
+ if (HandleCaret(&this->text)) w->InvalidateWidget(wid);
+}
+
+void QueryString::DrawEditBox(Window *w, int wid)
{
const Widget *wi = &w->widget[wid];
@@ -1111,7 +960,7 @@
/* We will take the current widget length as maximum width, with a small
* space reserved at the end for the caret to show */
- const Textbuf *tb = &string->text;
+ const Textbuf *tb = &this->text;
delta = (wi->right - wi->left) - tb->width - 10;
if (delta > 0) delta = 0;
@@ -1124,6 +973,21 @@
_cur_dpi = old_dpi;
}
+int QueryStringBaseWindow::HandleEditBoxKey(int wid, uint16 key, uint16 keycode, bool &cont)
+{
+ return this->QueryString::HandleEditBoxKey(this, wid, key, keycode, cont);
+}
+
+void QueryStringBaseWindow::HandleEditBox(int wid)
+{
+ this->QueryString::HandleEditBox(this, wid);
+}
+
+void QueryStringBaseWindow::DrawEditBox(int wid)
+{
+ this->QueryString::DrawEditBox(this, wid);
+}
+
enum QueryStringWidgets {
QUERY_STR_WIDGET_TEXT = 3,
QUERY_STR_WIDGET_CANCEL,
@@ -1131,76 +995,79 @@
};
-static void QueryStringWndProc(Window *w, WindowEvent *e)
+struct QueryStringWindow : public QueryStringBaseWindow
{
- querystr_d *qs = &WP(w, querystr_d);
-
- switch (e->event) {
- case WE_CREATE:
- SetBit(_no_scroll, SCROLL_EDIT);
- break;
-
- case WE_PAINT:
- SetDParam(0, qs->caption);
- DrawWindowWidgets(w);
-
- DrawEditBox(w, qs, QUERY_STR_WIDGET_TEXT);
- break;
-
- case WE_CLICK:
- switch (e->we.click.widget) {
- case QUERY_STR_WIDGET_TEXT:
- ShowOnScreenKeyboard(w, &WP(w, querystr_d), QUERY_STR_WIDGET_TEXT, QUERY_STR_WIDGET_CANCEL, QUERY_STR_WIDGET_OK);
- break;
-
- case QUERY_STR_WIDGET_OK:
- press_ok:;
- if (qs->orig == NULL || strcmp(qs->text.buf, qs->orig) != 0) {
- Window *parent = w->parent;
- qs->handled = true;
+ Window *parent;
- /* If the parent is NULL, the editbox is handled by general function
- * HandleOnEditText */
- if (parent != NULL) {
- WindowEvent e;
- e.event = WE_ON_EDIT_TEXT;
- e.we.edittext.str = qs->text.buf;
- parent->HandleWindowEvent(&e);
- } else {
- HandleOnEditText(qs->text.buf);
- }
- }
- /* Fallthrough */
- case QUERY_STR_WIDGET_CANCEL:
- delete w;
- break;
- }
- break;
+ QueryStringWindow(const WindowDesc *desc, Window *parent) : QueryStringBaseWindow(desc), parent(parent)
+ {
+ SetBit(_no_scroll, SCROLL_EDIT);
- case WE_MOUSELOOP:
- HandleEditBox(w, qs, QUERY_STR_WIDGET_TEXT);
- break;
-
- case WE_KEYPRESS:
- switch (HandleEditBoxKey(w, qs, QUERY_STR_WIDGET_TEXT, e)) {
- case 1: goto press_ok; // Enter pressed, confirms change
- case 2: delete w; break; // ESC pressed, closes window, abandons changes
- }
- break;
+ this->FindWindowPlacementAndResize(desc);
+ }
- case WE_DESTROY: // Call cancellation of query, if we have not handled it before
- if (!qs->handled && w->parent != NULL) {
- WindowEvent e;
- Window *parent = w->parent;
+ virtual void OnPaint()
+ {
+ SetDParam(0, this->caption);
+ DrawWindowWidgets(this);
- qs->handled = true;
- e.event = WE_ON_EDIT_TEXT_CANCEL;
- parent->HandleWindowEvent(&e);
+ this->DrawEditBox(QUERY_STR_WIDGET_TEXT);
+ }
+
+ void OnOk()
+ {
+ if (this->orig == NULL || strcmp(this->text.buf, this->orig) != 0) {
+ /* If the parent is NULL, the editbox is handled by general function
+ * HandleOnEditText */
+ if (this->parent != NULL) {
+ this->parent->OnQueryTextFinished(this->text.buf);
+ } else {
+ HandleOnEditText(this->text.buf);
}
- ClrBit(_no_scroll, SCROLL_EDIT);
- break;
}
-}
+ }
+
+ virtual void OnClick(Point pt, int widget)
+ {
+ switch (widget) {
+ case QUERY_STR_WIDGET_TEXT:
+ ShowOnScreenKeyboard(this, QUERY_STR_WIDGET_TEXT, QUERY_STR_WIDGET_CANCEL, QUERY_STR_WIDGET_OK);
+ break;
+
+ case QUERY_STR_WIDGET_OK:
+ this->OnOk();
+ /* Fallthrough */
+ case QUERY_STR_WIDGET_CANCEL:
+ delete this;
+ break;
+ }
+ }
+
+ virtual void OnMouseLoop()
+ {
+ this->HandleEditBox(QUERY_STR_WIDGET_TEXT);
+ }
+
+ virtual bool OnKeyPress(uint16 key, uint16 keycode)
+ {
+ bool cont;
+ switch (this->HandleEditBoxKey(QUERY_STR_WIDGET_TEXT, key, keycode, cont)) {
+ case 1: this->OnOk(); // Enter pressed, confirms change
+ /* FALL THROUGH */
+ case 2: delete this; break; // ESC pressed, closes window, abandons changes
+ }
+ return cont;
+ }
+
+ ~QueryStringWindow()
+ {
+ if (!this->handled && this->parent != NULL) {
+ this->handled = true;
+ this->parent->OnQueryTextFinished(NULL);
+ }
+ ClrBit(_no_scroll, SCROLL_EDIT);
+ }
+};
static const Widget _query_string_widgets[] = {
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
@@ -1217,12 +1084,9 @@
WC_QUERY_STRING, WC_NONE,
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
_query_string_widgets,
- QueryStringWndProc
+ NULL
};
-char _edit_str_buf[64];
-char _orig_str_buf[lengthof(_edit_str_buf)];
-
/** Show a query popup window with a textbox in it.
* @param str StringID for the text shown in the textbox
* @param caption StringID of text shown in caption of querywindow
@@ -1236,28 +1100,27 @@
{
uint realmaxlen = maxlen & ~0x1000;
- assert(realmaxlen < lengthof(_edit_str_buf));
-
DeleteWindowById(WC_QUERY_STRING, 0);
DeleteWindowById(WC_SAVELOAD, 0);
- Window *w = AllocateWindowDesc(&_query_string_desc);
- w->parent = parent;
+ QueryStringWindow *w = new QueryStringWindow(&_query_string_desc, parent);
- GetString(_edit_str_buf, str, lastof(_edit_str_buf));
- _edit_str_buf[realmaxlen - 1] = '\0';
+ assert(realmaxlen < lengthof(w->edit_str_buf));
+
+ GetString(w->edit_str_buf, str, lastof(w->edit_str_buf));
+ w->edit_str_buf[realmaxlen - 1] = '\0';
if (maxlen & 0x1000) {
- WP(w, querystr_d).orig = NULL;
+ w->orig = NULL;
} else {
- strecpy(_orig_str_buf, _edit_str_buf, lastof(_orig_str_buf));
- WP(w, querystr_d).orig = _orig_str_buf;
+ strecpy(w->orig_str_buf, w->edit_str_buf, lastof(w->orig_str_buf));
+ w->orig = w->orig_str_buf;
}
w->LowerWidget(QUERY_STR_WIDGET_TEXT);
- WP(w, querystr_d).caption = caption;
- WP(w, querystr_d).afilter = afilter;
- InitializeTextBuffer(&WP(w, querystr_d).text, _edit_str_buf, realmaxlen, maxwidth);
+ w->caption = caption;
+ w->afilter = afilter;
+ InitializeTextBuffer(&w->text, w->edit_str_buf, realmaxlen, maxwidth);
}
@@ -1267,63 +1130,78 @@
QUERY_WIDGET_YES
};
-
-struct query_d {
+/**
+ * Window used for asking the user a YES/NO question.
+ */
+struct QueryWindow : public Window {
void (*proc)(Window*, bool); ///< callback function executed on closing of popup. Window* points to parent, bool is true if 'yes' clicked, false otherwise
uint64 params[10]; ///< local copy of _decode_parameters
StringID message; ///< message shown for query window
- bool calledback; ///< has callback been executed already (internal usage for WE_DESTROY event)
-};
-assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(query_d));
-
-
-static void QueryWndProc(Window *w, WindowEvent *e)
-{
- query_d *q = &WP(w, query_d);
-
- switch (e->event) {
- case WE_PAINT:
- CopyInDParam(0, q->params, lengthof(q->params));
- DrawWindowWidgets(w);
- CopyInDParam(0, q->params, lengthof(q->params));
-
- DrawStringMultiCenter(w->width / 2, (w->height / 2) - 10, q->message, w->width - 2);
- break;
- case WE_CLICK:
- switch (e->we.click.widget) {
- case QUERY_WIDGET_YES:
- q->calledback = true;
- if (q->proc != NULL) q->proc(w->parent, true);
- /* Fallthrough */
- case QUERY_WIDGET_NO:
- delete w;
- break;
- }
- break;
+ QueryWindow(const WindowDesc *desc, StringID caption, StringID message, Window *parent, void (*callback)(Window*, bool)) : Window(desc)
+ {
+ if (parent == NULL) parent = FindWindowById(WC_MAIN_WINDOW, 0);
+ this->parent = parent;
+ this->left = parent->left + (parent->width / 2) - (this->width / 2);
+ this->top = parent->top + (parent->height / 2) - (this->height / 2);
- case WE_KEYPRESS: // ESC closes the window, Enter confirms the action
- switch (e->we.keypress.keycode) {
- case WKC_RETURN:
- case WKC_NUM_ENTER:
- q->calledback = true;
- if (q->proc != NULL) q->proc(w->parent, true);
- /* Fallthrough */
- case WKC_ESC:
- e->we.keypress.cont = false;
- delete w;
- break;
- }
- break;
+ /* Create a backup of the variadic arguments to strings because it will be
+ * overridden pretty often. We will copy these back for drawing */
+ CopyOutDParam(this->params, 0, lengthof(this->params));
+ this->widget[QUERY_WIDGET_CAPTION].data = caption;
+ this->message = message;
+ this->proc = callback;
- case WE_DESTROY: // Call callback function (if any) on window close if not yet called
- if (!q->calledback && q->proc != NULL) {
- q->calledback = true;
- q->proc(w->parent, false);
- }
- break;
+ this->FindWindowPlacementAndResize(desc);
}
-}
+
+ ~QueryWindow()
+ {
+ if (this->proc != NULL) this->proc(this->parent, false);
+ }
+
+ virtual void OnPaint()
+ {
+ CopyInDParam(0, this->params, lengthof(this->params));
+ DrawWindowWidgets(this);
+ CopyInDParam(0, this->params, lengthof(this->params));
+
+ DrawStringMultiCenter(this->width / 2, (this->height / 2) - 10, this->message, this->width - 2);
+ }
+
+ virtual void OnClick(Point pt, int widget)
+ {
+ switch (widget) {
+ case QUERY_WIDGET_YES:
+ if (this->proc != NULL) {
+ this->proc(this->parent, true);
+ this->proc = NULL;
+ }
+ /* Fallthrough */
+ case QUERY_WIDGET_NO:
+ delete this;
+ break;
+ }
+ }
+
+ virtual bool OnKeyPress(uint16 key, uint16 keycode)
+ {
+ /* ESC closes the window, Enter confirms the action */
+ switch (keycode) {
+ case WKC_RETURN:
+ case WKC_NUM_ENTER:
+ if (this->proc != NULL) {
+ this->proc(this->parent, true);
+ this->proc = NULL;
+ }
+ /* Fallthrough */
+ case WKC_ESC:
+ delete this;
+ return false;
+ }
+ return true;
+ }
+};
static const Widget _query_widgets[] = {
@@ -1340,7 +1218,7 @@
WC_CONFIRM_POPUP_QUERY, WC_NONE,
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_UNCLICK_BUTTONS | WDF_DEF_WIDGET | WDF_MODAL,
_query_widgets,
- QueryWndProc
+ NULL
};
/** Show a modal confirmation window with standard 'yes' and 'no' buttons
@@ -1353,21 +1231,7 @@
* @param callback callback function pointer to set in the window descriptor*/
void ShowQuery(StringID caption, StringID message, Window *parent, void (*callback)(Window*, bool))
{
- Window *w = AllocateWindowDesc(&_query_desc);
- if (w == NULL) return;
-
- if (parent == NULL) parent = FindWindowById(WC_MAIN_WINDOW, 0);
- w->parent = parent;
- w->left = parent->left + (parent->width / 2) - (w->width / 2);
- w->top = parent->top + (parent->height / 2) - (w->height / 2);
-
- /* Create a backup of the variadic arguments to strings because it will be
- * overridden pretty often. We will copy these back for drawing */
- CopyOutDParam(WP(w, query_d).params, 0, lengthof(WP(w, query_d).params));
- w->widget[QUERY_WIDGET_CAPTION].data = caption;
- WP(w, query_d).message = message;
- WP(w, query_d).proc = callback;
- WP(w, query_d).calledback = false;
+ new QueryWindow(&_query_desc, caption, message, parent, callback);
}
@@ -1466,230 +1330,276 @@
}
}
-static void GenerateFileName()
-{
- /* Check if we are not a spectator who wants to generate a name..
- Let's use the name of player #0 for now. */
- const Player *p = GetPlayer(IsValidPlayer(_local_player) ? _local_player : PLAYER_FIRST);
-
- SetDParam(0, p->index);
- SetDParam(1, _date);
- GetString(_edit_str_buf, STR_4004, lastof(_edit_str_buf));
- SanitizeFilename(_edit_str_buf);
-}
-
extern void StartupEngines();
-static void SaveLoadDlgWndProc(Window *w, WindowEvent *e)
-{
- static FiosItem o_dir;
-
- switch (e->event) {
- case WE_CREATE: // Set up OPENTTD button
- w->vscroll.cap = 10;
- w->resize.step_width = 2;
- w->resize.step_height = 10;
-
- o_dir.type = FIOS_TYPE_DIRECT;
- switch (_saveload_mode) {
- case SLD_SAVE_GAME:
- case SLD_LOAD_GAME:
- FioGetDirectory(o_dir.name, lengthof(o_dir.name), SAVE_DIR);
- break;
-
- case SLD_SAVE_SCENARIO:
- case SLD_LOAD_SCENARIO:
- FioGetDirectory(o_dir.name, lengthof(o_dir.name), SCENARIO_DIR);
- break;
-
- case SLD_LOAD_HEIGHTMAP:
- FioGetDirectory(o_dir.name, lengthof(o_dir.name), HEIGHTMAP_DIR);
- break;
+struct SaveLoadWindow : public QueryStringBaseWindow {
+ FiosItem o_dir;
- default:
- ttd_strlcpy(o_dir.name, _personal_dir, lengthof(o_dir.name));
- }
- break;
-
- case WE_PAINT: {
- int pos;
- int y;
-
- SetVScrollCount(w, _fios_num);
- DrawWindowWidgets(w);
- DrawFiosTexts(w->width);
+ void GenerateFileName()
+ {
+ /* Check if we are not a spectator who wants to generate a name..
+ Let's use the name of player #0 for now. */
+ const Player *p = GetPlayer(IsValidPlayer(_local_player) ? _local_player : PLAYER_FIRST);
- if (_savegame_sort_dirty) {
- _savegame_sort_dirty = false;
- MakeSortedSaveGameList();
- }
-
- GfxFillRect(w->widget[7].left + 1, w->widget[7].top + 1, w->widget[7].right, w->widget[7].bottom, 0xD7);
- DrawSortButtonState(w, _savegame_sort_order & SORT_BY_NAME ? 2 : 3, _savegame_sort_order & SORT_DESCENDING ? SBS_DOWN : SBS_UP);
+ SetDParam(0, p->index);
+ SetDParam(1, _date);
+ GetString(this->edit_str_buf, STR_4004, lastof(this->edit_str_buf));
+ SanitizeFilename(this->edit_str_buf);
+ }
- y = w->widget[7].top + 1;
- for (pos = w->vscroll.pos; pos < _fios_num; pos++) {
- const FiosItem *item = _fios_list + pos;
+ SaveLoadWindow(const WindowDesc *desc, SaveLoadDialogMode mode) : QueryStringBaseWindow(desc)
+ {
+ static const StringID saveload_captions[] = {
+ STR_4001_LOAD_GAME,
+ STR_0298_LOAD_SCENARIO,
+ STR_4000_SAVE_GAME,
+ STR_0299_SAVE_SCENARIO,
+ STR_LOAD_HEIGHTMAP,
+ };
- DoDrawStringTruncated(item->title, 4, y, _fios_colors[item->type], w->width - 18);
- y += 10;
- if (y >= w->vscroll.cap * 10 + w->widget[7].top + 1) break;
- }
+ SetObjectToPlace(SPR_CURSOR_ZZZ, PAL_NONE, VHM_NONE, WC_MAIN_WINDOW, 0);
+ SetBit(_no_scroll, SCROLL_SAVE);
- if (_saveload_mode == SLD_SAVE_GAME || _saveload_mode == SLD_SAVE_SCENARIO) {
- DrawEditBox(w, &WP(w, querystr_d), 10);
- }
- break;
+ /* Use an array to define what will be the current file type being handled
+ * by current file mode */
+ switch (mode) {
+ case SLD_SAVE_GAME: this->GenerateFileName(); break;
+ case SLD_SAVE_SCENARIO: strcpy(this->edit_str_buf, "UNNAMED"); break;
+ default: break;
}
- case WE_CLICK:
- switch (e->we.click.widget) {
- case 2: // Sort save names by name
- _savegame_sort_order = (_savegame_sort_order == SORT_BY_NAME) ?
- SORT_BY_NAME | SORT_DESCENDING : SORT_BY_NAME;
- _savegame_sort_dirty = true;
- w->SetDirty();
- break;
-
- case 3: // Sort save names by date
- _savegame_sort_order = (_savegame_sort_order == SORT_BY_DATE) ?
- SORT_BY_DATE | SORT_DESCENDING : SORT_BY_DATE;
- _savegame_sort_dirty = true;
- w->SetDirty();
- break;
-
- case 6: // OpenTTD 'button', jumps to OpenTTD directory
- FiosBrowseTo(&o_dir);
- w->SetDirty();
- BuildFileList();
- break;
-
- case 7: { // Click the listbox
- int y = (e->we.click.pt.y - w->widget[e->we.click.widget].top - 1) / 10;
- char *name;
- const FiosItem *file;
-
- if (y < 0 || (y += w->vscroll.pos) >= w->vscroll.count) return;
-
- file = _fios_list + y;
-
- name = FiosBrowseTo(file);
- if (name != NULL) {
- if (_saveload_mode == SLD_LOAD_GAME || _saveload_mode == SLD_LOAD_SCENARIO) {
- _switch_mode = (_game_mode == GM_EDITOR) ? SM_LOAD_SCENARIO : SM_LOAD;
-
- SetFiosType(file->type);
- ttd_strlcpy(_file_to_saveload.name, name, sizeof(_file_to_saveload.name));
- ttd_strlcpy(_file_to_saveload.title, file->title, sizeof(_file_to_saveload.title));
+ assert((uint)mode < lengthof(saveload_captions));
- delete w;
- } else if (_saveload_mode == SLD_LOAD_HEIGHTMAP) {
- SetFiosType(file->type);
- ttd_strlcpy(_file_to_saveload.name, name, sizeof(_file_to_saveload.name));
- ttd_strlcpy(_file_to_saveload.title, file->title, sizeof(_file_to_saveload.title));
+ this->widget[1].data = saveload_captions[mode];
+ this->LowerWidget(7);
- delete w;
- ShowHeightmapLoad();
- } else {
- /* SLD_SAVE_GAME, SLD_SAVE_SCENARIO copy clicked name to editbox */
- ttd_strlcpy(WP(w, querystr_d).text.buf, file->title, WP(w, querystr_d).text.maxlength);
- UpdateTextBufferSize(&WP(w, querystr_d).text);
- w->InvalidateWidget(10);
- }
+ this->afilter = CS_ALPHANUMERAL;
+ InitializeTextBuffer(&this->text, this->edit_str_buf, lengthof(this->edit_str_buf), 240);
+
+ /* pause is only used in single-player, non-editor mode, non-menu mode. It
+ * will be unpaused in the WE_DESTROY event handler. */
+ if (_game_mode != GM_MENU && !_networking && _game_mode != GM_EDITOR) {
+ if (_pause_game >= 0) DoCommandP(0, 1, 0, NULL, CMD_PAUSE);
+ }
+
+ BuildFileList();
+
+ ResetObjectToPlace();
+
+ o_dir.type = FIOS_TYPE_DIRECT;
+ switch (_saveload_mode) {
+ case SLD_SAVE_GAME:
+ case SLD_LOAD_GAME:
+ FioGetDirectory(o_dir.name, lengthof(o_dir.name), SAVE_DIR);
+ break;
+
+ case SLD_SAVE_SCENARIO:
+ case SLD_LOAD_SCENARIO:
+ FioGetDirectory(o_dir.name, lengthof(o_dir.name), SCENARIO_DIR);
+ break;
+
+ case SLD_LOAD_HEIGHTMAP:
+ FioGetDirectory(o_dir.name, lengthof(o_dir.name), HEIGHTMAP_DIR);
+ break;
+
+ default:
+ ttd_strlcpy(o_dir.name, _personal_dir, lengthof(o_dir.name));
+ }
+
+ this->vscroll.cap = 10;
+ this->resize.step_width = 2;
+ this->resize.step_height = 10;
+
+ this->FindWindowPlacementAndResize(desc);
+ }
+
+ virtual ~SaveLoadWindow()
+ {
+ /* pause is only used in single-player, non-editor mode, non menu mode */
+ if (!_networking && _game_mode != GM_EDITOR && _game_mode != GM_MENU) {
+ if (_pause_game >= 0) DoCommandP(0, 0, 0, NULL, CMD_PAUSE);
+ }
+ FiosFreeSavegameList();
+ ClrBit(_no_scroll, SCROLL_SAVE);
+ }
+
+ virtual void OnPaint()
+ {
+ int pos;
+ int y;
+
+ SetVScrollCount(this, _fios_num);
+ DrawWindowWidgets(this);
+ DrawFiosTexts(this->width);
+
+ if (_savegame_sort_dirty) {
+ _savegame_sort_dirty = false;
+ MakeSortedSaveGameList();
+ }
+
+ GfxFillRect(this->widget[7].left + 1, this->widget[7].top + 1, this->widget[7].right, this->widget[7].bottom, 0xD7);
+ DrawSortButtonState(this, _savegame_sort_order & SORT_BY_NAME ? 2 : 3, _savegame_sort_order & SORT_DESCENDING ? SBS_DOWN : SBS_UP);
+
+ y = this->widget[7].top + 1;
+ for (pos = this->vscroll.pos; pos < _fios_num; pos++) {
+ const FiosItem *item = _fios_list + pos;
+
+ DoDrawStringTruncated(item->title, 4, y, _fios_colors[item->type], this->width - 18);
+ y += 10;
+ if (y >= this->vscroll.cap * 10 + this->widget[7].top + 1) break;
+ }
+
+ if (_saveload_mode == SLD_SAVE_GAME || _saveload_mode == SLD_SAVE_SCENARIO) {
+ this->DrawEditBox(10);
+ }
+ }
+
+ virtual void OnClick(Point pt, int widget)
+ {
+ switch (widget) {
+ case 2: // Sort save names by name
+ _savegame_sort_order = (_savegame_sort_order == SORT_BY_NAME) ?
+ SORT_BY_NAME | SORT_DESCENDING : SORT_BY_NAME;
+ _savegame_sort_dirty = true;
+ this->SetDirty();
+ break;
+
+ case 3: // Sort save names by date
+ _savegame_sort_order = (_savegame_sort_order == SORT_BY_DATE) ?
+ SORT_BY_DATE | SORT_DESCENDING : SORT_BY_DATE;
+ _savegame_sort_dirty = true;
+ this->SetDirty();
+ break;
+
+ case 6: // OpenTTD 'button', jumps to OpenTTD directory
+ FiosBrowseTo(&o_dir);
+ this->SetDirty();
+ BuildFileList();
+ break;
+
+ case 7: { // Click the listbox
+ int y = (pt.y - this->widget[widget].top - 1) / 10;
+ char *name;
+ const FiosItem *file;
+
+ if (y < 0 || (y += this->vscroll.pos) >= this->vscroll.count) return;
+
+ file = _fios_list + y;
+
+ name = FiosBrowseTo(file);
+ if (name != NULL) {
+ if (_saveload_mode == SLD_LOAD_GAME || _saveload_mode == SLD_LOAD_SCENARIO) {
+ _switch_mode = (_game_mode == GM_EDITOR) ? SM_LOAD_SCENARIO : SM_LOAD;
+
+ SetFiosType(file->type);
+ ttd_strlcpy(_file_to_saveload.name, name, sizeof(_file_to_saveload.name));
+ ttd_strlcpy(_file_to_saveload.title, file->title, sizeof(_file_to_saveload.title));
+
+ delete this;
+ } else if (_saveload_mode == SLD_LOAD_HEIGHTMAP) {
+ SetFiosType(file->type);
+ ttd_strlcpy(_file_to_saveload.name, name, sizeof(_file_to_saveload.name));
+ ttd_strlcpy(_file_to_saveload.title, file->title, sizeof(_file_to_saveload.title));
+
+ delete this;
+ ShowHeightmapLoad();
} else {
- /* Changed directory, need repaint. */
- w->SetDirty();
- BuildFileList();
+ /* SLD_SAVE_GAME, SLD_SAVE_SCENARIO copy clicked name to editbox */
+ ttd_strlcpy(this->text.buf, file->title, this->text.maxlength);
+ UpdateTextBufferSize(&this->text);
+ this->InvalidateWidget(10);
}
- break;
+ } else {
+ /* Changed directory, need repaint. */
+ this->SetDirty();
+ BuildFileList();
}
-
- case 10: // edit box
- ShowOnScreenKeyboard(w, &WP(w, querystr_d), e->we.click.widget, 0, 0);
- break;
-
- case 11: case 12: // Delete, Save game
- break;
- }
- break;
-
- case WE_MOUSELOOP:
- if (_saveload_mode == SLD_SAVE_GAME || _saveload_mode == SLD_SAVE_SCENARIO) {
- HandleEditBox(w, &WP(w, querystr_d), 10);
- }
- break;
-
- case WE_KEYPRESS:
- if (e->we.keypress.keycode == WKC_ESC) {
- delete w;
- return;
+ break;
}
- if ((_saveload_mode == SLD_SAVE_GAME || _saveload_mode == SLD_SAVE_SCENARIO) &&
- HandleEditBoxKey(w, &WP(w, querystr_d), 10, e) == 1) { // Press Enter
- w->HandleButtonClick(12);
- }
- break;
-
- case WE_TIMEOUT:
- /* This test protects against using widgets 11 and 12 which are only available
- * in those two saveload mode */
- if (!(_saveload_mode == SLD_SAVE_GAME || _saveload_mode == SLD_SAVE_SCENARIO)) break;
-
- if (w->IsWidgetLowered(11)) { // Delete button clicked
- if (!FiosDelete(WP(w, querystr_d).text.buf)) {
- ShowErrorMessage(INVALID_STRING_ID, STR_4008_UNABLE_TO_DELETE_FILE, 0, 0);
- } else {
- BuildFileList();
- /* Reset file name to current date on successful delete */
- if (_saveload_mode == SLD_SAVE_GAME) GenerateFileName();
- }
-
- UpdateTextBufferSize(&WP(w, querystr_d).text);
- w->SetDirty();
- } else if (w->IsWidgetLowered(12)) { // Save button clicked
- _switch_mode = SM_SAVE;
- FiosMakeSavegameName(_file_to_saveload.name, WP(w, querystr_d).text.buf, sizeof(_file_to_saveload.name));
+ case 10: // edit box
+ ShowOnScreenKeyboard(this, widget, 0, 0);
+ break;
- /* In the editor set up the vehicle engines correctly (date might have changed) */
- if (_game_mode == GM_EDITOR) StartupEngines();
- }
- break;
+ case 11: case 12: // Delete, Save game
+ break;
+ }
+ }
- case WE_DESTROY:
- /* pause is only used in single-player, non-editor mode, non menu mode */
- if (!_networking && _game_mode != GM_EDITOR && _game_mode != GM_MENU) {
- if (_pause_game >= 0) DoCommandP(0, 0, 0, NULL, CMD_PAUSE);
- }
- FiosFreeSavegameList();
- ClrBit(_no_scroll, SCROLL_SAVE);
- break;
+ virtual void OnMouseLoop()
+ {
+ if (_saveload_mode == SLD_SAVE_GAME || _saveload_mode == SLD_SAVE_SCENARIO) {
+ this->HandleEditBox(10);
+ }
+ }
- case WE_RESIZE: {
- /* Widget 2 and 3 have to go with halve speed, make it so obiwan */
- uint diff = e->we.sizing.diff.x / 2;
- w->widget[2].right += diff;
- w->widget[3].left += diff;
- w->widget[3].right += e->we.sizing.diff.x;
+ virtual bool OnKeyPress(uint16 key, uint16 keycode)
+ {
+ if (keycode == WKC_ESC) {
+ delete this;
+ return false;
+ }
- /* Same for widget 11 and 12 in save-dialog */
- if (_saveload_mode == SLD_SAVE_GAME || _saveload_mode == SLD_SAVE_SCENARIO) {
- w->widget[11].right += diff;
- w->widget[12].left += diff;
- w->widget[12].right += e->we.sizing.diff.x;
+ bool cont = true;
+ if ((_saveload_mode == SLD_SAVE_GAME || _saveload_mode == SLD_SAVE_SCENARIO) &&
+ this->HandleEditBoxKey(10, key, keycode, cont) == 1) { // Press Enter
+ this->HandleButtonClick(12);
+ }
+
+ return cont;
+ }
+
+ virtual void OnTimeout()
+ {
+ /* This test protects against using widgets 11 and 12 which are only available
+ * in those two saveload mode */
+ if (!(_saveload_mode == SLD_SAVE_GAME || _saveload_mode == SLD_SAVE_SCENARIO)) return;
+
+ if (this->IsWidgetLowered(11)) { // Delete button clicked
+ if (!FiosDelete(this->text.buf)) {
+ ShowErrorMessage(INVALID_STRING_ID, STR_4008_UNABLE_TO_DELETE_FILE, 0, 0);
+ } else {
+ BuildFileList();
+ /* Reset file name to current date on successful delete */
+ if (_saveload_mode == SLD_SAVE_GAME) GenerateFileName();
}
- w->vscroll.cap += e->we.sizing.diff.y / 10;
- } break;
+ UpdateTextBufferSize(&this->text);
+ this->SetDirty();
+ } else if (this->IsWidgetLowered(12)) { // Save button clicked
+ _switch_mode = SM_SAVE;
+ FiosMakeSavegameName(_file_to_saveload.name, this->text.buf, sizeof(_file_to_saveload.name));
+
+ /* In the editor set up the vehicle engines correctly (date might have changed) */
+ if (_game_mode == GM_EDITOR) StartupEngines();
+ }
}
-}
+
+ virtual void OnResize(Point new_size, Point delta)
+ {
+ /* Widget 2 and 3 have to go with halve speed, make it so obiwan */
+ uint diff = delta.x / 2;
+ this->widget[2].right += diff;
+ this->widget[3].left += diff;
+ this->widget[3].right += delta.x;
+
+ /* Same for widget 11 and 12 in save-dialog */
+ if (_saveload_mode == SLD_SAVE_GAME || _saveload_mode == SLD_SAVE_SCENARIO) {
+ this->widget[11].right += diff;
+ this->widget[12].left += diff;
+ this->widget[12].right += delta.x;
+ }
+
+ this->vscroll.cap += delta.y / 10;
+ }
+};
static const WindowDesc _load_dialog_desc = {
WDP_CENTER, WDP_CENTER, 257, 154, 257, 294,
WC_SAVELOAD, WC_NONE,
WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_STD_BTN | WDF_UNCLICK_BUTTONS | WDF_RESIZABLE,
_load_dialog_widgets,
- SaveLoadDlgWndProc,
+ NULL,
};
static const WindowDesc _save_dialog_desc = {
@@ -1697,7 +1607,7 @@
WC_SAVELOAD, WC_NONE,
WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_STD_BTN | WDF_UNCLICK_BUTTONS | WDF_RESIZABLE,
_save_dialog_widgets,
- SaveLoadDlgWndProc,
+ NULL,
};
/** These values are used to convert the file/operations mode into a corresponding file type.
@@ -1713,50 +1623,22 @@
void ShowSaveLoadDialog(SaveLoadDialogMode mode)
{
- static const StringID saveload_captions[] = {
- STR_4001_LOAD_GAME,
- STR_0298_LOAD_SCENARIO,
- STR_4000_SAVE_GAME,
- STR_0299_SAVE_SCENARIO,
- STR_LOAD_HEIGHTMAP,
- };
-
- const WindowDesc *sld = &_save_dialog_desc;
-
- SetObjectToPlace(SPR_CURSOR_ZZZ, PAL_NONE, VHM_NONE, WC_MAIN_WINDOW, 0);
DeleteWindowById(WC_QUERY_STRING, 0);
DeleteWindowById(WC_SAVELOAD, 0);
- _saveload_mode = mode;
- SetBit(_no_scroll, SCROLL_SAVE);
-
- /* Use an array to define what will be the current file type being handled
- * by current file mode */
- _file_to_saveload.filetype = _file_modetotype[mode];
+ const WindowDesc *sld;
switch (mode) {
- case SLD_SAVE_GAME: GenerateFileName(); break;
- case SLD_SAVE_SCENARIO: strcpy(_edit_str_buf, "UNNAMED"); break;
- default: sld = &_load_dialog_desc; break;
+ case SLD_SAVE_GAME:
+ case SLD_SAVE_SCENARIO:
+ sld = &_save_dialog_desc; break;
+ default:
+ sld = &_load_dialog_desc; break;
}
- assert((uint)mode < lengthof(saveload_captions));
-
- Window *w = AllocateWindowDesc(sld);
- w->widget[1].data = saveload_captions[mode];
- w->LowerWidget(7);
-
- WP(w, querystr_d).afilter = CS_ALPHANUMERAL;
- InitializeTextBuffer(&WP(w, querystr_d).text, _edit_str_buf, lengthof(_edit_str_buf), 240);
+ _saveload_mode = mode;
+ _file_to_saveload.filetype = _file_modetotype[mode];
- /* pause is only used in single-player, non-editor mode, non-menu mode. It
- * will be unpaused in the WE_DESTROY event handler. */
- if (_game_mode != GM_MENU && !_networking && _game_mode != GM_EDITOR) {
- if (_pause_game >= 0) DoCommandP(0, 1, 0, NULL, CMD_PAUSE);
- }
-
- BuildFileList();
-
- ResetObjectToPlace();
+ new SaveLoadWindow(sld, mode);
}
void RedrawAutosave()
--- a/src/music_gui.cpp Wed May 07 21:09:51 2008 +0000
+++ b/src/music_gui.cpp Sun May 11 20:09:34 2008 +0000
@@ -334,7 +334,7 @@
static void ShowMusicTrackSelection()
{
- AllocateWindowDescFront(&_music_track_selection_desc, 0);
+ AllocateWindowDescFront<Window>(&_music_track_selection_desc, 0);
}
static void MusicWindowWndProc(Window *w, WindowEvent *e)
@@ -463,7 +463,7 @@
}
break;
- case WE_MOUSELOOP:
+ case WE_TICK:
InvalidateWindowWidget(WC_MUSIC_WINDOW, 0, 7);
break;
}
@@ -502,5 +502,5 @@
void ShowMusicWindow()
{
- AllocateWindowDescFront(&_music_window_desc, 0);
+ AllocateWindowDescFront<Window>(&_music_window_desc, 0);
}
--- a/src/network/network_gui.cpp Wed May 07 21:09:51 2008 +0000
+++ b/src/network/network_gui.cpp Sun May 11 20:09:34 2008 +0000
@@ -29,6 +29,7 @@
#include "../player_func.h"
#include "../settings_type.h"
#include "../widgets/dropdown_func.h"
+#include "../querystring_gui.h"
#include "table/strings.h"
#include "../table/sprites.h"
@@ -36,33 +37,9 @@
#define BGC 5
#define BTC 15
-struct chatquerystr_d : public querystr_d {
- DestType dtype;
- int dest;
-};
-assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(chatquerystr_d));
-
-struct network_d {
- PlayerID company; // select company in network lobby
- byte field; // select text-field in start-server and game-listing
- byte widget_id; ///< The widget that has the pop-up input menu
- NetworkGameList *server; // selected server in lobby and game-listing
- FiosItem *map; // selected map in start-server
-};
-assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(network_d));
-
-struct network_ql_d {
- network_d n; // see above; general stuff
- querystr_d q; // text-input in start-server and game-listing
- NetworkGameList **sort_list; // list of games (sorted)
- list_d l; // accompanying list-administration
-};
-assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(network_ql_d));
-
/* Global to remember sorting after window has been closed */
static Listing _ng_sorting;
-static char _edit_str_net_buf[150];
static bool _chat_tab_completion_active;
static void ShowNetworkStartServerWindow();
@@ -106,7 +83,7 @@
* @param unselect unselect the currently selected item */
void UpdateNetworkGameWindow(bool unselect)
{
- SendWindowMessage(WC_NETWORK_WINDOW, 0, unselect, 0, 0);
+ InvalidateWindowData(WC_NETWORK_WINDOW, 0, unselect);
}
static bool _internal_sort_order; // Used for Qsort order-flipping
@@ -160,64 +137,6 @@
return _internal_sort_order ? -r : r;
}
-/** (Re)build the network game list as its amount has changed because
- * an item has been added or deleted for example
- * @param ngl list_d struct that contains all necessary information for sorting */
-static void BuildNetworkGameList(network_ql_d *nqld)
-{
- NetworkGameList *ngl_temp;
- uint n = 0;
-
- if (!(nqld->l.flags & VL_REBUILD)) return;
-
- /* Count the number of games in the list */
- for (ngl_temp = _network_game_list; ngl_temp != NULL; ngl_temp = ngl_temp->next) n++;
- if (n == 0) return;
-
- /* Create temporary array of games to use for listing */
- free(nqld->sort_list);
- nqld->sort_list = MallocT<NetworkGameList*>(n);
- nqld->l.list_length = n;
-
- for (n = 0, ngl_temp = _network_game_list; ngl_temp != NULL; ngl_temp = ngl_temp->next) {
- nqld->sort_list[n++] = ngl_temp;
- }
-
- /* Force resort */
- nqld->l.flags &= ~VL_REBUILD;
- nqld->l.flags |= VL_RESORT;
-}
-
-static void SortNetworkGameList(network_ql_d *nqld)
-{
- static NGameNameSortFunction * const ngame_sorter[] = {
- &NGameNameSorter,
- &NGameClientSorter,
- &NGameAllowedSorter
- };
-
- NetworkGameList *item;
- uint i;
-
- if (!(nqld->l.flags & VL_RESORT)) return;
- if (nqld->l.list_length == 0) return;
-
- _internal_sort_order = !!(nqld->l.flags & VL_DESC);
- qsort(nqld->sort_list, nqld->l.list_length, sizeof(nqld->sort_list[0]), ngame_sorter[nqld->l.sort_type]);
-
- /* After sorting ngl->sort_list contains the sorted items. Put these back
- * into the original list. Basically nothing has changed, we are only
- * shuffling the ->next pointers */
- _network_game_list = nqld->sort_list[0];
- for (item = _network_game_list, i = 1; i != nqld->l.list_length; i++) {
- item->next = nqld->sort_list[i];
- item = item->next;
- }
- item->next = NULL;
-
- nqld->l.flags &= ~VL_RESORT;
-}
-
/** Enum for NetworkGameWindow, referring to _network_game_window_widgets */
enum NetworkGameWindowWidgets {
NGWW_CLOSE, ///< Close 'X' button
@@ -249,364 +168,433 @@
NGWW_CANCEL, ///< 'Cancel' button
};
-/**
- * Draw a single server line.
- * @param cur_item the server to draw.
- * @param y from where to draw?
- * @param highlight does the line need to be highlighted?
- */
-static void DrawServerLine(const Window *w, const NetworkGameList *cur_item, uint y, bool highlight)
-{
- /* show highlighted item with a different colour */
- if (highlight) GfxFillRect(w->widget[NGWW_NAME].left + 1, y - 2, w->widget[NGWW_INFO].right - 1, y + 9, 10);
-
- SetDParamStr(0, cur_item->info.server_name);
- DrawStringTruncated(w->widget[NGWW_NAME].left + 5, y, STR_02BD, TC_BLACK, w->widget[NGWW_NAME].right - w->widget[NGWW_NAME].left - 5);
-
- SetDParam(0, cur_item->info.clients_on);
- SetDParam(1, cur_item->info.clients_max);
- SetDParam(2, cur_item->info.companies_on);
- SetDParam(3, cur_item->info.companies_max);
- DrawStringCentered(w->widget[NGWW_CLIENTS].left + 39, y, STR_NETWORK_GENERAL_ONLINE, TC_GOLD);
-
- /* only draw icons if the server is online */
- if (cur_item->online) {
- /* draw a lock if the server is password protected */
- if (cur_item->info.use_password) DrawSprite(SPR_LOCK, PAL_NONE, w->widget[NGWW_INFO].left + 5, y - 1);
-
- /* draw red or green icon, depending on compatibility with server */
- DrawSprite(SPR_BLOT, (cur_item->info.compatible ? PALETTE_TO_GREEN : (cur_item->info.version_compatible ? PALETTE_TO_YELLOW : PALETTE_TO_RED)), w->widget[NGWW_INFO].left + 15, y);
-
- /* draw flag according to server language */
- DrawSprite(SPR_FLAGS_BASE + cur_item->info.server_lang, PAL_NONE, w->widget[NGWW_INFO].left + 25, y);
- }
-}
-
-/**
- * Handler of actions done in the NetworkStartServer window
- *
- * @param w pointer to the Window structure
- * @param e pointer to window event
- * @note Uses network_ql_d (network_d, querystr_d and list_d) WP macro
- * @see struct _network_game_window_widgets
- * @see enum NetworkGameWindowWidgets
- */
-
-static void NetworkGameWindowWndProc(Window *w, WindowEvent *e)
-{
- network_d *nd = &WP(w, network_ql_d).n;
- list_d *ld = &WP(w, network_ql_d).l;
-
- switch (e->event) {
- case WE_CREATE: // Focus input box
- w->vscroll.cap = 11;
- w->resize.step_height = NET_PRC__SIZE_OF_ROW;
-
- nd->field = NGWW_PLAYER;
- nd->server = NULL;
-
- WP(w, network_ql_d).sort_list = NULL;
- ld->flags = VL_REBUILD | (_ng_sorting.order ? VL_DESC : VL_NONE);
- ld->sort_type = _ng_sorting.criteria;
- break;
-
- case WE_PAINT: {
- const NetworkGameList *sel = nd->server;
- const SortButtonState arrow = (ld->flags & VL_DESC) ? SBS_DOWN : SBS_UP;
+typedef GUIList<NetworkGameList*> GUIGameServerList;
- if (ld->flags & VL_REBUILD) {
- BuildNetworkGameList(&WP(w, network_ql_d));
- SetVScrollCount(w, ld->list_length);
- }
- if (ld->flags & VL_RESORT) SortNetworkGameList(&WP(w, network_ql_d));
-
- /* 'Refresh' button invisible if no server selected */
- w->SetWidgetDisabledState(NGWW_REFRESH, sel == NULL);
- /* 'Join' button disabling conditions */
- w->SetWidgetDisabledState(NGWW_JOIN, sel == NULL || // no Selected Server
- !sel->online || // Server offline
- sel->info.clients_on >= sel->info.clients_max || // Server full
- !sel->info.compatible); // Revision mismatch
-
- /* 'NewGRF Settings' button invisible if no NewGRF is used */
- w->SetWidgetHiddenState(NGWW_NEWGRF, sel == NULL ||
- !sel->online ||
- sel->info.grfconfig == NULL);
-
- SetDParam(0, 0x00);
- SetDParam(1, _lan_internet_types_dropdown[_network_lan_internet]);
- DrawWindowWidgets(w);
-
- /* Edit box to set player name */
- DrawEditBox(w, &WP(w, network_ql_d).q, NGWW_PLAYER);
-
- DrawString(w->widget[NGWW_PLAYER].left - 100, 23, STR_NETWORK_PLAYER_NAME, TC_GOLD);
-
- /* Sort based on widgets: name, clients, compatibility */
- switch (ld->sort_type) {
- case NGWW_NAME - NGWW_NAME: DrawSortButtonState(w, NGWW_NAME, arrow); break;
- case NGWW_CLIENTS - NGWW_NAME: DrawSortButtonState(w, NGWW_CLIENTS, arrow); break;
- case NGWW_INFO - NGWW_NAME: DrawSortButtonState(w, NGWW_INFO, arrow); break;
- }
+struct NetworkGameWindow : public QueryStringBaseWindow {
+ byte field; ///< selected text-field
+ NetworkGameList *server; ///< selected server
+ GUIGameServerList servers; ///< list with game servers.
- uint16 y = NET_PRC__OFFSET_TOP_WIDGET + 3;
- int32 n = 0;
- int32 pos = w->vscroll.pos;
- const NetworkGameList *cur_item = _network_game_list;
-
- while (pos > 0 && cur_item != NULL) {
- pos--;
- cur_item = cur_item->next;
- }
-
- while (cur_item != NULL) {
- DrawServerLine(w, cur_item, y, cur_item == sel);
-
- cur_item = cur_item->next;
- y += NET_PRC__SIZE_OF_ROW;
- if (++n == w->vscroll.cap) break; // max number of games in the window
- }
+ NetworkGameWindow(const WindowDesc *desc) : QueryStringBaseWindow(desc)
+ {
+ ttd_strlcpy(this->edit_str_buf, _network_player_name, lengthof(this->edit_str_buf));
+ this->afilter = CS_ALPHANUMERAL;
+ InitializeTextBuffer(&this->text, this->edit_str_buf, lengthof(this->edit_str_buf), 120);
- const NetworkGameList *last_joined = NetworkGameListAddItem(inet_addr(_network_last_host), _network_last_port);
- /* Draw the last joined server, if any */
- if (last_joined != NULL) DrawServerLine(w, last_joined, y = w->widget[NGWW_LASTJOINED].top + 3, last_joined == sel);
+ UpdateNetworkGameWindow(true);
- /* Draw the right menu */
- GfxFillRect(w->widget[NGWW_DETAILS].left + 1, 43, w->widget[NGWW_DETAILS].right - 1, 92, 157);
- if (sel == NULL) {
- DrawStringCentered(w->widget[NGWW_DETAILS].left + 115, 58, STR_NETWORK_GAME_INFO, TC_FROMSTRING);
- } else if (!sel->online) {
- SetDParamStr(0, sel->info.server_name);
- DrawStringCentered(w->widget[NGWW_DETAILS].left + 115, 68, STR_ORANGE, TC_FROMSTRING); // game name
+ this->vscroll.cap = 11;
+ this->resize.step_height = NET_PRC__SIZE_OF_ROW;
- DrawStringCentered(w->widget[NGWW_DETAILS].left + 115, 132, STR_NETWORK_SERVER_OFFLINE, TC_FROMSTRING); // server offline
- } else { // show game info
- uint16 y = 100;
- const uint16 x = w->widget[NGWW_DETAILS].left + 5;
+ this->field = NGWW_PLAYER;
+ this->server = NULL;
- DrawStringCentered(w->widget[NGWW_DETAILS].left + 115, 48, STR_NETWORK_GAME_INFO, TC_FROMSTRING);
+ this->servers.sort_list = NULL;
+ this->servers.flags = VL_REBUILD | (_ng_sorting.order ? VL_DESC : VL_NONE);
+ this->servers.sort_type = _ng_sorting.criteria;
+
+ this->FindWindowPlacementAndResize(desc);
+ }
+
+ ~NetworkGameWindow()
+ {
+ free(this->servers.sort_list);
+ }
+
+ /**
+ * (Re)build the network game list as its amount has changed because
+ * an item has been added or deleted for example
+ */
+ void BuildNetworkGameList()
+ {
+ NetworkGameList *ngl_temp;
+ uint n = 0;
+
+ if (!(this->servers.flags & VL_REBUILD)) return;
+
+ /* Count the number of games in the list */
+ for (ngl_temp = _network_game_list; ngl_temp != NULL; ngl_temp = ngl_temp->next) n++;
+ if (n == 0) return;
+
+ /* Create temporary array of games to use for listing */
+ this->servers.sort_list = ReallocT(this->servers.sort_list, n);
+ this->servers.list_length = n;
+
+ for (n = 0, ngl_temp = _network_game_list; ngl_temp != NULL; ngl_temp = ngl_temp->next) {
+ this->servers.sort_list[n++] = ngl_temp;
+ }
+
+ /* Force resort */
+ this->servers.flags &= ~VL_REBUILD;
+ this->servers.flags |= VL_RESORT;
+ }
+
+ void SortNetworkGameList()
+ {
+ static NGameNameSortFunction * const ngame_sorter[] = {
+ &NGameNameSorter,
+ &NGameClientSorter,
+ &NGameAllowedSorter
+ };
+
+ NetworkGameList *item;
+ uint i;
+
+ if (!(this->servers.flags & VL_RESORT)) return;
+ if (this->servers.list_length == 0) return;
+
+ _internal_sort_order = !!(this->servers.flags & VL_DESC);
+ qsort(this->servers.sort_list, this->servers.list_length, sizeof(this->servers.sort_list[0]), ngame_sorter[this->servers.sort_type]);
+
+ /* After sorting ngl->sort_list contains the sorted items. Put these back
+ * into the original list. Basically nothing has changed, we are only
+ * shuffling the ->next pointers */
+ _network_game_list = this->servers.sort_list[0];
+ for (item = _network_game_list, i = 1; i != this->servers.list_length; i++) {
+ item->next = this->servers.sort_list[i];
+ item = item->next;
+ }
+ item->next = NULL;
+
+ this->servers.flags &= ~VL_RESORT;
+ }
+
+ /**
+ * Draw a single server line.
+ * @param cur_item the server to draw.
+ * @param y from where to draw?
+ * @param highlight does the line need to be highlighted?
+ */
+ void DrawServerLine(const NetworkGameList *cur_item, uint y, bool highlight)
+ {
+ /* show highlighted item with a different colour */
+ if (highlight) GfxFillRect(this->widget[NGWW_NAME].left + 1, y - 2, this->widget[NGWW_INFO].right - 1, y + 9, 10);
+
+ SetDParamStr(0, cur_item->info.server_name);
+ DrawStringTruncated(this->widget[NGWW_NAME].left + 5, y, STR_02BD, TC_BLACK, this->widget[NGWW_NAME].right - this->widget[NGWW_NAME].left - 5);
+
+ SetDParam(0, cur_item->info.clients_on);
+ SetDParam(1, cur_item->info.clients_max);
+ SetDParam(2, cur_item->info.companies_on);
+ SetDParam(3, cur_item->info.companies_max);
+ DrawStringCentered(this->widget[NGWW_CLIENTS].left + 39, y, STR_NETWORK_GENERAL_ONLINE, TC_GOLD);
+
+ /* only draw icons if the server is online */
+ if (cur_item->online) {
+ /* draw a lock if the server is password protected */
+ if (cur_item->info.use_password) DrawSprite(SPR_LOCK, PAL_NONE, this->widget[NGWW_INFO].left + 5, y - 1);
+
+ /* draw red or green icon, depending on compatibility with server */
+ DrawSprite(SPR_BLOT, (cur_item->info.compatible ? PALETTE_TO_GREEN : (cur_item->info.version_compatible ? PALETTE_TO_YELLOW : PALETTE_TO_RED)), this->widget[NGWW_INFO].left + 15, y);
+
+ /* draw flag according to server language */
+ DrawSprite(SPR_FLAGS_BASE + cur_item->info.server_lang, PAL_NONE, this->widget[NGWW_INFO].left + 25, y);
+ }
+ }
+
+ virtual void OnPaint()
+ {
+ const NetworkGameList *sel = this->server;
+ const SortButtonState arrow = (this->servers.flags & VL_DESC) ? SBS_DOWN : SBS_UP;
+
+ if (this->servers.flags & VL_REBUILD) {
+ this->BuildNetworkGameList();
+ SetVScrollCount(this, this->servers.list_length);
+ }
+ if (this->servers.flags & VL_RESORT) this->SortNetworkGameList();
+
+ /* 'Refresh' button invisible if no server selected */
+ this->SetWidgetDisabledState(NGWW_REFRESH, sel == NULL);
+ /* 'Join' button disabling conditions */
+ this->SetWidgetDisabledState(NGWW_JOIN, sel == NULL || // no Selected Server
+ !sel->online || // Server offline
+ sel->info.clients_on >= sel->info.clients_max || // Server full
+ !sel->info.compatible); // Revision mismatch
+
+ /* 'NewGRF Settings' button invisible if no NewGRF is used */
+ this->SetWidgetHiddenState(NGWW_NEWGRF, sel == NULL ||
+ !sel->online ||
+ sel->info.grfconfig == NULL);
+
+ SetDParam(0, 0x00);
+ SetDParam(1, _lan_internet_types_dropdown[_network_lan_internet]);
+ DrawWindowWidgets(this);
+
+ /* Edit box to set player name */
+ this->DrawEditBox(NGWW_PLAYER);
+
+ DrawString(this->widget[NGWW_PLAYER].left - 100, 23, STR_NETWORK_PLAYER_NAME, TC_GOLD);
+
+ /* Sort based on widgets: name, clients, compatibility */
+ switch (this->servers.sort_type) {
+ case NGWW_NAME - NGWW_NAME: DrawSortButtonState(this, NGWW_NAME, arrow); break;
+ case NGWW_CLIENTS - NGWW_NAME: DrawSortButtonState(this, NGWW_CLIENTS, arrow); break;
+ case NGWW_INFO - NGWW_NAME: DrawSortButtonState(this, NGWW_INFO, arrow); break;
+ }
+
+ uint16 y = NET_PRC__OFFSET_TOP_WIDGET + 3;
+ int32 n = 0;
+ int32 pos = this->vscroll.pos;
+ const NetworkGameList *cur_item = _network_game_list;
+
+ while (pos > 0 && cur_item != NULL) {
+ pos--;
+ cur_item = cur_item->next;
+ }
+
+ while (cur_item != NULL) {
+ this->DrawServerLine(cur_item, y, cur_item == sel);
+
+ cur_item = cur_item->next;
+ y += NET_PRC__SIZE_OF_ROW;
+ if (++n == this->vscroll.cap) break; // max number of games in the window
+ }
+
+ const NetworkGameList *last_joined = NetworkGameListAddItem(inet_addr(_network_last_host), _network_last_port);
+ /* Draw the last joined server, if any */
+ if (last_joined != NULL) this->DrawServerLine(last_joined, y = this->widget[NGWW_LASTJOINED].top + 3, last_joined == sel);
+
+ /* Draw the right menu */
+ GfxFillRect(this->widget[NGWW_DETAILS].left + 1, 43, this->widget[NGWW_DETAILS].right - 1, 92, 157);
+ if (sel == NULL) {
+ DrawStringCentered(this->widget[NGWW_DETAILS].left + 115, 58, STR_NETWORK_GAME_INFO, TC_FROMSTRING);
+ } else if (!sel->online) {
+ SetDParamStr(0, sel->info.server_name);
+ DrawStringCentered(this->widget[NGWW_DETAILS].left + 115, 68, STR_ORANGE, TC_FROMSTRING); // game name
+
+ DrawStringCentered(this->widget[NGWW_DETAILS].left + 115, 132, STR_NETWORK_SERVER_OFFLINE, TC_FROMSTRING); // server offline
+ } else { // show game info
+ uint16 y = 100;
+ const uint16 x = this->widget[NGWW_DETAILS].left + 5;
+
+ DrawStringCentered(this->widget[NGWW_DETAILS].left + 115, 48, STR_NETWORK_GAME_INFO, TC_FROMSTRING);
- SetDParamStr(0, sel->info.server_name);
- DrawStringCenteredTruncated(w->widget[NGWW_DETAILS].left, w->widget[NGWW_DETAILS].right, 62, STR_ORANGE, TC_BLACK); // game name
-
- SetDParamStr(0, sel->info.map_name);
- DrawStringCenteredTruncated(w->widget[NGWW_DETAILS].left, w->widget[NGWW_DETAILS].right, 74, STR_02BD, TC_BLACK); // map name
-
- SetDParam(0, sel->info.clients_on);
- SetDParam(1, sel->info.clients_max);
- SetDParam(2, sel->info.companies_on);
- SetDParam(3, sel->info.companies_max);
- DrawString(x, y, STR_NETWORK_CLIENTS, TC_GOLD);
- y += 10;
-
- SetDParam(0, STR_NETWORK_LANG_ANY + sel->info.server_lang);
- DrawString(x, y, STR_NETWORK_LANGUAGE, TC_GOLD); // server language
- y += 10;
-
- SetDParam(0, STR_TEMPERATE_LANDSCAPE + sel->info.map_set);
- DrawString(x, y, STR_NETWORK_TILESET, TC_GOLD); // tileset
- y += 10;
-
- SetDParam(0, sel->info.map_width);
- SetDParam(1, sel->info.map_height);
- DrawString(x, y, STR_NETWORK_MAP_SIZE, TC_GOLD); // map size
- y += 10;
-
- SetDParamStr(0, sel->info.server_revision);
- DrawString(x, y, STR_NETWORK_SERVER_VERSION, TC_GOLD); // server version
- y += 10;
-
- SetDParamStr(0, sel->info.hostname);
- SetDParam(1, sel->port);
- DrawString(x, y, STR_NETWORK_SERVER_ADDRESS, TC_GOLD); // server address
- y += 10;
-
- SetDParam(0, sel->info.start_date);
- DrawString(x, y, STR_NETWORK_START_DATE, TC_GOLD); // start date
- y += 10;
-
- SetDParam(0, sel->info.game_date);
- DrawString(x, y, STR_NETWORK_CURRENT_DATE, TC_GOLD); // current date
- y += 10;
-
- y += 2;
-
- if (!sel->info.compatible) {
- DrawStringCentered(w->widget[NGWW_DETAILS].left + 115, y, sel->info.version_compatible ? STR_NETWORK_GRF_MISMATCH : STR_NETWORK_VERSION_MISMATCH, TC_FROMSTRING); // server mismatch
- } else if (sel->info.clients_on == sel->info.clients_max) {
- /* Show: server full, when clients_on == clients_max */
- DrawStringCentered(w->widget[NGWW_DETAILS].left + 115, y, STR_NETWORK_SERVER_FULL, TC_FROMSTRING); // server full
- } else if (sel->info.use_password) {
- DrawStringCentered(w->widget[NGWW_DETAILS].left + 115, y, STR_NETWORK_PASSWORD, TC_FROMSTRING); // password warning
- }
-
- y += 10;
- }
- } break;
-
- case WE_CLICK:
- nd->field = e->we.click.widget;
- switch (e->we.click.widget) {
- case NGWW_PLAYER:
- ShowOnScreenKeyboard(w, &WP(w, network_ql_d).q, NGWW_PLAYER, 0, 0);
- break;
-
- case NGWW_CANCEL: // Cancel button
- DeleteWindowById(WC_NETWORK_WINDOW, 0);
- break;
-
- case NGWW_CONN_BTN: // 'Connection' droplist
- ShowDropDownMenu(w, _lan_internet_types_dropdown, _network_lan_internet, NGWW_CONN_BTN, 0, 0); // do it for widget NSSW_CONN_BTN
- break;
+ SetDParamStr(0, sel->info.server_name);
+ DrawStringCenteredTruncated(this->widget[NGWW_DETAILS].left, this->widget[NGWW_DETAILS].right, 62, STR_ORANGE, TC_BLACK); // game name
- case NGWW_NAME: // Sort by name
- case NGWW_CLIENTS: // Sort by connected clients
- case NGWW_INFO: // Connectivity (green dot)
- if (ld->sort_type == e->we.click.widget - NGWW_NAME) ld->flags ^= VL_DESC;
- ld->flags |= VL_RESORT;
- ld->sort_type = e->we.click.widget - NGWW_NAME;
-
- _ng_sorting.order = !!(ld->flags & VL_DESC);
- _ng_sorting.criteria = ld->sort_type;
- SetWindowDirty(w);
- break;
-
- case NGWW_MATRIX: { // Matrix to show networkgames
- NetworkGameList *cur_item;
- uint32 id_v = (e->we.click.pt.y - NET_PRC__OFFSET_TOP_WIDGET) / NET_PRC__SIZE_OF_ROW;
-
- if (id_v >= w->vscroll.cap) return; // click out of bounds
- id_v += w->vscroll.pos;
-
- cur_item = _network_game_list;
- for (; id_v > 0 && cur_item != NULL; id_v--) cur_item = cur_item->next;
-
- nd->server = cur_item;
- SetWindowDirty(w);
- } break;
-
- case NGWW_LASTJOINED: {
- NetworkGameList *last_joined = NetworkGameListAddItem(inet_addr(_network_last_host), _network_last_port);
- if (last_joined != NULL) {
- nd->server = last_joined;
- SetWindowDirty(w);
- }
- } break;
+ SetDParamStr(0, sel->info.map_name);
+ DrawStringCenteredTruncated(this->widget[NGWW_DETAILS].left, this->widget[NGWW_DETAILS].right, 74, STR_02BD, TC_BLACK); // map name
- case NGWW_FIND: // Find server automatically
- switch (_network_lan_internet) {
- case 0: NetworkUDPSearchGame(); break;
- case 1: NetworkUDPQueryMasterServer(); break;
- }
- break;
-
- case NGWW_ADD: // Add a server
- ShowQueryString(
- BindCString(_network_default_ip),
- STR_NETWORK_ENTER_IP,
- 31 | 0x1000, // maximum number of characters OR
- 250, // characters up to this width pixels, whichever is satisfied first
- w, CS_ALPHANUMERAL);
- break;
-
- case NGWW_START: // Start server
- ShowNetworkStartServerWindow();
- break;
+ SetDParam(0, sel->info.clients_on);
+ SetDParam(1, sel->info.clients_max);
+ SetDParam(2, sel->info.companies_on);
+ SetDParam(3, sel->info.companies_max);
+ DrawString(x, y, STR_NETWORK_CLIENTS, TC_GOLD);
+ y += 10;
- case NGWW_JOIN: // Join Game
- if (nd->server != NULL) {
- snprintf(_network_last_host, sizeof(_network_last_host), "%s", inet_ntoa(*(struct in_addr *)&nd->server->ip));
- _network_last_port = nd->server->port;
- ShowNetworkLobbyWindow(nd->server);
- }
- break;
-
- case NGWW_REFRESH: // Refresh
- if (nd->server != NULL) NetworkUDPQueryServer(nd->server->info.hostname, nd->server->port);
- break;
+ SetDParam(0, STR_NETWORK_LANG_ANY + sel->info.server_lang);
+ DrawString(x, y, STR_NETWORK_LANGUAGE, TC_GOLD); // server language
+ y += 10;
- case NGWW_NEWGRF: // NewGRF Settings
- if (nd->server != NULL) ShowNewGRFSettings(false, false, false, &nd->server->info.grfconfig);
- break;
- }
- break;
+ SetDParam(0, STR_TEMPERATE_LANDSCAPE + sel->info.map_set);
+ DrawString(x, y, STR_NETWORK_TILESET, TC_GOLD); // tileset
+ y += 10;
- case WE_DROPDOWN_SELECT: // we have selected a dropdown item in the list
- switch (e->we.dropdown.button) {
- case NGWW_CONN_BTN:
- _network_lan_internet = e->we.dropdown.index;
- break;
+ SetDParam(0, sel->info.map_width);
+ SetDParam(1, sel->info.map_height);
+ DrawString(x, y, STR_NETWORK_MAP_SIZE, TC_GOLD); // map size
+ y += 10;
- default:
- NOT_REACHED();
+ SetDParamStr(0, sel->info.server_revision);
+ DrawString(x, y, STR_NETWORK_SERVER_VERSION, TC_GOLD); // server version
+ y += 10;
+
+ SetDParamStr(0, sel->info.hostname);
+ SetDParam(1, sel->port);
+ DrawString(x, y, STR_NETWORK_SERVER_ADDRESS, TC_GOLD); // server address
+ y += 10;
+
+ SetDParam(0, sel->info.start_date);
+ DrawString(x, y, STR_NETWORK_START_DATE, TC_GOLD); // start date
+ y += 10;
+
+ SetDParam(0, sel->info.game_date);
+ DrawString(x, y, STR_NETWORK_CURRENT_DATE, TC_GOLD); // current date
+ y += 10;
+
+ y += 2;
+
+ if (!sel->info.compatible) {
+ DrawStringCentered(this->widget[NGWW_DETAILS].left + 115, y, sel->info.version_compatible ? STR_NETWORK_GRF_MISMATCH : STR_NETWORK_VERSION_MISMATCH, TC_FROMSTRING); // server mismatch
+ } else if (sel->info.clients_on == sel->info.clients_max) {
+ /* Show: server full, when clients_on == clients_max */
+ DrawStringCentered(this->widget[NGWW_DETAILS].left + 115, y, STR_NETWORK_SERVER_FULL, TC_FROMSTRING); // server full
+ } else if (sel->info.use_password) {
+ DrawStringCentered(this->widget[NGWW_DETAILS].left + 115, y, STR_NETWORK_PASSWORD, TC_FROMSTRING); // password warning
}
- SetWindowDirty(w);
- break;
-
- case WE_MOUSELOOP:
- if (nd->field == NGWW_PLAYER) HandleEditBox(w, &WP(w, network_ql_d).q, NGWW_PLAYER);
- break;
+ y += 10;
+ }
+ }
- case WE_MESSAGE:
- if (e->we.message.msg != 0) nd->server = NULL;
- ld->flags |= VL_REBUILD;
- SetWindowDirty(w);
- break;
+ virtual void OnClick(Point pt, int widget)
+ {
+ this->field = widget;
+ switch (widget) {
+ case NGWW_PLAYER:
+ ShowOnScreenKeyboard(this, NGWW_PLAYER, 0, 0);
+ break;
- case WE_KEYPRESS:
- if (nd->field != NGWW_PLAYER) {
- if (nd->server != NULL) {
- if (e->we.keypress.keycode == WKC_DELETE) { // Press 'delete' to remove servers
- NetworkGameListRemoveItem(nd->server);
- NetworkRebuildHostList();
- nd->server = NULL;
- }
+ case NGWW_CANCEL: // Cancel button
+ DeleteWindowById(WC_NETWORK_WINDOW, 0);
+ break;
+
+ case NGWW_CONN_BTN: // 'Connection' droplist
+ ShowDropDownMenu(this, _lan_internet_types_dropdown, _network_lan_internet, NGWW_CONN_BTN, 0, 0); // do it for widget NSSW_CONN_BTN
+ break;
+
+ case NGWW_NAME: // Sort by name
+ case NGWW_CLIENTS: // Sort by connected clients
+ case NGWW_INFO: // Connectivity (green dot)
+ if (this->servers.sort_type == widget - NGWW_NAME) this->servers.flags ^= VL_DESC;
+ this->servers.flags |= VL_RESORT;
+ this->servers.sort_type = widget - NGWW_NAME;
+
+ _ng_sorting.order = !!(this->servers.flags & VL_DESC);
+ _ng_sorting.criteria = this->servers.sort_type;
+ this->SetDirty();
+ break;
+
+ case NGWW_MATRIX: { // Matrix to show networkgames
+ NetworkGameList *cur_item;
+ uint32 id_v = (pt.y - NET_PRC__OFFSET_TOP_WIDGET) / NET_PRC__SIZE_OF_ROW;
+
+ if (id_v >= this->vscroll.cap) return; // click out of bounds
+ id_v += this->vscroll.pos;
+
+ cur_item = _network_game_list;
+ for (; id_v > 0 && cur_item != NULL; id_v--) cur_item = cur_item->next;
+
+ this->server = cur_item;
+ this->SetDirty();
+ } break;
+
+ case NGWW_LASTJOINED: {
+ NetworkGameList *last_joined = NetworkGameListAddItem(inet_addr(_network_last_host), _network_last_port);
+ if (last_joined != NULL) {
+ this->server = last_joined;
+ this->SetDirty();
+ }
+ } break;
+
+ case NGWW_FIND: // Find server automatically
+ switch (_network_lan_internet) {
+ case 0: NetworkUDPSearchGame(); break;
+ case 1: NetworkUDPQueryMasterServer(); break;
}
break;
- }
-
- if (HandleEditBoxKey(w, &WP(w, network_ql_d).q, NGWW_PLAYER, e) == 1) break; // enter pressed
-
- /* The name is only allowed when it starts with a letter! */
- if (_edit_str_net_buf[0] != '\0' && _edit_str_net_buf[0] != ' ') {
- ttd_strlcpy(_network_player_name, _edit_str_net_buf, lengthof(_network_player_name));
- } else {
- ttd_strlcpy(_network_player_name, "Player", lengthof(_network_player_name));
- }
-
- break;
-
- case WE_ON_EDIT_TEXT:
- NetworkAddServer(e->we.edittext.str);
- NetworkRebuildHostList();
- break;
-
- case WE_RESIZE: {
- w->vscroll.cap += e->we.sizing.diff.y / (int)w->resize.step_height;
- w->widget[NGWW_MATRIX].data = (w->vscroll.cap << 8) + 1;
-
- SetVScrollCount(w, ld->list_length);
-
- int widget_width = w->widget[NGWW_FIND].right - w->widget[NGWW_FIND].left;
- int space = (w->width - 4 * widget_width - 25) / 3;
+ case NGWW_ADD: // Add a server
+ ShowQueryString(
+ BindCString(_network_default_ip),
+ STR_NETWORK_ENTER_IP,
+ 31 | 0x1000, // maximum number of characters OR
+ 250, // characters up to this width pixels, whichever is satisfied first
+ this, CS_ALPHANUMERAL);
+ break;
- int offset = 10;
- for (uint i = 0; i < 4; i++) {
- w->widget[NGWW_FIND + i].left = offset;
- offset += widget_width;
- w->widget[NGWW_FIND + i].right = offset;
- offset += space;
+ case NGWW_START: // Start server
+ ShowNetworkStartServerWindow();
+ break;
+
+ case NGWW_JOIN: // Join Game
+ if (this->server != NULL) {
+ snprintf(_network_last_host, sizeof(_network_last_host), "%s", inet_ntoa(*(struct in_addr *)&this->server->ip));
+ _network_last_port = this->server->port;
+ ShowNetworkLobbyWindow(this->server);
+ }
+ break;
+
+ case NGWW_REFRESH: // Refresh
+ if (this->server != NULL) NetworkUDPQueryServer(this->server->info.hostname, this->server->port);
+ break;
+
+ case NGWW_NEWGRF: // NewGRF Settings
+ if (this->server != NULL) ShowNewGRFSettings(false, false, false, &this->server->info.grfconfig);
+ break;
+ }
+ }
+
+ virtual void OnDropdownSelect(int widget, int index)
+ {
+ switch (widget) {
+ case NGWW_CONN_BTN:
+ _network_lan_internet = index;
+ break;
+
+ default:
+ NOT_REACHED();
+ }
+
+ this->SetDirty();
+ }
+
+ virtual void OnMouseLoop()
+ {
+ if (this->field == NGWW_PLAYER) this->HandleEditBox(NGWW_PLAYER);
+ }
+
+ virtual void OnInvalidateData(int data)
+ {
+ if (data != 0) this->server = NULL;
+ this->servers.flags |= VL_REBUILD;
+ this->SetDirty();
+ }
+
+ virtual bool OnKeyPress(uint16 key, uint16 keycode)
+ {
+ bool cont = true;
+ if (this->field != NGWW_PLAYER) {
+ if (this->server != NULL) {
+ if (keycode == WKC_DELETE) { // Press 'delete' to remove servers
+ NetworkGameListRemoveItem(this->server);
+ NetworkRebuildHostList();
+ this->server = NULL;
+ }
}
- } break;
+ return cont;
+ }
- case WE_DESTROY: // Nicely clean up the sort-list
- free(WP(w, network_ql_d).sort_list);
- break;
+ if (this->HandleEditBoxKey(NGWW_PLAYER, keycode, key, cont) == 1) return cont; // enter pressed
+
+ /* The name is only allowed when it starts with a letter! */
+ if (StrEmpty(this->edit_str_buf) && this->edit_str_buf[0] != ' ') {
+ ttd_strlcpy(_network_player_name, this->edit_str_buf, lengthof(_network_player_name));
+ } else {
+ ttd_strlcpy(_network_player_name, "Player", lengthof(_network_player_name));
+ }
+ return cont;
}
-}
+
+ virtual void OnQueryTextFinished(char *str)
+ {
+ if (!StrEmpty(str)) {
+ NetworkAddServer(str);
+ NetworkRebuildHostList();
+ }
+ }
+
+ virtual void OnResize(Point new_size, Point delta)
+ {
+ this->vscroll.cap += delta.y / (int)this->resize.step_height;
+
+ this->widget[NGWW_MATRIX].data = (this->vscroll.cap << 8) + 1;
+
+ SetVScrollCount(this, this->servers.list_length);
+
+ int widget_width = this->widget[NGWW_FIND].right - this->widget[NGWW_FIND].left;
+ int space = (this->width - 4 * widget_width - 25) / 3;
+
+ int offset = 10;
+ for (uint i = 0; i < 4; i++) {
+ this->widget[NGWW_FIND + i].left = offset;
+ offset += widget_width;
+ this->widget[NGWW_FIND + i].right = offset;
+ offset += space;
+ }
+ }
+};
static const Widget _network_game_window_widgets[] = {
/* TOP */
@@ -653,7 +641,7 @@
WC_NETWORK_WINDOW, WC_NONE,
WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_STD_BTN | WDF_UNCLICK_BUTTONS | WDF_RESIZABLE,
_network_game_window_widgets,
- NetworkGameWindowWndProc,
+ NULL,
};
void ShowNetworkGameWindow()
@@ -675,16 +663,7 @@
_ng_sorting.order = 0; // sort ascending by default
}
- Window *w = AllocateWindowDesc(&_network_game_window_desc);
- if (w != NULL) {
- querystr_d *querystr = &WP(w, network_ql_d).q;
-
- ttd_strlcpy(_edit_str_net_buf, _network_player_name, lengthof(_edit_str_net_buf));
- querystr->afilter = CS_ALPHANUMERAL;
- InitializeTextBuffer(&querystr->text, _edit_str_net_buf, lengthof(_edit_str_net_buf), 120);
-
- UpdateNetworkGameWindow(true);
- }
+ new NetworkGameWindow(&_network_game_window_desc);
}
enum {
@@ -714,225 +693,237 @@
NSSW_CANCEL = 27, ///< 'Cancel' button
};
-/**
- * Handler of actions done in the NetworkStartServer window
- *
- * @param w pointer to the Window structure
- * @param e pointer to window event
- * @note Uses network_ql_d (network_d, querystr_d and list_d) WP macro
- * @see struct _network_start_server_window_widgets
- * @see enum NetworkStartServerWidgets
- */
-static void NetworkStartServerWindowWndProc(Window *w, WindowEvent *e)
-{
- network_d *nd = &WP(w, network_ql_d).n;
-
- switch (e->event) {
- case WE_CREATE: // focus input box
- nd->field = NSSW_GAMENAME;
- _network_game_info.use_password = (_network_server_password[0] != '\0');
- break;
-
- case WE_PAINT: {
- int y = NSSWND_START, pos;
- const FiosItem *item;
-
- /* draw basic widgets */
- SetDParam(1, _connection_types_dropdown[_network_advertise]);
- SetDParam(2, _network_game_info.clients_max);
- SetDParam(3, _network_game_info.companies_max);
- SetDParam(4, _network_game_info.spectators_max);
- SetDParam(5, STR_NETWORK_LANG_ANY + _network_game_info.server_lang);
- DrawWindowWidgets(w);
-
- /* editbox to set game name */
- DrawEditBox(w, &WP(w, network_ql_d).q, NSSW_GAMENAME);
-
- /* if password is set, draw red '*' next to 'Set password' button */
- if (_network_game_info.use_password) DoDrawString("*", 408, 23, TC_RED);
-
- /* draw list of maps */
- GfxFillRect(11, 63, 258, 215, 0xD7); // black background of maps list
-
- pos = w->vscroll.pos;
- while (pos < _fios_num + 1) {
- item = _fios_list + pos - 1;
- if (item == nd->map || (pos == 0 && nd->map == NULL))
- GfxFillRect(11, y - 1, 258, y + 10, 155); // show highlighted item with a different colour
-
- if (pos == 0) {
- DrawString(14, y, STR_4010_GENERATE_RANDOM_NEW_GAME, TC_DARK_GREEN);
- } else {
- DoDrawString(item->title, 14, y, _fios_colors[item->type] );
- }
- pos++;
- y += NSSWND_ROWSIZE;
-
- if (y >= w->vscroll.cap * NSSWND_ROWSIZE + NSSWND_START) break;
- }
- } break;
-
- case WE_CLICK:
- if (e->we.click.widget != NSSW_CONNTYPE_BTN && e->we.click.widget != NSSW_LANGUAGE_BTN) HideDropDownMenu(w);
- nd->field = e->we.click.widget;
- switch (e->we.click.widget) {
- case NSSW_CLOSE: // Close 'X'
- case NSSW_CANCEL: // Cancel button
- ShowNetworkGameWindow();
- break;
-
- case NSSW_GAMENAME:
- ShowOnScreenKeyboard(w, &WP(w, network_ql_d).q, NSSW_GAMENAME, 0, 0);
- break;
-
- case NSSW_SETPWD: // Set password button
- nd->widget_id = NSSW_SETPWD;
- ShowQueryString(BindCString(_network_server_password), STR_NETWORK_SET_PASSWORD, 20, 250, w, CS_ALPHANUMERAL);
- break;
-
- case NSSW_SELMAP: { // Select map
- int y = (e->we.click.pt.y - NSSWND_START) / NSSWND_ROWSIZE;
-
- y += w->vscroll.pos;
- if (y >= w->vscroll.count) return;
-
- nd->map = (y == 0) ? NULL : _fios_list + y - 1;
- SetWindowDirty(w);
- } break;
-
- case NSSW_CONNTYPE_BTN: // Connection type
- ShowDropDownMenu(w, _connection_types_dropdown, _network_advertise, NSSW_CONNTYPE_BTN, 0, 0); // do it for widget NSSW_CONNTYPE_BTN
- break;
+struct NetworkStartServerWindow : public QueryStringBaseWindow {
+ byte field; ///< Selected text-field
+ FiosItem *map; ///< Selected map
+ byte widget_id; ///< The widget that has the pop-up input menu
- case NSSW_CLIENTS_BTND: case NSSW_CLIENTS_BTNU: // Click on up/down button for number of clients
- case NSSW_COMPANIES_BTND: case NSSW_COMPANIES_BTNU: // Click on up/down button for number of companies
- case NSSW_SPECTATORS_BTND: case NSSW_SPECTATORS_BTNU: // Click on up/down button for number of spectators
- /* Don't allow too fast scrolling */
- if ((w->flags4 & WF_TIMEOUT_MASK) <= 2 << WF_TIMEOUT_SHL) {
- w->HandleButtonClick(e->we.click.widget);
- SetWindowDirty(w);
- switch (e->we.click.widget) {
- default: NOT_REACHED();
- case NSSW_CLIENTS_BTND: case NSSW_CLIENTS_BTNU:
- _network_game_info.clients_max = Clamp(_network_game_info.clients_max + e->we.click.widget - NSSW_CLIENTS_TXT, 2, MAX_CLIENTS);
- break;
- case NSSW_COMPANIES_BTND: case NSSW_COMPANIES_BTNU:
- _network_game_info.companies_max = Clamp(_network_game_info.companies_max + e->we.click.widget - NSSW_COMPANIES_TXT, 1, MAX_PLAYERS);
- break;
- case NSSW_SPECTATORS_BTND: case NSSW_SPECTATORS_BTNU:
- _network_game_info.spectators_max = Clamp(_network_game_info.spectators_max + e->we.click.widget - NSSW_SPECTATORS_TXT, 0, MAX_CLIENTS);
- break;
- }
- }
- _left_button_clicked = false;
- break;
-
- case NSSW_CLIENTS_TXT: // Click on number of players
- nd->widget_id = NSSW_CLIENTS_TXT;
- SetDParam(0, _network_game_info.clients_max);
- ShowQueryString(STR_CONFIG_PATCHES_INT32, STR_NETWORK_NUMBER_OF_CLIENTS, 3, 50, w, CS_NUMERAL);
- break;
-
- case NSSW_COMPANIES_TXT: // Click on number of companies
- nd->widget_id = NSSW_COMPANIES_TXT;
- SetDParam(0, _network_game_info.companies_max);
- ShowQueryString(STR_CONFIG_PATCHES_INT32, STR_NETWORK_NUMBER_OF_COMPANIES, 3, 50, w, CS_NUMERAL);
- break;
-
- case NSSW_SPECTATORS_TXT: // Click on number of spectators
- nd->widget_id = NSSW_SPECTATORS_TXT;
- SetDParam(0, _network_game_info.spectators_max);
- ShowQueryString(STR_CONFIG_PATCHES_INT32, STR_NETWORK_NUMBER_OF_SPECTATORS, 3, 50, w, CS_NUMERAL);
- break;
-
- case NSSW_LANGUAGE_BTN: { // Language
- uint sel = 0;
- for (uint i = 0; i < lengthof(_language_dropdown) - 1; i++) {
- if (_language_dropdown[i] == STR_NETWORK_LANG_ANY + _network_game_info.server_lang) {
- sel = i;
- break;
- }
- }
- ShowDropDownMenu(w, _language_dropdown, sel, NSSW_LANGUAGE_BTN, 0, 0);
- } break;
-
- case NSSW_START: // Start game
- _is_network_server = true;
+ NetworkStartServerWindow(const WindowDesc *desc) : QueryStringBaseWindow(desc)
+ {
+ ttd_strlcpy(this->edit_str_buf, _network_server_name, lengthof(this->edit_str_buf));
- if (nd->map == NULL) { // start random new game
- ShowGenerateLandscape();
- } else { // load a scenario
- char *name = FiosBrowseTo(nd->map);
- if (name != NULL) {
- SetFiosType(nd->map->type);
- _file_to_saveload.filetype = FT_SCENARIO;
- ttd_strlcpy(_file_to_saveload.name, name, sizeof(_file_to_saveload.name));
- ttd_strlcpy(_file_to_saveload.title, nd->map->title, sizeof(_file_to_saveload.title));
-
- delete w;
- SwitchMode(SM_START_SCENARIO);
- }
- }
- break;
+ _saveload_mode = SLD_NEW_GAME;
+ BuildFileList();
+ this->vscroll.cap = 12;
+ this->vscroll.count = _fios_num + 1;
- case NSSW_LOAD: // Load game
- _is_network_server = true;
- /* XXX - WC_NETWORK_WINDOW (this window) should stay, but if it stays, it gets
- * copied all the elements of 'load game' and upon closing that, it segfaults */
- delete w;
- ShowSaveLoadDialog(SLD_LOAD_GAME);
- break;
- }
- break;
+ this->afilter = CS_ALPHANUMERAL;
+ InitializeTextBuffer(&this->text, this->edit_str_buf, lengthof(this->edit_str_buf), 160);
- case WE_DROPDOWN_SELECT: // we have selected a dropdown item in the list
- switch (e->we.dropdown.button) {
- case NSSW_CONNTYPE_BTN:
- _network_advertise = (e->we.dropdown.index != 0);
- break;
- case NSSW_LANGUAGE_BTN:
- _network_game_info.server_lang = _language_dropdown[e->we.dropdown.index] - STR_NETWORK_LANG_ANY;
- break;
- default:
- NOT_REACHED();
+ this->field = NSSW_GAMENAME;
+ _network_game_info.use_password = !StrEmpty(_network_server_password);
+
+ this->FindWindowPlacementAndResize(desc);
+ }
+
+ virtual void OnPaint()
+ {
+ int y = NSSWND_START, pos;
+ const FiosItem *item;
+
+ /* draw basic widgets */
+ SetDParam(1, _connection_types_dropdown[_network_advertise]);
+ SetDParam(2, _network_game_info.clients_max);
+ SetDParam(3, _network_game_info.companies_max);
+ SetDParam(4, _network_game_info.spectators_max);
+ SetDParam(5, STR_NETWORK_LANG_ANY + _network_game_info.server_lang);
+ DrawWindowWidgets(this);
+
+ /* editbox to set game name */
+ this->DrawEditBox(NSSW_GAMENAME);
+
+ /* if password is set, draw red '*' next to 'Set password' button */
+ if (_network_game_info.use_password) DoDrawString("*", 408, 23, TC_RED);
+
+ /* draw list of maps */
+ GfxFillRect(11, 63, 258, 215, 0xD7); // black background of maps list
+
+ pos = this->vscroll.pos;
+ while (pos < _fios_num + 1) {
+ item = _fios_list + pos - 1;
+ if (item == this->map || (pos == 0 && this->map == NULL))
+ GfxFillRect(11, y - 1, 258, y + 10, 155); // show highlighted item with a different colour
+
+ if (pos == 0) {
+ DrawString(14, y, STR_4010_GENERATE_RANDOM_NEW_GAME, TC_DARK_GREEN);
+ } else {
+ DoDrawString(item->title, 14, y, _fios_colors[item->type] );
}
-
- SetWindowDirty(w);
- break;
-
- case WE_MOUSELOOP:
- if (nd->field == NSSW_GAMENAME) HandleEditBox(w, &WP(w, network_ql_d).q, NSSW_GAMENAME);
- break;
-
- case WE_KEYPRESS:
- if (nd->field == NSSW_GAMENAME) {
- if (HandleEditBoxKey(w, &WP(w, network_ql_d).q, NSSW_GAMENAME, e) == 1) break; // enter pressed
-
- ttd_strlcpy(_network_server_name, WP(w, network_ql_d).q.text.buf, sizeof(_network_server_name));
- }
- break;
+ pos++;
+ y += NSSWND_ROWSIZE;
- case WE_ON_EDIT_TEXT:
- if (e->we.edittext.str == NULL) break;
+ if (y >= this->vscroll.cap * NSSWND_ROWSIZE + NSSWND_START) break;
+ }
+ }
- if (nd->widget_id == NSSW_SETPWD) {
- ttd_strlcpy(_network_server_password, e->we.edittext.str, lengthof(_network_server_password));
- _network_game_info.use_password = (_network_server_password[0] != '\0');
- } else {
- int32 value = atoi(e->we.edittext.str);
- w->InvalidateWidget(nd->widget_id);
- switch (nd->widget_id) {
- default: NOT_REACHED();
- case NSSW_CLIENTS_TXT: _network_game_info.clients_max = Clamp(value, 2, MAX_CLIENTS); break;
- case NSSW_COMPANIES_TXT: _network_game_info.companies_max = Clamp(value, 1, MAX_PLAYERS); break;
- case NSSW_SPECTATORS_TXT: _network_game_info.spectators_max = Clamp(value, 0, MAX_CLIENTS); break;
+ virtual void OnClick(Point pt, int widget)
+ {
+ if (widget != NSSW_CONNTYPE_BTN && widget != NSSW_LANGUAGE_BTN) HideDropDownMenu(this);
+ this->field = widget;
+ switch (widget) {
+ case NSSW_CLOSE: // Close 'X'
+ case NSSW_CANCEL: // Cancel button
+ ShowNetworkGameWindow();
+ break;
+
+ case NSSW_GAMENAME:
+ ShowOnScreenKeyboard(this, NSSW_GAMENAME, 0, 0);
+ break;
+
+ case NSSW_SETPWD: // Set password button
+ this->widget_id = NSSW_SETPWD;
+ ShowQueryString(BindCString(_network_server_password), STR_NETWORK_SET_PASSWORD, 20, 250, this, CS_ALPHANUMERAL);
+ break;
+
+ case NSSW_SELMAP: { // Select map
+ int y = (pt.y - NSSWND_START) / NSSWND_ROWSIZE;
+
+ y += this->vscroll.pos;
+ if (y >= this->vscroll.count) return;
+
+ this->map = (y == 0) ? NULL : _fios_list + y - 1;
+ this->SetDirty();
+ } break;
+
+ case NSSW_CONNTYPE_BTN: // Connection type
+ ShowDropDownMenu(this, _connection_types_dropdown, _network_advertise, NSSW_CONNTYPE_BTN, 0, 0); // do it for widget NSSW_CONNTYPE_BTN
+ break;
+
+ case NSSW_CLIENTS_BTND: case NSSW_CLIENTS_BTNU: // Click on up/down button for number of clients
+ case NSSW_COMPANIES_BTND: case NSSW_COMPANIES_BTNU: // Click on up/down button for number of companies
+ case NSSW_SPECTATORS_BTND: case NSSW_SPECTATORS_BTNU: // Click on up/down button for number of spectators
+ /* Don't allow too fast scrolling */
+ if ((this->flags4 & WF_TIMEOUT_MASK) <= 2 << WF_TIMEOUT_SHL) {
+ this->HandleButtonClick(widget);
+ this->SetDirty();
+ switch (widget) {
+ default: NOT_REACHED();
+ case NSSW_CLIENTS_BTND: case NSSW_CLIENTS_BTNU:
+ _network_game_info.clients_max = Clamp(_network_game_info.clients_max + widget - NSSW_CLIENTS_TXT, 2, MAX_CLIENTS);
+ break;
+ case NSSW_COMPANIES_BTND: case NSSW_COMPANIES_BTNU:
+ _network_game_info.companies_max = Clamp(_network_game_info.companies_max + widget - NSSW_COMPANIES_TXT, 1, MAX_PLAYERS);
+ break;
+ case NSSW_SPECTATORS_BTND: case NSSW_SPECTATORS_BTNU:
+ _network_game_info.spectators_max = Clamp(_network_game_info.spectators_max + widget - NSSW_SPECTATORS_TXT, 0, MAX_CLIENTS);
+ break;
+ }
}
- }
+ _left_button_clicked = false;
+ break;
- SetWindowDirty(w);
- break;
+ case NSSW_CLIENTS_TXT: // Click on number of players
+ this->widget_id = NSSW_CLIENTS_TXT;
+ SetDParam(0, _network_game_info.clients_max);
+ ShowQueryString(STR_CONFIG_PATCHES_INT32, STR_NETWORK_NUMBER_OF_CLIENTS, 3, 50, this, CS_NUMERAL);
+ break;
+
+ case NSSW_COMPANIES_TXT: // Click on number of companies
+ this->widget_id = NSSW_COMPANIES_TXT;
+ SetDParam(0, _network_game_info.companies_max);
+ ShowQueryString(STR_CONFIG_PATCHES_INT32, STR_NETWORK_NUMBER_OF_COMPANIES, 3, 50, this, CS_NUMERAL);
+ break;
+
+ case NSSW_SPECTATORS_TXT: // Click on number of spectators
+ this->widget_id = NSSW_SPECTATORS_TXT;
+ SetDParam(0, _network_game_info.spectators_max);
+ ShowQueryString(STR_CONFIG_PATCHES_INT32, STR_NETWORK_NUMBER_OF_SPECTATORS, 3, 50, this, CS_NUMERAL);
+ break;
+
+ case NSSW_LANGUAGE_BTN: { // Language
+ uint sel = 0;
+ for (uint i = 0; i < lengthof(_language_dropdown) - 1; i++) {
+ if (_language_dropdown[i] == STR_NETWORK_LANG_ANY + _network_game_info.server_lang) {
+ sel = i;
+ break;
+ }
+ }
+ ShowDropDownMenu(this, _language_dropdown, sel, NSSW_LANGUAGE_BTN, 0, 0);
+ } break;
+
+ case NSSW_START: // Start game
+ _is_network_server = true;
+
+ if (this->map == NULL) { // start random new game
+ ShowGenerateLandscape();
+ } else { // load a scenario
+ char *name = FiosBrowseTo(this->map);
+ if (name != NULL) {
+ SetFiosType(this->map->type);
+ _file_to_saveload.filetype = FT_SCENARIO;
+ ttd_strlcpy(_file_to_saveload.name, name, sizeof(_file_to_saveload.name));
+ ttd_strlcpy(_file_to_saveload.title, this->map->title, sizeof(_file_to_saveload.title));
+
+ delete this;
+ SwitchMode(SM_START_SCENARIO);
+ }
+ }
+ break;
+
+ case NSSW_LOAD: // Load game
+ _is_network_server = true;
+ /* XXX - WC_NETWORK_WINDOW (this window) should stay, but if it stays, it gets
+ * copied all the elements of 'load game' and upon closing that, it segfaults */
+ delete this;
+ ShowSaveLoadDialog(SLD_LOAD_GAME);
+ break;
+ }
}
-}
+
+ virtual void OnDropdownSelect(int widget, int index)
+ {
+ switch (widget) {
+ case NSSW_CONNTYPE_BTN:
+ _network_advertise = (index != 0);
+ break;
+ case NSSW_LANGUAGE_BTN:
+ _network_game_info.server_lang = _language_dropdown[index] - STR_NETWORK_LANG_ANY;
+ break;
+ default:
+ NOT_REACHED();
+ }
+
+ this->SetDirty();
+ }
+
+ virtual void OnMouseLoop()
+ {
+ if (this->field == NSSW_GAMENAME) this->HandleEditBox(NSSW_GAMENAME);
+ }
+
+ virtual bool OnKeyPress(uint16 key, uint16 keycode)
+ {
+ bool cont = true;
+ if (this->field == NSSW_GAMENAME) {
+ if (this->HandleEditBoxKey(NSSW_GAMENAME, key, keycode, cont) == 1) return cont; // enter pressed
+
+ ttd_strlcpy(_network_server_name, this->text.buf, sizeof(_network_server_name));
+ }
+
+ return cont;
+ }
+
+ virtual void OnQueryTextFinished(char *str)
+ {
+ if (str == NULL) return;
+
+ if (this->widget_id == NSSW_SETPWD) {
+ ttd_strlcpy(_network_server_password, str, lengthof(_network_server_password));
+ _network_game_info.use_password = !StrEmpty(_network_server_password);
+ } else {
+ int32 value = atoi(str);
+ this->InvalidateWidget(this->widget_id);
+ switch (this->widget_id) {
+ default: NOT_REACHED();
+ case NSSW_CLIENTS_TXT: _network_game_info.clients_max = Clamp(value, 2, MAX_CLIENTS); break;
+ case NSSW_COMPANIES_TXT: _network_game_info.companies_max = Clamp(value, 1, MAX_PLAYERS); break;
+ case NSSW_SPECTATORS_TXT: _network_game_info.spectators_max = Clamp(value, 0, MAX_CLIENTS); break;
+ }
+ }
+
+ this->SetDirty();
+ }
+};
static const Widget _network_start_server_window_widgets[] = {
/* Window decoration and background panel */
@@ -985,23 +976,14 @@
WC_NETWORK_WINDOW, WC_NONE,
WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
_network_start_server_window_widgets,
- NetworkStartServerWindowWndProc,
+ NULL,
};
static void ShowNetworkStartServerWindow()
{
DeleteWindowById(WC_NETWORK_WINDOW, 0);
- Window *w = AllocateWindowDesc(&_network_start_server_window_desc);
- ttd_strlcpy(_edit_str_net_buf, _network_server_name, lengthof(_edit_str_net_buf));
-
- _saveload_mode = SLD_NEW_GAME;
- BuildFileList();
- w->vscroll.cap = 12;
- w->vscroll.count = _fios_num + 1;
-
- WP(w, network_ql_d).q.afilter = CS_ALPHANUMERAL;
- InitializeTextBuffer(&WP(w, network_ql_d).q.text, _edit_str_net_buf, lengthof(_edit_str_net_buf), 160);
+ new NetworkStartServerWindow(&_network_start_server_window_desc);
}
static PlayerID NetworkLobbyFindCompanyIndex(byte pos)
@@ -1028,164 +1010,156 @@
NLWW_CANCEL = 12, ///< 'Cancel' button
};
-/**
- * Handler of actions done in the NetworkLobby window
- *
- * @param w pointer to the Window structure
- * @param e pointer to window event
- * @note uses network_d WP macro
- * @see struct _network_lobby_window_widgets
- * @see enum NetworkLobbyWindowWidgets
- */
-static void NetworkLobbyWindowWndProc(Window *w, WindowEvent *e)
-{
- network_d *nd = &WP(w, network_d);
-
- switch (e->event) {
- case WE_CREATE:
- nd->company = INVALID_PLAYER;
- break;
-
- case WE_PAINT: {
- const NetworkGameInfo *gi = &nd->server->info;
- int y = NET_PRC__OFFSET_TOP_WIDGET_COMPANY, pos;
+struct NetworkLobbyWindow : public Window {
+ PlayerID company; ///< Select company
+ NetworkGameList *server; ///< Selected server
- /* Join button is disabled when no company is selected */
- w->SetWidgetDisabledState(NLWW_JOIN, nd->company == INVALID_PLAYER);
- /* Cannot start new company if there are too many */
- w->SetWidgetDisabledState(NLWW_NEW, gi->companies_on >= gi->companies_max);
- /* Cannot spectate if there are too many spectators */
- w->SetWidgetDisabledState(NLWW_SPECTATE, gi->spectators_on >= gi->spectators_max);
-
- /* Draw window widgets */
- SetDParamStr(0, gi->server_name);
- DrawWindowWidgets(w);
+ NetworkLobbyWindow(const WindowDesc *desc, NetworkGameList *ngl) :
+ Window(desc), company(INVALID_PLAYER), server(ngl)
+ {
+ this->vscroll.cap = 10;
- /* Draw company list */
- pos = w->vscroll.pos;
- while (pos < gi->companies_on) {
- byte company = NetworkLobbyFindCompanyIndex(pos);
- bool income = false;
- if (nd->company == company)
- GfxFillRect(11, y - 1, 154, y + 10, 10); // show highlighted item with a different colour
+ this->FindWindowPlacementAndResize(desc);
+ }
- DoDrawStringTruncated(_network_player_info[company].company_name, 13, y, TC_BLACK, 135 - 13);
- if (_network_player_info[company].use_password != 0) DrawSprite(SPR_LOCK, PAL_NONE, 135, y);
+ virtual void OnPaint()
+ {
+ const NetworkGameInfo *gi = &this->server->info;
+ int y = NET_PRC__OFFSET_TOP_WIDGET_COMPANY, pos;
- /* If the company's income was positive puts a green dot else a red dot */
- if (_network_player_info[company].income >= 0) income = true;
- DrawSprite(SPR_BLOT, income ? PALETTE_TO_GREEN : PALETTE_TO_RED, 145, y);
+ /* Join button is disabled when no company is selected */
+ this->SetWidgetDisabledState(NLWW_JOIN, this->company == INVALID_PLAYER);
+ /* Cannot start new company if there are too many */
+ this->SetWidgetDisabledState(NLWW_NEW, gi->companies_on >= gi->companies_max);
+ /* Cannot spectate if there are too many spectators */
+ this->SetWidgetDisabledState(NLWW_SPECTATE, gi->spectators_on >= gi->spectators_max);
- pos++;
- y += NET_PRC__SIZE_OF_ROW;
- if (pos >= w->vscroll.cap) break;
+ /* Draw window widgets */
+ SetDParamStr(0, gi->server_name);
+ DrawWindowWidgets(this);
+
+ /* Draw company list */
+ pos = this->vscroll.pos;
+ while (pos < gi->companies_on) {
+ byte company = NetworkLobbyFindCompanyIndex(pos);
+ bool income = false;
+ if (this->company == company) {
+ GfxFillRect(11, y - 1, 154, y + 10, 10); // show highlighted item with a different colour
}
- /* Draw info about selected company when it is selected in the left window */
- GfxFillRect(174, 39, 403, 75, 157);
- DrawStringCentered(290, 50, STR_NETWORK_COMPANY_INFO, TC_FROMSTRING);
- if (nd->company != INVALID_PLAYER) {
- const uint x = 183;
- const uint trunc_width = w->widget[NLWW_DETAILS].right - x;
- y = 80;
-
- SetDParam(0, nd->server->info.clients_on);
- SetDParam(1, nd->server->info.clients_max);
- SetDParam(2, nd->server->info.companies_on);
- SetDParam(3, nd->server->info.companies_max);
- DrawString(x, y, STR_NETWORK_CLIENTS, TC_GOLD);
- y += 10;
-
- SetDParamStr(0, _network_player_info[nd->company].company_name);
- DrawStringTruncated(x, y, STR_NETWORK_COMPANY_NAME, TC_GOLD, trunc_width);
- y += 10;
-
- SetDParam(0, _network_player_info[nd->company].inaugurated_year);
- DrawString(x, y, STR_NETWORK_INAUGURATION_YEAR, TC_GOLD); // inauguration year
- y += 10;
-
- SetDParam(0, _network_player_info[nd->company].company_value);
- DrawString(x, y, STR_NETWORK_VALUE, TC_GOLD); // company value
- y += 10;
-
- SetDParam(0, _network_player_info[nd->company].money);
- DrawString(x, y, STR_NETWORK_CURRENT_BALANCE, TC_GOLD); // current balance
- y += 10;
-
- SetDParam(0, _network_player_info[nd->company].income);
- DrawString(x, y, STR_NETWORK_LAST_YEARS_INCOME, TC_GOLD); // last year's income
- y += 10;
-
- SetDParam(0, _network_player_info[nd->company].performance);
- DrawString(x, y, STR_NETWORK_PERFORMANCE, TC_GOLD); // performance
- y += 10;
-
- SetDParam(0, _network_player_info[nd->company].num_vehicle[0]);
- SetDParam(1, _network_player_info[nd->company].num_vehicle[1]);
- SetDParam(2, _network_player_info[nd->company].num_vehicle[2]);
- SetDParam(3, _network_player_info[nd->company].num_vehicle[3]);
- SetDParam(4, _network_player_info[nd->company].num_vehicle[4]);
- DrawString(x, y, STR_NETWORK_VEHICLES, TC_GOLD); // vehicles
- y += 10;
+ DoDrawStringTruncated(_network_player_info[company].company_name, 13, y, TC_BLACK, 135 - 13);
+ if (_network_player_info[company].use_password != 0) DrawSprite(SPR_LOCK, PAL_NONE, 135, y);
- SetDParam(0, _network_player_info[nd->company].num_station[0]);
- SetDParam(1, _network_player_info[nd->company].num_station[1]);
- SetDParam(2, _network_player_info[nd->company].num_station[2]);
- SetDParam(3, _network_player_info[nd->company].num_station[3]);
- SetDParam(4, _network_player_info[nd->company].num_station[4]);
- DrawString(x, y, STR_NETWORK_STATIONS, TC_GOLD); // stations
- y += 10;
-
- SetDParamStr(0, _network_player_info[nd->company].players);
- DrawStringTruncated(x, y, STR_NETWORK_PLAYERS, TC_GOLD, trunc_width); // players
- }
- } break;
-
- case WE_CLICK:
- switch (e->we.click.widget) {
- case NLWW_CLOSE: // Close 'X'
- case NLWW_CANCEL: // Cancel button
- ShowNetworkGameWindow();
- break;
-
- case NLWW_MATRIX: { // Company list
- uint32 id_v = (e->we.click.pt.y - NET_PRC__OFFSET_TOP_WIDGET_COMPANY) / NET_PRC__SIZE_OF_ROW;
-
- if (id_v >= w->vscroll.cap) break;
+ /* If the company's income was positive puts a green dot else a red dot */
+ if (_network_player_info[company].income >= 0) income = true;
+ DrawSprite(SPR_BLOT, income ? PALETTE_TO_GREEN : PALETTE_TO_RED, 145, y);
- id_v += w->vscroll.pos;
- nd->company = (id_v >= nd->server->info.companies_on) ? INVALID_PLAYER : NetworkLobbyFindCompanyIndex(id_v);
- SetWindowDirty(w);
- } break;
-
- case NLWW_JOIN: // Join company
- /* Button can be clicked only when it is enabled */
- _network_playas = nd->company;
- NetworkClientConnectGame(_network_last_host, _network_last_port);
- break;
-
- case NLWW_NEW: // New company
- _network_playas = PLAYER_NEW_COMPANY;
- NetworkClientConnectGame(_network_last_host, _network_last_port);
- break;
+ pos++;
+ y += NET_PRC__SIZE_OF_ROW;
+ if (pos >= this->vscroll.cap) break;
+ }
- case NLWW_SPECTATE: // Spectate game
- _network_playas = PLAYER_SPECTATOR;
- NetworkClientConnectGame(_network_last_host, _network_last_port);
- break;
+ /* Draw info about selected company when it is selected in the left window */
+ GfxFillRect(174, 39, 403, 75, 157);
+ DrawStringCentered(290, 50, STR_NETWORK_COMPANY_INFO, TC_FROMSTRING);
+ if (this->company != INVALID_PLAYER) {
+ const uint x = 183;
+ const uint trunc_width = this->widget[NLWW_DETAILS].right - x;
+ y = 80;
- case NLWW_REFRESH: // Refresh
- NetworkTCPQueryServer(_network_last_host, _network_last_port); // company info
- NetworkUDPQueryServer(_network_last_host, _network_last_port); // general data
- break;
- }
- break;
+ SetDParam(0, gi->clients_on);
+ SetDParam(1, gi->clients_max);
+ SetDParam(2, gi->companies_on);
+ SetDParam(3, gi->companies_max);
+ DrawString(x, y, STR_NETWORK_CLIENTS, TC_GOLD);
+ y += 10;
- case WE_MESSAGE:
- SetWindowDirty(w);
- break;
+ SetDParamStr(0, _network_player_info[this->company].company_name);
+ DrawStringTruncated(x, y, STR_NETWORK_COMPANY_NAME, TC_GOLD, trunc_width);
+ y += 10;
+
+ SetDParam(0, _network_player_info[this->company].inaugurated_year);
+ DrawString(x, y, STR_NETWORK_INAUGURATION_YEAR, TC_GOLD); // inauguration year
+ y += 10;
+
+ SetDParam(0, _network_player_info[this->company].company_value);
+ DrawString(x, y, STR_NETWORK_VALUE, TC_GOLD); // company value
+ y += 10;
+
+ SetDParam(0, _network_player_info[this->company].money);
+ DrawString(x, y, STR_NETWORK_CURRENT_BALANCE, TC_GOLD); // current balance
+ y += 10;
+
+ SetDParam(0, _network_player_info[this->company].income);
+ DrawString(x, y, STR_NETWORK_LAST_YEARS_INCOME, TC_GOLD); // last year's income
+ y += 10;
+
+ SetDParam(0, _network_player_info[this->company].performance);
+ DrawString(x, y, STR_NETWORK_PERFORMANCE, TC_GOLD); // performance
+ y += 10;
+
+ SetDParam(0, _network_player_info[this->company].num_vehicle[0]);
+ SetDParam(1, _network_player_info[this->company].num_vehicle[1]);
+ SetDParam(2, _network_player_info[this->company].num_vehicle[2]);
+ SetDParam(3, _network_player_info[this->company].num_vehicle[3]);
+ SetDParam(4, _network_player_info[this->company].num_vehicle[4]);
+ DrawString(x, y, STR_NETWORK_VEHICLES, TC_GOLD); // vehicles
+ y += 10;
+
+ SetDParam(0, _network_player_info[this->company].num_station[0]);
+ SetDParam(1, _network_player_info[this->company].num_station[1]);
+ SetDParam(2, _network_player_info[this->company].num_station[2]);
+ SetDParam(3, _network_player_info[this->company].num_station[3]);
+ SetDParam(4, _network_player_info[this->company].num_station[4]);
+ DrawString(x, y, STR_NETWORK_STATIONS, TC_GOLD); // stations
+ y += 10;
+
+ SetDParamStr(0, _network_player_info[this->company].players);
+ DrawStringTruncated(x, y, STR_NETWORK_PLAYERS, TC_GOLD, trunc_width); // players
+ }
}
-}
+
+ virtual void OnClick(Point pt, int widget)
+ {
+ switch (widget) {
+ case NLWW_CLOSE: // Close 'X'
+ case NLWW_CANCEL: // Cancel button
+ ShowNetworkGameWindow();
+ break;
+
+ case NLWW_MATRIX: { // Company list
+ uint32 id_v = (pt.y - NET_PRC__OFFSET_TOP_WIDGET_COMPANY) / NET_PRC__SIZE_OF_ROW;
+
+ if (id_v >= this->vscroll.cap) break;
+
+ id_v += this->vscroll.pos;
+ this->company = (id_v >= this->server->info.companies_on) ? INVALID_PLAYER : NetworkLobbyFindCompanyIndex(id_v);
+ this->SetDirty();
+ } break;
+
+ case NLWW_JOIN: // Join company
+ /* Button can be clicked only when it is enabled */
+ _network_playas = this->company;
+ NetworkClientConnectGame(_network_last_host, _network_last_port);
+ break;
+
+ case NLWW_NEW: // New company
+ _network_playas = PLAYER_NEW_COMPANY;
+ NetworkClientConnectGame(_network_last_host, _network_last_port);
+ break;
+
+ case NLWW_SPECTATE: // Spectate game
+ _network_playas = PLAYER_SPECTATOR;
+ NetworkClientConnectGame(_network_last_host, _network_last_port);
+ break;
+
+ case NLWW_REFRESH: // Refresh
+ NetworkTCPQueryServer(_network_last_host, _network_last_port); // company info
+ NetworkUDPQueryServer(_network_last_host, _network_last_port); // general data
+ break;
+ }
+ }
+};
static const Widget _network_lobby_window_widgets[] = {
{ WWT_CLOSEBOX, RESIZE_NONE, BGC, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW }, // NLWW_CLOSE
@@ -1216,7 +1190,7 @@
WC_NETWORK_WINDOW, WC_NONE,
WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
_network_lobby_window_widgets,
- NetworkLobbyWindowWndProc,
+ NULL,
};
/* Show the networklobbywindow with the selected server
@@ -1228,12 +1202,7 @@
NetworkTCPQueryServer(_network_last_host, _network_last_port); // company info
NetworkUDPQueryServer(_network_last_host, _network_last_port); // general data
- Window *w = AllocateWindowDesc(&_network_lobby_window_desc);
- if (w != NULL) {
- WP(w, network_ql_d).n.server = ngl;
- strcpy(_edit_str_net_buf, "");
- w->vscroll.cap = 10;
- }
+ new NetworkLobbyWindow(&_network_lobby_window_desc, ngl);
}
// The window below gives information about the connected clients
@@ -1381,10 +1350,10 @@
/* If height is changed */
if (w->height != CLNWND_OFFSET + num + 1) {
// XXX - magic unfortunately; (num + 2) has to be one bigger than heigh (num + 1)
- SetWindowDirty(w);
+ w->SetDirty();
w->widget[3].bottom = w->widget[3].top + num + 2;
w->height = CLNWND_OFFSET + num + 1;
- SetWindowDirty(w);
+ w->SetDirty();
return false;
}
return true;
@@ -1471,7 +1440,7 @@
int h = ClientListPopupHeight();
/* Allocate the popup */
- w = AllocateWindow(x, y, 150, h + 1, ClientListPopupWndProc, WC_TOOLBAR_MENU, _client_list_popup_widgets);
+ w = new Window(x, y, 150, h + 1, ClientListPopupWndProc, WC_TOOLBAR_MENU, _client_list_popup_widgets);
w->widget[0].bottom = w->widget[0].top + h;
w->widget[0].right = w->widget[0].left + 150;
@@ -1480,8 +1449,6 @@
// Save our client
WP(w, menu_d).main_button = client_no;
WP(w, menu_d).sel_index = 0;
- // We are a popup
- _popup_menu_active = true;
return w;
}
@@ -1513,25 +1480,22 @@
}
} break;
- case WE_POPUPMENU_SELECT: {
+ case WE_MOUSELOOP: {
/* We selected an action */
- int index = (e->we.popupmenu.pt.y - w->top) / CLNWND_ROWSIZE;
-
- if (index >= 0 && e->we.popupmenu.pt.y >= w->top) {
- HandleClientListPopupClick(index, WP(w, menu_d).main_button);
- }
+ int index = (_cursor.pos.y - w->top) / CLNWND_ROWSIZE;
- DeleteWindowById(WC_TOOLBAR_MENU, 0);
- } break;
+ if (_left_button_down) {
+ if (index == -1 || index == WP(w, menu_d).sel_index) return;
- case WE_POPUPMENU_OVER: {
- /* Our mouse hoovers over an action? Select it! */
- int index = (e->we.popupmenu.pt.y - w->top) / CLNWND_ROWSIZE;
+ WP(w, menu_d).sel_index = index;
+ w->SetDirty();
+ } else {
+ if (index >= 0 && _cursor.pos.y >= w->top) {
+ HandleClientListPopupClick(index, WP(w, menu_d).main_button);
+ }
- if (index == -1 || index == WP(w, menu_d).sel_index) return;
-
- WP(w, menu_d).sel_index = index;
- SetWindowDirty(w);
+ DeleteWindowById(WC_TOOLBAR_MENU, 0);
+ }
} break;
}
}
@@ -1589,7 +1553,7 @@
if (e->we.mouseover.pt.y == -1) {
_selected_clientlist_y = 0;
_selected_clientlist_item = 255;
- SetWindowDirty(w);
+ w->SetDirty();
break;
}
/* It did not change.. no update! */
@@ -1604,7 +1568,7 @@
}
/* Repaint */
- SetWindowDirty(w);
+ w->SetDirty();
break;
case WE_DESTROY: case WE_CREATE:
@@ -1617,7 +1581,7 @@
void ShowClientList()
{
- AllocateWindowDescFront(&_client_list_desc, 0);
+ AllocateWindowDescFront<Window>(&_client_list_desc, 0);
}
@@ -1672,21 +1636,19 @@
case WE_CLICK:
if (e->we.click.widget == 2) { //Disconnect button
NetworkDisconnect();
- delete w;
SwitchMode(SM_MENU);
ShowNetworkGameWindow();
}
break;
- /* If the server asks for a password, we need to fill it in */
- case WE_ON_EDIT_TEXT_CANCEL:
+ case WE_ON_EDIT_TEXT:
+ if (StrEmpty(e->we.edittext.str)) {
NetworkDisconnect();
ShowNetworkGameWindow();
- break;
-
- case WE_ON_EDIT_TEXT:
+ } else {
SEND_COMMAND(PACKET_CLIENT_PASSWORD)(pw_type, e->we.edittext.str);
- break;
+ }
+ break;
}
}
@@ -1708,7 +1670,7 @@
void ShowJoinStatusWindow()
{
DeleteWindowById(WC_NETWORK_STATUS_WINDOW, 0);
- Window *w = AllocateWindowDesc(&_network_join_status_window_desc);
+ Window *w = new Window(&_network_join_status_window_desc);
/* Parent the status window to the lobby */
if (w != NULL) w->parent = FindWindowById(WC_NETWORK_WINDOW, 0);
}
@@ -1723,202 +1685,217 @@
}
}
-/**
- * Find the next item of the list of things that can be auto-completed.
- * @param item The current indexed item to return. This function can, and most
- * likely will, alter item, to skip empty items in the arrays.
- * @return Returns the char that matched to the index.
- */
-static const char *ChatTabCompletionNextItem(uint *item)
-{
- static char chat_tab_temp_buffer[64];
- /* First, try clients */
- if (*item < MAX_CLIENT_INFO) {
- /* Skip inactive clients */
- while (_network_client_info[*item].client_index == NETWORK_EMPTY_INDEX && *item < MAX_CLIENT_INFO) (*item)++;
- if (*item < MAX_CLIENT_INFO) return _network_client_info[*item].client_name;
+struct NetworkChatWindow : public QueryStringBaseWindow {
+ DestType dtype;
+ int dest;
+
+ NetworkChatWindow (const WindowDesc *desc, DestType type, int dest) : QueryStringBaseWindow(desc)
+ {
+ this->LowerWidget(2);
+ this->dtype = type;
+ this->dest = dest;
+ this->afilter = CS_ALPHANUMERAL;
+ InitializeTextBuffer(&this->text, this->edit_str_buf, lengthof(this->edit_str_buf), 0);
+
+ InvalidateWindowData(WC_NEWS_WINDOW, 0, this->height);
+ SetBit(_no_scroll, SCROLL_CHAT); // do not scroll the game with the arrow-keys
+
+ _chat_tab_completion_active = false;
+
+ this->FindWindowPlacementAndResize(desc);
}
- /* Then, try townnames */
- /* Not that the following assumes all town indices are adjacent, ie no
- * towns have been deleted. */
- if (*item <= (uint)MAX_CLIENT_INFO + GetMaxTownIndex()) {
- const Town *t;
+ ~NetworkChatWindow ()
+ {
+ InvalidateWindowData(WC_NEWS_WINDOW, 0, 0);
+ ClrBit(_no_scroll, SCROLL_CHAT);
+ }
- FOR_ALL_TOWNS_FROM(t, *item - MAX_CLIENT_INFO) {
- /* Get the town-name via the string-system */
- SetDParam(0, t->index);
- GetString(chat_tab_temp_buffer, STR_TOWN, lastof(chat_tab_temp_buffer));
- return &chat_tab_temp_buffer[0];
+ /**
+ * Find the next item of the list of things that can be auto-completed.
+ * @param item The current indexed item to return. This function can, and most
+ * likely will, alter item, to skip empty items in the arrays.
+ * @return Returns the char that matched to the index.
+ */
+ const char *ChatTabCompletionNextItem(uint *item)
+ {
+ static char chat_tab_temp_buffer[64];
+
+ /* First, try clients */
+ if (*item < MAX_CLIENT_INFO) {
+ /* Skip inactive clients */
+ while (_network_client_info[*item].client_index == NETWORK_EMPTY_INDEX && *item < MAX_CLIENT_INFO) (*item)++;
+ if (*item < MAX_CLIENT_INFO) return _network_client_info[*item].client_name;
+ }
+
+ /* Then, try townnames */
+ /* Not that the following assumes all town indices are adjacent, ie no
+ * towns have been deleted. */
+ if (*item <= (uint)MAX_CLIENT_INFO + GetMaxTownIndex()) {
+ const Town *t;
+
+ FOR_ALL_TOWNS_FROM(t, *item - MAX_CLIENT_INFO) {
+ /* Get the town-name via the string-system */
+ SetDParam(0, t->index);
+ GetString(chat_tab_temp_buffer, STR_TOWN, lastof(chat_tab_temp_buffer));
+ return &chat_tab_temp_buffer[0];
+ }
+ }
+
+ return NULL;
+ }
+
+ /**
+ * Find what text to complete. It scans for a space from the left and marks
+ * the word right from that as to complete. It also writes a \0 at the
+ * position of the space (if any). If nothing found, buf is returned.
+ */
+ static char *ChatTabCompletionFindText(char *buf)
+ {
+ char *p = strrchr(buf, ' ');
+ if (p == NULL) return buf;
+
+ *p = '\0';
+ return p + 1;
+ }
+
+ /**
+ * See if we can auto-complete the current text of the user.
+ */
+ void ChatTabCompletion()
+ {
+ static char _chat_tab_completion_buf[lengthof(this->edit_str_buf)];
+ Textbuf *tb = &this->text;
+ size_t len, tb_len;
+ uint item;
+ char *tb_buf, *pre_buf;
+ const char *cur_name;
+ bool second_scan = false;
+
+ item = 0;
+
+ /* Copy the buffer so we can modify it without damaging the real data */
+ pre_buf = (_chat_tab_completion_active) ? strdup(_chat_tab_completion_buf) : strdup(tb->buf);
+
+ tb_buf = ChatTabCompletionFindText(pre_buf);
+ tb_len = strlen(tb_buf);
+
+ while ((cur_name = ChatTabCompletionNextItem(&item)) != NULL) {
+ item++;
+
+ if (_chat_tab_completion_active) {
+ /* We are pressing TAB again on the same name, is there an other name
+ * that starts with this? */
+ if (!second_scan) {
+ size_t offset;
+ size_t length;
+
+ /* If we are completing at the begin of the line, skip the ': ' we added */
+ if (tb_buf == pre_buf) {
+ offset = 0;
+ length = tb->length - 2;
+ } else {
+ /* Else, find the place we are completing at */
+ offset = strlen(pre_buf) + 1;
+ length = tb->length - offset;
+ }
+
+ /* Compare if we have a match */
+ if (strlen(cur_name) == length && strncmp(cur_name, tb->buf + offset, length) == 0) second_scan = true;
+
+ continue;
+ }
+
+ /* Now any match we make on _chat_tab_completion_buf after this, is perfect */
+ }
+
+ len = strlen(cur_name);
+ if (tb_len < len && strncasecmp(cur_name, tb_buf, tb_len) == 0) {
+ /* Save the data it was before completion */
+ if (!second_scan) snprintf(_chat_tab_completion_buf, lengthof(_chat_tab_completion_buf), "%s", tb->buf);
+ _chat_tab_completion_active = true;
+
+ /* Change to the found name. Add ': ' if we are at the start of the line (pretty) */
+ if (pre_buf == tb_buf) {
+ snprintf(tb->buf, lengthof(this->edit_str_buf), "%s: ", cur_name);
+ } else {
+ snprintf(tb->buf, lengthof(this->edit_str_buf), "%s %s", pre_buf, cur_name);
+ }
+
+ /* Update the textbuffer */
+ UpdateTextBufferSize(&this->text);
+
+ this->SetDirty();
+ free(pre_buf);
+ return;
+ }
+ }
+
+ if (second_scan) {
+ /* We walked all posibilities, and the user presses tab again.. revert to original text */
+ strcpy(tb->buf, _chat_tab_completion_buf);
+ _chat_tab_completion_active = false;
+
+ /* Update the textbuffer */
+ UpdateTextBufferSize(&this->text);
+
+ this->SetDirty();
+ }
+ free(pre_buf);
+ }
+
+ virtual void OnPaint()
+ {
+ static const StringID chat_captions[] = {
+ STR_NETWORK_CHAT_ALL_CAPTION,
+ STR_NETWORK_CHAT_COMPANY_CAPTION,
+ STR_NETWORK_CHAT_CLIENT_CAPTION
+ };
+
+ DrawWindowWidgets(this);
+
+ assert((uint)this->dtype < lengthof(chat_captions));
+ DrawStringRightAligned(this->widget[2].left - 2, this->widget[2].top + 1, chat_captions[this->dtype], TC_BLACK);
+ this->DrawEditBox(2);
+ }
+
+ virtual void OnClick(Point pt, int widget)
+ {
+ switch (widget) {
+ case 2:
+ ShowOnScreenKeyboard(this, 2, 0, 3);
+ break;
+
+ case 3: /* Send */
+ SendChat(this->text.buf, this->dtype, this->dest);
+ /* FALLTHROUGH */
+ case 0: /* Cancel */ delete this; break;
}
}
- return NULL;
-}
-
-/**
- * Find what text to complete. It scans for a space from the left and marks
- * the word right from that as to complete. It also writes a \0 at the
- * position of the space (if any). If nothing found, buf is returned.
- */
-static char *ChatTabCompletionFindText(char *buf)
-{
- char *p = strrchr(buf, ' ');
- if (p == NULL) return buf;
-
- *p = '\0';
- return p + 1;
-}
-
-/**
- * See if we can auto-complete the current text of the user.
- */
-static void ChatTabCompletion(Window *w)
-{
- static char _chat_tab_completion_buf[lengthof(_edit_str_net_buf)];
- Textbuf *tb = &WP(w, chatquerystr_d).text;
- uint len, tb_len;
- uint item;
- char *tb_buf, *pre_buf;
- const char *cur_name;
- bool second_scan = false;
-
- item = 0;
-
- /* Copy the buffer so we can modify it without damaging the real data */
- pre_buf = (_chat_tab_completion_active) ? strdup(_chat_tab_completion_buf) : strdup(tb->buf);
-
- tb_buf = ChatTabCompletionFindText(pre_buf);
- tb_len = strlen(tb_buf);
-
- while ((cur_name = ChatTabCompletionNextItem(&item)) != NULL) {
- item++;
-
- if (_chat_tab_completion_active) {
- /* We are pressing TAB again on the same name, is there an other name
- * that starts with this? */
- if (!second_scan) {
- uint offset;
- uint length;
-
- /* If we are completing at the begin of the line, skip the ': ' we added */
- if (tb_buf == pre_buf) {
- offset = 0;
- length = tb->length - 2;
- } else {
- /* Else, find the place we are completing at */
- offset = strlen(pre_buf) + 1;
- length = tb->length - offset;
- }
-
- /* Compare if we have a match */
- if (strlen(cur_name) == length && strncmp(cur_name, tb->buf + offset, length) == 0) second_scan = true;
-
- continue;
- }
-
- /* Now any match we make on _chat_tab_completion_buf after this, is perfect */
- }
-
- len = strlen(cur_name);
- if (tb_len < len && strncasecmp(cur_name, tb_buf, tb_len) == 0) {
- /* Save the data it was before completion */
- if (!second_scan) snprintf(_chat_tab_completion_buf, lengthof(_chat_tab_completion_buf), "%s", tb->buf);
- _chat_tab_completion_active = true;
-
- /* Change to the found name. Add ': ' if we are at the start of the line (pretty) */
- if (pre_buf == tb_buf) {
- snprintf(tb->buf, lengthof(_edit_str_net_buf), "%s: ", cur_name);
- } else {
- snprintf(tb->buf, lengthof(_edit_str_net_buf), "%s %s", pre_buf, cur_name);
- }
-
- /* Update the textbuffer */
- UpdateTextBufferSize(&WP(w, chatquerystr_d).text);
-
- SetWindowDirty(w);
- free(pre_buf);
- return;
- }
+ virtual void OnMouseLoop()
+ {
+ this->HandleEditBox(2);
}
- if (second_scan) {
- /* We walked all posibilities, and the user presses tab again.. revert to original text */
- strcpy(tb->buf, _chat_tab_completion_buf);
- _chat_tab_completion_active = false;
-
- /* Update the textbuffer */
- UpdateTextBufferSize(&WP(w, chatquerystr_d).text);
-
- SetWindowDirty(w);
+ virtual bool OnKeyPress(uint16 key, uint16 keycode)
+ {
+ bool cont = true;
+ if (keycode == WKC_TAB) {
+ ChatTabCompletion();
+ } else {
+ _chat_tab_completion_active = false;
+ switch (this->HandleEditBoxKey(2, key, keycode, cont)) {
+ case 1: /* Return */
+ SendChat(this->text.buf, this->dtype, this->dest);
+ /* FALLTHROUGH */
+ case 2: /* Escape */ delete this; break;
+ }
+ }
+ return cont;
}
- free(pre_buf);
-}
-
-/*
- * uses chatquerystr_d WP macro
- * uses chatquerystr_d->dtype to store type of chat message (Private/Team/All)
- */
-static void ChatWindowWndProc(Window *w, WindowEvent *e)
-{
- switch (e->event) {
- case WE_CREATE:
- SendWindowMessage(WC_NEWS_WINDOW, 0, WE_CREATE, w->height, 0);
- SetBit(_no_scroll, SCROLL_CHAT); // do not scroll the game with the arrow-keys
- break;
-
- case WE_PAINT: {
- static const StringID chat_captions[] = {
- STR_NETWORK_CHAT_ALL_CAPTION,
- STR_NETWORK_CHAT_COMPANY_CAPTION,
- STR_NETWORK_CHAT_CLIENT_CAPTION
- };
-
- DrawWindowWidgets(w);
-
- assert((uint)WP(w, chatquerystr_d).dtype < lengthof(chat_captions));
- DrawStringRightAligned(w->widget[2].left - 2, w->widget[2].top + 1, chat_captions[WP(w, chatquerystr_d).dtype], TC_BLACK);
- DrawEditBox(w, &WP(w, chatquerystr_d), 2);
- } break;
-
- case WE_CLICK:
- switch (e->we.click.widget) {
- case 2:
- ShowOnScreenKeyboard(w, &WP(w, chatquerystr_d), 2, 0, 3);
- break;
-
- case 3: /* Send */
- SendChat(WP(w, chatquerystr_d).text.buf, WP(w, chatquerystr_d).dtype, WP(w, chatquerystr_d).dest);
- /* FALLTHROUGH */
- case 0: /* Cancel */ delete w; break;
- }
- break;
-
- case WE_MOUSELOOP:
- HandleEditBox(w, &WP(w, chatquerystr_d), 2);
- break;
-
- case WE_KEYPRESS:
- if (e->we.keypress.keycode == WKC_TAB) {
- ChatTabCompletion(w);
- } else {
- _chat_tab_completion_active = false;
- switch (HandleEditBoxKey(w, &WP(w, chatquerystr_d), 2, e)) {
- case 1: /* Return */
- SendChat(WP(w, chatquerystr_d).text.buf, WP(w, chatquerystr_d).dtype, WP(w, chatquerystr_d).dest);
- /* FALLTHROUGH */
- case 2: /* Escape */ delete w; break;
- }
- }
- break;
-
- case WE_DESTROY:
- SendWindowMessage(WC_NEWS_WINDOW, 0, WE_DESTROY, 0, 0);
- ClrBit(_no_scroll, SCROLL_CHAT);
- break;
- }
-}
+};
static const Widget _chat_window_widgets[] = {
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
@@ -1933,23 +1910,13 @@
WC_SEND_NETWORK_MSG, WC_NONE,
WDF_STD_TOOLTIPS | WDF_DEF_WIDGET,
_chat_window_widgets,
- ChatWindowWndProc
+ NULL
};
void ShowNetworkChatQueryWindow(DestType type, int dest)
{
DeleteWindowById(WC_SEND_NETWORK_MSG, 0);
-
- _edit_str_net_buf[0] = '\0';
- _chat_tab_completion_active = false;
-
- Window *w = AllocateWindowDesc(&_chat_window_desc);
-
- w->LowerWidget(2);
- WP(w, chatquerystr_d).dtype = type;
- WP(w, chatquerystr_d).dest = dest;
- WP(w, chatquerystr_d).afilter = CS_ALPHANUMERAL;
- InitializeTextBuffer(&WP(w, chatquerystr_d).text, _edit_str_net_buf, lengthof(_edit_str_net_buf), 0);
+ new NetworkChatWindow (&_chat_window_desc, type, dest);
}
/** Enum for NetworkGameWindow, referring to _network_game_window_widgets */
@@ -1964,61 +1931,75 @@
NCPWW_OK, ///< Safe the password etc.
};
-static void NetworkCompanyPasswordWindowWndProc(Window *w, WindowEvent *e)
-{
- switch (e->event) {
- case WE_PAINT:
- DrawWindowWidgets(w);
- DrawEditBox(w, &WP(w, chatquerystr_d), 4);
- break;
-
- case WE_CLICK:
- switch (e->we.click.widget) {
- case NCPWW_OK: {
- if (w->IsWidgetLowered(NCPWW_SAVE_AS_DEFAULT_PASSWORD)) {
- snprintf(_network_default_company_pass, lengthof(_network_default_company_pass), "%s", _edit_str_net_buf);
- }
-
- /* empty password is a '*' because of console argument */
- if (StrEmpty(_edit_str_net_buf)) snprintf(_edit_str_net_buf, lengthof(_edit_str_net_buf), "*");
- char *password = _edit_str_net_buf;
- NetworkChangeCompanyPassword(1, &password);
- }
-
- /* FALL THROUGH */
- case NCPWW_CANCEL:
- delete w;
- break;
+struct NetworkCompanyPasswordWindow : public QueryStringBaseWindow {
+ NetworkCompanyPasswordWindow(const WindowDesc *desc) : QueryStringBaseWindow(desc)
+ {
+ this->afilter = CS_ALPHANUMERAL;
+ InitializeTextBuffer(&this->text, this->edit_str_buf, min(lengthof(_network_default_company_pass), lengthof(this->edit_str_buf)), 0);
- case NCPWW_SAVE_AS_DEFAULT_PASSWORD:
- w->ToggleWidgetLoweredState(NCPWW_SAVE_AS_DEFAULT_PASSWORD);
- SetWindowDirty(w);
- break;
- case NCPWW_PASSWORD:
- ShowOnScreenKeyboard(w, &WP(w, chatquerystr_d), NCPWW_PASSWORD, 2, 1);
- break;
- }
- break;
-
- case WE_MOUSELOOP:
- HandleEditBox(w, &WP(w, chatquerystr_d), 4);
- break;
+ this->FindWindowPlacementAndResize(desc);
+ }
- case WE_KEYPRESS:
- switch (HandleEditBoxKey(w, &WP(w, chatquerystr_d), 4, e)) {
- case 1: // Return
- e->event = WE_CLICK;
- e->we.click.widget = NCPWW_OK;
- NetworkCompanyPasswordWindowWndProc(w, e);
- break;
+ void OnOk()
+ {
+ if (this->IsWidgetLowered(NCPWW_SAVE_AS_DEFAULT_PASSWORD)) {
+ snprintf(_network_default_company_pass, lengthof(_network_default_company_pass), "%s", this->edit_str_buf);
+ }
- case 2: // Escape
- delete w;
- break;
- }
- break;
+ /* empty password is a '*' because of console argument */
+ if (StrEmpty(this->edit_str_buf)) snprintf(this->edit_str_buf, lengthof(this->edit_str_buf), "*");
+ char *password = this->edit_str_buf;
+ NetworkChangeCompanyPassword(1, &password);
}
-}
+
+ virtual void OnPaint()
+ {
+ DrawWindowWidgets(this);
+ this->DrawEditBox(4);
+ }
+
+ virtual void OnClick(Point pt, int widget)
+ {
+ switch (widget) {
+ case NCPWW_OK:
+ this->OnOk();
+
+ /* FALL THROUGH */
+ case NCPWW_CANCEL:
+ delete this;
+ break;
+
+ case NCPWW_SAVE_AS_DEFAULT_PASSWORD:
+ this->ToggleWidgetLoweredState(NCPWW_SAVE_AS_DEFAULT_PASSWORD);
+ this->SetDirty();
+ break;
+
+ case NCPWW_PASSWORD:
+ ShowOnScreenKeyboard(this, NCPWW_PASSWORD, 2, 1);
+ break;
+ }
+ }
+
+ virtual void OnMouseLoop()
+ {
+ this->HandleEditBox(4);
+ }
+
+ virtual bool OnKeyPress(uint16 key, uint16 keycode)
+ {
+ bool cont;
+ switch (this->HandleEditBoxKey(4, key, keycode, cont)) {
+ case 1: // Return
+ this->OnOk();
+ /* FALL THROUGH */
+
+ case 2: // Escape
+ delete this;
+ break;
+ }
+ return cont;
+ }
+};
static const Widget _ncp_window_widgets[] = {
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
@@ -2037,17 +2018,14 @@
WC_COMPANY_PASSWORD_WINDOW, WC_NONE,
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON,
_ncp_window_widgets,
- NetworkCompanyPasswordWindowWndProc
+ NULL
};
void ShowNetworkCompanyPasswordWindow()
{
DeleteWindowById(WC_COMPANY_PASSWORD_WINDOW, 0);
- _edit_str_net_buf[0] = '\0';
- Window *w = AllocateWindowDesc(&_ncp_window_desc);
- WP(w, chatquerystr_d).afilter = CS_ALPHANUMERAL;
- InitializeTextBuffer(&WP(w, chatquerystr_d).text, _edit_str_net_buf, min(lengthof(_network_default_company_pass), lengthof(_edit_str_net_buf)), 0);
+ new NetworkCompanyPasswordWindow(&_ncp_window_desc);
}
#endif /* ENABLE_NETWORK */
--- a/src/network/network_udp.cpp Wed May 07 21:09:51 2008 +0000
+++ b/src/network/network_udp.cpp Sun May 11 20:09:34 2008 +0000
@@ -205,7 +205,7 @@
const GRFConfig *in_reply[NETWORK_MAX_GRF_COUNT];
uint8 in_reply_count = 0;
- uint packet_len = 0;
+ size_t packet_len = 0;
DEBUG(net, 6, "[udp] newgrf data request from %s:%d", inet_ntoa(client_addr->sin_addr), ntohs(client_addr->sin_port));
--- a/src/newgrf.cpp Wed May 07 21:09:51 2008 +0000
+++ b/src/newgrf.cpp Sun May 11 20:09:34 2008 +0000
@@ -96,7 +96,7 @@
static GrfDataType _grf_data_type;
-typedef void (*SpecialSpriteHandler)(byte *buf, int len);
+typedef void (*SpecialSpriteHandler)(byte *buf, size_t len);
enum {
MAX_STATIONS = 256,
@@ -152,7 +152,7 @@
DEBUG(grf, severity, "[%s:%d] %s", _cur_grfconfig->filename, _nfo_line, buf);
}
-static inline bool check_length(int real, int wanted, const char *str)
+static inline bool check_length(size_t real, size_t wanted, const char *str)
{
if (real >= wanted) return true;
grfmsg(0, "%s: Invalid pseudo sprite length %d (expected %d)!", str, real, wanted);
@@ -2248,7 +2248,7 @@
}
/* Action 0x00 */
-static void FeatureChangeInfo(byte *buf, int len)
+static void FeatureChangeInfo(byte *buf, size_t len)
{
byte *bufend = buf + len;
@@ -2363,7 +2363,7 @@
}
/* Action 0x00 (GLS_SAFETYSCAN) */
-static void SafeChangeInfo(byte *buf, int len)
+static void SafeChangeInfo(byte *buf, size_t len)
{
if (!check_length(len, 6, "SafeChangeInfo")) return;
buf++;
@@ -2386,7 +2386,7 @@
}
/* Action 0x00 (GLS_RESERVE) */
-static void ReserveChangeInfo(byte *buf, int len)
+static void ReserveChangeInfo(byte *buf, size_t len)
{
byte *bufend = buf + len;
@@ -2482,7 +2482,7 @@
}
/* Action 0x01 */
-static void NewSpriteSet(byte *buf, int len)
+static void NewSpriteSet(byte *buf, size_t len)
{
/* <01> <feature> <num-sets> <num-ent>
*
@@ -2518,7 +2518,7 @@
}
/* Action 0x01 (SKIP) */
-static void SkipAct1(byte *buf, int len)
+static void SkipAct1(byte *buf, size_t len)
{
if (!check_length(len, 4, "SkipAct1")) return;
buf++;
@@ -2577,7 +2577,7 @@
}
/* Action 0x02 */
-static void NewSpriteGroup(byte *buf, int len)
+static void NewSpriteGroup(byte *buf, size_t len)
{
/* <02> <feature> <set-id> <type/num-entries> <feature-specific-data...>
*
@@ -3182,7 +3182,7 @@
/* Action 0x03 */
-static void FeatureMapSpriteGroup(byte *buf, int len)
+static void FeatureMapSpriteGroup(byte *buf, size_t len)
{
/* <03> <feature> <n-id> <ids>... <num-cid> [<cargo-type> <cid>]... <def-cid>
* id-list := [<id>] [id-list]
@@ -3267,7 +3267,7 @@
}
/* Action 0x04 */
-static void FeatureNewName(byte *buf, int len)
+static void FeatureNewName(byte *buf, size_t len)
{
/* <04> <veh-type> <language-id> <num-veh> <offset> <data...>
*
@@ -3421,7 +3421,7 @@
}
/* Action 0x05 */
-static void GraphicsNew(byte *buf, int len)
+static void GraphicsNew(byte *buf, size_t len)
{
/* <05> <graphics-type> <num-sprites> <other data...>
*
@@ -3535,7 +3535,7 @@
}
/* Action 0x05 (SKIP) */
-static void SkipAct5(byte *buf, int len)
+static void SkipAct5(byte *buf, size_t len)
{
if (!check_length(len, 2, "SkipAct5")) return;
buf++;
@@ -3711,7 +3711,7 @@
}
/* Action 0x06 */
-static void CfgApply(byte *buf, int len)
+static void CfgApply(byte *buf, size_t len)
{
/* <06> <param-num> <param-size> <offset> ... <FF>
*
@@ -3799,7 +3799,7 @@
/* Action 0x07 */
/* Action 0x09 */
-static void SkipIf(byte *buf, int len)
+static void SkipIf(byte *buf, size_t len)
{
/* <07/09> <param-num> <param-size> <condition-type> <value> <num-sprites>
*
@@ -3954,7 +3954,7 @@
/* Action 0x08 (GLS_FILESCAN) */
-static void ScanInfo(byte *buf, int len)
+static void ScanInfo(byte *buf, size_t len)
{
if (!check_length(len, 8, "Info")) return;
buf++;
@@ -3981,7 +3981,7 @@
}
/* Action 0x08 */
-static void GRFInfo(byte *buf, int len)
+static void GRFInfo(byte *buf, size_t len)
{
/* <08> <version> <grf-id> <name> <info>
*
@@ -4005,7 +4005,7 @@
}
/* Action 0x0A */
-static void SpriteReplace(byte *buf, int len)
+static void SpriteReplace(byte *buf, size_t len)
{
/* <0A> <num-sets> <set1> [<set2> ...]
* <set>: <num-sprites> <first-sprite>
@@ -4041,7 +4041,7 @@
}
/* Action 0x0A (SKIP) */
-static void SkipActA(byte *buf, int len)
+static void SkipActA(byte *buf, size_t len)
{
buf++;
uint8 num_sets = grf_load_byte(&buf);
@@ -4057,7 +4057,7 @@
}
/* Action 0x0B */
-static void GRFLoadError(byte *buf, int len)
+static void GRFLoadError(byte *buf, size_t len)
{
/* <0B> <severity> <language-id> <message-id> [<message...> 00] [<data...>] 00 [<parnum>]
*
@@ -4167,7 +4167,7 @@
}
/* Action 0x0C */
-static void GRFComment(byte *buf, int len)
+static void GRFComment(byte *buf, size_t len)
{
/* <0C> [<ignored...>]
*
@@ -4175,13 +4175,13 @@
if (len == 1) return;
- int text_len = len - 1;
+ size_t text_len = len - 1;
const char *text = (const char*)(buf + 1);
grfmsg(2, "GRFComment: %.*s", text_len, text);
}
/* Action 0x0D (GLS_SAFETYSCAN) */
-static void SafeParamSet(byte *buf, int len)
+static void SafeParamSet(byte *buf, size_t len)
{
if (!check_length(len, 5, "SafeParamSet")) return;
buf++;
@@ -4313,7 +4313,7 @@
/* Action 0x0D */
-static void ParamSet(byte *buf, int len)
+static void ParamSet(byte *buf, size_t len)
{
/* <0D> <target> <operation> <source1> <source2> [<data>]
*
@@ -4604,7 +4604,7 @@
}
/* Action 0x0E (GLS_SAFETYSCAN) */
-static void SafeGRFInhibit(byte *buf, int len)
+static void SafeGRFInhibit(byte *buf, size_t len)
{
/* <0E> <num> <grfids...>
*
@@ -4632,7 +4632,7 @@
}
/* Action 0x0E */
-static void GRFInhibit(byte *buf, int len)
+static void GRFInhibit(byte *buf, size_t len)
{
/* <0E> <num> <grfids...>
*
@@ -4657,7 +4657,7 @@
}
/* Action 0x0F */
-static void FeatureTownName(byte *buf, int len)
+static void FeatureTownName(byte *buf, size_t len)
{
/* <0F> <id> <style-name> <num-parts> <parts>
*
@@ -4757,7 +4757,7 @@
}
/* Action 0x10 */
-static void DefineGotoLabel(byte *buf, int len)
+static void DefineGotoLabel(byte *buf, size_t len)
{
/* <10> <label> [<comment>]
*
@@ -4787,7 +4787,7 @@
}
/* Action 0x11 */
-static void GRFSound(byte *buf, int len)
+static void GRFSound(byte *buf, size_t len)
{
/* <11> <num>
*
@@ -4804,7 +4804,7 @@
}
/* Action 0x11 (SKIP) */
-static void SkipAct11(byte *buf, int len)
+static void SkipAct11(byte *buf, size_t len)
{
/* <11> <num>
*
@@ -4930,7 +4930,7 @@
}
/* Action 0x12 */
-static void LoadFontGlyph(byte *buf, int len)
+static void LoadFontGlyph(byte *buf, size_t len)
{
/* <12> <num_def> <font_size> <num_char> <base_char>
*
@@ -4962,7 +4962,7 @@
}
/* Action 0x12 (SKIP) */
-static void SkipAct12(byte *buf, int len)
+static void SkipAct12(byte *buf, size_t len)
{
/* <12> <num_def> <font_size> <num_char> <base_char>
*
@@ -4992,7 +4992,7 @@
}
/* Action 0x13 */
-static void TranslateGRFStrings(byte *buf, int len)
+static void TranslateGRFStrings(byte *buf, size_t len)
{
/* <13> <grfid> <num-ent> <offset> <text...>
*
@@ -5086,7 +5086,7 @@
/* Used during safety scan on unsafe actions */
-static void GRFUnsafe(byte *buf, int len)
+static void GRFUnsafe(byte *buf, size_t len)
{
SetBit(_cur_grfconfig->flags, GCF_UNSAFE);
--- a/src/newgrf_config.cpp Wed May 07 21:09:51 2008 +0000
+++ b/src/newgrf_config.cpp Sun May 11 20:09:34 2008 +0000
@@ -309,7 +309,7 @@
}
/* Scan a path for NewGRFs */
-static uint ScanPath(const char *path, int basepath_length)
+static uint ScanPath(const char *path, size_t basepath_length)
{
extern bool FiosIsValidFile(const char *path, const struct dirent *ent, struct stat *sb);
--- a/src/newgrf_gui.cpp Wed May 07 21:09:51 2008 +0000
+++ b/src/newgrf_gui.cpp Sun May 11 20:09:34 2008 +0000
@@ -408,7 +408,7 @@
Window *w;
DeleteWindowByClass(WC_SAVELOAD);
- w = AllocateWindowDesc(&_newgrf_add_dlg_desc);
+ w = new Window(&_newgrf_add_dlg_desc);
w->resize.step_height = 10;
WP(w, newgrf_add_d).list = list;
@@ -516,8 +516,9 @@
/* parse_intlist returns -1 on error */
if (c->num_params == (byte)-1) c->num_params = 0;
+
+ w->SetDirty();
}
- w->SetDirty();
break;
case WE_DESTROY:
@@ -582,7 +583,7 @@
Window *w;
DeleteWindowByClass(WC_GAME_OPTIONS);
- w = AllocateWindowDesc(&_newgrf_desc);
+ w = new Window(&_newgrf_desc);
if (w == NULL) return;
w->resize.step_height = 14;
--- a/src/news_gui.cpp Wed May 07 21:09:51 2008 +0000
+++ b/src/news_gui.cpp Sun May 11 20:09:34 2008 +0000
@@ -60,12 +60,8 @@
static NewsID _oldest_news = 0; ///< points to first item in fifo queue
static NewsID _latest_news = INVALID_NEWS; ///< points to last item in fifo queue
-struct news_d : vp_d {
- uint16 follow_vehicle;
- int32 scrollpos_x;
- int32 scrollpos_y;
- int32 dest_scrollpos_x;
- int32 dest_scrollpos_y;
+struct news_d {
+ uint16 chat_height;
NewsItem *ni;
};
assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(news_d));
@@ -131,7 +127,7 @@
switch (e->event) {
case WE_CREATE: { // If chatbar is open at creation time, we need to go above it
const Window *w1 = FindWindowById(WC_SEND_NETWORK_MSG, 0);
- w->message.msg = (w1 != NULL) ? w1->height : 0;
+ WP(w, news_d).chat_height = (w1 != NULL) ? w1->height : 0;
break;
}
@@ -209,11 +205,11 @@
} else if (ni->flags & NF_TILE) {
if (_ctrl_pressed) {
ShowExtraViewPortWindow(ni->data_a);
- if (ni->data_b != 0) {
+ if (ni->flags & NF_TILE2) {
ShowExtraViewPortWindow(ni->data_b);
}
} else {
- if (!ScrollMainWindowToTile(ni->data_a) && ni->data_b != 0) {
+ if (!ScrollMainWindowToTile(ni->data_a) && ni->flags & NF_TILE2) {
ScrollMainWindowToTile(ni->data_b);
}
}
@@ -231,15 +227,12 @@
}
break;
- case WE_MESSAGE: // The chatbar has notified us that is was either created or closed
- switch (e->we.message.msg) {
- case WE_CREATE: w->message.msg = e->we.message.wparam; break;
- case WE_DESTROY: w->message.msg = 0; break;
- }
+ case WE_INVALIDATE_DATA: // The chatbar has notified us that is was either created or closed
+ WP(w, news_d).chat_height = e->we.invalidate.data;
break;
case WE_TICK: { // Scroll up newsmessages from the bottom in steps of 4 pixels
- int y = max(w->top - 4, _screen.height - w->height - 12 - w->message.msg);
+ int y = max(w->top - 4, _screen.height - w->height - 12 - WP(w, news_d).chat_height);
if (y == w->top) return;
if (w->viewport != NULL) {
@@ -432,7 +425,7 @@
case NM_NORMAL:
case NM_CALLBACK:
_news_type13_desc.top = top;
- w = AllocateWindowDesc(&_news_type13_desc);
+ w = new Window(&_news_type13_desc);
if (ni->flags & NF_VIEWPORT) {
InitializeWindowViewport(w, 2, 58, 426, 110,
ni->data_a | (ni->flags & NF_VEHICLE ? 0x80000000 : 0), ZOOM_LVL_NEWS);
@@ -441,7 +434,7 @@
case NM_THIN:
_news_type2_desc.top = top;
- w = AllocateWindowDesc(&_news_type2_desc);
+ w = new Window(&_news_type2_desc);
if (ni->flags & NF_VIEWPORT) {
InitializeWindowViewport(w, 2, 58, 426, 70,
ni->data_a | (ni->flags & NF_VEHICLE ? 0x80000000 : 0), ZOOM_LVL_NEWS);
@@ -450,7 +443,7 @@
default:
_news_type0_desc.top = top;
- w = AllocateWindowDesc(&_news_type0_desc);
+ w = new Window(&_news_type0_desc);
if (ni->flags & NF_VIEWPORT) {
InitializeWindowViewport(w, 3, 17, 274, 47,
ni->data_a | (ni->flags & NF_VEHICLE ? 0x80000000 : 0), ZOOM_LVL_NEWS);
@@ -711,7 +704,7 @@
void ShowMessageHistory()
{
DeleteWindowById(WC_MESSAGE_HISTORY, 0);
- Window *w = AllocateWindowDesc(&_message_history_desc);
+ Window *w = new Window(&_message_history_desc);
if (w == NULL) return;
@@ -933,7 +926,7 @@
void ShowMessageOptions()
{
DeleteWindowById(WC_GAME_OPTIONS, 0);
- AllocateWindowDesc(&_message_options_desc);
+ new Window(&_message_options_desc);
}
--- a/src/news_type.h Wed May 07 21:09:51 2008 +0000
+++ b/src/news_type.h Sun May 11 20:09:34 2008 +0000
@@ -48,10 +48,11 @@
enum NewsFlag {
NF_NONE = 0, ///< No flag is set.
NF_VIEWPORT = (1 << 1), ///< Does the news message have a viewport? (ingame picture of happening)
- NF_TILE = (1 << 2), ///< When clicked on the news message scroll to a given tile? Tile is in data_a/data_b
+ NF_TILE = (1 << 2), ///< When clicked on the news message scroll to a given tile? Tile is in data_a
NF_VEHICLE = (1 << 3), ///< When clicked on the message scroll to the vehicle? VehicleID is in data_a
NF_FORCE_BIG = (1 << 4), ///< Force the appearance of a news message if it has already been shown (internal)
NF_INCOLOR = (1 << 5), ///< Show the newsmessage in colour, otherwise it defaults to black & white
+ NF_TILE2 = (1 << 6), ///< There is a second tile to scroll to; tile is in data_b
};
DECLARE_ENUM_AS_BIT_SET(NewsFlag);
--- a/src/openttd.cpp Wed May 07 21:09:51 2008 +0000
+++ b/src/openttd.cpp Sun May 11 20:09:34 2008 +0000
@@ -61,6 +61,7 @@
#include "cheat_func.h"
#include "animated_tile_func.h"
#include "functions.h"
+#include "elrail_func.h"
#include "rev.h"
#include "newgrf.h"
@@ -98,6 +99,7 @@
void ResetMusic();
void ResetOldNames();
void ProcessAsyncSaveFinish();
+void CallWindowTickEvent();
extern void SetDifficultyLevel(int mode, GameOptions *gm_opt);
extern Player* DoStartupNewPlayer(bool is_ai);
@@ -295,8 +297,20 @@
}
-static void UnInitializeGame()
+/** Unitializes drivers, frees allocated memory, cleans pools, ...
+ * Generally, prepares the game for shutting down
+ */
+static void ShutdownGame()
{
+ /* stop the AI */
+ AI_Uninitialize();
+
+ IConsoleFree();
+
+ if (_network_available) NetworkShutDown(); // Shut down the network and close any open connections
+
+ DriverFactoryBase::ShutdownDrivers();
+
UnInitWindowSystem();
/* Uninitialize airport state machines */
@@ -317,6 +331,9 @@
free((void*)_industry_sort);
free(_config_file);
+
+ /* Close all and any open filehandles */
+ FioCloseAll();
}
static void LoadIntroGame()
@@ -632,13 +649,6 @@
_video_driver->MainLoop();
WaitTillSaved();
- IConsoleFree();
-
- if (_network_available) NetworkShutDown(); // Shut down the network and close any open connections
-
- _video_driver->Stop();
- _music_driver->Stop();
- _sound_driver->Stop();
/* only save config if we have to */
if (save_config) {
@@ -646,14 +656,8 @@
SaveToHighScore();
}
- /* Reset windowing system and free config file */
- UnInitializeGame();
-
- /* stop the AI */
- AI_Uninitialize();
-
- /* Close all and any open filehandles */
- FioCloseAll();
+ /* Reset windowing system, stop drivers, free used memory, ... */
+ ShutdownGame();
return 0;
}
@@ -1098,8 +1102,8 @@
Window *w = FindWindowById(WC_MAIN_WINDOW, 0);
assert(w);
- WP(w, vp_d).dest_scrollpos_x += ScaleByZoom(x, w->viewport->zoom);
- WP(w, vp_d).dest_scrollpos_y += ScaleByZoom(y, w->viewport->zoom);
+ w->viewport->dest_scrollpos_x += ScaleByZoom(x, w->viewport->zoom);
+ w->viewport->dest_scrollpos_y += ScaleByZoom(y, w->viewport->zoom);
}
}
@@ -1209,8 +1213,8 @@
const Window *w = FindWindowById(WC_MAIN_WINDOW, 0);
if (w != NULL) {
- _saved_scrollpos_x = WP(w, const vp_d).scrollpos_x;
- _saved_scrollpos_y = WP(w, const vp_d).scrollpos_y;
+ _saved_scrollpos_x = w->viewport->scrollpos_x;
+ _saved_scrollpos_y = w->viewport->scrollpos_y;
_saved_scrollpos_zoom = w->viewport->zoom;
}
}
@@ -1322,10 +1326,10 @@
Window *w = FindWindowById(WC_MAIN_WINDOW, 0);
- WP(w, vp_d).scrollpos_x = _saved_scrollpos_x;
- WP(w, vp_d).scrollpos_y = _saved_scrollpos_y;
- WP(w, vp_d).dest_scrollpos_x = _saved_scrollpos_x;
- WP(w, vp_d).dest_scrollpos_y = _saved_scrollpos_y;
+ w->viewport->scrollpos_x = _saved_scrollpos_x;
+ w->viewport->scrollpos_y = _saved_scrollpos_y;
+ w->viewport->dest_scrollpos_x = _saved_scrollpos_x;
+ w->viewport->dest_scrollpos_y = _saved_scrollpos_y;
ViewPort *vp = w->viewport;
vp->zoom = min(_saved_scrollpos_zoom, ZOOM_LVL_MAX);
--- a/src/order_gui.cpp Wed May 07 21:09:51 2008 +0000
+++ b/src/order_gui.cpp Sun May 11 20:09:34 2008 +0000
@@ -1185,9 +1185,9 @@
DeleteWindowById(WC_VEHICLE_DETAILS, veh);
if (v->owner != _local_player) {
- w = AllocateWindowDescFront(&_other_orders_desc, veh);
+ w = AllocateWindowDescFront<Window>(&_other_orders_desc, veh);
} else {
- w = AllocateWindowDescFront((v->type == VEH_TRAIN || v->type == VEH_ROAD) ? &_orders_train_desc : &_orders_desc, veh);
+ w = AllocateWindowDescFront<Window>((v->type == VEH_TRAIN || v->type == VEH_ROAD) ? &_orders_train_desc : &_orders_desc, veh);
}
if (w != NULL) {
--- a/src/osk_gui.cpp Wed May 07 21:09:51 2008 +0000
+++ b/src/osk_gui.cpp Sun May 11 20:09:34 2008 +0000
@@ -12,20 +12,11 @@
#include "debug.h"
#include "window_func.h"
#include "gfx_func.h"
+#include "querystring_gui.h"
#include "table/sprites.h"
#include "table/strings.h"
-struct osk_d {
- querystr_d *qs; // text-input
- int text_btn; // widget number of parent's text field
- int ok_btn; // widget number of parent's ok button (=0 when ok shouldn't be passed on)
- int cancel_btn; // widget number of parent's cancel button (=0 when cancel shouldn't be passed on; text will be reverted to original)
- Textbuf *text; // pointer to parent's textbuffer (to update caret position)
- char *orig; // the original text, in case we cancel
-};
-assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(osk_d));
-
enum OskWidgets {
OSK_WIDGET_TEXT = 3,
OSK_WIDGET_CANCEL = 5,
@@ -50,149 +41,162 @@
};
static byte _keystate = KEYS_NONE;
-/*
- * Only show valid characters; do not show characters that would
- * only insert a space when we have a spacebar to do that or
- * characters that are not allowed to be entered.
- */
-static void ChangeOskDiabledState(Window *w, const querystr_d *qs, bool shift)
-{
- for (uint i = 0; i < OSK_KEYBOARD_ENTRIES; i++) {
- w->SetWidgetDisabledState(OSK_WIDGET_LETTERS + i,
- !IsValidChar(_keyboard[shift][i], qs->afilter) || _keyboard[shift][i] == ' ');
+struct OskWindow : public Window {
+ QueryString *qs; ///< text-input
+ int text_btn; ///< widget number of parent's text field
+ int ok_btn; ///< widget number of parent's ok button (=0 when ok shouldn't be passed on)
+ int cancel_btn; ///< widget number of parent's cancel button (=0 when cancel shouldn't be passed on; text will be reverted to original)
+ Textbuf *text; ///< pointer to parent's textbuffer (to update caret position)
+ char orig_str_buf[64]; ///< Original string.
+
+ OskWindow(const WindowDesc *desc, QueryStringBaseWindow *parent, int button, int cancel, int ok) : Window(desc)
+ {
+ this->parent = parent;
+ assert(parent != NULL);
+
+ if (parent->widget[button].data != 0) parent->caption = parent->widget[button].data;
+
+ this->qs = parent;
+ this->text_btn = button;
+ this->cancel_btn = cancel;
+ this->ok_btn = ok;
+ this->text = &parent->text;
+
+ /* make a copy in case we need to reset later */
+ strcpy(this->orig_str_buf, this->qs->text.buf);
+
+ SetBit(_no_scroll, SCROLL_EDIT);
+ /* Not needed by default. */
+ this->DisableWidget(OSK_WIDGET_SPECIAL);
+
+ this->FindWindowPlacementAndResize(desc);
}
- w->SetWidgetDisabledState(OSK_WIDGET_SPACE, !IsValidChar(' ', qs->afilter));
-}
-
-/* on screen keyboard */
-static void OskWndProc(Window *w, WindowEvent *e)
-{
- querystr_d *qs = WP(w, osk_d).qs;
- switch (e->event) {
- case WE_CREATE:
- SetBit(_no_scroll, SCROLL_EDIT);
- /* Not needed by default. */
- w->DisableWidget(OSK_WIDGET_SPECIAL);
- break;
+ /**
+ * Only show valid characters; do not show characters that would
+ * only insert a space when we have a spacebar to do that or
+ * characters that are not allowed to be entered.
+ */
+ void ChangeOskDiabledState(bool shift)
+ {
+ for (uint i = 0; i < OSK_KEYBOARD_ENTRIES; i++) {
+ this->SetWidgetDisabledState(OSK_WIDGET_LETTERS + i,
+ !IsValidChar(_keyboard[shift][i], this->qs->afilter) || _keyboard[shift][i] == ' ');
+ }
+ this->SetWidgetDisabledState(OSK_WIDGET_SPACE, !IsValidChar(' ', this->qs->afilter));
+ }
- case WE_PAINT: {
+ virtual void OnPaint()
+ {
+ bool shift = HasBit(_keystate, KEYS_CAPS) ^ HasBit(_keystate, KEYS_SHIFT);
+
+ this->LowerWidget(OSK_WIDGET_TEXT);
+ this->SetWidgetLoweredState(OSK_WIDGET_SHIFT, HasBit(_keystate, KEYS_SHIFT));
+ this->SetWidgetLoweredState(OSK_WIDGET_CAPS, HasBit(_keystate, KEYS_CAPS));
+
+ this->ChangeOskDiabledState(shift);
+
+ SetDParam(0, this->qs->caption);
+ DrawWindowWidgets(this);
+
+ for (uint i = 0; i < OSK_KEYBOARD_ENTRIES; i++) {
+ DrawCharCentered(_keyboard[shift][i],
+ this->widget[OSK_WIDGET_LETTERS + i].left + 8,
+ this->widget[OSK_WIDGET_LETTERS + i].top + 3,
+ TC_BLACK);
+ }
+
+ this->qs->DrawEditBox(this, OSK_WIDGET_TEXT);
+ }
+
+ virtual void OnClick(Point pt, int widget)
+ {
+ /* clicked a letter */
+ if (widget >= OSK_WIDGET_LETTERS) {
bool shift = HasBit(_keystate, KEYS_CAPS) ^ HasBit(_keystate, KEYS_SHIFT);
- w->LowerWidget(OSK_WIDGET_TEXT);
- w->SetWidgetLoweredState(OSK_WIDGET_SHIFT, HasBit(_keystate, KEYS_SHIFT));
- w->SetWidgetLoweredState(OSK_WIDGET_CAPS, HasBit(_keystate, KEYS_CAPS));
-
- ChangeOskDiabledState(w, qs, shift);
-
- SetDParam(0, qs->caption);
- DrawWindowWidgets(w);
+ WChar c = _keyboard[shift][widget - OSK_WIDGET_LETTERS];
- for (uint i = 0; i < OSK_KEYBOARD_ENTRIES; i++) {
- DrawCharCentered(_keyboard[shift][i],
- w->widget[OSK_WIDGET_LETTERS + i].left + 8,
- w->widget[OSK_WIDGET_LETTERS + i].top + 3,
- TC_BLACK);
+ if (!IsValidChar(c, this->qs->afilter)) return;
+
+ if (InsertTextBufferChar(&this->qs->text, c)) this->InvalidateWidget(OSK_WIDGET_TEXT);
+
+ if (HasBit(_keystate, KEYS_SHIFT)) {
+ ToggleBit(_keystate, KEYS_SHIFT);
+ this->widget[OSK_WIDGET_SHIFT].color = HasBit(_keystate, KEYS_SHIFT) ? 15 : 14;
+ this->SetDirty();
}
-
- DrawEditBox(w, qs, OSK_WIDGET_TEXT);
- break;
+ return;
}
- case WE_CLICK:
- /* clicked a letter */
- if (e->we.click.widget >= OSK_WIDGET_LETTERS) {
- bool shift = HasBit(_keystate, KEYS_CAPS) ^ HasBit(_keystate, KEYS_SHIFT);
-
- WChar c = _keyboard[shift][e->we.click.widget - OSK_WIDGET_LETTERS];
+ switch (widget) {
+ case OSK_WIDGET_BACKSPACE:
+ if (DeleteTextBufferChar(&this->qs->text, WKC_BACKSPACE)) this->InvalidateWidget(OSK_WIDGET_TEXT);
+ break;
- if (!IsValidChar(c, qs->afilter)) break;
-
- if (InsertTextBufferChar(&qs->text, c)) w->InvalidateWidget(OSK_WIDGET_TEXT);
+ case OSK_WIDGET_SPECIAL:
+ /*
+ * Anything device specific can go here.
+ * The button itself is hidden by default, and when you need it you
+ * can not hide it in the create event.
+ */
+ break;
- if (HasBit(_keystate, KEYS_SHIFT)) {
- ToggleBit(_keystate, KEYS_SHIFT);
- w->widget[OSK_WIDGET_SHIFT].color = HasBit(_keystate, KEYS_SHIFT) ? 15 : 14;
- w->SetDirty();
+ case OSK_WIDGET_CAPS:
+ ToggleBit(_keystate, KEYS_CAPS);
+ this->SetDirty();
+ break;
+
+ case OSK_WIDGET_SHIFT:
+ ToggleBit(_keystate, KEYS_SHIFT);
+ this->SetDirty();
+ break;
+
+ case OSK_WIDGET_SPACE:
+ if (InsertTextBufferChar(&this->qs->text, ' ')) this->InvalidateWidget(OSK_WIDGET_TEXT);
+ break;
+
+ case OSK_WIDGET_LEFT:
+ if (MoveTextBufferPos(&this->qs->text, WKC_LEFT)) this->InvalidateWidget(OSK_WIDGET_TEXT);
+ break;
+
+ case OSK_WIDGET_RIGHT:
+ if (MoveTextBufferPos(&this->qs->text, WKC_RIGHT)) this->InvalidateWidget(OSK_WIDGET_TEXT);
+ break;
+
+ case OSK_WIDGET_OK:
+ if (this->qs->orig == NULL || strcmp(this->qs->text.buf, this->qs->orig) != 0) {
+ /* pass information by simulating a button press on parent window */
+ if (this->ok_btn != 0) {
+ this->parent->OnClick(pt, this->ok_btn);
+ }
+ }
+ delete this;
+ break;
+
+ case OSK_WIDGET_CANCEL:
+ if (this->cancel_btn != 0) { // pass a cancel event to the parent window
+ this->parent->OnClick(pt, this->cancel_btn);
+ /* Window gets deleted when the parent window removes itself. */
+ } else { // or reset to original string
+ strcpy(qs->text.buf, this->orig_str_buf);
+ UpdateTextBufferSize(&qs->text);
+ MoveTextBufferPos(&qs->text, WKC_END);
+ delete this;
}
break;
- }
-
- switch (e->we.click.widget) {
- case OSK_WIDGET_BACKSPACE:
- if (DeleteTextBufferChar(&qs->text, WKC_BACKSPACE)) w->InvalidateWidget(OSK_WIDGET_TEXT);
- break;
-
- case OSK_WIDGET_SPECIAL:
- /*
- * Anything device specific can go here.
- * The button itself is hidden by default, and when you need it you
- * can not hide it in the create event.
- */
- break;
-
- case OSK_WIDGET_CAPS:
- ToggleBit(_keystate, KEYS_CAPS);
- w->SetDirty();
- break;
-
- case OSK_WIDGET_SHIFT:
- ToggleBit(_keystate, KEYS_SHIFT);
- w->SetDirty();
- break;
-
- case OSK_WIDGET_SPACE:
- if (InsertTextBufferChar(&qs->text, ' ')) w->InvalidateWidget(OSK_WIDGET_TEXT);
- break;
-
- case OSK_WIDGET_LEFT:
- if (MoveTextBufferPos(&qs->text, WKC_LEFT)) w->InvalidateWidget(OSK_WIDGET_TEXT);
- break;
-
- case OSK_WIDGET_RIGHT:
- if (MoveTextBufferPos(&qs->text, WKC_RIGHT)) w->InvalidateWidget(OSK_WIDGET_TEXT);
- break;
+ }
+ /* make sure that the parent window's textbox also gets updated */
+ if (this->parent != NULL) this->parent->InvalidateWidget(this->text_btn);
+ }
- case OSK_WIDGET_OK:
- if (qs->orig == NULL || strcmp(qs->text.buf, qs->orig) != 0) {
- /* pass information by simulating a button press on parent window */
- if (WP(w, osk_d).ok_btn != 0) {
- Window *parent = w->parent;
- WindowEvent e;
- e.event = WE_CLICK;
- e.we.click.widget = WP(w, osk_d).ok_btn;
- parent->HandleWindowEvent(&e);
- }
- }
- delete w;
- break;
-
- case OSK_WIDGET_CANCEL:
- if (WP(w, osk_d).cancel_btn != 0) { // pass a cancel event to the parent window
- Window *parent = w->parent;
- WindowEvent e;
- e.event = WE_CLICK;
- e.we.click.widget = WP(w, osk_d).cancel_btn;
- parent->HandleWindowEvent(&e);
- } else { // or reset to original string
- strcpy(qs->text.buf, WP(w, osk_d).orig);
- UpdateTextBufferSize(&qs->text);
- MoveTextBufferPos(&qs->text, WKC_END);
- }
- delete w;
- break;
- }
- /* make sure that the parent window's textbox also gets updated */
- if (w->parent != NULL) w->parent->InvalidateWidget(WP(w, osk_d).text_btn);
- break;
-
- case WE_MOUSELOOP:
- HandleEditBox(w, qs, OSK_WIDGET_TEXT);
- /* make the caret of the parent window also blink */
- w->parent->InvalidateWidget(WP(w, osk_d).text_btn);
- break;
+ virtual void OnMouseLoop()
+ {
+ this->qs->HandleEditBox(this, OSK_WIDGET_TEXT);
+ /* make the caret of the parent window also blink */
+ this->parent->InvalidateWidget(this->text_btn);
}
-}
+};
static const Widget _osk_widgets[] = {
{ WWT_EMPTY, RESIZE_NONE, 0, 0, 0, 0, 0, 0x0, STR_NULL},
@@ -277,7 +281,7 @@
WC_OSK, WC_NONE,
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
_osk_widgets,
- OskWndProc
+ NULL
};
/**
@@ -345,26 +349,10 @@
* @param ok widget number of parent's ok button (0 if ok events should not
* be passed)
*/
-void ShowOnScreenKeyboard(Window *parent, querystr_d *q, int button, int cancel, int ok)
+void ShowOnScreenKeyboard(QueryStringBaseWindow *parent, int button, int cancel, int ok)
{
DeleteWindowById(WC_OSK, 0);
- Window *w = AllocateWindowDesc(&_osk_desc);
-
- w->parent = parent;
- assert(parent != NULL);
-
- if (parent->widget[button].data != 0) q->caption = parent->widget[button].data;
-
- WP(w, osk_d).qs = q;
- WP(w, osk_d).text_btn = button;
- WP(w, osk_d).cancel_btn = cancel;
- WP(w, osk_d).ok_btn = ok;
- WP(w, osk_d).text = &q->text;
-
GetKeyboardLayout();
-
- /* make a copy in case we need to reset later */
- strcpy(_orig_str_buf, WP(w, osk_d).qs->text.buf);
- WP(w, osk_d).orig = _orig_str_buf;
+ new OskWindow(&_osk_desc, parent, button, cancel, ok);
}
--- a/src/player_gui.cpp Wed May 07 21:09:51 2008 +0000
+++ b/src/player_gui.cpp Sun May 11 20:09:34 2008 +0000
@@ -42,6 +42,12 @@
};
assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(facesel_d));
+struct highscore_d {
+ uint32 background_img;
+ int8 rank;
+};
+assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(highscore_d));
+
enum {
FIRST_GUI_CALL = INT_MAX, ///< default value to specify thuis is the first call of the resizable gui
};
@@ -247,7 +253,7 @@
{
if (!IsValidPlayer(player)) return;
- Window *w = AllocateWindowDescFront(show_small ? &_player_finances_small_desc : &_player_finances_desc, player);
+ Window *w = AllocateWindowDescFront<Window>(show_small ? &_player_finances_small_desc : &_player_finances_desc, player);
if (w != NULL) {
w->caption_color = w->window_number;
WP(w, def_d).data_1 = show_small;
@@ -973,6 +979,7 @@
break;
case WE_ON_EDIT_TEXT:
+ if (e->we.edittext.str == NULL) break;
/* Set a new player face number */
if (!StrEmpty(e->we.edittext.str)) {
*pf = strtoul(e->we.edittext.str, NULL, 10);
@@ -1018,7 +1025,7 @@
{
if (!IsValidPlayer(player)) return;
- Window *w = AllocateWindowDescFront(adv ? &_select_player_face_adv_desc : &_select_player_face_desc, player); // simple or advanced window
+ Window *w = AllocateWindowDescFront<Window>(adv ? &_select_player_face_adv_desc : &_select_player_face_desc, player); // simple or advanced window
if (w != NULL) {
w->caption_color = w->window_number;
@@ -1235,7 +1242,7 @@
case PCW_WIDGET_NEW_FACE: DoSelectPlayerFace((PlayerID)w->window_number, false); break;
case PCW_WIDGET_COLOR_SCHEME: {
- Window *wf = AllocateWindowDescFront(_loaded_newgrf_features.has_2CC ? &_select_player_livery_2cc_desc : &_select_player_livery_desc, w->window_number);
+ Window *wf = AllocateWindowDescFront<Window>(_loaded_newgrf_features.has_2CC ? &_select_player_livery_2cc_desc : &_select_player_livery_desc, w->window_number);
if (wf != NULL) {
wf->caption_color = wf->window_number;
WP(wf, livery_d).livery_class = LC_OTHER;
@@ -1303,7 +1310,7 @@
}
break;
- case WE_MOUSELOOP:
+ case WE_TICK:
/* redraw the window every now and then */
if ((++w->vscroll.pos & 0x1F) == 0) w->SetDirty();
break;
@@ -1325,7 +1332,7 @@
break;
case WE_ON_EDIT_TEXT:
- if (StrEmpty(e->we.edittext.str)) return;
+ if (StrEmpty(e->we.edittext.str)) break;
_cmd_text = e->we.edittext.str;
switch (WP(w, def_d).byte_1) {
@@ -1355,7 +1362,7 @@
if (!IsValidPlayer(player)) return;
- w = AllocateWindowDescFront(&_player_company_desc, player);
+ w = AllocateWindowDescFront<Window>(&_player_company_desc, player);
if (w != NULL) w->caption_color = w->window_number;
}
@@ -1411,7 +1418,7 @@
void ShowBuyCompanyDialog(uint player)
{
- AllocateWindowDescFront(&_buy_company_desc, player);
+ AllocateWindowDescFront<Window>(&_buy_company_desc, player);
}
/********** HIGHSCORE and ENDGAME windows */
@@ -1552,7 +1559,7 @@
if (_game_mode != GM_MENU) HideVitalWindows();
DeleteWindowByClass(WC_HIGHSCORE);
- w = AllocateWindowDesc(&_highscore_desc);
+ w = new Window(&_highscore_desc);
if (w != NULL) {
MarkWholeScreenDirty();
@@ -1575,7 +1582,7 @@
HideVitalWindows();
DeleteWindowByClass(WC_ENDSCREEN);
- w = AllocateWindowDesc(&_endgame_desc);
+ w = new Window(&_endgame_desc);
if (w != NULL) {
MarkWholeScreenDirty();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/querystring_gui.h Sun May 11 20:09:34 2008 +0000
@@ -0,0 +1,38 @@
+/* $Id$ */
+
+/** @file querystring_gui.h Base for the GUIs that have an edit box in them. */
+
+#ifndef QUERYSTRING_GUI_H
+#define QUERYSTRING_GUI_H
+
+#include "textbuf_gui.h"
+#include "window_gui.h"
+
+struct QueryString {
+ StringID caption;
+ Textbuf text;
+ const char *orig;
+ CharSetFilter afilter;
+ bool handled;
+
+ void DrawEditBox(Window *w, int wid);
+ void HandleEditBox(Window *w, int wid);
+ int HandleEditBoxKey(Window *w, int wid, uint16 key, uint16 keycode, bool &cont);
+};
+
+struct QueryStringBaseWindow : public Window, public QueryString {
+ char edit_str_buf[64];
+ char orig_str_buf[64];
+
+ QueryStringBaseWindow(const WindowDesc *desc, void *data = NULL, WindowNumber window_number = 0) : Window(desc, data, window_number)
+ {
+ }
+
+ void DrawEditBox(int wid);
+ void HandleEditBox(int wid);
+ int HandleEditBoxKey(int wid, uint16 key, uint16 keycode, bool &cont);
+};
+
+void ShowOnScreenKeyboard(QueryStringBaseWindow *parent, int button, int cancel, int ok);
+
+#endif /* QUERYSTRING_GUI_H */
--- a/src/rail.h Wed May 07 21:09:51 2008 +0000
+++ b/src/rail.h Sun May 11 20:09:34 2008 +0000
@@ -11,7 +11,7 @@
#include "gfx_type.h"
#include "core/bitmath_func.hpp"
#include "economy_func.h"
-#include "tile_cmd.h"
+#include "slope_type.h"
enum RailTypeFlag {
RTF_CATENARY = 0, ///< Set if the rail type should have catenary drawn
@@ -198,29 +198,8 @@
void *EnsureNoTrainOnTrackProc(Vehicle *v, void *data);
int TicksToLeaveDepot(const Vehicle *v);
-
-/**
- * Test if a rail type has catenary
- * @param rt Rail type to test
- */
-static inline bool HasCatenary(RailType rt)
-{
- return HasBit(GetRailTypeInfo(rt)->flags, RTF_CATENARY);
-}
-
-
-/**
- * Draws overhead wires and pylons for electric railways.
- * @param ti The TileInfo struct of the tile being drawn
- * @see DrawCatenaryRailway
- */
-void DrawCatenary(const TileInfo *ti);
-void DrawCatenaryOnTunnel(const TileInfo *ti);
-void DrawCatenaryOnBridge(const TileInfo *ti);
-
Foundation GetRailFoundation(Slope tileh, TrackBits bits);
-int32 SettingsDisableElrail(int32 p1); ///< _patches.disable_elrail callback
/**
* Finds out if a Player has a certain railtype available
--- a/src/rail_cmd.cpp Wed May 07 21:09:51 2008 +0000
+++ b/src/rail_cmd.cpp Sun May 11 20:09:34 2008 +0000
@@ -44,6 +44,7 @@
#include "station_map.h"
#include "water_map.h"
#include "functions.h"
+#include "elrail_func.h"
#include "oldpool_func.h"
#include "table/sprites.h"
@@ -1761,7 +1762,7 @@
if (HasBit(_display_opt, DO_FULL_DETAIL)) DrawTrackDetails(ti);
- if (HasCatenary(GetRailType(ti->tile))) DrawCatenary(ti);
+ if (HasCatenaryDrawn(GetRailType(ti->tile))) DrawCatenary(ti);
if (HasSignals(ti->tile)) DrawSignals(ti->tile, rails);
} else {
@@ -1840,7 +1841,7 @@
DrawGroundSprite(image, PAL_NONE);
- if (HasCatenary(GetRailType(ti->tile))) DrawCatenary(ti);
+ if (HasCatenaryDrawn(GetRailType(ti->tile))) DrawCatenary(ti);
/* End now if buildings are invisible */
if (IsInvisibilitySet(TO_BUILDINGS)) return;
--- a/src/rail_gui.cpp Wed May 07 21:09:51 2008 +0000
+++ b/src/rail_gui.cpp Sun May 11 20:09:34 2008 +0000
@@ -251,11 +251,6 @@
CMD_BUILD_TUNNEL | CMD_MSG(STR_5016_CAN_T_BUILD_TUNNEL_HERE));
}
-void PlaceProc_BuyLand(TileIndex tile)
-{
- DoCommandP(tile, 0, 0, CcPlaySound1E, CMD_PURCHASE_LAND_AREA | CMD_NO_WATER | CMD_MSG(STR_5806_CAN_T_PURCHASE_THIS_LAND));
-}
-
static void PlaceRail_ConvertRail(TileIndex tile)
{
VpStartPlaceSizing(tile, VPM_X_AND_Y, DDSP_CONVERT_RAIL);
@@ -752,7 +747,7 @@
if (button < 0 || !(w = FindWindowById(WC_BUILD_TOOLBAR, TRANSPORT_RAIL))) {
DeleteWindowByClass(WC_BUILD_TOOLBAR);
_cur_railtype = railtype;
- w = AllocateWindowDescFront(&_build_rail_desc, TRANSPORT_RAIL);
+ w = AllocateWindowDescFront<Window>(&_build_rail_desc, TRANSPORT_RAIL);
SetupRailToolbar(railtype, w);
}
@@ -1127,7 +1122,7 @@
w->SetDirty();
break;
- case WE_MOUSELOOP:
+ case WE_TICK:
if (WP(w, def_d).close) {
delete w;
return;
@@ -1226,10 +1221,10 @@
{
Window *w;
if (GetNumStationClasses() <= 2 && GetNumCustomStations(STAT_CLASS_DFLT) == 1) {
- w = AllocateWindowDesc(&_station_builder_desc);
+ w = new Window(&_station_builder_desc);
_railstation.newstations = false;
} else {
- w = AllocateWindowDesc(&_newstation_builder_desc);
+ w = new Window(&_newstation_builder_desc);
_railstation.newstations = true;
_railstation.station_count = GetNumCustomStations(_railstation.station_class);
@@ -1350,7 +1345,7 @@
w->SetDirty();
break;
- case WE_MOUSELOOP:
+ case WE_TICK:
if (WP(w, def_d).close) delete w;
return;
@@ -1397,7 +1392,7 @@
*/
static void ShowSignalBuilder()
{
- AllocateWindowDesc(&_signal_builder_desc);
+ new Window(&_signal_builder_desc);
}
/** Enum referring to the widgets of the build rail depot window */
@@ -1441,7 +1436,7 @@
}
break;
- case WE_MOUSELOOP:
+ case WE_TICK:
if (WP(w, def_d).close) delete w;
return;
@@ -1473,7 +1468,7 @@
static void ShowBuildTrainDepotPicker()
{
- AllocateWindowDesc(&_build_depot_desc);
+ new Window(&_build_depot_desc);
}
/** Enum referring to the widgets of the build NewGRF rail waypoint window */
@@ -1540,7 +1535,7 @@
break;
}
- case WE_MOUSELOOP:
+ case WE_TICK:
if (WP(w, def_d).close) delete w;
break;
@@ -1576,7 +1571,7 @@
static void ShowBuildWaypointPicker()
{
- Window *w = AllocateWindowDesc(&_build_waypoint_desc);
+ Window *w = new Window(&_build_waypoint_desc);
w->hscroll.cap = 5;
w->hscroll.count = _waypoint_count;
}
--- a/src/road_cmd.cpp Wed May 07 21:09:51 2008 +0000
+++ b/src/road_cmd.cpp Sun May 11 20:09:34 2008 +0000
@@ -37,6 +37,7 @@
#include "cheat_func.h"
#include "functions.h"
#include "effectvehicle_func.h"
+#include "elrail_func.h"
#include "oldpool_func.h"
#include "table/sprites.h"
@@ -1138,7 +1139,7 @@
DrawGroundSprite(SPR_TRAMWAY_OVERLAY + (GetCrossingRoadAxis(ti->tile) ^ 1), pal);
DrawTramCatenary(ti, GetCrossingRoadBits(ti->tile));
}
- if (HasCatenary(GetRailType(ti->tile))) DrawCatenary(ti);
+ if (HasCatenaryDrawn(GetRailType(ti->tile))) DrawCatenary(ti);
break;
}
--- a/src/road_gui.cpp Wed May 07 21:09:51 2008 +0000
+++ b/src/road_gui.cpp Sun May 11 20:09:34 2008 +0000
@@ -574,7 +574,7 @@
break;
case DDSP_DEMOLISH_AREA:
- DoCommandP(end_tile, start_tile, 0, CcPlaySound10, CMD_CLEAR_AREA | CMD_MSG(STR_00B5_CAN_T_CLEAR_THIS_AREA));
+ GUIPlaceProcDragXY(e);
break;
case DDSP_PLACE_ROAD_X_DIR:
@@ -679,7 +679,7 @@
_cur_roadtype = roadtype;
DeleteWindowByClass(WC_BUILD_TOOLBAR);
- Window *w = AllocateWindowDescFront(roadtype == ROADTYPE_ROAD ? &_build_road_desc : &_build_tramway_desc, TRANSPORT_ROAD);
+ Window *w = AllocateWindowDescFront<Window>(roadtype == ROADTYPE_ROAD ? &_build_road_desc : &_build_tramway_desc, TRANSPORT_ROAD);
if (_patches.link_terraform_toolbar) ShowTerraformToolbar(w);
}
@@ -714,7 +714,7 @@
void ShowBuildRoadScenToolbar()
{
_cur_roadtype = ROADTYPE_ROAD;
- AllocateWindowDescFront(&_build_road_scen_desc, 0);
+ AllocateWindowDescFront<Window>(&_build_road_scen_desc, 0);
}
/** Enum referring to the widgets of the build road depot window */
@@ -762,7 +762,7 @@
}
break;
- case WE_MOUSELOOP:
+ case WE_TICK:
if (WP(w, def_d).close) delete w;
break;
@@ -817,7 +817,7 @@
static void ShowRoadDepotPicker()
{
- AllocateWindowDesc(_cur_roadtype == ROADTYPE_ROAD ? &_build_road_depot_desc : &_build_tram_depot_desc);
+ new Window(_cur_roadtype == ROADTYPE_ROAD ? &_build_road_depot_desc : &_build_tram_depot_desc);
}
/** Enum referring to the widgets of the build road station window */
@@ -919,7 +919,7 @@
}
break;
- case WE_MOUSELOOP:
+ case WE_TICK:
if (WP(w, def_d).close) {
delete w;
return;
@@ -966,7 +966,7 @@
static void ShowRVStationPicker(RoadStopType rs)
{
- Window *w = AllocateWindowDesc(&_rv_station_picker_desc);
+ Window *w = new Window(&_rv_station_picker_desc);
if (w == NULL) return;
w->window_class = (rs == ROADSTOP_BUS) ? WC_BUS_STATION : WC_TRUCK_STATION;
--- a/src/saveload.cpp Wed May 07 21:09:51 2008 +0000
+++ b/src/saveload.cpp Sun May 11 20:09:34 2008 +0000
@@ -531,7 +531,7 @@
static inline size_t SlCalcNetStringLen(const char *ptr, size_t length)
{
if (ptr == NULL) return 0;
- return minu(strlen(ptr), length - 1);
+ return min(strlen(ptr), length - 1);
}
/** Calculate the gross length of the string that it
@@ -911,7 +911,7 @@
static void SlLoadChunk(const ChunkHandler *ch)
{
byte m = SlReadByte();
- size_t len;
+ uint32 len;
uint32 endoffs;
_sl.block_mode = m;
@@ -1204,9 +1204,9 @@
_z.avail_out = 4096;
do {
- /* read more bytes from the file?*/
+ /* read more bytes from the file? */
if (_z.avail_in == 0) {
- _z.avail_in = fread(_z.next_in = _sl.buf + 4096, 1, 4096, _sl.fh);
+ _z.avail_in = (uint)fread(_z.next_in = _sl.buf + 4096, 1, 4096, _sl.fh);
}
/* inflate the data */
@@ -1493,7 +1493,7 @@
_fast_forward = 0;
if (_cursor.sprite == SPR_CURSOR_MOUSE) SetMouseCursor(SPR_CURSOR_ZZZ, PAL_NONE);
- SendWindowMessage(WC_STATUS_BAR, 0, true, 0, 0);
+ InvalidateWindowData(WC_STATUS_BAR, 0, true);
_ts.saveinprogress = true;
}
@@ -1504,7 +1504,7 @@
_fast_forward = _ts.ff_state;
if (_cursor.sprite == SPR_CURSOR_ZZZ) SetMouseCursor(SPR_CURSOR_MOUSE, PAL_NONE);
- SendWindowMessage(WC_STATUS_BAR, 0, false, 0, 0);
+ InvalidateWindowData(WC_STATUS_BAR, 0, false);
_ts.saveinprogress = false;
}
--- a/src/settings.cpp Wed May 07 21:09:51 2008 +0000
+++ b/src/settings.cpp Sun May 11 20:09:34 2008 +0000
@@ -53,6 +53,7 @@
#include "textbuf_gui.h"
#include "string_func.h"
#include "rail_gui.h"
+#include "elrail_func.h"
#include "gui.h"
#include "town.h"
#include "video/video_driver.hpp"
@@ -78,18 +79,18 @@
typedef void SettingDescProcList(IniFile *ini, const char *grpname, char **list, uint len, SettingListCallbackProc proc);
static void pool_init(SettingsMemoryPool **pool);
-static void *pool_alloc(SettingsMemoryPool **pool, uint size);
-static void *pool_strdup(SettingsMemoryPool **pool, const char *mem, uint size);
+static void *pool_alloc(SettingsMemoryPool **pool, size_t size);
+static void *pool_strdup(SettingsMemoryPool **pool, const char *mem, size_t size);
static void pool_free(SettingsMemoryPool **pool);
static bool IsSignedVarMemType(VarType vt);
struct SettingsMemoryPool {
- uint pos, size;
+ size_t pos, size;
SettingsMemoryPool *next;
byte mem[1];
};
-static SettingsMemoryPool *pool_new(uint minsize)
+static SettingsMemoryPool *pool_new(size_t minsize)
{
SettingsMemoryPool *p;
if (minsize < 4096 - 12) minsize = 4096 - 12;
@@ -106,9 +107,9 @@
*pool = pool_new(0);
}
-static void *pool_alloc(SettingsMemoryPool **pool, uint size)
+static void *pool_alloc(SettingsMemoryPool **pool, size_t size)
{
- uint pos;
+ size_t pos;
SettingsMemoryPool *p = *pool;
size = Align(size, sizeof(void*));
@@ -129,7 +130,7 @@
return p->mem + pos;
}
-static void *pool_strdup(SettingsMemoryPool **pool, const char *mem, uint size)
+static void *pool_strdup(SettingsMemoryPool **pool, const char *mem, size_t size)
{
byte *p = (byte*)pool_alloc(pool, size + 1);
p[size] = 0;
@@ -186,7 +187,7 @@
}
/** allocate an ini group object */
-static IniGroup *ini_group_alloc(IniFile *ini, const char *grpt, int len)
+static IniGroup *ini_group_alloc(IniFile *ini, const char *grpt, size_t len)
{
IniGroup *grp = (IniGroup*)pool_alloc(&ini->pool, sizeof(IniGroup));
grp->ini = ini;
@@ -205,7 +206,7 @@
return grp;
}
-static IniItem *ini_item_alloc(IniGroup *group, const char *name, int len)
+static IniItem *ini_item_alloc(IniGroup *group, const char *name, size_t len)
{
IniItem *item = (IniItem*)pool_alloc(&group->ini->pool, sizeof(IniItem));
item->name = (char*)pool_strdup(&group->ini->pool, name, len);
@@ -324,11 +325,11 @@
}
/** lookup a group or make a new one */
-static IniGroup *ini_getgroup(IniFile *ini, const char *name, int len)
+static IniGroup *ini_getgroup(IniFile *ini, const char *name, size_t len = 0)
{
IniGroup *group;
- if (len == -1) len = strlen(name);
+ if (len == 0) len = strlen(name);
/* does it exist already? */
for (group = ini->group; group; group = group->next)
@@ -345,7 +346,7 @@
static IniItem *ini_getitem(IniGroup *group, const char *name, bool create)
{
IniItem *item;
- uint len = strlen(name);
+ size_t len = strlen(name);
for (item = group->item; item; item = item->next)
if (strcmp(item->name, name) == 0) return item;
@@ -404,12 +405,12 @@
* @param one the current value of the setting for which a value needs found
* @param onelen force calculation of the *one parameter
* @return the integer index of the full-list, or -1 if not found */
-static int lookup_oneofmany(const char *many, const char *one, int onelen)
+static int lookup_oneofmany(const char *many, const char *one, size_t onelen = 0)
{
const char *s;
int idx;
- if (onelen == -1) onelen = strlen(one);
+ if (onelen == 0) onelen = strlen(one);
/* check if it's an integer */
if (*one >= '0' && *one <= '9')
@@ -420,7 +421,7 @@
/* find end of item */
s = many;
while (*s != '|' && *s != 0) s++;
- if (s - many == onelen && !memcmp(one, many, onelen)) return idx;
+ if ((size_t)(s - many) == onelen && !memcmp(one, many, onelen)) return idx;
if (*s == 0) return -1;
many = s + 1;
idx++;
@@ -615,7 +616,7 @@
return (void*)val;
}
case SDT_ONEOFMANY: {
- long r = lookup_oneofmany(desc->many, str, -1);
+ long r = lookup_oneofmany(desc->many, str);
/* if the first attempt of conversion from string to the appropriate value fails,
* look if we have defined a converter from old value to new value. */
if (r == -1 && desc->proc_cnvt != NULL) r = desc->proc_cnvt(str);
@@ -706,7 +707,7 @@
static void ini_load_settings(IniFile *ini, const SettingDesc *sd, const char *grpname, void *object)
{
IniGroup *group;
- IniGroup *group_def = ini_getgroup(ini, grpname, -1);
+ IniGroup *group_def = ini_getgroup(ini, grpname);
IniItem *item;
const void *p;
void *ptr;
@@ -801,7 +802,7 @@
group = ini_getgroup(ini, sdb->name, s - sdb->name);
s++;
} else {
- if (group_def == NULL) group_def = ini_getgroup(ini, grpname, -1);
+ if (group_def == NULL) group_def = ini_getgroup(ini, grpname);
s = sdb->name;
group = group_def;
}
@@ -896,7 +897,7 @@
* inside the list */
static void ini_load_setting_list(IniFile *ini, const char *grpname, char **list, uint len, SettingListCallbackProc proc)
{
- IniGroup *group = ini_getgroup(ini, grpname, -1);
+ IniGroup *group = ini_getgroup(ini, grpname);
IniItem *item;
const char *entry;
uint i, j;
@@ -924,7 +925,7 @@
* @param proc callback function that can will provide the source data if defined */
static void ini_save_setting_list(IniFile *ini, const char *grpname, char **list, uint len, SettingListCallbackProc proc)
{
- IniGroup *group = ini_getgroup(ini, grpname, -1);
+ IniGroup *group = ini_getgroup(ini, grpname);
IniItem *item = NULL;
const char *entry;
uint i;
@@ -1140,6 +1141,14 @@
return 0;
}
+static int32 CloseSignalGUI(int32 p1)
+{
+ if (p1 == 0) {
+ DeleteWindowByClass(WC_BUILD_SIGNAL);
+ }
+ return 0;
+}
+
static int32 UpdateConsists(int32 p1)
{
Vehicle *v;
@@ -1236,7 +1245,7 @@
static int32 ConvertLandscape(const char *value)
{
/* try with the old values */
- return lookup_oneofmany("normal|hilly|desert|candy", value, -1);
+ return lookup_oneofmany("normal|hilly|desert|candy", value);
}
/* End - Callback Functions */
@@ -1407,7 +1416,7 @@
SDT_BOOL(Patches, longbridges, 0,NN, true, STR_CONFIG_PATCHES_LONGBRIDGES, NULL),
SDT_BOOL(Patches, signal_side, N,NN, true, STR_CONFIG_PATCHES_SIGNALSIDE, RedrawScreen),
SDT_BOOL(Patches, always_small_airport, 0,NN, false, STR_CONFIG_PATCHES_SMALL_AIRPORTS, NULL),
- SDT_BOOL(Patches, enable_signal_gui, S, 0, false, STR_CONFIG_PATCHES_ENABLE_SIGNAL_GUI, NULL),
+ SDT_BOOL(Patches, enable_signal_gui, S, 0, false, STR_CONFIG_PATCHES_ENABLE_SIGNAL_GUI, CloseSignalGUI),
SDT_VAR(Patches, drag_signals_density,SLE_UINT8,S, 0, 4, 1, 20, 0, STR_CONFIG_PATCHES_DRAG_SIGNALS_DENSITY,DragSignalsDensityChanged),
SDT_VAR(Patches, semaphore_build_before,SLE_INT32, S, NC, 1975, MIN_YEAR, MAX_YEAR, 1, STR_CONFIG_PATCHES_SEMAPHORE_BUILD_BEFORE_DATE, ResetSignalVariant),
SDT_CONDVAR(Patches, town_layout, SLE_UINT8, 59, SL_MAX_VERSION, 0, MS, TL_ORIGINAL, TL_NO_ROADS, NUM_TLS - 1, 1, STR_CONFIG_PATCHES_TOWN_LAYOUT, CheckTownLayout),
@@ -1650,7 +1659,7 @@
static void NewsDisplayLoadConfig(IniFile *ini, const char *grpname)
{
- IniGroup *group = ini_getgroup(ini, grpname, -1);
+ IniGroup *group = ini_getgroup(ini, grpname);
IniItem *item;
/* If no group exists, return */
@@ -1685,7 +1694,7 @@
/* Load a GRF configuration from the given group name */
static GRFConfig *GRFLoadConfig(IniFile *ini, const char *grpname, bool is_static)
{
- IniGroup *group = ini_getgroup(ini, grpname, -1);
+ IniGroup *group = ini_getgroup(ini, grpname);
IniItem *item;
GRFConfig *first = NULL;
GRFConfig **curr = &first;
@@ -1737,7 +1746,7 @@
static void NewsDisplaySaveConfig(IniFile *ini, const char *grpname)
{
- IniGroup *group = ini_getgroup(ini, grpname, -1);
+ IniGroup *group = ini_getgroup(ini, grpname);
IniItem **item;
if (group == NULL) return;
@@ -1762,7 +1771,7 @@
*/
static void SaveVersionInConfig(IniFile *ini)
{
- IniGroup *group = ini_getgroup(ini, "version", -1);
+ IniGroup *group = ini_getgroup(ini, "version");
if (group == NULL) return;
group->item = NULL;
@@ -1786,7 +1795,7 @@
/* Save a GRF configuration to the given group name */
static void GRFSaveConfig(IniFile *ini, const char *grpname, const GRFConfig *list)
{
- IniGroup *group = ini_getgroup(ini, grpname, -1);
+ IniGroup *group = ini_getgroup(ini, grpname);
IniItem **item;
const GRFConfig *c;
--- a/src/settings_gui.cpp Wed May 07 21:09:51 2008 +0000
+++ b/src/settings_gui.cpp Sun May 11 20:09:34 2008 +0000
@@ -389,7 +389,7 @@
void ShowGameOptions()
{
DeleteWindowById(WC_GAME_OPTIONS, 0);
- AllocateWindowDesc(&_game_options_desc);
+ new Window(&_game_options_desc);
}
struct GameSettingData {
@@ -655,7 +655,7 @@
break;
} break;
- case WE_MOUSELOOP: /* Handle the visual 'clicking' of the buttons */
+ case WE_TICK: /* Handle the visual 'clicking' of the buttons */
if (diffic_d->timeout != 0) {
diffic_d->timeout--;
if (diffic_d->timeout == 0) diffic_d->clicked_button = NO_SETTINGS_BUTTON;
@@ -698,7 +698,7 @@
/* Copy current settings (ingame or in intro) to temporary holding place
* change that when setting stuff, copy back on clicking 'OK' */
_opt_mod_temp = *_opt_ptr;
- AllocateWindowDesc(&_game_difficulty_desc);
+ new Window(&_game_difficulty_desc);
}
static const char *_patches_ui[] = {
@@ -1058,7 +1058,7 @@
break;
case WE_ON_EDIT_TEXT:
- if (e->we.edittext.str != NULL) {
+ if (!StrEmpty(e->we.edittext.str)) {
const PatchEntry *pe = &_patches_page[WP(w, def_d).data_1].entries[WP(w, def_d).data_3];
const SettingDesc *sd = pe->setting;
int32 value = atoi(e->we.edittext.str);
@@ -1103,7 +1103,7 @@
void ShowPatchesSelection()
{
DeleteWindowById(WC_GAME_OPTIONS, 0);
- AllocateWindowDesc(&_patches_selection_desc);
+ new Window(&_patches_selection_desc);
}
@@ -1270,6 +1270,8 @@
} break;
case WE_ON_EDIT_TEXT: {
+ if (e->we.edittext.str == NULL) break;
+
const char *b = e->we.edittext.str;
switch (WP(w, def_d).data_2) {
@@ -1278,7 +1280,7 @@
break;
case CUSTCURR_SEPARATOR: /* Thousands seperator */
- _custom_currency.separator = (b[0] == '\0') ? ' ' : b[0];
+ _custom_currency.separator = StrEmpty(b) ? ' ' : b[0];
ttd_strlcpy(_str_separator, b, lengthof(_str_separator));
break;
@@ -1333,5 +1335,5 @@
_str_separator[1] = '\0';
DeleteWindowById(WC_CUSTOM_CURRENCY, 0);
- AllocateWindowDesc(&_cust_currency_desc);
+ new Window(&_cust_currency_desc);
}
--- a/src/signs.cpp Wed May 07 21:09:51 2008 +0000
+++ b/src/signs.cpp Sun May 11 20:09:34 2008 +0000
@@ -13,6 +13,7 @@
#include "variables.h"
#include "strings_func.h"
#include "viewport_func.h"
+#include "tilehighlight_func.h"
#include "zoom_func.h"
#include "functions.h"
#include "window_func.h"
--- a/src/signs_gui.cpp Wed May 07 21:09:51 2008 +0000
+++ b/src/signs_gui.cpp Sun May 11 20:09:34 2008 +0000
@@ -19,6 +19,7 @@
#include "map_func.h"
#include "gfx_func.h"
#include "viewport_func.h"
+#include "querystring_gui.h"
#include "table/strings.h"
#include "table/sprites.h"
@@ -135,7 +136,7 @@
void ShowSignList()
{
- Window *w = AllocateWindowDescFront(&_sign_list_desc, 0);
+ Window *w = AllocateWindowDescFront<Window>(&_sign_list_desc, 0);
if (w != NULL) {
w->vscroll.cap = 12;
w->resize.step_height = 10;
@@ -143,11 +144,11 @@
}
}
-/** Edit sign window stuff */
-struct editsign_d : querystr_d {
- SignID cur_sign;
-};
-assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(editsign_d));
+static void RenameSign(SignID index, const char *text)
+{
+ _cmd_text = text;
+ DoCommandP(0, index, 0, NULL, CMD_RENAME_SIGN | CMD_MSG(STR_280C_CAN_T_CHANGE_SIGN_NAME));
+}
enum QueryEditSignWidgets {
QUERY_EDIT_SIGN_WIDGET_TEXT = 3,
@@ -158,120 +159,122 @@
QUERY_EDIT_SIGN_WIDGET_NEXT,
};
-static void UpdateSignEditWindow(Window *w, const Sign *si)
-{
- /* Display an empty string when the sign hasnt been edited yet */
- if (si->name != NULL) {
- SetDParam(0, si->index);
- GetString(_edit_str_buf, STR_SIGN_NAME, lastof(_edit_str_buf));
- } else {
- GetString(_edit_str_buf, STR_EMPTY, lastof(_edit_str_buf));
- }
- _edit_str_buf[lengthof(_edit_str_buf) - 1] = '\0';
-
- WP(w, editsign_d).cur_sign = si->index;
- InitializeTextBuffer(&WP(w, querystr_d).text, _edit_str_buf, 31, 255); // Allow 31 characters (including \0)
-
- w->InvalidateWidget(QUERY_EDIT_SIGN_WIDGET_TEXT);
-}
-
-static void RenameSign(SignID index, const char *text)
-{
- _cmd_text = text;
- DoCommandP(0, index, 0, NULL, CMD_RENAME_SIGN | CMD_MSG(STR_280C_CAN_T_CHANGE_SIGN_NAME));
-}
-
-static void QuerySignEditWndProc(Window *w, WindowEvent *e)
-{
- editsign_d *qs = &WP(w, editsign_d);
- Sign *si;
- uint sign_index = 0;
-
- switch (e->event) {
- case WE_CREATE:
- SetBit(_no_scroll, SCROLL_EDIT);
- break;
-
- case WE_PAINT:
- SetDParam(0, qs->caption);
- DrawWindowWidgets(w);
- DrawEditBox(w, qs, QUERY_EDIT_SIGN_WIDGET_TEXT);
- break;
-
- case WE_CLICK:
- switch (e->we.click.widget) {
- case QUERY_EDIT_SIGN_WIDGET_PREVIOUS:
- if (_sign_sort_dirty) GlobalSortSignList();
- sign_index = _sign_sort[_num_sign_sort - 1]->index;
- for (uint i = 1; i < _num_sign_sort; i++) {
- if (qs->cur_sign == _sign_sort[i]->index) {
- sign_index = _sign_sort[i - 1]->index;
- break;
- }
- }
- si = GetSign(sign_index);
+struct SignWindow : QueryStringBaseWindow {
+ SignID cur_sign;
- /* Scroll to sign and reopen window */
- ScrollMainWindowToTile(TileVirtXY(si->x, si->y));
- UpdateSignEditWindow(w, si);
- break;
-
- case QUERY_EDIT_SIGN_WIDGET_NEXT:
- if (_sign_sort_dirty) GlobalSortSignList();
- sign_index = _sign_sort[0]->index;
- for (uint i = 0; i < _num_sign_sort - 1; i++) {
- if (qs->cur_sign == _sign_sort[i]->index) {
- sign_index = _sign_sort[i + 1]->index;
- break;
- }
- }
- si = GetSign(sign_index);
-
- /* Scroll to sign and reopen window */
- ScrollMainWindowToTile(TileVirtXY(si->x, si->y));
- UpdateSignEditWindow(w, si);
- break;
-
- case QUERY_EDIT_SIGN_WIDGET_TEXT:
- ShowOnScreenKeyboard(w, qs, e->we.click.widget, QUERY_EDIT_SIGN_WIDGET_CANCEL, QUERY_EDIT_SIGN_WIDGET_OK);
- break;
-
- case QUERY_EDIT_SIGN_WIDGET_DELETE:
- /* Only need to set the buffer to null, the rest is handled as the OK button */
- DeleteTextBufferAll(&qs->text);
- /* FALL THROUGH */
+ SignWindow(const WindowDesc *desc, const Sign *si) : QueryStringBaseWindow(desc)
+ {
+ SetBit(_no_scroll, SCROLL_EDIT);
+ this->caption = STR_280B_EDIT_SIGN_TEXT;
+ this->afilter = CS_ALPHANUMERAL;
+ this->LowerWidget(QUERY_EDIT_SIGN_WIDGET_TEXT);
- case QUERY_EDIT_SIGN_WIDGET_OK:
- RenameSign(qs->cur_sign, qs->text.buf);
- /* FALL THROUGH */
-
- case QUERY_EDIT_SIGN_WIDGET_CANCEL:
- delete w;
- break;
- }
- break;
+ UpdateSignEditWindow(si);
+ }
- case WE_KEYPRESS:
- switch (HandleEditBoxKey(w, qs, QUERY_EDIT_SIGN_WIDGET_TEXT, e)) {
- case 1: // Enter pressed, confirms change
- RenameSign(qs->cur_sign, qs->text.buf);
- /* FALL THROUGH */
+ ~SignWindow()
+ {
+ ClrBit(_no_scroll, SCROLL_EDIT);
+ }
- case 2: // ESC pressed, closes window, abandons changes
- delete w;
- break;
- }
- break;
+ void UpdateSignEditWindow(const Sign *si)
+ {
+ /* Display an empty string when the sign hasnt been edited yet */
+ if (si->name != NULL) {
+ SetDParam(0, si->index);
+ GetString(this->edit_str_buf, STR_SIGN_NAME, lastof(this->edit_str_buf));
+ } else {
+ GetString(this->edit_str_buf, STR_EMPTY, lastof(this->edit_str_buf));
+ }
+ this->edit_str_buf[lengthof(this->edit_str_buf) - 1] = '\0';
- case WE_MOUSELOOP:
- HandleEditBox(w, qs, QUERY_EDIT_SIGN_WIDGET_TEXT);
- break;
+ this->cur_sign = si->index;
+ InitializeTextBuffer(&this->text, this->edit_str_buf, 31, 255); // Allow 31 characters (including \0)
- case WE_DESTROY:
- ClrBit(_no_scroll, SCROLL_EDIT);
- break;
+ this->InvalidateWidget(QUERY_EDIT_SIGN_WIDGET_TEXT);
}
-}
+
+ virtual void OnPaint()
+ {
+ SetDParam(0, this->caption);
+ DrawWindowWidgets(this);
+ this->DrawEditBox(QUERY_EDIT_SIGN_WIDGET_TEXT);
+ }
+
+ virtual void OnClick(Point pt, int widget)
+ {
+ switch (widget) {
+ case QUERY_EDIT_SIGN_WIDGET_PREVIOUS: {
+ if (_sign_sort_dirty) GlobalSortSignList();
+ SignID sign_index = _sign_sort[_num_sign_sort - 1]->index;
+ for (uint i = 1; i < _num_sign_sort; i++) {
+ if (this->cur_sign == _sign_sort[i]->index) {
+ sign_index = _sign_sort[i - 1]->index;
+ break;
+ }
+ }
+ const Sign *si = GetSign(sign_index);
+
+ /* Scroll to sign and reopen window */
+ ScrollMainWindowToTile(TileVirtXY(si->x, si->y));
+ UpdateSignEditWindow(si);
+ } break;
+
+ case QUERY_EDIT_SIGN_WIDGET_NEXT: {
+ if (_sign_sort_dirty) GlobalSortSignList();
+ SignID sign_index = _sign_sort[0]->index;
+ for (uint i = 0; i < _num_sign_sort - 1; i++) {
+ if (this->cur_sign == _sign_sort[i]->index) {
+ sign_index = _sign_sort[i + 1]->index;
+ break;
+ }
+ }
+ const Sign *si = GetSign(sign_index);
+
+ /* Scroll to sign and reopen window */
+ ScrollMainWindowToTile(TileVirtXY(si->x, si->y));
+ UpdateSignEditWindow(si);
+ } break;
+
+ case QUERY_EDIT_SIGN_WIDGET_TEXT:
+ ShowOnScreenKeyboard(this, widget, QUERY_EDIT_SIGN_WIDGET_CANCEL, QUERY_EDIT_SIGN_WIDGET_OK);
+ break;
+
+ case QUERY_EDIT_SIGN_WIDGET_DELETE:
+ /* Only need to set the buffer to null, the rest is handled as the OK button */
+ DeleteTextBufferAll(&this->text);
+ /* FALL THROUGH */
+
+ case QUERY_EDIT_SIGN_WIDGET_OK:
+ RenameSign(this->cur_sign, this->text.buf);
+ /* FALL THROUGH */
+
+ case QUERY_EDIT_SIGN_WIDGET_CANCEL:
+ delete this;
+ break;
+ }
+ }
+
+ virtual bool OnKeyPress(uint16 key, uint16 keycode)
+ {
+ bool cont = true;
+ switch (this->HandleEditBoxKey(QUERY_EDIT_SIGN_WIDGET_TEXT, key, keycode, cont)) {
+ case 1: // Enter pressed, confirms change
+ RenameSign(this->cur_sign, this->text.buf);
+ /* FALL THROUGH */
+
+ case 2: // ESC pressed, closes window, abandons changes
+ delete this;
+ break;
+ }
+ return cont;
+ }
+
+ virtual void OnMouseLoop()
+ {
+ this->HandleEditBox(QUERY_EDIT_SIGN_WIDGET_TEXT);
+ }
+};
static const Widget _query_sign_edit_widgets[] = {
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
@@ -292,7 +295,7 @@
WC_QUERY_STRING, WC_NONE,
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
_query_sign_edit_widgets,
- QuerySignEditWndProc
+ NULL
};
void ShowRenameSignWindow(const Sign *si)
@@ -301,11 +304,5 @@
DeleteWindowById(WC_QUERY_STRING, 0);
DeleteWindowById(WC_SAVELOAD, 0);
- Window *w = AllocateWindowDesc(&_query_sign_edit_desc);
-
- WP(w, editsign_d).caption = STR_280B_EDIT_SIGN_TEXT;
- WP(w, editsign_d).afilter = CS_ALPHANUMERAL;
- w->LowerWidget(QUERY_EDIT_SIGN_WIDGET_TEXT);
-
- UpdateSignEditWindow(w, si);
+ new SignWindow(&_query_sign_edit_desc, si);
}
--- a/src/smallmap_gui.cpp Wed May 07 21:09:51 2008 +0000
+++ b/src/smallmap_gui.cpp Sun May 11 20:09:34 2008 +0000
@@ -554,539 +554,536 @@
SM_WIDGET_RESIZEBOX,
};
-enum SmallMapType {
- SMT_CONTOUR,
- SMT_VEHICLES,
- SMT_INDUSTRY,
- SMT_OWNER = 5,
-};
-
-/**
- * Draws the small map.
- *
- * Basically, the small map is draw column of pixels by column of pixels. The pixels
- * are drawn directly into the screen buffer. The final map is drawn in multiple passes.
- * The passes are:
- * <ol><li>The colors of tiles in the different modes.</li>
- * <li>Town names (optional)</li></ol>
- *
- * @param dpi pointer to pixel to write onto
- * @param w pointer to Window struct
- * @param type type of map requested (vegetation, owners, routes, etc)
- * @param show_towns true if the town names should be displayed, false if not.
- */
-static void DrawSmallMap(DrawPixelInfo *dpi, Window *w, int type, bool show_towns)
+class SmallMapWindow : public Window
{
- Blitter *blitter = BlitterFactoryBase::GetCurrentBlitter();
- DrawPixelInfo *old_dpi;
- int dx,dy, x, y, x2, y2;
- void *ptr;
- int tile_x;
- int tile_y;
- ViewPort *vp;
-
- old_dpi = _cur_dpi;
- _cur_dpi = dpi;
-
- /* clear it */
- GfxFillRect(dpi->left, dpi->top, dpi->left + dpi->width - 1, dpi->top + dpi->height - 1, 0);
-
- /* setup owner table */
- if (type == SMT_OWNER) {
- const Player *p;
+ enum SmallMapType {
+ SMT_CONTOUR,
+ SMT_VEHICLES,
+ SMT_INDUSTRY,
+ SMT_OWNER = 5,
+ };
- /* fill with some special colors */
- _owner_colors[OWNER_TOWN] = MKCOLOR(0xB4B4B4B4);
- _owner_colors[OWNER_NONE] = MKCOLOR(0x54545454);
- _owner_colors[OWNER_WATER] = MKCOLOR(0xCACACACA);
- _owner_colors[OWNER_END] = MKCOLOR(0x20202020); /* industry */
-
- /* now fill with the player colors */
- FOR_ALL_PLAYERS(p) {
- if (p->is_active) {
- _owner_colors[p->index] =
- _colour_gradient[p->player_color][5] * 0x01010101;
- }
- }
- }
-
- tile_x = WP(w, smallmap_d).scroll_x / TILE_SIZE;
- tile_y = WP(w, smallmap_d).scroll_y / TILE_SIZE;
-
- dx = dpi->left + WP(w, smallmap_d).subscroll;
- tile_x -= dx / 4;
- tile_y += dx / 4;
- dx &= 3;
+ enum {
+ BASE_NB_PER_COLUMN = 6,
+ };
- dy = dpi->top;
- tile_x += dy / 2;
- tile_y += dy / 2;
-
- if (dy & 1) {
- tile_x++;
- dx += 2;
- if (dx > 3) {
- dx -= 4;
- tile_x--;
- tile_y++;
- }
- }
+ int32 scroll_x;
+ int32 scroll_y;
+ int32 subscroll;
- ptr = blitter->MoveTo(dpi->dst_ptr, -dx - 4, 0);
- x = - dx - 4;
- y = 0;
+public:
+ /**
+ * Draws the small map.
+ *
+ * Basically, the small map is draw column of pixels by column of pixels. The pixels
+ * are drawn directly into the screen buffer. The final map is drawn in multiple passes.
+ * The passes are:
+ * <ol><li>The colors of tiles in the different modes.</li>
+ * <li>Town names (optional)</li></ol>
+ *
+ * @param dpi pointer to pixel to write onto
+ * @param w pointer to Window struct
+ * @param type type of map requested (vegetation, owners, routes, etc)
+ * @param show_towns true if the town names should be displayed, false if not.
+ */
+ void DrawSmallMap(DrawPixelInfo *dpi, int type, bool show_towns)
+ {
+ Blitter *blitter = BlitterFactoryBase::GetCurrentBlitter();
+ DrawPixelInfo *old_dpi;
+ int dx,dy, x, y, x2, y2;
+ void *ptr;
+ int tile_x;
+ int tile_y;
+ ViewPort *vp;
- for (;;) {
- uint32 mask = 0xFFFFFFFF;
- int reps;
- int t;
+ old_dpi = _cur_dpi;
+ _cur_dpi = dpi;
- /* distance from left edge */
- if (x < 0) {
- if (x < -3) goto skip_column;
- /* mask to use at the left edge */
- mask = _smallmap_mask_left[x + 3];
+ /* clear it */
+ GfxFillRect(dpi->left, dpi->top, dpi->left + dpi->width - 1, dpi->top + dpi->height - 1, 0);
+
+ /* setup owner table */
+ if (type == SMT_OWNER) {
+ const Player *p;
+
+ /* fill with some special colors */
+ _owner_colors[OWNER_TOWN] = MKCOLOR(0xB4B4B4B4);
+ _owner_colors[OWNER_NONE] = MKCOLOR(0x54545454);
+ _owner_colors[OWNER_WATER] = MKCOLOR(0xCACACACA);
+ _owner_colors[OWNER_END] = MKCOLOR(0x20202020); /* industry */
+
+ /* now fill with the player colors */
+ FOR_ALL_PLAYERS(p) {
+ if (p->is_active) {
+ _owner_colors[p->index] =
+ _colour_gradient[p->player_color][5] * 0x01010101;
+ }
+ }
}
- /* distance from right edge */
- t = dpi->width - x;
- if (t < 4) {
- if (t <= 0) break; /* exit loop */
- /* mask to use at the right edge */
- mask &= _smallmap_mask_right[t - 1];
- }
+ tile_x = this->scroll_x / TILE_SIZE;
+ tile_y = this->scroll_y / TILE_SIZE;
- /* number of lines */
- reps = (dpi->height - y + 1) / 2;
- if (reps > 0) {
- DrawSmallMapStuff(ptr, tile_x, tile_y, dpi->pitch * 2, reps, mask, _smallmap_draw_procs[type]);
+ dx = dpi->left + this->subscroll;
+ tile_x -= dx / 4;
+ tile_y += dx / 4;
+ dx &= 3;
+
+ dy = dpi->top;
+ tile_x += dy / 2;
+ tile_y += dy / 2;
+
+ if (dy & 1) {
+ tile_x++;
+ dx += 2;
+ if (dx > 3) {
+ dx -= 4;
+ tile_x--;
+ tile_y++;
+ }
}
-skip_column:
- if (y == 0) {
- tile_y++;
- y++;
- ptr = blitter->MoveTo(ptr, 0, 1);
- } else {
- tile_x--;
- y--;
- ptr = blitter->MoveTo(ptr, 0, -1);
- }
- ptr = blitter->MoveTo(ptr, 2, 0);
- x += 2;
- }
+ ptr = blitter->MoveTo(dpi->dst_ptr, -dx - 4, 0);
+ x = - dx - 4;
+ y = 0;
- /* draw vehicles? */
- if (type == SMT_CONTOUR || type == SMT_VEHICLES) {
- Vehicle *v;
- bool skip;
- byte color;
+ for (;;) {
+ uint32 mask = 0xFFFFFFFF;
+ int reps;
+ int t;
- FOR_ALL_VEHICLES(v) {
- if (v->type != VEH_EFFECT &&
- (v->vehstatus & (VS_HIDDEN | VS_UNCLICKABLE)) == 0) {
- /* Remap into flat coordinates. */
+ /* distance from left edge */
+ if (x < 0) {
+ if (x < -3) goto skip_column;
+ /* mask to use at the left edge */
+ mask = _smallmap_mask_left[x + 3];
+ }
+
+ /* distance from right edge */
+ t = dpi->width - x;
+ if (t < 4) {
+ if (t <= 0) break; /* exit loop */
+ /* mask to use at the right edge */
+ mask &= _smallmap_mask_right[t - 1];
+ }
+
+ /* number of lines */
+ reps = (dpi->height - y + 1) / 2;
+ if (reps > 0) {
+ DrawSmallMapStuff(ptr, tile_x, tile_y, dpi->pitch * 2, reps, mask, _smallmap_draw_procs[type]);
+ }
+
+ skip_column:
+ if (y == 0) {
+ tile_y++;
+ y++;
+ ptr = blitter->MoveTo(ptr, 0, 1);
+ } else {
+ tile_x--;
+ y--;
+ ptr = blitter->MoveTo(ptr, 0, -1);
+ }
+ ptr = blitter->MoveTo(ptr, 2, 0);
+ x += 2;
+ }
+
+ /* draw vehicles? */
+ if (type == SMT_CONTOUR || type == SMT_VEHICLES) {
+ Vehicle *v;
+ bool skip;
+ byte color;
+
+ FOR_ALL_VEHICLES(v) {
+ if (v->type != VEH_EFFECT &&
+ (v->vehstatus & (VS_HIDDEN | VS_UNCLICKABLE)) == 0) {
+ /* Remap into flat coordinates. */
+ Point pt = RemapCoords(
+ v->x_pos / TILE_SIZE - this->scroll_x / TILE_SIZE, // divide each one separately because (a-b)/c != a/c-b/c in integer world
+ v->y_pos / TILE_SIZE - this->scroll_y / TILE_SIZE, // dtto
+ 0);
+ x = pt.x;
+ y = pt.y;
+
+ /* Check if y is out of bounds? */
+ y -= dpi->top;
+ if (!IsInsideMM(y, 0, dpi->height)) continue;
+
+ /* Default is to draw both pixels. */
+ skip = false;
+
+ /* Offset X coordinate */
+ x -= this->subscroll + 3 + dpi->left;
+
+ if (x < 0) {
+ /* if x+1 is 0, that means we're on the very left edge,
+ * and should thus only draw a single pixel */
+ if (++x != 0) continue;
+ skip = true;
+ } else if (x >= dpi->width - 1) {
+ /* Check if we're at the very right edge, and if so draw only a single pixel */
+ if (x != dpi->width - 1) continue;
+ skip = true;
+ }
+
+ /* Calculate pointer to pixel and the color */
+ color = (type == SMT_VEHICLES) ? _vehicle_type_colors[v->type] : 0xF;
+
+ /* And draw either one or two pixels depending on clipping */
+ blitter->SetPixel(dpi->dst_ptr, x, y, color);
+ if (!skip) blitter->SetPixel(dpi->dst_ptr, x + 1, y, color);
+ }
+ }
+ }
+
+ if (show_towns) {
+ const Town *t;
+
+ FOR_ALL_TOWNS(t) {
+ /* Remap the town coordinate */
Point pt = RemapCoords(
- v->x_pos / TILE_SIZE - WP(w, smallmap_d).scroll_x / TILE_SIZE, // divide each one separately because (a-b)/c != a/c-b/c in integer world
- v->y_pos / TILE_SIZE - WP(w, smallmap_d).scroll_y / TILE_SIZE, // dtto
+ (int)(TileX(t->xy) * TILE_SIZE - this->scroll_x) / TILE_SIZE,
+ (int)(TileY(t->xy) * TILE_SIZE - this->scroll_y) / TILE_SIZE,
0);
- x = pt.x;
+ x = pt.x - this->subscroll + 3 - (t->sign.width_2 >> 1);
y = pt.y;
- /* Check if y is out of bounds? */
- y -= dpi->top;
- if (!IsInsideMM(y, 0, dpi->height)) continue;
-
- /* Default is to draw both pixels. */
- skip = false;
-
- /* Offset X coordinate */
- x -= WP(w, smallmap_d).subscroll + 3 + dpi->left;
-
- if (x < 0) {
- /* if x+1 is 0, that means we're on the very left edge,
- * and should thus only draw a single pixel */
- if (++x != 0) continue;
- skip = true;
- } else if (x >= dpi->width - 1) {
- /* Check if we're at the very right edge, and if so draw only a single pixel */
- if (x != dpi->width - 1) continue;
- skip = true;
+ /* Check if the town sign is within bounds */
+ if (x + t->sign.width_2 > dpi->left &&
+ x < dpi->left + dpi->width &&
+ y + 6 > dpi->top &&
+ y < dpi->top + dpi->height) {
+ /* And draw it. */
+ SetDParam(0, t->index);
+ DrawString(x, y, STR_2056, TC_WHITE);
}
-
- /* Calculate pointer to pixel and the color */
- color = (type == SMT_VEHICLES) ? _vehicle_type_colors[v->type] : 0xF;
-
- /* And draw either one or two pixels depending on clipping */
- blitter->SetPixel(dpi->dst_ptr, x, y, color);
- if (!skip) blitter->SetPixel(dpi->dst_ptr, x + 1, y, color);
}
}
+
+ /* Draw map indicators */
+ {
+ Point pt;
+
+ /* Find main viewport. */
+ vp = FindWindowById(WC_MAIN_WINDOW,0)->viewport;
+
+ pt = RemapCoords(this->scroll_x, this->scroll_y, 0);
+
+ x = vp->virtual_left - pt.x;
+ y = vp->virtual_top - pt.y;
+ x2 = (x + vp->virtual_width) / TILE_SIZE;
+ y2 = (y + vp->virtual_height) / TILE_SIZE;
+ x /= TILE_SIZE;
+ y /= TILE_SIZE;
+
+ x -= this->subscroll;
+ x2 -= this->subscroll;
+
+ DrawVertMapIndicator(x, y, x, y2);
+ DrawVertMapIndicator(x2, y, x2, y2);
+
+ DrawHorizMapIndicator(x, y, x2, y);
+ DrawHorizMapIndicator(x, y2, x2, y2);
+ }
+ _cur_dpi = old_dpi;
}
- if (show_towns) {
- const Town *t;
+ void SmallMapCenterOnCurrentPos()
+ {
+ int x, y;
+ ViewPort *vp;
+ vp = FindWindowById(WC_MAIN_WINDOW, 0)->viewport;
- FOR_ALL_TOWNS(t) {
- /* Remap the town coordinate */
- Point pt = RemapCoords(
- (int)(TileX(t->xy) * TILE_SIZE - WP(w, smallmap_d).scroll_x) / TILE_SIZE,
- (int)(TileY(t->xy) * TILE_SIZE - WP(w, smallmap_d).scroll_y) / TILE_SIZE,
- 0);
- x = pt.x - WP(w, smallmap_d).subscroll + 3 - (t->sign.width_2 >> 1);
- y = pt.y;
+ x = ((vp->virtual_width - (this->widget[SM_WIDGET_MAP].right - this->widget[SM_WIDGET_MAP].left) * TILE_SIZE) / 2 + vp->virtual_left) / 4;
+ y = ((vp->virtual_height - (this->widget[SM_WIDGET_MAP].bottom - this->widget[SM_WIDGET_MAP].top ) * TILE_SIZE) / 2 + vp->virtual_top ) / 2 - TILE_SIZE * 2;
+ this->scroll_x = (y - x) & ~0xF;
+ this->scroll_y = (x + y) & ~0xF;
+ this->SetDirty();
+ }
- /* Check if the town sign is within bounds */
- if (x + t->sign.width_2 > dpi->left &&
- x < dpi->left + dpi->width &&
- y + 6 > dpi->top &&
- y < dpi->top + dpi->height) {
- /* And draw it. */
- SetDParam(0, t->index);
- DrawString(x, y, STR_2056, TC_WHITE);
+ SmallMapWindow(const WindowDesc *desc, void *data, int window_number) : Window(desc, data, window_number)
+ {
+ /* Resize the window to fit industries list */
+ if (_industries_per_column > BASE_NB_PER_COLUMN) {
+ uint diff = ((_industries_per_column - BASE_NB_PER_COLUMN) * BASE_NB_PER_COLUMN) + 1;
+
+ this->height = this->height + diff;
+
+ Widget *wi = &this->widget[SM_WIDGET_LEGEND]; // label panel
+ wi->bottom = wi->bottom + diff;
+
+ wi = &this->widget[SM_WIDGET_BUTTONSPANEL]; // filler panel under smallmap buttons
+ wi->bottom = wi->bottom + diff - 1;
+
+ /* Change widget position
+ * - footer panel
+ * - enable all industry
+ * - disable all industry
+ * - resize window button
+ */
+ for (uint i = SM_WIDGET_BOTTOMPANEL; i <= SM_WIDGET_RESIZEBOX; i++) {
+ wi = &this->widget[i];
+ wi->top = wi->top + diff;
+ wi->bottom = wi->bottom + diff;
}
}
+
+ this->LowerWidget(_smallmap_type + SMT_OWNER);
+ this->SetWidgetLoweredState(SM_WIDGET_TOGGLETOWNNAME, _smallmap_show_towns);
+
+ this->SmallMapCenterOnCurrentPos();
+ this->FindWindowPlacementAndResize(desc);
+ }
+
+ virtual void OnPaint()
+ {
+ const LegendAndColour *tbl;
+ int x, y, y_org;
+ uint diff;
+ DrawPixelInfo new_dpi;
+
+ /* Hide Enable all/Disable all buttons if is not industry type small map*/
+ this->SetWidgetHiddenState(SM_WIDGET_ENABLEINDUSTRIES, _smallmap_type != SMT_INDUSTRY);
+ this->SetWidgetHiddenState(SM_WIDGET_DISABLEINDUSTRIES, _smallmap_type != SMT_INDUSTRY);
+
+ /* draw the window */
+ SetDParam(0, STR_00E5_CONTOURS + _smallmap_type);
+ DrawWindowWidgets(this);
+
+ tbl = _legend_table[_smallmap_type];
+
+ /* difference in window size */
+ diff = (_industries_per_column > BASE_NB_PER_COLUMN) ? ((_industries_per_column - BASE_NB_PER_COLUMN) * BASE_NB_PER_COLUMN) + 1 : 0;
+
+ x = 4;
+ y_org = this->height - 44 - 11 - diff;
+ y = y_org;
+
+ for (;;) {
+ if (_smallmap_type == SMT_INDUSTRY) {
+ /* Industry name must be formated, since it's not in tiny font in the specs.
+ * So, draw with a parameter and use the STR_SMALLMAP_INDUSTRY string, which is tiny font.*/
+ SetDParam(0, tbl->legend);
+ assert(tbl->type < NUM_INDUSTRYTYPES);
+ SetDParam(1, _industry_counts[tbl->type]);
+ if (!tbl->show_on_map) {
+ /* Simply draw the string, not the black border of the legend color.
+ * This will enforce the idea of the disabled item */
+ DrawString(x + 11, y, STR_SMALLMAP_INDUSTRY, TC_GREY);
+ } else {
+ DrawString(x + 11, y, STR_SMALLMAP_INDUSTRY, TC_BLACK);
+ GfxFillRect(x, y + 1, x + 8, y + 5, 0); // outer border of the legend color
+ }
+ } else {
+ /* Anything that is not an industry is using normal process */
+ GfxFillRect(x, y + 1, x + 8, y + 5, 0);
+ DrawString(x + 11, y, tbl->legend, TC_FROMSTRING);
+ }
+ GfxFillRect(x + 1, y + 2, x + 7, y + 4, tbl->colour); // legend color
+
+ tbl += 1;
+ y += 6;
+
+ if (tbl->end) { // end of the list
+ break;
+ } else if (tbl->col_break) {
+ /* break asked, continue at top, 123 pixels (one "row") to the right */
+ x += 123;
+ y = y_org;
+ }
+ }
+
+ if (!FillDrawPixelInfo(&new_dpi, 3, 17, this->width - 28 + 22, this->height - 64 - 11 - diff)) return;
+
+ this->DrawSmallMap(&new_dpi, _smallmap_type, _smallmap_show_towns);
+ }
+
+ virtual void OnClick(Point pt, int widget)
+ {
+ switch (widget) {
+ case SM_WIDGET_MAP: { // Map window
+ /*
+ * XXX: scrolling with the left mouse button is done by subsequently
+ * clicking with the left mouse button; clicking once centers the
+ * large map at the selected point. So by unclicking the left mouse
+ * button here, it gets reclicked during the next inputloop, which
+ * would make it look like the mouse is being dragged, while it is
+ * actually being (virtually) clicked every inputloop.
+ */
+ _left_button_clicked = false;
+
+ Point pt = RemapCoords(this->scroll_x, this->scroll_y, 0);
+ Window *w = FindWindowById(WC_MAIN_WINDOW, 0);
+ w->viewport->dest_scrollpos_x = pt.x + ((_cursor.pos.x - this->left + 2) << 4) - (w->viewport->virtual_width >> 1);
+ w->viewport->dest_scrollpos_y = pt.y + ((_cursor.pos.y - this->top - 16) << 4) - (w->viewport->virtual_height >> 1);
+
+ this->SetDirty();
+ } break;
+
+ case SM_WIDGET_CONTOUR: // Show land contours
+ case SM_WIDGET_VEHICLES: // Show vehicles
+ case SM_WIDGET_INDUSTRIES: // Show industries
+ case SM_WIDGET_ROUTES: // Show transport routes
+ case SM_WIDGET_VEGETATION: // Show vegetation
+ case SM_WIDGET_OWNERS: // Show land owners
+ this->RaiseWidget(_smallmap_type + SM_WIDGET_CONTOUR);
+ _smallmap_type = widget - SM_WIDGET_CONTOUR;
+ this->LowerWidget(_smallmap_type + SM_WIDGET_CONTOUR);
+
+ this->SetDirty();
+ SndPlayFx(SND_15_BEEP);
+ break;
+
+ case SM_WIDGET_CENTERMAP: // Center the smallmap again
+ this->SmallMapCenterOnCurrentPos();
+
+ this->SetDirty();
+ SndPlayFx(SND_15_BEEP);
+ break;
+
+ case SM_WIDGET_TOGGLETOWNNAME: // Toggle town names
+ this->ToggleWidgetLoweredState(SM_WIDGET_TOGGLETOWNNAME);
+ _smallmap_show_towns = this->IsWidgetLowered(SM_WIDGET_TOGGLETOWNNAME);
+
+ this->SetDirty();
+ SndPlayFx(SND_15_BEEP);
+ break;
+
+ case SM_WIDGET_LEGEND: // Legend
+ /* if industry type small map*/
+ if (_smallmap_type == SMT_INDUSTRY) {
+ /* if click on industries label, find right industry type and enable/disable it */
+ Widget *wi = &this->widget[SM_WIDGET_LEGEND]; // label panel
+ uint column = (pt.x - 4) / 123;
+ uint line = (pt.y - wi->top - 2) / 6;
+ uint free = _smallmap_industry_count % 3;
+
+ if (column <= 3) {
+ /* check if click is on industry label*/
+ uint industry_pos = 0;
+ for (uint i = 0; i <= column; i++) {
+ uint diff = (free > 0) ? 1 : 0;
+ uint max_column_lines = _industries_per_column + diff;
+
+ if (i < column) industry_pos = industry_pos + _industries_per_column + diff;
+
+ if (i == column && line <= max_column_lines - 1) {
+ industry_pos = industry_pos + line;
+ _legend_from_industries[industry_pos].show_on_map = !_legend_from_industries[industry_pos].show_on_map;
+ }
+ if( free > 0) free--;
+ }
+ }
+ /* Raise the two buttons "all", as we have done a specific choice */
+ this->RaiseWidget(SM_WIDGET_ENABLEINDUSTRIES);
+ this->RaiseWidget(SM_WIDGET_DISABLEINDUSTRIES);
+ this->SetDirty();
+ }
+ break;
+
+ case SM_WIDGET_ENABLEINDUSTRIES: // Enable all industries
+ for (int i = 0; i != _smallmap_industry_count; i++) {
+ _legend_from_industries[i].show_on_map = true;
+ }
+ /* toggle appeareance indicating the choice */
+ this->LowerWidget(SM_WIDGET_ENABLEINDUSTRIES);
+ this->RaiseWidget(SM_WIDGET_DISABLEINDUSTRIES);
+ this->SetDirty();
+ break;
+
+ case SM_WIDGET_DISABLEINDUSTRIES: // disable all industries
+ for (int i = 0; i != _smallmap_industry_count; i++) {
+ _legend_from_industries[i].show_on_map = false;
+ }
+ /* toggle appeareance indicating the choice */
+ this->RaiseWidget(SM_WIDGET_ENABLEINDUSTRIES);
+ this->LowerWidget(SM_WIDGET_DISABLEINDUSTRIES);
+ this->SetDirty();
+ break;
+ }
}
- /* Draw map indicators */
+ virtual void OnRightClick(Point pt, int widget)
{
- Point pt;
-
- /* Find main viewport. */
- vp = FindWindowById(WC_MAIN_WINDOW,0)->viewport;
-
- pt = RemapCoords(WP(w, smallmap_d).scroll_x, WP(w, smallmap_d).scroll_y, 0);
-
- x = vp->virtual_left - pt.x;
- y = vp->virtual_top - pt.y;
- x2 = (x + vp->virtual_width) / TILE_SIZE;
- y2 = (y + vp->virtual_height) / TILE_SIZE;
- x /= TILE_SIZE;
- y /= TILE_SIZE;
-
- x -= WP(w, smallmap_d).subscroll;
- x2 -= WP(w, smallmap_d).subscroll;
-
- DrawVertMapIndicator(x, y, x, y2);
- DrawVertMapIndicator(x2, y, x2, y2);
-
- DrawHorizMapIndicator(x, y, x2, y);
- DrawHorizMapIndicator(x, y2, x2, y2);
+ if (widget == SM_WIDGET_MAP) {
+ if (_scrolling_viewport) return;
+ _scrolling_viewport = true;
+ _cursor.delta.x = 0;
+ _cursor.delta.y = 0;
+ }
}
- _cur_dpi = old_dpi;
-}
-
-void SmallMapCenterOnCurrentPos(Window *w)
-{
- int x, y;
- ViewPort *vp;
- vp = FindWindowById(WC_MAIN_WINDOW, 0)->viewport;
-
- x = ((vp->virtual_width - (w->widget[SM_WIDGET_MAP].right - w->widget[SM_WIDGET_MAP].left) * TILE_SIZE) / 2 + vp->virtual_left) / 4;
- y = ((vp->virtual_height - (w->widget[SM_WIDGET_MAP].bottom - w->widget[SM_WIDGET_MAP].top ) * TILE_SIZE) / 2 + vp->virtual_top ) / 2 - TILE_SIZE * 2;
- WP(w, smallmap_d).scroll_x = (y - x) & ~0xF;
- WP(w, smallmap_d).scroll_y = (x + y) & ~0xF;
- w->SetDirty();
-}
-
-enum {
- BASE_NB_PER_COLUMN = 6,
-};
-
-static void SmallMapWindowProc(Window *w, WindowEvent *e)
-{
- switch (e->event) {
- case WE_PAINT: {
- const LegendAndColour *tbl;
- int x, y, y_org;
- uint diff;
- DrawPixelInfo new_dpi;
-
- /* Hide Enable all/Disable all buttons if is not industry type small map*/
- w->SetWidgetHiddenState(SM_WIDGET_ENABLEINDUSTRIES, _smallmap_type != SMT_INDUSTRY);
- w->SetWidgetHiddenState(SM_WIDGET_DISABLEINDUSTRIES, _smallmap_type != SMT_INDUSTRY);
-
- /* draw the window */
- SetDParam(0, STR_00E5_CONTOURS + _smallmap_type);
- DrawWindowWidgets(w);
-
- tbl = _legend_table[_smallmap_type];
-
- /* difference in window size */
- diff = (_industries_per_column > BASE_NB_PER_COLUMN) ? ((_industries_per_column - BASE_NB_PER_COLUMN) * BASE_NB_PER_COLUMN) + 1 : 0;
-
- x = 4;
- y_org = w->height - 44 - 11 - diff;
- y = y_org;
-
- for (;;) {
-
- if (_smallmap_type == SMT_INDUSTRY) {
- /* Industry name must be formated, since it's not in tiny font in the specs.
- * So, draw with a parameter and use the STR_SMALLMAP_INDUSTRY string, which is tiny font.*/
- SetDParam(0, tbl->legend);
- assert(tbl->type < NUM_INDUSTRYTYPES);
- SetDParam(1, _industry_counts[tbl->type]);
- if (!tbl->show_on_map) {
- /* Simply draw the string, not the black border of the legend color.
- * This will enforce the idea of the disabled item */
- DrawString(x + 11, y, STR_SMALLMAP_INDUSTRY, TC_GREY);
- } else {
- DrawString(x + 11, y, STR_SMALLMAP_INDUSTRY, TC_BLACK);
- GfxFillRect(x, y + 1, x + 8, y + 5, 0); // outer border of the legend color
- }
- } else {
- /* Anything that is not an industry is using normal process */
- GfxFillRect(x, y + 1, x + 8, y + 5, 0);
- DrawString(x + 11, y, tbl->legend, TC_FROMSTRING);
- }
- GfxFillRect(x + 1, y + 2, x + 7, y + 4, tbl->colour); // legend color
-
- tbl += 1;
- y += 6;
-
- if (tbl->end) { // end of the list
- break;
- } else if (tbl->col_break) {
- /* break asked, continue at top, 123 pixels (one "row") to the right */
- x += 123;
- y = y_org;
- }
- }
-
- if (!FillDrawPixelInfo(&new_dpi, 3, 17, w->width - 28 + 22, w->height - 64 - 11 - diff))
- return;
-
- DrawSmallMap(&new_dpi, w, _smallmap_type, _smallmap_show_towns);
- } break;
-
- case WE_CLICK:
- switch (e->we.click.widget) {
- case SM_WIDGET_MAP: { // Map window
- Window *w2 = FindWindowById(WC_MAIN_WINDOW, 0);
- Point pt;
-
- /*
- * XXX: scrolling with the left mouse button is done by subsequently
- * clicking with the left mouse button; clicking once centers the
- * large map at the selected point. So by unclicking the left mouse
- * button here, it gets reclicked during the next inputloop, which
- * would make it look like the mouse is being dragged, while it is
- * actually being (virtually) clicked every inputloop.
- */
- _left_button_clicked = false;
-
- pt = RemapCoords(WP(w, smallmap_d).scroll_x, WP(w,smallmap_d).scroll_y, 0);
- WP(w2, vp_d).dest_scrollpos_x = pt.x + ((_cursor.pos.x - w->left + 2) << 4) - (w2->viewport->virtual_width >> 1);
- WP(w2, vp_d).dest_scrollpos_y = pt.y + ((_cursor.pos.y - w->top - 16) << 4) - (w2->viewport->virtual_height >> 1);
-
- w->SetDirty();
- } break;
-
- case SM_WIDGET_CONTOUR: // Show land contours
- case SM_WIDGET_VEHICLES: // Show vehicles
- case SM_WIDGET_INDUSTRIES: // Show industries
- case SM_WIDGET_ROUTES: // Show transport routes
- case SM_WIDGET_VEGETATION: // Show vegetation
- case SM_WIDGET_OWNERS: // Show land owners
- w->RaiseWidget(_smallmap_type + SM_WIDGET_CONTOUR);
- _smallmap_type = e->we.click.widget - SM_WIDGET_CONTOUR;
- w->LowerWidget(_smallmap_type + SM_WIDGET_CONTOUR);
- w->SetDirty();
- SndPlayFx(SND_15_BEEP);
- break;
-
- case SM_WIDGET_CENTERMAP: // Center the smallmap again
- SmallMapCenterOnCurrentPos(w);
-
- w->SetDirty();
- SndPlayFx(SND_15_BEEP);
- break;
-
- case SM_WIDGET_TOGGLETOWNNAME: // Toggle town names
- w->ToggleWidgetLoweredState(SM_WIDGET_TOGGLETOWNNAME);
- _smallmap_show_towns = w->IsWidgetLowered(SM_WIDGET_TOGGLETOWNNAME);
-
- w->SetDirty();
- SndPlayFx(SND_15_BEEP);
- break;
-
- case SM_WIDGET_LEGEND: // Legend
- /* if industry type small map*/
- if (_smallmap_type == SMT_INDUSTRY) {
- /* if click on industries label, find right industry type and enable/disable it */
- Widget *wi = &w->widget[SM_WIDGET_LEGEND]; // label panel
- uint column = (e->we.click.pt.x - 4) / 123;
- uint line = (e->we.click.pt.y - wi->top - 2) / 6;
- uint free = _smallmap_industry_count % 3;
-
- if (column <= 3) {
- /* check if click is on industry label*/
- uint industry_pos = 0;
- for (uint i = 0; i <= column; i++) {
- uint diff = (free > 0) ? 1 : 0;
- uint max_column_lines = _industries_per_column + diff;
-
- if (i < column) industry_pos = industry_pos + _industries_per_column + diff;
-
- if (i == column && line <= max_column_lines - 1) {
- industry_pos = industry_pos + line;
- _legend_from_industries[industry_pos].show_on_map = !_legend_from_industries[industry_pos].show_on_map;
- }
- if( free > 0) free--;
- }
- }
- /* Raise the two buttons "all", as we have done a specific choice */
- w->RaiseWidget(SM_WIDGET_ENABLEINDUSTRIES);
- w->RaiseWidget(SM_WIDGET_DISABLEINDUSTRIES);
- w->SetDirty();
- }
- break;
-
- case SM_WIDGET_ENABLEINDUSTRIES: // Enable all industries
- for (int i = 0; i != _smallmap_industry_count; i++) {
- _legend_from_industries[i].show_on_map = true;
- }
- /* toggle appeareance indicating the choice */
- w->LowerWidget(SM_WIDGET_ENABLEINDUSTRIES);
- w->RaiseWidget(SM_WIDGET_DISABLEINDUSTRIES);
- w->SetDirty();
- break;
-
- case SM_WIDGET_DISABLEINDUSTRIES: // disable all industries
- for (int i = 0; i != _smallmap_industry_count; i++) {
- _legend_from_industries[i].show_on_map = false;
- }
- /* toggle appeareance indicating the choice */
- w->RaiseWidget(SM_WIDGET_ENABLEINDUSTRIES);
- w->LowerWidget(SM_WIDGET_DISABLEINDUSTRIES);
- w->SetDirty();
- break;
- }
- break;
+ virtual void OnTick()
+ {
+ /* update the window every now and then */
+ if ((++this->vscroll.pos & 0x1F) == 0) this->SetDirty();
+ }
- case WE_RCLICK:
- if (e->we.click.widget == SM_WIDGET_MAP) {
- if (_scrolling_viewport) return;
- _scrolling_viewport = true;
- _cursor.delta.x = 0;
- _cursor.delta.y = 0;
- }
- break;
-
- case WE_MOUSELOOP:
- /* update the window every now and then */
- if ((++w->vscroll.pos & 0x1F) == 0) w->SetDirty();
- break;
-
- case WE_SCROLL: {
- int x;
- int y;
- int sub;
- int hx;
- int hy;
- int hvx;
- int hvy;
-
- _cursor.fix_at = true;
-
- x = WP(w, smallmap_d).scroll_x;
- y = WP(w, smallmap_d).scroll_y;
-
- sub = WP(w, smallmap_d).subscroll + e->we.scroll.delta.x;
-
- x -= (sub >> 2) << 4;
- y += (sub >> 2) << 4;
- sub &= 3;
-
- x += (e->we.scroll.delta.y >> 1) << 4;
- y += (e->we.scroll.delta.y >> 1) << 4;
+ virtual void OnScroll(Point delta)
+ {
+ _cursor.fix_at = true;
- if (e->we.scroll.delta.y & 1) {
- x += TILE_SIZE;
- sub += 2;
- if (sub > 3) {
- sub -= 4;
- x -= TILE_SIZE;
- y += TILE_SIZE;
- }
- }
+ int x = this->scroll_x;
+ int y = this->scroll_y;
- hx = (w->widget[SM_WIDGET_MAP].right - w->widget[SM_WIDGET_MAP].left) / 2;
- hy = (w->widget[SM_WIDGET_MAP].bottom - w->widget[SM_WIDGET_MAP].top ) / 2;
- hvx = hx * -4 + hy * 8;
- hvy = hx * 4 + hy * 8;
- if (x < -hvx) {
- x = -hvx;
- sub = 0;
+ int sub = this->subscroll + delta.x;
+
+ x -= (sub >> 2) << 4;
+ y += (sub >> 2) << 4;
+ sub &= 3;
+
+ x += (delta.y >> 1) << 4;
+ y += (delta.y >> 1) << 4;
+
+ if (delta.y & 1) {
+ x += TILE_SIZE;
+ sub += 2;
+ if (sub > 3) {
+ sub -= 4;
+ x -= TILE_SIZE;
+ y += TILE_SIZE;
}
- if (x > (int)MapMaxX() * TILE_SIZE - hvx) {
- x = MapMaxX() * TILE_SIZE - hvx;
- sub = 0;
- }
- if (y < -hvy) {
- y = -hvy;
- sub = 0;
- }
- if (y > (int)MapMaxY() * TILE_SIZE - hvy) {
- y = MapMaxY() * TILE_SIZE - hvy;
- sub = 0;
- }
+ }
- WP(w, smallmap_d).scroll_x = x;
- WP(w, smallmap_d).scroll_y = y;
- WP(w, smallmap_d).subscroll = sub;
+ int hx = (this->widget[SM_WIDGET_MAP].right - this->widget[SM_WIDGET_MAP].left) / 2;
+ int hy = (this->widget[SM_WIDGET_MAP].bottom - this->widget[SM_WIDGET_MAP].top ) / 2;
+ int hvx = hx * -4 + hy * 8;
+ int hvy = hx * 4 + hy * 8;
+ if (x < -hvx) {
+ x = -hvx;
+ sub = 0;
+ }
+ if (x > (int)MapMaxX() * TILE_SIZE - hvx) {
+ x = MapMaxX() * TILE_SIZE - hvx;
+ sub = 0;
+ }
+ if (y < -hvy) {
+ y = -hvy;
+ sub = 0;
+ }
+ if (y > (int)MapMaxY() * TILE_SIZE - hvy) {
+ y = MapMaxY() * TILE_SIZE - hvy;
+ sub = 0;
+ }
- w->SetDirty();
- } break;
+ this->scroll_x = x;
+ this->scroll_y = y;
+ this->subscroll = sub;
+
+ this->SetDirty();
}
-}
+};
static const WindowDesc _smallmap_desc = {
WDP_AUTO, WDP_AUTO, 350, 214, 446, 314,
WC_SMALLMAP, WC_NONE,
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_STICKY_BUTTON | WDF_RESIZABLE,
_smallmap_widgets,
- SmallMapWindowProc
+ NULL
};
void ShowSmallMap()
{
- Window *w;
-
- w = AllocateWindowDescFront(&_smallmap_desc, 0);
- if (w == NULL) return;
-
- /* Resize the window to fit industries list */
- if (_industries_per_column > BASE_NB_PER_COLUMN) {
- uint diff = ((_industries_per_column - BASE_NB_PER_COLUMN) * BASE_NB_PER_COLUMN) + 1;
-
- w->height = w->height + diff;
-
- Widget *wi = &w->widget[SM_WIDGET_LEGEND]; // label panel
- wi->bottom = wi->bottom + diff;
-
- wi = &w->widget[SM_WIDGET_BUTTONSPANEL]; // filler panel under smallmap buttons
- wi->bottom = wi->bottom + diff - 1;
-
- /* Change widget position
- * - footer panel
- * - enable all industry
- * - disable all industry
- * - resize window button
- */
- for (uint i = SM_WIDGET_BOTTOMPANEL; i <= SM_WIDGET_RESIZEBOX; i++) {
- wi = &w->widget[i];
- wi->top = wi->top + diff;
- wi->bottom = wi->bottom + diff;
- }
- }
-
- w->LowerWidget(_smallmap_type + SMT_OWNER);
- w->SetWidgetLoweredState(SM_WIDGET_TOGGLETOWNNAME, _smallmap_show_towns);
-
- SmallMapCenterOnCurrentPos(w);
+ AllocateWindowDescFront<SmallMapWindow>(&_smallmap_desc, 0);
}
/* Extra ViewPort Window Stuff */
@@ -1131,21 +1128,21 @@
case 7: { // location button (move main view to same spot as this view) 'Paste Location'
Window *w2 = FindWindowById(WC_MAIN_WINDOW, 0);
- int x = WP(w, vp_d).scrollpos_x; // Where is the main looking at
- int y = WP(w, vp_d).scrollpos_y;
+ int x = w->viewport->scrollpos_x; // Where is the main looking at
+ int y = w->viewport->scrollpos_y;
/* set this view to same location. Based on the center, adjusting for zoom */
- WP(w2, vp_d).dest_scrollpos_x = x - (w2->viewport->virtual_width - w->viewport->virtual_width) / 2;
- WP(w2, vp_d).dest_scrollpos_y = y - (w2->viewport->virtual_height - w->viewport->virtual_height) / 2;
+ w2->viewport->dest_scrollpos_x = x - (w2->viewport->virtual_width - w->viewport->virtual_width) / 2;
+ w2->viewport->dest_scrollpos_y = y - (w2->viewport->virtual_height - w->viewport->virtual_height) / 2;
} break;
case 8: { // inverse location button (move this view to same spot as main view) 'Copy Location'
const Window *w2 = FindWindowById(WC_MAIN_WINDOW, 0);
- int x = WP(w2, const vp_d).scrollpos_x;
- int y = WP(w2, const vp_d).scrollpos_y;
+ int x = w2->viewport->scrollpos_x;
+ int y = w2->viewport->scrollpos_y;
- WP(w, vp_d).dest_scrollpos_x = x + (w2->viewport->virtual_width - w->viewport->virtual_width) / 2;
- WP(w, vp_d).dest_scrollpos_y = y + (w2->viewport->virtual_height - w->viewport->virtual_height) / 2;
+ w->viewport->dest_scrollpos_x = x + (w2->viewport->virtual_width - w->viewport->virtual_width) / 2;
+ w->viewport->dest_scrollpos_y = y + (w2->viewport->virtual_height - w->viewport->virtual_height) / 2;
} break;
}
break;
@@ -1165,20 +1162,18 @@
_scrolling_viewport = false;
}
- WP(w, vp_d).scrollpos_x += ScaleByZoom(e->we.scroll.delta.x, vp->zoom);
- WP(w, vp_d).scrollpos_y += ScaleByZoom(e->we.scroll.delta.y, vp->zoom);
- WP(w, vp_d).dest_scrollpos_x = WP(w, vp_d).scrollpos_x;
- WP(w, vp_d).dest_scrollpos_y = WP(w, vp_d).scrollpos_y;
+ w->viewport->scrollpos_x += ScaleByZoom(e->we.scroll.delta.x, vp->zoom);
+ w->viewport->scrollpos_y += ScaleByZoom(e->we.scroll.delta.y, vp->zoom);
+ w->viewport->dest_scrollpos_x = w->viewport->scrollpos_x;
+ w->viewport->dest_scrollpos_y = w->viewport->scrollpos_y;
} break;
case WE_MOUSEWHEEL:
ZoomInOrOutToCursorWindow(e->we.wheel.wheel < 0, w);
break;
-
- case WE_MESSAGE:
+ case WE_INVALIDATE_DATA:
/* Only handle zoom message if intended for us (msg ZOOM_IN/ZOOM_OUT) */
- if (e->we.message.wparam != w->window_number) break;
HandleZoomMessage(w, w->viewport, 5, 6);
break;
}
@@ -1199,7 +1194,7 @@
/* find next free window number for extra viewport */
while (FindWindowById(WC_EXTRA_VIEW_PORT, i) != NULL) i++;
- Window *w = AllocateWindowDescFront(&_extra_view_port_desc, i);
+ Window *w = AllocateWindowDescFront<Window>(&_extra_view_port_desc, i);
if (w != NULL) {
Point pt;
@@ -1208,15 +1203,31 @@
const Window *v = FindWindowById(WC_MAIN_WINDOW, 0);
/* center on same place as main window (zoom is maximum, no adjustment needed) */
- pt.x = WP(v, vp_d).scrollpos_x + v->viewport->virtual_height / 2;
- pt.y = WP(v, vp_d).scrollpos_y + v->viewport->virtual_height / 2;
+ pt.x = v->viewport->scrollpos_x + v->viewport->virtual_height / 2;
+ pt.y = v->viewport->scrollpos_y + v->viewport->virtual_height / 2;
} else {
pt = RemapCoords(TileX(tile) * TILE_SIZE + TILE_SIZE / 2, TileY(tile) * TILE_SIZE + TILE_SIZE / 2, TileHeight(tile));
}
- WP(w, vp_d).scrollpos_x = pt.x - ((w->widget[4].right - w->widget[4].left) - 1) / 2;
- WP(w, vp_d).scrollpos_y = pt.y - ((w->widget[4].bottom - w->widget[4].top) - 1) / 2;
- WP(w, vp_d).dest_scrollpos_x = WP(w, vp_d).scrollpos_x;
- WP(w, vp_d).dest_scrollpos_y = WP(w, vp_d).scrollpos_y;
+ w->viewport->scrollpos_x = pt.x - ((w->widget[4].right - w->widget[4].left) - 1) / 2;
+ w->viewport->scrollpos_y = pt.y - ((w->widget[4].bottom - w->widget[4].top) - 1) / 2;
+ w->viewport->dest_scrollpos_x = w->viewport->scrollpos_x;
+ w->viewport->dest_scrollpos_y = w->viewport->scrollpos_y;
}
}
+
+bool ScrollMainWindowTo(int x, int y, bool instant)
+{
+ bool res = ScrollWindowTo(x, y, FindWindowById(WC_MAIN_WINDOW, 0), instant);
+
+ /* If a user scrolls to a tile (via what way what so ever) and already is on
+ * that tile (e.g.: pressed twice), move the smallmap to that location,
+ * so you directly see where you are on the smallmap. */
+
+ if (res) return res;
+
+ SmallMapWindow *w = dynamic_cast<SmallMapWindow*>(FindWindowById(WC_SMALLMAP, 0));
+ if (w != NULL) w->SmallMapCenterOnCurrentPos();
+
+ return res;
+}
--- a/src/spritecache.cpp Wed May 07 21:09:51 2008 +0000
+++ b/src/spritecache.cpp Sun May 11 20:09:34 2008 +0000
@@ -61,7 +61,7 @@
struct MemBlock {
- uint32 size;
+ size_t size;
byte data[VARARRAY_SIZE];
};
--- a/src/spriteloader/png.cpp Wed May 07 21:09:51 2008 +0000
+++ b/src/spriteloader/png.cpp Sun May 11 20:09:34 2008 +0000
@@ -44,7 +44,7 @@
return false;
}
-static bool LoadPNG(SpriteLoader::Sprite *sprite, const char *filename, uint32 id, bool mask)
+static bool LoadPNG(SpriteLoader::Sprite *sprite, const char *filename, uint32 id, volatile bool mask)
{
png_byte header[8];
png_structp png_ptr;
--- a/src/station_cmd.cpp Wed May 07 21:09:51 2008 +0000
+++ b/src/station_cmd.cpp Sun May 11 20:09:34 2008 +0000
@@ -42,6 +42,7 @@
#include "signal_func.h"
#include "oldpool_func.h"
#include "animated_tile_func.h"
+#include "elrail_func.h"
#include "table/sprites.h"
#include "table/strings.h"
@@ -2106,7 +2107,7 @@
DrawGroundSprite(image, HasBit(image, PALETTE_MODIFIER_COLOR) ? palette : PAL_NONE);
}
- if (IsRailwayStation(ti->tile) && HasCatenary(GetRailType(ti->tile)) && IsStationTileElectrifiable(ti->tile)) DrawCatenary(ti);
+ if (IsRailwayStation(ti->tile) && HasCatenaryDrawn(GetRailType(ti->tile)) && IsStationTileElectrifiable(ti->tile)) DrawCatenary(ti);
if (HasBit(roadtypes, ROADTYPE_TRAM)) {
Axis axis = GetRoadStopDir(ti->tile) == DIAGDIR_NE ? AXIS_X : AXIS_Y;
--- a/src/station_gui.cpp Wed May 07 21:09:51 2008 +0000
+++ b/src/station_gui.cpp Sun May 11 20:09:34 2008 +0000
@@ -25,6 +25,7 @@
#include "gfx_func.h"
#include "widgets/dropdown_func.h"
#include "newgrf_cargo.h"
+#include "string_func.h"
#include "table/strings.h"
#include "table/sprites.h"
@@ -164,60 +165,43 @@
return (_internal_sort_order & 1) ? maxr2 - maxr1 : maxr1 - maxr2;
}
-/** Flags for station list */
-enum StationListFlags {
- SL_ORDER = 1 << 0, ///< Order - ascending (=0), descending (=1)
- SL_RESORT = 1 << 1, ///< Resort the list
- SL_REBUILD = 1 << 2, ///< Rebuild the list
-};
-
-DECLARE_ENUM_AS_BIT_SET(StationListFlags);
-
-/** Information about station list */
-struct plstations_d {
- const Station **sort_list; ///< Pointer to list of stations
- uint16 list_length; ///< Number of stations in list
- uint16 resort_timer; ///< Tick counter to resort the list
- byte sort_type; ///< Sort type - name, waiting, ...
- byte flags; ///< Flags - SL_ORDER, SL_RESORT, SL_REBUILD
-};
-assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(plstations_d));
+typedef GUIList<const Station*> GUIStationList;
/**
* Set the station sort flag for all station-list windows.
* @param sl_flag Sort list flag to set for all station-list windows
*/
-static void SetStationListsFlag(StationListFlags sl_flag)
+static void SetStationListsFlag(SortListFlags sl_flag)
{
Window *const *wz;
FOR_ALL_WINDOWS(wz) {
Window *w = *wz;
if (w->window_class == WC_STATION_LIST) {
- WP(w, plstations_d).flags |= sl_flag;
+ dynamic_cast<GUIStationList*>(w)->flags |= sl_flag;
w->SetDirty();
}
}
}
/**
- * Set the 'SL_REBUILD' flag for all station lists
+ * Set the 'VL_REBUILD' flag for all station lists
*/
void RebuildStationLists()
{
- SetStationListsFlag(SL_REBUILD);
+ SetStationListsFlag(VL_REBUILD);
}
/**
- * Set the 'SL_RESORT' flag for all station lists
+ * Set the 'VL_RESORT' flag for all station lists
*/
void ResortStationLists()
{
- SetStationListsFlag(SL_RESORT);
+ SetStationListsFlag(VL_RESORT);
}
/**
- * Rebuild station list if the SL_REBUILD flag is set
+ * Rebuild station list if the VL_REBUILD flag is set
*
* @param sl pointer to plstations_d (station list and flags)
* @param owner player whose stations are to be in list
@@ -225,12 +209,12 @@
* @param cargo_filter bitmap of cargo types to include
* @param include_empty whether we should include stations without waiting cargo
*/
-static void BuildStationsList(plstations_d *sl, PlayerID owner, byte facilities, uint32 cargo_filter, bool include_empty)
+static void BuildStationsList(GUIStationList *sl, PlayerID owner, byte facilities, uint32 cargo_filter, bool include_empty)
{
uint n = 0;
const Station *st;
- if (!(sl->flags & SL_REBUILD)) return;
+ if (!(sl->flags & VL_REBUILD)) return;
/* Create array for sorting */
const Station **station_sort = MallocT<const Station*>(GetMaxStationIndex() + 1);
@@ -264,18 +248,18 @@
for (uint i = 0; i < n; ++i) sl->sort_list[i] = station_sort[i];
- sl->flags &= ~SL_REBUILD;
- sl->flags |= SL_RESORT;
+ sl->flags &= ~VL_REBUILD;
+ sl->flags |= VL_RESORT;
free((void*)station_sort);
}
/**
- * Sort station list if the SL_RESORT flag is set
+ * Sort station list if the VL_RESORT flag is set
*
* @param sl pointer to plstations_d (station list and flags)
*/
-static void SortStationsList(plstations_d *sl)
+static void SortStationsList(GUIStationList *sl)
{
static StationSortListingTypeFunction *const _station_sorter[] = {
&StationNameSorter,
@@ -284,298 +268,351 @@
&StationRatingMaxSorter
};
- if (!(sl->flags & SL_RESORT)) return;
+ if (!(sl->flags & VL_RESORT)) return;
- _internal_sort_order = sl->flags & SL_ORDER;
+ _internal_sort_order = sl->flags & VL_DESC;
_last_station = NULL; // used for "cache" in namesorting
qsort((void*)sl->sort_list, sl->list_length, sizeof(sl->sort_list[0]), _station_sorter[sl->sort_type]);
sl->resort_timer = DAY_TICKS * PERIODIC_RESORT_DAYS;
- sl->flags &= ~SL_RESORT;
+ sl->flags &= ~VL_RESORT;
}
/**
- * Fuction called when any WindowEvent occurs for PlayerStations window
- *
- * @param w pointer to the PlayerStations window
- * @param e pointer to window event
+ * The list of stations per player.
*/
-static void PlayerStationsWndProc(Window *w, WindowEvent *e)
+struct PlayerStationsWindow : public Window, public GUIStationList
{
- const PlayerID owner = (PlayerID)w->window_number;
- static byte facilities = FACIL_TRAIN | FACIL_TRUCK_STOP | FACIL_BUS_STOP | FACIL_AIRPORT | FACIL_DOCK;
- static Listing station_sort = {0, 0};
- static bool include_empty = true;
-
- plstations_d *sl = &WP(w, plstations_d);
-
- switch (e->event) {
- case WE_CREATE:
- if (_cargo_filter == _cargo_filter_max) _cargo_filter = _cargo_mask;
-
- for (uint i = 0; i < 5; i++) {
- if (HasBit(facilities, i)) w->LowerWidget(i + SLW_TRAIN);
- }
- w->SetWidgetLoweredState(SLW_FACILALL, facilities == (FACIL_TRAIN | FACIL_TRUCK_STOP | FACIL_BUS_STOP | FACIL_AIRPORT | FACIL_DOCK));
- w->SetWidgetLoweredState(SLW_CARGOALL, _cargo_filter == _cargo_mask && include_empty);
- w->SetWidgetLoweredState(SLW_NOCARGOWAITING, include_empty);
-
- sl->sort_list = NULL;
- sl->flags = SL_REBUILD;
- sl->sort_type = station_sort.criteria;
- if (station_sort.order) sl->flags |= SL_ORDER;
+ static Listing station_sort;
+ static byte facilities;
+ static bool include_empty;
- /* set up resort timer */
- sl->resort_timer = DAY_TICKS * PERIODIC_RESORT_DAYS;
- break;
-
- case WE_PAINT: {
- BuildStationsList(sl, owner, facilities, _cargo_filter, include_empty);
- SortStationsList(sl);
-
- SetVScrollCount(w, sl->list_length);
-
- /* draw widgets, with player's name in the caption */
- SetDParam(0, owner);
- SetDParam(1, w->vscroll.count);
-
- /* Set text of sort by dropdown */
- w->widget[SLW_SORTDROPBTN].data = _station_sort_listing[sl->sort_type];
+ PlayerStationsWindow(const WindowDesc *desc, void *data, WindowNumber window_number) : Window(desc, data, window_number)
+ {
+ this->caption_color = (byte)this->window_number;
+ this->vscroll.cap = 12;
+ this->resize.step_height = 10;
+ this->resize.height = this->height - 10 * 7; // minimum if 5 in the list
- DrawWindowWidgets(w);
-
- /* draw arrow pointing up/down for ascending/descending sorting */
- DrawSortButtonState(w, SLW_SORTBY, sl->flags & SL_ORDER ? SBS_DOWN : SBS_UP);
-
- int cg_ofst;
- int x = 89;
- int y = 14;
- int xb = 2; ///< offset from left of widget
+ /* Add cargo filter buttons */
+ uint num_active = 0;
+ for (CargoID c = 0; c < NUM_CARGO; c++) {
+ if (GetCargo(c)->IsValid()) num_active++;
+ }
- uint i = 0;
- for (CargoID c = 0; c < NUM_CARGO; c++) {
- const CargoSpec *cs = GetCargo(c);
- if (!cs->IsValid()) continue;
+ this->widget_count += num_active;
+ this->widget = ReallocT(this->widget, this->widget_count + 1);
+ this->widget[this->widget_count].type = WWT_LAST;
- cg_ofst = HasBit(_cargo_filter, c) ? 2 : 1;
- GfxFillRect(x + cg_ofst, y + cg_ofst, x + cg_ofst + 10 , y + cg_ofst + 7, cs->rating_colour);
- DrawStringCentered(x + 6 + cg_ofst, y + cg_ofst, cs->abbrev, TC_BLACK);
- x += 14;
- i++;
+ uint i = 0;
+ for (CargoID c = 0; c < NUM_CARGO; c++) {
+ if (!GetCargo(c)->IsValid()) continue;
+
+ Widget *wi = &this->widget[SLW_CARGOSTART + i];
+ wi->type = WWT_PANEL;
+ wi->display_flags = RESIZE_NONE;
+ wi->color = 14;
+ wi->left = 89 + i * 14;
+ wi->right = wi->left + 13;
+ wi->top = 14;
+ wi->bottom = 24;
+ wi->data = 0;
+ wi->tooltips = STR_USE_CTRL_TO_SELECT_MORE;
+
+ if (HasBit(_cargo_filter, c)) this->LowerWidget(SLW_CARGOSTART + i);
+ i++;
+ }
+
+ this->widget[SLW_NOCARGOWAITING].left += num_active * 14;
+ this->widget[SLW_NOCARGOWAITING].right += num_active * 14;
+ this->widget[SLW_CARGOALL].left += num_active * 14;
+ this->widget[SLW_CARGOALL].right += num_active * 14;
+ this->widget[SLW_PAN_RIGHT].left += num_active * 14;
+
+ if (num_active > 15) {
+ /* Resize and fix the minimum width, if necessary */
+ ResizeWindow(this, (num_active - 15) * 14, 0);
+ this->resize.width = this->width;
+ }
+
+ if (_cargo_filter == _cargo_filter_max) _cargo_filter = _cargo_mask;
+
+ for (uint i = 0; i < 5; i++) {
+ if (HasBit(facilities, i)) this->LowerWidget(i + SLW_TRAIN);
+ }
+ this->SetWidgetLoweredState(SLW_FACILALL, facilities == (FACIL_TRAIN | FACIL_TRUCK_STOP | FACIL_BUS_STOP | FACIL_AIRPORT | FACIL_DOCK));
+ this->SetWidgetLoweredState(SLW_CARGOALL, _cargo_filter == _cargo_mask && include_empty);
+ this->SetWidgetLoweredState(SLW_NOCARGOWAITING, include_empty);
+
+ this->sort_list = NULL;
+ this->flags = VL_REBUILD;
+ this->sort_type = station_sort.criteria;
+ if (station_sort.order) this->flags |= VL_DESC;
+
+ /* set up resort timer */
+ this->resort_timer = DAY_TICKS * PERIODIC_RESORT_DAYS;
+ }
+
+ virtual void OnPaint()
+ {
+ PlayerID owner = (PlayerID)this->window_number;
+
+ BuildStationsList(this, owner, facilities, _cargo_filter, include_empty);
+ SortStationsList(this);
+
+ SetVScrollCount(this, this->list_length);
+
+ /* draw widgets, with player's name in the caption */
+ SetDParam(0, owner);
+ SetDParam(1, this->vscroll.count);
+
+ /* Set text of sort by dropdown */
+ this->widget[SLW_SORTDROPBTN].data = _station_sort_listing[this->sort_type];
+
+ DrawWindowWidgets(this);
+
+ /* draw arrow pointing up/down for ascending/descending sorting */
+ DrawSortButtonState(this, SLW_SORTBY, this->flags & VL_DESC ? SBS_DOWN : SBS_UP);
+
+ int cg_ofst;
+ int x = 89;
+ int y = 14;
+ int xb = 2; ///< offset from left of widget
+
+ uint i = 0;
+ for (CargoID c = 0; c < NUM_CARGO; c++) {
+ const CargoSpec *cs = GetCargo(c);
+ if (!cs->IsValid()) continue;
+
+ cg_ofst = HasBit(_cargo_filter, c) ? 2 : 1;
+ GfxFillRect(x + cg_ofst, y + cg_ofst, x + cg_ofst + 10 , y + cg_ofst + 7, cs->rating_colour);
+ DrawStringCentered(x + 6 + cg_ofst, y + cg_ofst, cs->abbrev, TC_BLACK);
+ x += 14;
+ i++;
+ }
+
+ x += 6;
+ cg_ofst = this->IsWidgetLowered(SLW_NOCARGOWAITING) ? 2 : 1;
+ DrawStringCentered(x + cg_ofst, y + cg_ofst, STR_ABBREV_NONE, TC_BLACK);
+ x += 14;
+ cg_ofst = this->IsWidgetLowered(SLW_CARGOALL) ? 2 : 1;
+ DrawStringCentered(x + cg_ofst, y + cg_ofst, STR_ABBREV_ALL, TC_BLACK);
+
+ cg_ofst = this->IsWidgetLowered(SLW_FACILALL) ? 2 : 1;
+ DrawString(71 + cg_ofst, y + cg_ofst, STR_ABBREV_ALL, TC_BLACK);
+
+ if (this->vscroll.count == 0) { // player has no stations
+ DrawString(xb, 40, STR_304A_NONE, TC_FROMSTRING);
+ return;
+ }
+
+ int max = min(this->vscroll.pos + this->vscroll.cap, this->list_length);
+ y = 40; // start of the list-widget
+
+ for (int i = this->vscroll.pos; i < max; ++i) { // do until max number of stations of owner
+ const Station *st = this->sort_list[i];
+ int x;
+
+ assert(st->xy != 0);
+
+ /* 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 && !st->IsBuoy()));
+
+ SetDParam(0, st->index);
+ SetDParam(1, st->facilities);
+ x = DrawString(xb, y, STR_3049_0, TC_FROMSTRING) + 5;
+
+ /* show cargo waiting and station ratings */
+ for (CargoID j = 0; j < NUM_CARGO; j++) {
+ if (!st->goods[j].cargo.Empty()) {
+ StationsWndShowStationRating(x, y, j, st->goods[j].cargo.Count(), st->goods[j].rating);
+ x += 20;
+ }
+ }
+ y += 10;
+ }
+ }
+
+ virtual void OnClick(Point pt, int widget)
+ {
+ PlayerID owner = (PlayerID)this->window_number;
+
+ switch (widget) {
+ case SLW_LIST: {
+ uint32 id_v = (pt.y - 41) / 10;
+
+ if (id_v >= this->vscroll.cap) return; // click out of bounds
+
+ id_v += this->vscroll.pos;
+
+ if (id_v >= this->list_length) return; // click out of list bound
+
+ const Station *st = this->sort_list[id_v];
+ /* do not check HasStationInUse - it is slow and may be invalid */
+ assert(st->owner == owner || (st->owner == OWNER_NONE && !st->IsBuoy()));
+
+ if (_ctrl_pressed) {
+ ShowExtraViewPortWindow(st->xy);
+ } else {
+ ScrollMainWindowToTile(st->xy);
+ }
+ break;
}
- x += 6;
- cg_ofst = w->IsWidgetLowered(SLW_NOCARGOWAITING) ? 2 : 1;
- DrawStringCentered(x + cg_ofst, y + cg_ofst, STR_ABBREV_NONE, TC_BLACK);
- x += 14;
- cg_ofst = w->IsWidgetLowered(SLW_CARGOALL) ? 2 : 1;
- DrawStringCentered(x + cg_ofst, y + cg_ofst, STR_ABBREV_ALL, TC_BLACK);
+ case SLW_TRAIN:
+ case SLW_TRUCK:
+ case SLW_BUS:
+ case SLW_AIRPLANE:
+ case SLW_SHIP:
+ if (_ctrl_pressed) {
+ ToggleBit(facilities, widget - SLW_TRAIN);
+ this->ToggleWidgetLoweredState(widget);
+ } else {
+ uint i;
+ FOR_EACH_SET_BIT(i, facilities) {
+ this->RaiseWidget(i + SLW_TRAIN);
+ }
+ SetBit(facilities, widget - SLW_TRAIN);
+ this->LowerWidget(widget);
+ }
+ this->SetWidgetLoweredState(SLW_FACILALL, facilities == (FACIL_TRAIN | FACIL_TRUCK_STOP | FACIL_BUS_STOP | FACIL_AIRPORT | FACIL_DOCK));
+ this->flags |= VL_REBUILD;
+ this->SetDirty();
+ break;
- cg_ofst = w->IsWidgetLowered(SLW_FACILALL) ? 2 : 1;
- DrawString(71 + cg_ofst, y + cg_ofst, STR_ABBREV_ALL, TC_BLACK);
+ case SLW_FACILALL:
+ for (uint i = 0; i < 5; i++) {
+ this->LowerWidget(i + SLW_TRAIN);
+ }
+ this->LowerWidget(SLW_FACILALL);
- if (w->vscroll.count == 0) { // player has no stations
- DrawString(xb, 40, STR_304A_NONE, TC_FROMSTRING);
- return;
+ facilities = FACIL_TRAIN | FACIL_TRUCK_STOP | FACIL_BUS_STOP | FACIL_AIRPORT | FACIL_DOCK;
+ this->flags |= VL_REBUILD;
+ this->SetDirty();
+ break;
+
+ case SLW_CARGOALL: {
+ uint i = 0;
+ for (CargoID c = 0; c < NUM_CARGO; c++) {
+ if (!GetCargo(c)->IsValid()) continue;
+ this->LowerWidget(i + SLW_CARGOSTART);
+ i++;
+ }
+ this->LowerWidget(SLW_NOCARGOWAITING);
+ this->LowerWidget(SLW_CARGOALL);
+
+ _cargo_filter = _cargo_mask;
+ include_empty = true;
+ this->flags |= VL_REBUILD;
+ this->SetDirty();
+ break;
}
- int max = min(w->vscroll.pos + w->vscroll.cap, sl->list_length);
- y = 40; // start of the list-widget
-
- for (int i = w->vscroll.pos; i < max; ++i) { // do until max number of stations of owner
- const Station *st = sl->sort_list[i];
- int x;
-
- assert(st->xy != 0);
-
- /* 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 && !st->IsBuoy()));
-
- SetDParam(0, st->index);
- SetDParam(1, st->facilities);
- x = DrawString(xb, y, STR_3049_0, TC_FROMSTRING) + 5;
+ case SLW_SORTBY: // flip sorting method asc/desc
+ this->flags ^= VL_DESC; //DESC-flag
+ station_sort.order = HasBit(this->flags, 0);
+ this->flags |= VL_RESORT;
+ this->flags4 |= 5 << WF_TIMEOUT_SHL;
+ this->LowerWidget(SLW_SORTBY);
+ this->SetDirty();
+ break;
- /* show cargo waiting and station ratings */
- for (CargoID j = 0; j < NUM_CARGO; j++) {
- if (!st->goods[j].cargo.Empty()) {
- StationsWndShowStationRating(x, y, j, st->goods[j].cargo.Count(), st->goods[j].rating);
- x += 20;
- }
- }
- y += 10;
- }
- break;
- }
+ case SLW_SORTDROPBTN: // select sorting criteria dropdown menu
+ ShowDropDownMenu(this, _station_sort_listing, this->sort_type, SLW_SORTDROPBTN, 0, 0);
+ break;
- case WE_CLICK:
- switch (e->we.click.widget) {
- case SLW_LIST: {
- uint32 id_v = (e->we.click.pt.y - 41) / 10;
-
- if (id_v >= w->vscroll.cap) return; // click out of bounds
+ case SLW_NOCARGOWAITING:
+ if (_ctrl_pressed) {
+ include_empty = !include_empty;
+ this->ToggleWidgetLoweredState(SLW_NOCARGOWAITING);
+ } else {
+ for (uint i = SLW_CARGOSTART; i < this->widget_count; i++) {
+ this->RaiseWidget(i);
+ }
- id_v += w->vscroll.pos;
+ _cargo_filter = 0;
+ include_empty = true;
- if (id_v >= sl->list_length) return; // click out of list bound
+ this->LowerWidget(SLW_NOCARGOWAITING);
+ }
+ this->flags |= VL_REBUILD;
+ this->SetWidgetLoweredState(SLW_CARGOALL, _cargo_filter == _cargo_mask && include_empty);
+ this->SetDirty();
+ break;
- const Station *st = sl->sort_list[id_v];
- /* do not check HasStationInUse - it is slow and may be invalid */
- assert(st->owner == owner || (st->owner == OWNER_NONE && !st->IsBuoy()));
+ default:
+ if (widget >= SLW_CARGOSTART) { // change cargo_filter
+ /* Determine the selected cargo type */
+ CargoID c;
+ int i = 0;
+ for (c = 0; c < NUM_CARGO; c++) {
+ if (!GetCargo(c)->IsValid()) continue;
+ if (widget - SLW_CARGOSTART == i) break;
+ i++;
+ }
if (_ctrl_pressed) {
- ShowExtraViewPortWindow(st->xy);
+ ToggleBit(_cargo_filter, c);
+ this->ToggleWidgetLoweredState(widget);
} else {
- ScrollMainWindowToTile(st->xy);
- }
- break;
- }
-
- case SLW_TRAIN:
- case SLW_TRUCK:
- case SLW_BUS:
- case SLW_AIRPLANE:
- case SLW_SHIP:
- if (_ctrl_pressed) {
- ToggleBit(facilities, e->we.click.widget - SLW_TRAIN);
- w->ToggleWidgetLoweredState(e->we.click.widget);
- } else {
- uint i;
- FOR_EACH_SET_BIT(i, facilities) {
- w->RaiseWidget(i + SLW_TRAIN);
+ for (uint i = SLW_CARGOSTART; i < this->widget_count; i++) {
+ this->RaiseWidget(i);
}
- SetBit(facilities, e->we.click.widget - SLW_TRAIN);
- w->LowerWidget(e->we.click.widget);
- }
- w->SetWidgetLoweredState(SLW_FACILALL, facilities == (FACIL_TRAIN | FACIL_TRUCK_STOP | FACIL_BUS_STOP | FACIL_AIRPORT | FACIL_DOCK));
- sl->flags |= SL_REBUILD;
- w->SetDirty();
- break;
-
- case SLW_FACILALL:
- for (uint i = 0; i < 5; i++) {
- w->LowerWidget(i + SLW_TRAIN);
- }
- w->LowerWidget(SLW_FACILALL);
-
- facilities = FACIL_TRAIN | FACIL_TRUCK_STOP | FACIL_BUS_STOP | FACIL_AIRPORT | FACIL_DOCK;
- sl->flags |= SL_REBUILD;
- w->SetDirty();
- break;
-
- case SLW_CARGOALL: {
- uint i = 0;
- for (CargoID c = 0; c < NUM_CARGO; c++) {
- if (!GetCargo(c)->IsValid()) continue;
- w->LowerWidget(i + SLW_CARGOSTART);
- i++;
- }
- w->LowerWidget(SLW_NOCARGOWAITING);
- w->LowerWidget(SLW_CARGOALL);
-
- _cargo_filter = _cargo_mask;
- include_empty = true;
- sl->flags |= SL_REBUILD;
- w->SetDirty();
- break;
- }
-
- case SLW_SORTBY: // flip sorting method asc/desc
- sl->flags ^= SL_ORDER; //DESC-flag
- station_sort.order = HasBit(sl->flags, 0);
- sl->flags |= SL_RESORT;
- w->flags4 |= 5 << WF_TIMEOUT_SHL;
- w->LowerWidget(SLW_SORTBY);
- w->SetDirty();
- break;
-
- case SLW_SORTDROPBTN: // select sorting criteria dropdown menu
- ShowDropDownMenu(w, _station_sort_listing, sl->sort_type, SLW_SORTDROPBTN, 0, 0);
- break;
-
- case SLW_NOCARGOWAITING:
- if (_ctrl_pressed) {
- include_empty = !include_empty;
- w->ToggleWidgetLoweredState(SLW_NOCARGOWAITING);
- } else {
- for (uint i = SLW_CARGOSTART; i < w->widget_count; i++) {
- w->RaiseWidget(i);
- }
+ this->RaiseWidget(SLW_NOCARGOWAITING);
_cargo_filter = 0;
- include_empty = true;
-
- w->LowerWidget(SLW_NOCARGOWAITING);
- }
- sl->flags |= SL_REBUILD;
- w->SetWidgetLoweredState(SLW_CARGOALL, _cargo_filter == _cargo_mask && include_empty);
- w->SetDirty();
- break;
-
- default:
- if (e->we.click.widget >= SLW_CARGOSTART) { // change cargo_filter
- /* Determine the selected cargo type */
- CargoID c;
- int i = 0;
- for (c = 0; c < NUM_CARGO; c++) {
- if (!GetCargo(c)->IsValid()) continue;
- if (e->we.click.widget - SLW_CARGOSTART == i) break;
- i++;
- }
-
- if (_ctrl_pressed) {
- ToggleBit(_cargo_filter, c);
- w->ToggleWidgetLoweredState(e->we.click.widget);
- } else {
- for (uint i = SLW_CARGOSTART; i < w->widget_count; i++) {
- w->RaiseWidget(i);
- }
- w->RaiseWidget(SLW_NOCARGOWAITING);
-
- _cargo_filter = 0;
- include_empty = false;
+ include_empty = false;
- SetBit(_cargo_filter, c);
- w->LowerWidget(e->we.click.widget);
- }
- sl->flags |= SL_REBUILD;
- w->SetWidgetLoweredState(SLW_CARGOALL, _cargo_filter == _cargo_mask && include_empty);
- w->SetDirty();
+ SetBit(_cargo_filter, c);
+ this->LowerWidget(widget);
}
- break;
- }
- break;
+ this->flags |= VL_REBUILD;
+ this->SetWidgetLoweredState(SLW_CARGOALL, _cargo_filter == _cargo_mask && include_empty);
+ this->SetDirty();
+ }
+ break;
+ }
+ }
- case WE_DROPDOWN_SELECT: // we have selected a dropdown item in the list
- if (sl->sort_type != e->we.dropdown.index) {
- /* value has changed -> resort */
- sl->sort_type = e->we.dropdown.index;
- station_sort.criteria = sl->sort_type;
- sl->flags |= SL_RESORT;
- }
- w->SetDirty();
- break;
+ virtual void OnDropdownSelect(int widget, int index)
+ {
+ if (this->sort_type != index) {
+ /* value has changed -> resort */
+ this->sort_type = index;
+ station_sort.criteria = this->sort_type;
+ this->flags |= VL_RESORT;
+ }
+ this->SetDirty();
+ }
- case WE_TICK:
- if (_pause_game != 0) break;
- if (--sl->resort_timer == 0) {
- DEBUG(misc, 3, "Periodic rebuild station list player %d", owner);
- sl->resort_timer = DAY_TICKS * PERIODIC_RESORT_DAYS;
- sl->flags |= SL_REBUILD;
- w->SetDirty();
- }
- break;
+ virtual void OnTick()
+ {
+ if (_pause_game != 0) return;
+ if (--this->resort_timer == 0) {
+ DEBUG(misc, 3, "Periodic rebuild station list player %d", this->window_number);
+ this->resort_timer = DAY_TICKS * PERIODIC_RESORT_DAYS;
+ this->flags |= VL_REBUILD;
+ this->SetDirty();
+ }
+ }
- case WE_TIMEOUT:
- w->RaiseWidget(SLW_SORTBY);
- w->SetDirty();
- break;
+ virtual void OnTimeout()
+ {
+ this->RaiseWidget(SLW_SORTBY);
+ this->SetDirty();
+ }
- case WE_RESIZE:
- w->vscroll.cap += e->we.sizing.diff.y / 10;
- break;
+ virtual void OnResize(Point new_size, Point delta)
+ {
+ this->vscroll.cap += delta.y / 10;
}
-}
+};
+
+Listing PlayerStationsWindow::station_sort = {0, 0};
+byte PlayerStationsWindow::facilities = FACIL_TRAIN | FACIL_TRUCK_STOP | FACIL_BUS_STOP | FACIL_AIRPORT | FACIL_DOCK;
+bool PlayerStationsWindow::include_empty = true;
+
static const Widget _player_stations_widgets[] = {
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, // SLW_CLOSEBOX
@@ -608,7 +645,7 @@
WC_STATION_LIST, WC_NONE,
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_STICKY_BUTTON | WDF_RESIZABLE,
_player_stations_widgets,
- PlayerStationsWndProc
+ NULL
};
/**
@@ -620,54 +657,7 @@
{
if (!IsValidPlayer(player)) return;
- Window *w = AllocateWindowDescFront(&_player_stations_desc, player);
- if (w == NULL) return;
-
- w->caption_color = (byte)w->window_number;
- w->vscroll.cap = 12;
- w->resize.step_height = 10;
- w->resize.height = w->height - 10 * 7; // minimum if 5 in the list
-
- /* Add cargo filter buttons */
- uint num_active = 0;
- for (CargoID c = 0; c < NUM_CARGO; c++) {
- if (GetCargo(c)->IsValid()) num_active++;
- }
-
- w->widget_count += num_active;
- w->widget = ReallocT(w->widget, w->widget_count + 1);
- w->widget[w->widget_count].type = WWT_LAST;
-
- uint i = 0;
- for (CargoID c = 0; c < NUM_CARGO; c++) {
- if (!GetCargo(c)->IsValid()) continue;
-
- Widget *wi = &w->widget[SLW_CARGOSTART + i];
- wi->type = WWT_PANEL;
- wi->display_flags = RESIZE_NONE;
- wi->color = 14;
- wi->left = 89 + i * 14;
- wi->right = wi->left + 13;
- wi->top = 14;
- wi->bottom = 24;
- wi->data = 0;
- wi->tooltips = STR_USE_CTRL_TO_SELECT_MORE;
-
- if (HasBit(_cargo_filter, c)) w->LowerWidget(SLW_CARGOSTART + i);
- i++;
- }
-
- w->widget[SLW_NOCARGOWAITING].left += num_active * 14;
- w->widget[SLW_NOCARGOWAITING].right += num_active * 14;
- w->widget[SLW_CARGOALL].left += num_active * 14;
- w->widget[SLW_CARGOALL].right += num_active * 14;
- w->widget[SLW_PAN_RIGHT].left += num_active * 14;
-
- if (num_active > 15) {
- /* Resize and fix the minimum width, if necessary */
- ResizeWindow(w, (num_active - 15) * 14, 0);
- w->resize.width = w->width;
- }
+ AllocateWindowDescFront<PlayerStationsWindow>(&_player_stations_desc, player);
}
static const Widget _station_view_widgets[] = {
@@ -726,12 +716,6 @@
} 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;
@@ -747,285 +731,285 @@
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();
+struct StationViewWindow : public Window {
+ uint32 cargo; ///< Bitmask of cargo types to expand
+ uint16 cargo_rows[NUM_CARGO]; ///< Header row for each cargo type
- /* 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);
+ 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;
- /* Don't add cargo lines if not expanded */
- if (!HasBit(WP(w, stationview_d).cargo, i)) break;
+ this->FindWindowPlacementAndResize(desc);
+ }
- /* 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;
+ ~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
-
- /* 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));
-
- SetDParam(0, st->index);
- SetDParam(1, st->facilities);
- DrawWindowWidgets(w);
-
- int x = 2; ///< coordinates used for printing waiting/accepted/rating of cargo
- int y = 15;
- int pos = w->vscroll.pos; ///< = w->vscroll.pos
-
- uint width = w->widget[SVW_WAITING].right - w->widget[SVW_WAITING].left - 4;
- int maxrows = w->vscroll.cap;
-
- StringID str;
+ SetVScrollCount(this, cargolist.size() + 1); // update scrollbar
- 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;
- }
+ /* 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));
- for (CargoDataList::const_iterator it = cargolist.begin(); it != cargolist.end() && pos > -maxrows; ++it) {
+ 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 = this->vscroll.pos; ///< = this->vscroll.pos
+
+ uint width = this->widget[SVW_WAITING].right - this->widget[SVW_WAITING].left - 4;
+ int maxrows = this->vscroll.cap;
+
+ StringID str;
+
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);
- } else {
- DrawStringRightAligned(x + width, y, STR_0009, TC_FROMSTRING);
- }
- } else {
- SetDParam(0, cd->cargo);
- SetDParam(1, cd->count);
- SetDParam(2, cd->source);
- DrawStringRightAlignedTruncated(x + width, y, STR_EN_ROUTE_FROM, TC_FROMSTRING, width);
+ 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;
}
- }
-
- if (w->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);
- 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;
+ 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 {
- /* Add a comma if this is not the first item */
- *b++ = ',';
- *b++ = ' ';
+ SetDParam(0, cd->cargo);
+ SetDParam(1, cd->count);
+ SetDParam(2, cd->source);
+ DrawStringRightAlignedTruncated(x + width, y, STR_EN_ROUTE_FROM, TC_FROMSTRING, width);
}
- b = InlineString(b, GetCargo(i)->name);
+
+ y += 10;
}
}
- /* If first is still true then no cargo is accepted */
- if (first) b = InlineString(b, STR_00D0_NOTHING);
-
- *b = '\0';
-
- /* 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;
-
- 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;
+ if (this->widget[SVW_ACCEPTS].data == STR_3032_RATINGS) { // small window with list of accepted cargo
+ char *b = _userstring;
+ bool first = true;
- const GoodsEntry *ge = &st->goods[i];
- if (!HasBit(ge->acceptance_pickup, GoodsEntry::PICKUP)) continue;
+ b = InlineString(b, STR_000C_ACCEPTS);
- 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);
+ 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);
+ }
+ }
+
+ /* If first is still true then no cargo is accepted */
+ if (first) b = InlineString(b, STR_00D0_NOTHING);
+
+ *b = '\0';
+
+ /* Make sure we detect any buffer overflow */
+ assert(b < endof(_userstring));
+
+ 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;
- }
- }
-}
-static void HandleCargoWaitingClick(Window *w, int row)
-{
- if (row == 0) return;
+ for (CargoID i = 0; i < NUM_CARGO; i++) {
+ const CargoSpec *cs = GetCargo(i);
+ if (!cs->IsValid()) continue;
- 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;
+ 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;
+ }
}
}
-}
-
-
-/**
- * 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();
+ void HandleCargoWaitingClick(int row)
+ {
+ if (row == 0) return;
- 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);
- }
+ for (CargoID c = 0; c < NUM_CARGO; c++) {
+ if (this->cargo_rows[c] == row) {
+ ToggleBit(this->cargo, c);
+ this->InvalidateWidget(SVW_WAITING);
+ break;
+ }
+ }
+ }
- w->SetDirty();
- break;
+ 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;
- case SVW_RENAME:
- SetDParam(0, w->window_number);
- ShowQueryString(STR_STATION, STR_3030_RENAME_STATION_LOADING, 31, 180, w, CS_ALPHANUMERAL);
- break;
+ case SVW_LOCATION:
+ if (_ctrl_pressed) {
+ ShowExtraViewPortWindow(GetStation(this->window_number)->xy);
+ } else {
+ ScrollMainWindowToTile(GetStation(this->window_number)->xy);
+ }
+ break;
- 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;
+ case SVW_RATINGS:
+ this->SetDirty();
+
+ 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;
- }
-
- 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_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;
- }
- }
- break;
+ this->SetDirty();
+ break;
- case WE_ON_EDIT_TEXT:
- if (e->we.edittext.str[0] != '\0') {
- _cmd_text = e->we.edittext.str;
- DoCommandP(0, w->window_number, 0, NULL,
- CMD_RENAME_STATION | CMD_MSG(STR_3031_CAN_T_RENAME_STATION));
- }
- break;
-
- case WE_DESTROY: {
- WindowNumber wno =
- (w->window_number << 16) | VLW_STATION_LIST | GetStation(w->window_number)->owner;
+ case SVW_RENAME:
+ SetDParam(0, this->window_number);
+ ShowQueryString(STR_STATION, STR_3030_RENAME_STATION_LOADING, 31, 180, this, CS_ALPHANUMERAL);
+ break;
- DeleteWindowById(WC_TRAINS_LIST, wno);
- DeleteWindowById(WC_ROADVEH_LIST, wno);
- DeleteWindowById(WC_SHIPS_LIST, wno);
- DeleteWindowById(WC_AIRCRAFT_LIST, wno);
- 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;
+ }
+
+ 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;
+ }
+
+ 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;
+ }
}
+ }
- 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 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));
+ }
}
-}
+
+ 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 = {
@@ -1033,7 +1017,7 @@
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
};
/**
@@ -1043,11 +1027,5 @@
*/
void ShowStationViewWindow(StationID station)
{
- Window *w = AllocateWindowDescFront(&_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);
}
--- a/src/statusbar_gui.cpp Wed May 07 21:09:51 2008 +0000
+++ b/src/statusbar_gui.cpp Sun May 11 20:09:34 2008 +0000
@@ -12,7 +12,7 @@
#include "string_func.h"
#include "strings_func.h"
#include "player_base.h"
-#include "viewport_func.h"
+#include "tilehighlight_func.h"
#include "news_gui.h"
#include "player_gui.h"
#include "window_gui.h"
@@ -86,7 +86,7 @@
}
/* Draw status bar */
- if (w->message.msg) { // true when saving is active
+ if (WP(w, def_d).data_3) { // true when saving is active
DrawStringCenteredTruncated(w->widget[1].left + 1, w->widget[1].right - 1, 1, STR_SAVING_GAME, TC_FROMSTRING);
} else if (_do_autosave) {
DrawStringCenteredTruncated(w->widget[1].left + 1, w->widget[1].right - 1, 1, STR_032F_AUTOSAVE, TC_FROMSTRING);
@@ -113,9 +113,8 @@
if (WP(w, def_d).data_2 > 0) DrawSprite(SPR_BLOT, PALETTE_TO_RED, w->widget[1].right - 11, 2);
} break;
- case WE_MESSAGE:
- w->message.msg = e->we.message.msg;
- w->SetDirty();
+ case WE_INVALIDATE_DATA:
+ WP(w, def_d).data_3 = e->we.invalidate.data;
break;
case WE_CLICK:
@@ -163,7 +162,7 @@
void ShowStatusBar()
{
_main_status_desc.top = _screen.height - 12;
- Window *w = AllocateWindowDesc(&_main_status_desc);
+ Window *w = new Window(&_main_status_desc);
if (w != NULL) {
CLRBITS(w->flags4, WF_WHITE_BORDER_MASK);
WP(w, def_d).data_1 = -1280;
--- a/src/string_func.h Wed May 07 21:09:51 2008 +0000
+++ b/src/string_func.h Sun May 11 20:09:34 2008 +0000
@@ -45,10 +45,10 @@
/** Get the length of a string, within a limited buffer */
-static inline int ttd_strnlen(const char *str, int maxlen)
+static inline size_t ttd_strnlen(const char *str, size_t maxlen)
{
const char *t;
- for (t = str; *t != '\0' && t - str < maxlen; t++) {}
+ for (t = str; *t != '\0' && (size_t)(t - str) < maxlen; t++) {}
return t - str;
}
--- a/src/subsidy_gui.cpp Wed May 07 21:09:51 2008 +0000
+++ b/src/subsidy_gui.cpp Sun May 11 20:09:34 2008 +0000
@@ -197,5 +197,5 @@
void ShowSubsidiesList()
{
- AllocateWindowDescFront(&_subsidies_list_desc, 0);
+ AllocateWindowDescFront<Window>(&_subsidies_list_desc, 0);
}
--- a/src/table/engines.h Wed May 07 21:09:51 2008 +0000
+++ b/src/table/engines.h Sun May 11 20:09:34 2008 +0000
@@ -387,8 +387,8 @@
RVI( 0, G, 13, 112, 1000, 131, 120, RC_S, 0, 0 , 20, R, S), // 8
RVI( 1, G, 19, 128, 1200, 162, 140, RC_S, 0, 0 , 21, R, S), // 9
RVI( 0, G, 22, 144, 1600, 170, 130, RC_S, 0, 0 , 22, R, S), // 10
- RVI( 8, M, 11, 112, 600/2,32/2, 85/2, RC_D, 38, CT_PASSENGERS , 10, R, D), // 11
- RVI(10, M, 14, 120, 700/2,38/2, 70/2, RC_D, 40, CT_PASSENGERS , 11, R, D), // 12
+ RVI( 8, M, 11, 112, 600/2, 32, 85/2, RC_D, 38, CT_PASSENGERS , 10, R, D), // 11
+ RVI(10, M, 14, 120, 700/2, 38, 70/2, RC_D, 40, CT_PASSENGERS , 11, R, D), // 12
RVI( 4, G, 15, 128, 1250, 72, 95, RC_D, 0, 0 , 30, R, D), // 13
RVI( 5, G, 17, 144, 1750, 101, 120, RC_D, 0, 0 , 31, R, D), // 14
RVI( 4, G, 18, 160, 2580, 112, 140, RC_D, 0, 0 , 32, R, D), // 15
@@ -396,13 +396,13 @@
RVI(12, G, 16, 112, 2400, 120, 105, RC_D, 0, 0 , 34, R, D), // 17
RVI(13, G, 30, 112, 6600, 207, 155, RC_D, 0, 0 , 35, R, D), // 18
RVI(15, G, 18, 104, 1500, 110, 105, RC_D, 0, 0 , 29, R, D), // 19
- RVI(16, M, 35, 160, 3500/2,95/2, 205/2, RC_D, 0, 0 , 45, R, D), // 20
+ RVI(16, M, 35, 160, 3500/2, 95, 205/2, RC_D, 0, 0 , 45, R, D), // 20
RVI(18, G, 21, 104, 2200, 120, 145, RC_D, 0, 0 , 32, R, D), // 21
- RVI( 6, M, 20, 200, 4500/2,70/2, 190/2, RC_D, 4, CT_MAIL , 50, R, D), // 22
+ RVI( 6, M, 20, 200, 4500/2, 70, 190/2, RC_D, 4, CT_MAIL , 50, R, D), // 22
RVI(20, G, 26, 160, 3600, 84, 180, RC_E, 0, 0 , 40, C, E), // 23
RVI(20, G, 30, 176, 5000, 82, 205, RC_E, 0, 0 , 41, C, E), // 24
- RVI(21, M, 40, 240, 7000/2,90/2, 240/2, RC_E, 0, 0 , 51, C, E), // 25
- RVI(23, M, 43, 264, 8000/2,95/2, 250/2, RC_E, 0, 0 , 52, C, E), // 26
+ RVI(21, M, 40, 240, 7000/2, 90, 240/2, RC_E, 0, 0 , 51, C, E), // 25
+ RVI(23, M, 43, 264, 8000/2, 95, 250/2, RC_E, 0, 0 , 52, C, E), // 26
RVI(33, W, 247, 0, 0, 25, 0, RC_W, 40, CT_PASSENGERS , 0, R, A), // 27
RVI(35, W, 228, 0, 0, 21, 0, RC_W, 30, CT_MAIL , 0, R, A), // 28
RVI(34, W, 176, 0, 0, 18, 0, RC_W, 30, CT_COAL , 0, R, A), // 29
@@ -431,7 +431,7 @@
RVI(58, W, 193, 0, 0, 18, 0, RC_W, 25, CT_FIZZY_DRINKS, 0, R, A), // 52
RVI(59, W, 191, 0, 0, 18, 0, RC_W, 30, CT_PLASTIC , 0, R, A), // 53
RVI(25, G, 52, 304, 9000, 95, 230, RC_E, 0, 0 , 60, O, N), // 54
- RVI(26, M, 60, 336, 10000/2,85/2, 240/2, RC_E, 25, CT_PASSENGERS , 62, O, N), // 55
+ RVI(26, M, 60, 336, 10000/2, 85, 240/2, RC_E, 25, CT_PASSENGERS , 62, O, N), // 55
RVI(26, G, 53, 320, 5000, 95, 230, RC_E, 0, 0 , 63, O, N), // 56
RVI(60, W, 247, 0, 0, 25, 0, RC_W, 45, CT_PASSENGERS , 0, O, A), // 57
RVI(62, W, 228, 0, 0, 21, 0, RC_W, 35, CT_MAIL , 0, O, A), // 58
@@ -463,7 +463,7 @@
RVI(28, G, 70, 400, 10000, 105, 250, RC_E, 0, 0 , 70, L, V), // 84
RVI(29, G, 74, 448, 12000, 120, 253, RC_E, 0, 0 , 71, L, V), // 85
RVI(30, G, 82, 480, 15000, 130, 254, RC_E, 0, 0 , 72, L, V), // 86
- RVI(31, M, 95, 640, 20000/2,150/2,255/2, RC_E, 0, 0 , 73, L, V), // 87
+ RVI(31, M, 95, 640, 20000/2, 150, 255/2, RC_E, 0, 0 , 73, L, V), // 87
RVI(28, G, 70, 480, 10000, 120, 250, RC_E, 0, 0 , 74, L, V), // 88
RVI(60, W, 247, 0, 0, 25, 0, RC_W, 47, CT_PASSENGERS , 0, L, A), // 89
RVI(62, W, 228, 0, 0, 21, 0, RC_W, 37, CT_MAIL , 0, L, A), // 90
--- a/src/terraform_gui.cpp Wed May 07 21:09:51 2008 +0000
+++ b/src/terraform_gui.cpp Sun May 11 20:09:34 2008 +0000
@@ -159,6 +159,13 @@
'O',
};
+void CcPlaySound1E(bool success, TileIndex tile, uint32 p1, uint32 p2);
+
+static void PlaceProc_BuyLand(TileIndex tile)
+{
+ DoCommandP(tile, 0, 0, CcPlaySound1E, CMD_PURCHASE_LAND_AREA | CMD_NO_WATER | CMD_MSG(STR_5806_CAN_T_PURCHASE_THIS_LAND));
+}
+
void PlaceProc_DemolishArea(TileIndex tile)
{
VpStartPlaceSizing(tile, VPM_X_AND_Y, DDSP_DEMOLISH_AREA);
@@ -174,7 +181,7 @@
VpStartPlaceSizing(tile, VPM_X_AND_Y, DDSP_LOWER_AND_LEVEL_AREA);
}
-void PlaceProc_LevelLand(TileIndex tile)
+static void PlaceProc_LevelLand(TileIndex tile)
{
VpStartPlaceSizing(tile, VPM_X_AND_Y, DDSP_LEVEL_AREA);
}
@@ -304,7 +311,7 @@
void ShowTerraformToolbar(Window *link)
{
if (!IsValidPlayer(_current_player)) return;
- Window *w = AllocateWindowDescFront(&_terraform_desc, 0);
+ Window *w = AllocateWindowDescFront<Window>(&_terraform_desc, 0);
if (w != NULL && link != NULL) {
/* Align the terraform toolbar under the main toolbar and put the linked
* toolbar to left of it
@@ -679,5 +686,5 @@
void ShowEditorTerraformToolbar()
{
- AllocateWindowDescFront(&_scen_edit_land_gen_desc, 0);
+ AllocateWindowDescFront<Window>(&_scen_edit_land_gen_desc, 0);
}
--- a/src/textbuf_gui.h Wed May 07 21:09:51 2008 +0000
+++ b/src/textbuf_gui.h Sun May 11 20:09:34 2008 +0000
@@ -18,21 +18,6 @@
uint16 caretxoffs; ///< the current position of the caret in pixels
};
-struct querystr_d {
- StringID caption;
- Textbuf text;
- const char *orig;
- CharSetFilter afilter;
- bool handled;
-};
-assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(querystr_d));
-
-extern char _edit_str_buf[64];
-extern char _orig_str_buf[lengthof(_edit_str_buf)];
-
-void DrawEditBox(Window *w, querystr_d *string, int wid);
-void HandleEditBox(Window *w, querystr_d *string, int wid);
-int HandleEditBoxKey(Window *w, querystr_d *string, int wid, WindowEvent *we);
bool HandleCaret(Textbuf *tb);
void DeleteTextBufferAll(Textbuf *tb);
@@ -56,6 +41,4 @@
*/
extern char _keyboard_opt[2][OSK_KEYBOARD_ENTRIES * 4 + 1];
-void ShowOnScreenKeyboard(Window *parent, querystr_d *q, int button, int cancel, int ok);
-
#endif /* TEXTBUF_GUI_H */
--- a/src/tilehighlight_func.h Wed May 07 21:09:51 2008 +0000
+++ b/src/tilehighlight_func.h Sun May 11 20:09:34 2008 +0000
@@ -12,13 +12,17 @@
typedef void PlaceProc(TileIndex tile);
void PlaceProc_DemolishArea(TileIndex tile);
-void PlaceProc_LevelLand(TileIndex tile);
-void PlaceProc_BuyLand(TileIndex tile);
bool GUIPlaceProcDragXY(const WindowEvent *e);
bool HandlePlacePushButton(Window *w, int widget, CursorID cursor, ViewportHighlightMode mode, PlaceProc *placeproc);
void SetObjectToPlaceWnd(CursorID icon, SpriteID pal, ViewportHighlightMode mode, Window *w);
void SetObjectToPlace(CursorID icon, SpriteID pal, ViewportHighlightMode mode, WindowClass window_class, WindowNumber window_num);
+void ResetObjectToPlace();
+
+void VpSelectTilesWithMethod(int x, int y, ViewportPlaceMethod method);
+void VpStartPlaceSizing(TileIndex tile, ViewportPlaceMethod method, ViewportDragDropSelectionProcess process);
+void VpSetPresizeRange(TileIndex from, TileIndex to);
+void VpSetPlaceSizingLimit(int limit);
extern PlaceProc *_place_proc;
extern TileHighlightData _thd;
--- a/src/tilehighlight_type.h Wed May 07 21:09:51 2008 +0000
+++ b/src/tilehighlight_type.h Sun May 11 20:09:34 2008 +0000
@@ -69,7 +69,7 @@
WindowNumber window_number;
ViewportPlaceMethod select_method;
- byte select_proc;
+ ViewportDragDropSelectionProcess select_proc;
TileIndex redsq;
};
--- a/src/timetable_gui.cpp Wed May 07 21:09:51 2008 +0000
+++ b/src/timetable_gui.cpp Sun May 11 20:09:34 2008 +0000
@@ -249,6 +249,8 @@
} break;
case WE_ON_EDIT_TEXT: {
+ if (we->we.edittext.str == NULL) break;
+
const Vehicle *v = GetVehicle(w->window_number);
uint32 p1 = PackTimetableArgs(v, WP(w, timetable_d).sel);
@@ -301,7 +303,7 @@
void ShowTimetableWindow(const Vehicle *v)
{
- Window *w = AllocateWindowDescFront(&_timetable_desc, v->index);
+ Window *w = AllocateWindowDescFront<Window>(&_timetable_desc, v->index);
if (w != NULL) {
w->caption_color = v->owner;
--- a/src/toolbar_gui.cpp Wed May 07 21:09:51 2008 +0000
+++ b/src/toolbar_gui.cpp Sun May 11 20:09:34 2008 +0000
@@ -78,6 +78,29 @@
return pos;
}
+/**
+ * In a window with menu_d custom extension, retrieve the menu item number from a position
+ * @param w Window holding the menu items
+ * @param x X coordinate of the position
+ * @param y Y coordinate of the position
+ * @return Index number of the menu item, or \c -1 if no valid selection under position
+ */
+static int GetMenuItemIndex(const Window *w)
+{
+ int x = _cursor.pos.x;
+ int y = _cursor.pos.y;
+
+ if ((x -= w->left) >= 0 && x < w->width && (y -= w->top + 1) >= 0) {
+ y /= 10;
+
+ if (y < WP(w, const menu_d).item_count &&
+ !HasBit(WP(w, const menu_d).disabled_items, y)) {
+ return y;
+ }
+ }
+ return -1;
+}
+
/* --- Pausing --- */
static void ToolbarPauseClick(Window *w)
@@ -727,7 +750,7 @@
w->SetDirty();
break;
- case WE_MOUSELOOP:
+ case WE_TICK:
if (w->IsWidgetLowered(0) != !!_pause_game) {
w->ToggleWidgetLoweredState(0);
w->InvalidateWidget(0);
@@ -775,7 +798,7 @@
}
break;
- case WE_MESSAGE:
+ case WE_INVALIDATE_DATA:
if (FindWindowById(WC_MAIN_WINDOW, 0) != NULL) HandleZoomMessage(w, FindWindowById(WC_MAIN_WINDOW, 0)->viewport, 17, 18);
break;
}
@@ -999,7 +1022,7 @@
}
} break;
- case WE_MOUSELOOP:
+ case WE_TICK:
if (w->IsWidgetLowered(0) != !!_pause_game) {
w->ToggleWidgetLoweredState(0);
w->SetDirty();
@@ -1011,7 +1034,7 @@
}
break;
- case WE_MESSAGE:
+ case WE_INVALIDATE_DATA:
HandleZoomMessage(w, FindWindowById(WC_MAIN_WINDOW, 0)->viewport, 9, 10);
break;
}
@@ -1135,34 +1158,30 @@
return;
}
- case WE_POPUPMENU_SELECT: {
- int index = GetMenuItemIndex(w, e->we.popupmenu.pt.x, e->we.popupmenu.pt.y);
-
- if (index < 0) {
- Window *w2 = FindWindowById(WC_MAIN_TOOLBAR,0);
- if (GetWidgetFromPos(w2, e->we.popupmenu.pt.x - w2->left, e->we.popupmenu.pt.y - w2->top) == WP(w, menu_d).main_button)
- index = WP(w, menu_d).sel_index;
- }
-
- int action_id = WP(w, menu_d).action_id;
- delete w;
+ case WE_MOUSELOOP: {
+ int index = GetMenuItemIndex(w);
- if (index >= 0) {
- assert((uint)index <= lengthof(_menu_clicked_procs));
- _menu_clicked_procs[action_id](index);
- }
-
- } break;
+ if (_left_button_down) {
+ if (index == -1 || index == WP(w, menu_d).sel_index) return;
- case WE_POPUPMENU_OVER: {
- int index = GetMenuItemIndex(w, e->we.popupmenu.pt.x, e->we.popupmenu.pt.y);
+ WP(w, menu_d).sel_index = index;
+ w->SetDirty();
+ } else {
+ if (index < 0) {
+ Window *w2 = FindWindowById(WC_MAIN_TOOLBAR,0);
+ if (GetWidgetFromPos(w2, _cursor.pos.x - w2->left, _cursor.pos.y - w2->top) == WP(w, menu_d).main_button)
+ index = WP(w, menu_d).sel_index;
+ }
- if (index == -1 || index == WP(w, menu_d).sel_index) return;
+ int action_id = WP(w, menu_d).action_id;
+ delete w;
- WP(w, menu_d).sel_index = index;
- w->SetDirty();
- return;
- }
+ if (index >= 0) {
+ assert((uint)index <= lengthof(_menu_clicked_procs));
+ _menu_clicked_procs[action_id](index);
+ }
+ }
+ } break;
}
}
@@ -1232,7 +1251,7 @@
Point pos = GetToolbarDropdownPos(parent_button, width, height);
- w = AllocateWindow(pos.x, pos.y, width, height, MenuWndProc, WC_TOOLBAR_MENU, _menu_widgets);
+ w = new Window(pos.x, pos.y, width, height, MenuWndProc, WC_TOOLBAR_MENU, _menu_widgets);
w->widget[0].bottom = item_count * 10 + 1;
w->flags4 &= ~WF_WHITE_BORDER_MASK;
@@ -1244,8 +1263,6 @@
WP(w, menu_d).checked_items = 0;
WP(w, menu_d).disabled_items = disabled_mask;
- _popup_menu_active = true;
-
SndPlayFx(SND_15_BEEP);
return w;
}
@@ -1332,51 +1349,48 @@
return;
}
- case WE_POPUPMENU_SELECT: {
- int index = GetMenuItemIndex(w, e->we.popupmenu.pt.x, e->we.popupmenu.pt.y);
- int action_id = WP(w, menu_d).action_id;
+ case WE_MOUSELOOP: {
+ int index = GetMenuItemIndex(w);
- /* We have a new entry at the top of the list of menu 9 when networking
- * so keep that in count */
- if (_networking && WP(w, menu_d).main_button == 9) {
- if (index > 0) index = GetPlayerIndexFromMenu(index - 1) + 1;
+ if (_left_button_down) {
+ UpdatePlayerMenuHeight(w);
+ /* We have a new entry at the top of the list of menu 9 when networking
+ * so keep that in count */
+ if (_networking && WP(w, menu_d).main_button == 9) {
+ if (index > 0) index = GetPlayerIndexFromMenu(index - 1) + 1;
+ } else {
+ index = GetPlayerIndexFromMenu(index);
+ }
+
+ if (index == -1 || index == WP(w, menu_d).sel_index) return;
+
+ WP(w, menu_d).sel_index = index;
+ w->SetDirty();
} else {
- index = GetPlayerIndexFromMenu(index);
- }
+ int action_id = WP(w, menu_d).action_id;
- if (index < 0) {
- Window *w2 = FindWindowById(WC_MAIN_TOOLBAR,0);
- if (GetWidgetFromPos(w2, e->we.popupmenu.pt.x - w2->left, e->we.popupmenu.pt.y - w2->top) == WP(w, menu_d).main_button)
- index = WP(w, menu_d).sel_index;
- }
+ /* We have a new entry at the top of the list of menu 9 when networking
+ * so keep that in count */
+ if (_networking && WP(w, menu_d).main_button == 9) {
+ if (index > 0) index = GetPlayerIndexFromMenu(index - 1) + 1;
+ } else {
+ index = GetPlayerIndexFromMenu(index);
+ }
- delete w;
+ if (index < 0) {
+ Window *w2 = FindWindowById(WC_MAIN_TOOLBAR,0);
+ if (GetWidgetFromPos(w2, _cursor.pos.x - w2->left, _cursor.pos.y - w2->top) == WP(w, menu_d).main_button)
+ index = WP(w, menu_d).sel_index;
+ }
- if (index >= 0) {
- assert(index >= 0 && index < 30);
- _menu_clicked_procs[action_id](index);
+ delete w;
+
+ if (index >= 0) {
+ assert(index >= 0 && index < 30);
+ _menu_clicked_procs[action_id](index);
+ }
}
} break;
-
- case WE_POPUPMENU_OVER: {
- int index;
- UpdatePlayerMenuHeight(w);
- index = GetMenuItemIndex(w, e->we.popupmenu.pt.x, e->we.popupmenu.pt.y);
-
- /* We have a new entry at the top of the list of menu 9 when networking
- * so keep that in count */
- if (_networking && WP(w, menu_d).main_button == 9) {
- if (index > 0) index = GetPlayerIndexFromMenu(index - 1) + 1;
- } else {
- index = GetPlayerIndexFromMenu(index);
- }
-
- if (index == -1 || index == WP(w, menu_d).sel_index) return;
-
- WP(w, menu_d).sel_index = index;
- w->SetDirty();
- return;
- }
}
}
@@ -1392,7 +1406,7 @@
DeleteWindowById(WC_TOOLBAR_MENU, 0);
Point pos = GetToolbarDropdownPos(main_button, 241, 82);
- w = AllocateWindow(pos.x, pos.y, 241, 82, PlayerMenuWndProc, WC_TOOLBAR_MENU, _player_menu_widgets);
+ w = new Window(pos.x, pos.y, 241, 82, PlayerMenuWndProc, WC_TOOLBAR_MENU, _player_menu_widgets);
w->flags4 &= ~WF_WHITE_BORDER_MASK;
WP(w, menu_d).item_count = 0;
WP(w, menu_d).sel_index = (_local_player != PLAYER_SPECTATOR) ? _local_player : GetPlayerIndexFromMenu(0);
@@ -1408,7 +1422,7 @@
WP(w, menu_d).main_button = main_button;
WP(w, menu_d).checked_items = gray;
WP(w, menu_d).disabled_items = 0;
- _popup_menu_active = true;
+
SndPlayFx(SND_15_BEEP);
return w;
}
@@ -1420,7 +1434,7 @@
/* Clean old GUI values; railtype is (re)set by rail_gui.cpp */
_last_built_roadtype = ROADTYPE_ROAD;
- Window *w = AllocateWindowDesc((_game_mode != GM_EDITOR) ? &_toolb_normal_desc : &_toolb_scen_desc);
+ Window *w = new Window((_game_mode != GM_EDITOR) ? &_toolb_normal_desc : &_toolb_scen_desc);
if (w == NULL) return NULL;
CLRBITS(w->flags4, WF_WHITE_BORDER_MASK);
--- a/src/town_gui.cpp Wed May 07 21:09:51 2008 +0000
+++ b/src/town_gui.cpp Sun May 11 20:09:34 2008 +0000
@@ -23,6 +23,7 @@
#include "core/alloc_func.hpp"
#include "settings_type.h"
#include "tilehighlight_func.h"
+#include "string_func.h"
#include "table/sprites.h"
#include "table/strings.h"
@@ -252,7 +253,7 @@
}
break;
- case WE_4:
+ case WE_100_TICKS:
w->SetDirty();
break;
}
@@ -268,7 +269,7 @@
static void ShowTownAuthorityWindow(uint town)
{
- Window *w = AllocateWindowDescFront(&_town_authority_desc, town);
+ Window *w = AllocateWindowDescFront<Window>(&_town_authority_desc, town);
if (w != NULL) {
w->vscroll.cap = 5;
@@ -360,7 +361,7 @@
} break;
case WE_ON_EDIT_TEXT:
- if (e->we.edittext.str[0] != '\0') {
+ if (!StrEmpty(e->we.edittext.str)) {
_cmd_text = e->we.edittext.str;
DoCommandP(0, w->window_number, 0, NULL,
CMD_RENAME_TOWN | CMD_MSG(STR_2008_CAN_T_RENAME_TOWN));
@@ -397,7 +398,7 @@
{
Window *w;
- w = AllocateWindowDescFront(&_town_view_desc, town);
+ w = AllocateWindowDescFront<Window>(&_town_view_desc, town);
if (w != NULL) {
w->flags4 |= WF_DISABLE_VP_SCROLL;
@@ -555,7 +556,7 @@
}
break;
- case WE_4:
+ case WE_100_TICKS:
w->SetDirty();
break;
@@ -576,7 +577,7 @@
void ShowTownDirectory()
{
- Window *w = AllocateWindowDescFront(&_town_directory_desc, 0);
+ Window *w = AllocateWindowDescFront<Window>(&_town_directory_desc, 0);
if (w != NULL) {
w->vscroll.cap = 16;
@@ -705,6 +706,6 @@
void ShowBuildTownWindow()
{
if (_game_mode != GM_EDITOR && !IsValidPlayer(_current_player)) return;
- AllocateWindowDescFront(&_scen_edit_town_gen_desc, 0);
+ AllocateWindowDescFront<Window>(&_scen_edit_town_gen_desc, 0);
}
--- a/src/transparency_gui.cpp Wed May 07 21:09:51 2008 +0000
+++ b/src/transparency_gui.cpp Sun May 11 20:09:34 2008 +0000
@@ -126,5 +126,5 @@
void ShowTransparencyToolbar(void)
{
- AllocateWindowDescFront(&_transparency_desc, 0);
+ AllocateWindowDescFront<Window>(&_transparency_desc, 0);
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/tree_gui.cpp Sun May 11 20:09:34 2008 +0000
@@ -0,0 +1,193 @@
+/* $Id$ */
+
+/** @file tree_gui.cpp GUIs for building trees. */
+
+#include "stdafx.h"
+#include "openttd.h"
+#include "window_gui.h"
+#include "gfx_func.h"
+#include "tilehighlight_func.h"
+#include "player_func.h"
+#include "command_func.h"
+#include "sound_func.h"
+#include "settings_type.h"
+
+#include "table/sprites.h"
+#include "table/strings.h"
+#include "table/tree_land.h"
+
+struct tree_d {
+ uint16 base;
+ uint16 count;
+};
+assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(tree_d));
+
+static int _tree_to_plant;
+void PlaceTreesRandomly();
+
+static const PalSpriteID _tree_sprites[] = {
+ { 0x655, PAL_NONE }, { 0x663, PAL_NONE }, { 0x678, PAL_NONE }, { 0x62B, PAL_NONE },
+ { 0x647, PAL_NONE }, { 0x639, PAL_NONE }, { 0x64E, PAL_NONE }, { 0x632, PAL_NONE },
+ { 0x67F, PAL_NONE }, { 0x68D, PAL_NONE }, { 0x69B, PAL_NONE }, { 0x6A9, PAL_NONE },
+ { 0x6AF, PAL_NONE }, { 0x6D2, PAL_NONE }, { 0x6D9, PAL_NONE }, { 0x6C4, PAL_NONE },
+ { 0x6CB, PAL_NONE }, { 0x6B6, PAL_NONE }, { 0x6BD, PAL_NONE }, { 0x6E0, PAL_NONE },
+ { 0x72E, PAL_NONE }, { 0x734, PAL_NONE }, { 0x74A, PAL_NONE }, { 0x74F, PAL_NONE },
+ { 0x76B, PAL_NONE }, { 0x78F, PAL_NONE }, { 0x788, PAL_NONE }, { 0x77B, PAL_NONE },
+ { 0x75F, PAL_NONE }, { 0x774, PAL_NONE }, { 0x720, PAL_NONE }, { 0x797, PAL_NONE },
+ { 0x79E, PAL_NONE }, { 0x7A5, PALETTE_TO_GREEN }, { 0x7AC, PALETTE_TO_RED }, { 0x7B3, PAL_NONE },
+ { 0x7BA, PAL_NONE }, { 0x7C1, PALETTE_TO_RED, }, { 0x7C8, PALETTE_TO_PALE_GREEN }, { 0x7CF, PALETTE_TO_YELLOW }, { 0x7D6, PALETTE_TO_RED }
+};
+
+static void BuildTreesWndProc(Window *w, WindowEvent *e)
+{
+ switch (e->event) {
+ case WE_CREATE:
+ ResetObjectToPlace();
+ break;
+
+ case WE_PAINT: {
+ DrawWindowWidgets(w);
+
+ int i = WP(w, tree_d).base = _tree_base_by_landscape[_opt.landscape];
+ int count = WP(w, tree_d).count = _tree_count_by_landscape[_opt.landscape];
+
+ int x = 18;
+ int y = 54;
+ do {
+ DrawSprite(_tree_sprites[i].sprite, _tree_sprites[i].pal, x, y);
+ x += 35;
+ if (!(++i & 3)) {
+ x -= 35 * 4;
+ y += 47;
+ }
+ } while (--count);
+ } break;
+
+ case WE_CLICK: {
+ int wid = e->we.click.widget;
+
+ switch (wid) {
+ case 0:
+ ResetObjectToPlace();
+ break;
+
+ case 3: case 4: case 5: case 6:
+ case 7: case 8: case 9: case 10:
+ case 11:case 12: case 13: case 14:
+ if (wid - 3 >= WP(w, tree_d).count) break;
+
+ if (HandlePlacePushButton(w, wid, SPR_CURSOR_TREE, VHM_RECT, NULL)) {
+ _tree_to_plant = WP(w, tree_d).base + wid - 3;
+ }
+ break;
+
+ case 15: // tree of random type.
+ if (HandlePlacePushButton(w, 15, SPR_CURSOR_TREE, VHM_RECT, NULL)) {
+ _tree_to_plant = -1;
+ }
+ break;
+
+ case 16: // place trees randomly over the landscape
+ w->LowerWidget(16);
+ w->flags4 |= 5 << WF_TIMEOUT_SHL;
+ SndPlayFx(SND_15_BEEP);
+ PlaceTreesRandomly();
+ MarkWholeScreenDirty();
+ break;
+ }
+ } break;
+
+ case WE_PLACE_OBJ:
+ VpStartPlaceSizing(e->we.place.tile, VPM_X_AND_Y_LIMITED, DDSP_PLANT_TREES);
+ VpSetPlaceSizingLimit(20);
+ break;
+
+ case WE_PLACE_DRAG:
+ VpSelectTilesWithMethod(e->we.place.pt.x, e->we.place.pt.y, e->we.place.select_method);
+ return;
+
+ case WE_PLACE_MOUSEUP:
+ if (e->we.place.pt.x != -1 && e->we.place.select_proc == DDSP_PLANT_TREES) {
+ DoCommandP(e->we.place.tile, _tree_to_plant, e->we.place.starttile, NULL,
+ CMD_PLANT_TREE | CMD_MSG(STR_2805_CAN_T_PLANT_TREE_HERE));
+ }
+ break;
+
+ case WE_TIMEOUT:
+ w->RaiseWidget(16);
+ break;
+
+ case WE_ABORT_PLACE_OBJ:
+ w->RaiseButtons();
+ break;
+ }
+}
+
+static const Widget _build_trees_widgets[] = {
+{ WWT_CLOSEBOX, RESIZE_NONE, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
+{ WWT_CAPTION, RESIZE_NONE, 7, 11, 142, 0, 13, STR_2802_TREES, STR_018C_WINDOW_TITLE_DRAG_THIS},
+{ WWT_PANEL, RESIZE_NONE, 7, 0, 142, 14, 170, 0x0, STR_NULL},
+{ WWT_PANEL, RESIZE_NONE, 14, 2, 35, 16, 61, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT},
+{ WWT_PANEL, RESIZE_NONE, 14, 37, 70, 16, 61, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT},
+{ WWT_PANEL, RESIZE_NONE, 14, 72, 105, 16, 61, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT},
+{ WWT_PANEL, RESIZE_NONE, 14, 107, 140, 16, 61, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT},
+{ WWT_PANEL, RESIZE_NONE, 14, 2, 35, 63, 108, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT},
+{ WWT_PANEL, RESIZE_NONE, 14, 37, 70, 63, 108, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT},
+{ WWT_PANEL, RESIZE_NONE, 14, 72, 105, 63, 108, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT},
+{ WWT_PANEL, RESIZE_NONE, 14, 107, 140, 63, 108, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT},
+{ WWT_PANEL, RESIZE_NONE, 14, 2, 35, 110, 155, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT},
+{ WWT_PANEL, RESIZE_NONE, 14, 37, 70, 110, 155, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT},
+{ WWT_PANEL, RESIZE_NONE, 14, 72, 105, 110, 155, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT},
+{ WWT_PANEL, RESIZE_NONE, 14, 107, 140, 110, 155, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT},
+{ WWT_TEXTBTN, RESIZE_NONE, 14, 2, 140, 157, 168, STR_TREES_RANDOM_TYPE, STR_TREES_RANDOM_TYPE_TIP},
+{ WIDGETS_END},
+};
+
+static const WindowDesc _build_trees_desc = {
+ 497, 22, 143, 171, 143, 171,
+ WC_BUILD_TREES, WC_SCEN_LAND_GEN,
+ WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
+ _build_trees_widgets,
+ BuildTreesWndProc
+};
+
+static const Widget _build_trees_scen_widgets[] = {
+{ WWT_CLOSEBOX, RESIZE_NONE, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
+{ WWT_CAPTION, RESIZE_NONE, 7, 11, 142, 0, 13, STR_2802_TREES, STR_018C_WINDOW_TITLE_DRAG_THIS},
+{ WWT_PANEL, RESIZE_NONE, 7, 0, 142, 14, 183, 0x0, STR_NULL},
+{ WWT_PANEL, RESIZE_NONE, 14, 2, 35, 16, 61, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT},
+{ WWT_PANEL, RESIZE_NONE, 14, 37, 70, 16, 61, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT},
+{ WWT_PANEL, RESIZE_NONE, 14, 72, 105, 16, 61, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT},
+{ WWT_PANEL, RESIZE_NONE, 14, 107, 140, 16, 61, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT},
+{ WWT_PANEL, RESIZE_NONE, 14, 2, 35, 63, 108, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT},
+{ WWT_PANEL, RESIZE_NONE, 14, 37, 70, 63, 108, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT},
+{ WWT_PANEL, RESIZE_NONE, 14, 72, 105, 63, 108, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT},
+{ WWT_PANEL, RESIZE_NONE, 14, 107, 140, 63, 108, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT},
+{ WWT_PANEL, RESIZE_NONE, 14, 2, 35, 110, 155, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT},
+{ WWT_PANEL, RESIZE_NONE, 14, 37, 70, 110, 155, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT},
+{ WWT_PANEL, RESIZE_NONE, 14, 72, 105, 110, 155, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT},
+{ WWT_PANEL, RESIZE_NONE, 14, 107, 140, 110, 155, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT},
+{ WWT_TEXTBTN, RESIZE_NONE, 14, 2, 140, 157, 168, STR_TREES_RANDOM_TYPE, STR_TREES_RANDOM_TYPE_TIP},
+{ WWT_TEXTBTN, RESIZE_NONE, 14, 2, 140, 170, 181, STR_028A_RANDOM_TREES, STR_028B_PLANT_TREES_RANDOMLY_OVER},
+{ WIDGETS_END},
+};
+
+static const WindowDesc _build_trees_scen_desc = {
+ WDP_AUTO, WDP_AUTO, 143, 184, 143, 184,
+ WC_BUILD_TREES, WC_NONE,
+ WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
+ _build_trees_scen_widgets,
+ BuildTreesWndProc
+};
+
+
+void ShowBuildTreesToolbar()
+{
+ if (!IsValidPlayer(_current_player)) return;
+ AllocateWindowDescFront<Window>(&_build_trees_desc, 0);
+}
+
+void ShowBuildTreesScenToolbar()
+{
+ AllocateWindowDescFront<Window>(&_build_trees_scen_desc, 0);
+}
--- a/src/tunnelbridge_cmd.cpp Wed May 07 21:09:51 2008 +0000
+++ b/src/tunnelbridge_cmd.cpp Sun May 11 20:09:34 2008 +0000
@@ -39,6 +39,7 @@
#include "economy_func.h"
#include "rail.h"
#include "cheat_func.h"
+#include "elrail_func.h"
#include "landscape_type.h"
#include "table/sprites.h"
@@ -887,7 +888,7 @@
AddSortableSpriteToDraw(SPR_TRAMWAY_TUNNEL_WIRES + tunnelbridge_direction, PAL_NONE, ti->x, ti->y, BB_data[10], BB_data[11], TILE_HEIGHT, ti->z, IsTransparencySet(TO_CATENARY), BB_data[8], BB_data[9], BB_Z_SEPARATOR);
}
}
- } else if (!IsInvisibilitySet(TO_CATENARY) && HasCatenary(GetRailType(ti->tile))) {
+ } else if (HasCatenaryDrawn(GetRailType(ti->tile))) {
catenary = true;
StartSpriteCombine();
DrawCatenaryOnTunnel(ti);
@@ -960,7 +961,7 @@
DrawBridgeTramBits(ti->x, ti->y, z, offset, HasBit(rts, ROADTYPE_ROAD), true);
}
EndSpriteCombine();
- } else if (HasCatenary(GetRailType(ti->tile))) {
+ } else if (HasCatenaryDrawn(GetRailType(ti->tile))) {
DrawCatenary(ti);
}
@@ -1088,7 +1089,7 @@
EndSpriteCombine();
StartSpriteCombine();
}
- } else if (HasCatenary(GetRailType(rampsouth))) {
+ } else if (HasCatenaryDrawn(GetRailType(rampsouth))) {
DrawCatenaryOnBridge(ti);
}
--- a/src/vehicle.cpp Wed May 07 21:09:51 2008 +0000
+++ b/src/vehicle.cpp Sun May 11 20:09:34 2008 +0000
@@ -592,9 +592,9 @@
}
Window *w = FindWindowById(WC_MAIN_WINDOW, 0);
- if (w != NULL && WP(w, vp_d).follow_vehicle == this->index) {
+ if (w != NULL && w->viewport->follow_vehicle == this->index) {
ScrollMainWindowTo(this->x_pos, this->y_pos, true); // lock the main view on the vehicle's last position
- WP(w, vp_d).follow_vehicle = INVALID_VEHICLE;
+ w->viewport->follow_vehicle = INVALID_VEHICLE;
}
}
@@ -2693,7 +2693,7 @@
{
int length = CountVehiclesInChain(v);
- uint cargo_packages_count = 1;
+ size_t cargo_packages_count = 1;
for (const Vehicle *v_count = v; v_count != NULL; v_count=v_count->Next()) {
/* Now we count how many cargo packets we need to store.
* We started with an offset by one because we also need an end of array marker. */
--- a/src/vehicle_gui.cpp Wed May 07 21:09:51 2008 +0000
+++ b/src/vehicle_gui.cpp Sun May 11 20:09:34 2008 +0000
@@ -40,6 +40,11 @@
#include "table/sprites.h"
#include "table/strings.h"
+struct vehicledetails_d {
+ byte tab;
+};
+assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(vehicledetails_d));
+
struct refit_d {
int sel;
struct RefitOption *cargo;
@@ -49,15 +54,7 @@
};
assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(refit_d));
-struct Sorting {
- Listing aircraft;
- Listing roadveh;
- Listing ship;
- Listing train;
-};
-
-static Sorting _sorting;
-
+Sorting _sorting;
static bool _internal_sort_order; // descending/ascending
typedef int CDECL VehicleSortListingTypeFunction(const void*, const void*);
@@ -119,7 +116,7 @@
case WC_ROADVEH_LIST:
case WC_SHIPS_LIST:
case WC_AIRCRAFT_LIST:
- WP(w, vehiclelist_d).l.flags |= sl_flag;
+ dynamic_cast<VehicleListBase*>(w)->vehicles.flags |= sl_flag;
w->SetDirty();
break;
@@ -144,35 +141,35 @@
SetVehicleListsFlag(VL_RESORT);
}
-void BuildVehicleList(vehiclelist_d *vl, PlayerID owner, uint16 index, uint16 window_type)
+void BuildVehicleList(VehicleListBase *vl, PlayerID owner, uint16 index, uint16 window_type)
{
- if (!(vl->l.flags & VL_REBUILD)) return;
+ if (!(vl->vehicles.flags & VL_REBUILD)) return;
DEBUG(misc, 3, "Building vehicle list for player %d at station %d", owner, index);
- vl->l.list_length = GenerateVehicleSortList(&vl->sort_list, &vl->length_of_sort_list, vl->vehicle_type, owner, index, window_type);
+ vl->vehicles.list_length = GenerateVehicleSortList(&vl->vehicles.sort_list, &vl->vehicles.list_length, vl->vehicle_type, owner, index, window_type);
- vl->l.flags &= ~VL_REBUILD;
- vl->l.flags |= VL_RESORT;
+ vl->vehicles.flags &= ~VL_REBUILD;
+ vl->vehicles.flags |= VL_RESORT;
}
/* cached values for VehicleNameSorter to spare many GetString() calls */
static const Vehicle *_last_vehicle[2] = { NULL, NULL };
static char _last_name[2][64] = { "", "" };
-void SortVehicleList(vehiclelist_d *vl)
+void SortVehicleList(VehicleListBase *vl)
{
- if (!(vl->l.flags & VL_RESORT)) return;
+ if (!(vl->vehicles.flags & VL_RESORT)) return;
/* invalidate cached values for name sorter - vehicle names could change */
_last_vehicle[0] = _last_vehicle[1] = NULL;
- _internal_sort_order = (vl->l.flags & VL_DESC) != 0;
- qsort((void*)vl->sort_list, vl->l.list_length, sizeof(vl->sort_list[0]),
- _vehicle_sorter[vl->l.sort_type]);
+ _internal_sort_order = (vl->vehicles.flags & VL_DESC) != 0;
+ qsort((void*)vl->vehicles.sort_list, vl->vehicles.list_length, sizeof(vl->vehicles.sort_list[0]),
+ _vehicle_sorter[vl->vehicles.sort_type]);
- vl->l.resort_timer = DAY_TICKS * PERIODIC_RESORT_DAYS;
- vl->l.flags &= ~VL_RESORT;
+ vl->vehicles.resort_timer = DAY_TICKS * PERIODIC_RESORT_DAYS;
+ vl->vehicles.flags &= ~VL_RESORT;
}
void DepotSortList(Vehicle **v, uint16 length)
@@ -451,7 +448,7 @@
DeleteWindowById(WC_VEHICLE_REFIT, v->index);
- w = AllocateWindowDescFront(&_vehicle_refit_desc, v->index);
+ w = AllocateWindowDescFront<Window>(&_vehicle_refit_desc, v->index);
WP(w, refit_d).order = order;
if (w != NULL) {
@@ -741,7 +738,7 @@
if (w != NULL) {
w->window_number = to_index;
- WP(w, vp_d).follow_vehicle = to_index;
+ w->viewport->follow_vehicle = to_index;
w->SetDirty();
w = FindWindowById(WC_VEHICLE_ORDERS, from_index);
@@ -810,128 +807,6 @@
{ WIDGETS_END},
};
-static void CreateVehicleListWindow(Window *w)
-{
- vehiclelist_d *vl = &WP(w, vehiclelist_d);
- uint16 window_type = w->window_number & VLW_MASK;
- PlayerID player = (PlayerID)GB(w->window_number, 0, 8);
-
- vl->vehicle_type = (VehicleType)GB(w->window_number, 11, 5);
- vl->length_of_sort_list = 0;
- vl->sort_list = NULL;
- w->caption_color = player;
-
- /* Hide the widgets that we will not use in this window
- * Some windows contains actions only fit for the owner */
- if (player == _local_player) {
- w->HideWidget(VLW_WIDGET_OTHER_PLAYER_FILLER);
- w->SetWidgetDisabledState(VLW_WIDGET_AVAILABLE_VEHICLES, window_type != VLW_STANDARD);
- } else {
- w->SetWidgetsHiddenState(true,
- VLW_WIDGET_AVAILABLE_VEHICLES,
- VLW_WIDGET_MANAGE_VEHICLES_DROPDOWN,
- VLW_WIDGET_STOP_ALL,
- VLW_WIDGET_START_ALL,
- VLW_WIDGET_EMPTY_BOTTOM_RIGHT,
- WIDGET_LIST_END);
- }
-
- /* Set up the window widgets */
- switch (vl->vehicle_type) {
- case VEH_TRAIN:
- w->widget[VLW_WIDGET_LIST].tooltips = STR_883D_TRAINS_CLICK_ON_TRAIN_FOR;
- w->widget[VLW_WIDGET_AVAILABLE_VEHICLES].data = STR_AVAILABLE_TRAINS;
- break;
-
- case VEH_ROAD:
- w->widget[VLW_WIDGET_LIST].tooltips = STR_901A_ROAD_VEHICLES_CLICK_ON;
- w->widget[VLW_WIDGET_AVAILABLE_VEHICLES].data = STR_AVAILABLE_ROAD_VEHICLES;
- break;
-
- case VEH_SHIP:
- w->widget[VLW_WIDGET_LIST].tooltips = STR_9823_SHIPS_CLICK_ON_SHIP_FOR;
- w->widget[VLW_WIDGET_AVAILABLE_VEHICLES].data = STR_AVAILABLE_SHIPS;
- break;
-
- case VEH_AIRCRAFT:
- w->widget[VLW_WIDGET_LIST].tooltips = STR_A01F_AIRCRAFT_CLICK_ON_AIRCRAFT;
- w->widget[VLW_WIDGET_AVAILABLE_VEHICLES].data = STR_AVAILABLE_AIRCRAFT;
- break;
-
- default: NOT_REACHED();
- }
-
- switch (window_type) {
- case VLW_SHARED_ORDERS:
- w->widget[VLW_WIDGET_CAPTION].data = STR_VEH_WITH_SHARED_ORDERS_LIST;
- break;
- case VLW_STANDARD: /* Company Name - standard widget setup */
- switch (vl->vehicle_type) {
- case VEH_TRAIN: w->widget[VLW_WIDGET_CAPTION].data = STR_881B_TRAINS; break;
- case VEH_ROAD: w->widget[VLW_WIDGET_CAPTION].data = STR_9001_ROAD_VEHICLES; break;
- case VEH_SHIP: w->widget[VLW_WIDGET_CAPTION].data = STR_9805_SHIPS; break;
- case VEH_AIRCRAFT: w->widget[VLW_WIDGET_CAPTION].data = STR_A009_AIRCRAFT; break;
- default: NOT_REACHED(); break;
- }
- break;
- case VLW_STATION_LIST: /* Station Name */
- switch (vl->vehicle_type) {
- case VEH_TRAIN: w->widget[VLW_WIDGET_CAPTION].data = STR_SCHEDULED_TRAINS; break;
- case VEH_ROAD: w->widget[VLW_WIDGET_CAPTION].data = STR_SCHEDULED_ROAD_VEHICLES; break;
- case VEH_SHIP: w->widget[VLW_WIDGET_CAPTION].data = STR_SCHEDULED_SHIPS; break;
- case VEH_AIRCRAFT: w->widget[VLW_WIDGET_CAPTION].data = STR_SCHEDULED_AIRCRAFT; break;
- default: NOT_REACHED(); break;
- }
- break;
-
- case VLW_DEPOT_LIST:
- switch (vl->vehicle_type) {
- case VEH_TRAIN: w->widget[VLW_WIDGET_CAPTION].data = STR_VEHICLE_LIST_TRAIN_DEPOT; break;
- case VEH_ROAD: w->widget[VLW_WIDGET_CAPTION].data = STR_VEHICLE_LIST_ROADVEH_DEPOT; break;
- case VEH_SHIP: w->widget[VLW_WIDGET_CAPTION].data = STR_VEHICLE_LIST_SHIP_DEPOT; break;
- case VEH_AIRCRAFT: w->widget[VLW_WIDGET_CAPTION].data = STR_VEHICLE_LIST_AIRCRAFT_DEPOT; break;
- default: NOT_REACHED(); break;
- }
- break;
- default: NOT_REACHED(); break;
- }
-
- switch (vl->vehicle_type) {
- case VEH_TRAIN:
- w->resize.step_width = 1;
- /* Fallthrough */
- case VEH_ROAD:
- w->vscroll.cap = 7;
- w->resize.step_height = PLY_WND_PRC__SIZE_OF_ROW_SMALL;
- w->resize.height = 220 - (PLY_WND_PRC__SIZE_OF_ROW_SMALL * 3); // Minimum of 4 vehicles
- break;
- case VEH_SHIP:
- case VEH_AIRCRAFT:
- w->vscroll.cap = 4;
- w->resize.step_height = PLY_WND_PRC__SIZE_OF_ROW_BIG;
- break;
- default: NOT_REACHED();
- }
-
- w->widget[VLW_WIDGET_LIST].data = (w->vscroll.cap << 8) + 1;
-
- /* Set up sorting. Make the window-specific _sorting variable
- * point to the correct global _sorting struct so we are freed
- * from having conditionals during window operation */
- switch (vl->vehicle_type) {
- case VEH_TRAIN: vl->_sorting = &_sorting.train; break;
- case VEH_ROAD: vl->_sorting = &_sorting.roadveh; break;
- case VEH_SHIP: vl->_sorting = &_sorting.ship; break;
- case VEH_AIRCRAFT: vl->_sorting = &_sorting.aircraft; break;
- default: NOT_REACHED(); break;
- }
-
- vl->l.flags = VL_REBUILD | (vl->_sorting->order ? VL_DESC : VL_NONE);
- vl->l.sort_type = vl->_sorting->criteria;
- vl->sort_list = NULL;
- vl->l.resort_timer = DAY_TICKS * PERIODIC_RESORT_DAYS; // Set up resort timer
-}
-
void DrawSmallOrderList(const Vehicle *v, int x, int y)
{
const Order *order;
@@ -955,254 +830,371 @@
}
}
-static void DrawVehicleListWindow(Window *w)
-{
- vehiclelist_d *vl = &WP(w, vehiclelist_d);
- int x = 2;
- int y = PLY_WND_PRC__OFFSET_TOP_WIDGET;
- int max;
- int i;
- const PlayerID owner = (PlayerID)w->caption_color;
- const uint16 window_type = w->window_number & VLW_MASK;
- const uint16 index = GB(w->window_number, 16, 16);
-
- BuildVehicleList(vl, owner, index, window_type);
- SortVehicleList(vl);
- SetVScrollCount(w, vl->l.list_length);
-
- /* draw the widgets */
- switch (window_type) {
- case VLW_SHARED_ORDERS: /* Shared Orders */
- if (vl->l.list_length == 0) {
- /* We can't open this window without vehicles using this order
- * and we should close the window when deleting the order */
- NOT_REACHED();
- }
- SetDParam(0, w->vscroll.count);
- break;
-
- case VLW_STANDARD: /* Company Name */
- SetDParam(0, owner);
- SetDParam(1, w->vscroll.count);
- break;
-
- case VLW_STATION_LIST: /* Station Name */
- SetDParam(0, index);
- SetDParam(1, w->vscroll.count);
- break;
-
- case VLW_DEPOT_LIST:
- switch (vl->vehicle_type) {
- case VEH_TRAIN: SetDParam(0, STR_8800_TRAIN_DEPOT); break;
- case VEH_ROAD: SetDParam(0, STR_9003_ROAD_VEHICLE_DEPOT); break;
- case VEH_SHIP: SetDParam(0, STR_9803_SHIP_DEPOT); break;
- case VEH_AIRCRAFT: SetDParam(0, STR_A002_AIRCRAFT_HANGAR); break;
- default: NOT_REACHED(); break;
- }
- if (vl->vehicle_type == VEH_AIRCRAFT) {
- SetDParam(1, index); // Airport name
- } else {
- SetDParam(1, GetDepot(index)->town_index);
- }
- SetDParam(2, w->vscroll.count);
- break;
- default: NOT_REACHED(); break;
- }
-
- w->SetWidgetsDisabledState(vl->l.list_length == 0,
- VLW_WIDGET_MANAGE_VEHICLES_DROPDOWN,
- VLW_WIDGET_STOP_ALL,
- VLW_WIDGET_START_ALL,
- WIDGET_LIST_END);
-
- DrawWindowWidgets(w);
-
- /* draw sorting criteria string */
- DrawString(85, 15, _vehicle_sort_listing[vl->l.sort_type], TC_BLACK);
- /* draw arrow pointing up/down for ascending/descending sorting */
- DrawSortButtonState(w, VLW_WIDGET_SORT_ORDER, vl->l.flags & VL_DESC ? SBS_DOWN : SBS_UP);
-
- max = min(w->vscroll.pos + w->vscroll.cap, vl->l.list_length);
- for (i = w->vscroll.pos; i < max; ++i) {
- const Vehicle *v = vl->sort_list[i];
- StringID str;
-
- SetDParam(0, v->GetDisplayProfitThisYear());
- SetDParam(1, v->GetDisplayProfitLastYear());
-
- DrawVehicleImage(v, x + 19, y + 6, INVALID_VEHICLE, w->widget[VLW_WIDGET_LIST].right - w->widget[VLW_WIDGET_LIST].left - 20, 0);
- DrawString(x + 19, y + w->resize.step_height - 8, STR_0198_PROFIT_THIS_YEAR_LAST_YEAR, TC_FROMSTRING);
-
- if (v->name != NULL) {
- /* The vehicle got a name so we will print it */
- SetDParam(0, v->index);
- DrawString(x + 19, y, STR_01AB, TC_FROMSTRING);
- }
-
- if (w->resize.step_height == PLY_WND_PRC__SIZE_OF_ROW_BIG) DrawSmallOrderList(v, x + 138, y);
-
- if (v->IsInDepot()) {
- str = STR_021F;
- } else {
- str = (v->age > v->max_age - 366) ? STR_00E3 : STR_00E2;
- }
-
- SetDParam(0, v->unitnumber);
- DrawString(x, y + 2, str, TC_FROMSTRING);
-
- DrawVehicleProfitButton(v, x, y + 13);
-
- y += w->resize.step_height;
- }
-}
-
-/*
+/**
+ * Window for the (old) vehicle listing.
+ *
* bitmask for w->window_number
* 0-7 PlayerID (owner)
* 8-10 window type (use flags in vehicle_gui.h)
* 11-15 vehicle type (using VEH_, but can be compressed to fewer bytes if needed)
* 16-31 StationID or OrderID depending on window type (bit 8-10)
- **/
-void PlayerVehWndProc(Window *w, WindowEvent *e)
-{
- vehiclelist_d *vl = &WP(w, vehiclelist_d);
-
- switch (e->event) {
- case WE_CREATE:
- CreateVehicleListWindow(w);
- break;
-
- case WE_PAINT:
- DrawVehicleListWindow(w);
- break;
-
- case WE_CLICK: {
- switch (e->we.click.widget) {
- case VLW_WIDGET_SORT_ORDER: /* Flip sorting method ascending/descending */
- vl->l.flags ^= VL_DESC;
- vl->l.flags |= VL_RESORT;
-
- vl->_sorting->order = !!(vl->l.flags & VL_DESC);
- w->SetDirty();
- break;
- case VLW_WIDGET_SORT_BY_PULLDOWN:/* Select sorting criteria dropdown menu */
- ShowDropDownMenu(w, _vehicle_sort_listing, vl->l.sort_type, VLW_WIDGET_SORT_BY_PULLDOWN, 0, (vl->vehicle_type == VEH_TRAIN || vl->vehicle_type == VEH_ROAD) ? 0 : (1 << 10));
- return;
- case VLW_WIDGET_LIST: { /* Matrix to show vehicles */
- uint32 id_v = (e->we.click.pt.y - PLY_WND_PRC__OFFSET_TOP_WIDGET) / w->resize.step_height;
- const Vehicle *v;
-
- if (id_v >= w->vscroll.cap) return; // click out of bounds
-
- id_v += w->vscroll.pos;
-
- if (id_v >= vl->l.list_length) return; // click out of list bound
-
- v = vl->sort_list[id_v];
-
- ShowVehicleViewWindow(v);
- } break;
-
- case VLW_WIDGET_AVAILABLE_VEHICLES:
- ShowBuildVehicleWindow(0, vl->vehicle_type);
- break;
-
- case VLW_WIDGET_MANAGE_VEHICLES_DROPDOWN: {
- static StringID action_str[] = {
- STR_REPLACE_VEHICLES,
- STR_SEND_FOR_SERVICING,
- STR_NULL,
- INVALID_STRING_ID
- };
-
- static const StringID depot_name[] = {
- STR_SEND_TRAIN_TO_DEPOT,
- STR_SEND_ROAD_VEHICLE_TO_DEPOT,
- STR_SEND_SHIP_TO_DEPOT,
- STR_SEND_AIRCRAFT_TO_HANGAR
- };
-
- /* XXX - Substite string since the dropdown cannot handle dynamic strings */
- action_str[2] = depot_name[vl->vehicle_type];
- ShowDropDownMenu(w, action_str, 0, VLW_WIDGET_MANAGE_VEHICLES_DROPDOWN, 0, (w->window_number & VLW_MASK) == VLW_STANDARD ? 0 : 1);
- break;
- }
+ */
+struct VehicleListWindow : public Window, public VehicleListBase {
- case VLW_WIDGET_STOP_ALL:
- case VLW_WIDGET_START_ALL:
- DoCommandP(0, GB(w->window_number, 16, 16), (w->window_number & VLW_MASK) | (1 << 6) | (e->we.click.widget == VLW_WIDGET_START_ALL ? (1 << 5) : 0) | vl->vehicle_type, NULL, CMD_MASS_START_STOP);
- break;
- }
- } break;
-
- case WE_DROPDOWN_SELECT: /* we have selected a dropdown item in the list */
- switch (e->we.dropdown.button) {
- case VLW_WIDGET_SORT_BY_PULLDOWN:
- if (vl->l.sort_type != e->we.dropdown.index) {
- /* value has changed -> resort */
- vl->l.flags |= VL_RESORT;
- vl->l.sort_type = e->we.dropdown.index;
- vl->_sorting->criteria = vl->l.sort_type;
- }
- break;
- case VLW_WIDGET_MANAGE_VEHICLES_DROPDOWN:
- assert(vl->l.list_length != 0);
+ VehicleListWindow(const WindowDesc *desc, void *data, WindowNumber window_number) : Window(desc, data, window_number)
+ {
+ uint16 window_type = this->window_number & VLW_MASK;
+ PlayerID player = (PlayerID)GB(this->window_number, 0, 8);
- switch (e->we.dropdown.index) {
- case 0: /* Replace window */
- ShowReplaceGroupVehicleWindow(DEFAULT_GROUP, vl->vehicle_type);
- break;
- case 1: /* Send for servicing */
- DoCommandP(0, GB(w->window_number, 16, 16) /* StationID or OrderID (depending on VLW) */,
- (w->window_number & VLW_MASK) | DEPOT_MASS_SEND | DEPOT_SERVICE,
- NULL,
- GetCmdSendToDepot(vl->vehicle_type));
- break;
- case 2: /* Send to Depots */
- DoCommandP(0, GB(w->window_number, 16, 16) /* StationID or OrderID (depending on VLW) */,
- (w->window_number & VLW_MASK) | DEPOT_MASS_SEND,
- NULL,
- GetCmdSendToDepot(vl->vehicle_type));
- break;
+ this->vehicle_type = (VehicleType)GB(this->window_number, 11, 5);
+ this->vehicles.list_length = 0;
+ this->vehicles.sort_list = NULL;
+ this->caption_color = player;
- default: NOT_REACHED();
- }
- break;
- default: NOT_REACHED();
+ /* Hide the widgets that we will not use in this window
+ * Some windows contains actions only fit for the owner */
+ if (player == _local_player) {
+ this->HideWidget(VLW_WIDGET_OTHER_PLAYER_FILLER);
+ this->SetWidgetDisabledState(VLW_WIDGET_AVAILABLE_VEHICLES, window_type != VLW_STANDARD);
+ } else {
+ this->SetWidgetsHiddenState(true,
+ VLW_WIDGET_AVAILABLE_VEHICLES,
+ VLW_WIDGET_MANAGE_VEHICLES_DROPDOWN,
+ VLW_WIDGET_STOP_ALL,
+ VLW_WIDGET_START_ALL,
+ VLW_WIDGET_EMPTY_BOTTOM_RIGHT,
+ WIDGET_LIST_END);
+ }
+
+ /* Set up the window widgets */
+ switch (this->vehicle_type) {
+ case VEH_TRAIN:
+ this->widget[VLW_WIDGET_LIST].tooltips = STR_883D_TRAINS_CLICK_ON_TRAIN_FOR;
+ this->widget[VLW_WIDGET_AVAILABLE_VEHICLES].data = STR_AVAILABLE_TRAINS;
+ break;
+
+ case VEH_ROAD:
+ this->widget[VLW_WIDGET_LIST].tooltips = STR_901A_ROAD_VEHICLES_CLICK_ON;
+ this->widget[VLW_WIDGET_AVAILABLE_VEHICLES].data = STR_AVAILABLE_ROAD_VEHICLES;
+ break;
+
+ case VEH_SHIP:
+ this->widget[VLW_WIDGET_LIST].tooltips = STR_9823_SHIPS_CLICK_ON_SHIP_FOR;
+ this->widget[VLW_WIDGET_AVAILABLE_VEHICLES].data = STR_AVAILABLE_SHIPS;
+ break;
+
+ case VEH_AIRCRAFT:
+ this->widget[VLW_WIDGET_LIST].tooltips = STR_A01F_AIRCRAFT_CLICK_ON_AIRCRAFT;
+ this->widget[VLW_WIDGET_AVAILABLE_VEHICLES].data = STR_AVAILABLE_AIRCRAFT;
+ break;
+
+ default: NOT_REACHED();
+ }
+
+ switch (window_type) {
+ case VLW_SHARED_ORDERS:
+ this->widget[VLW_WIDGET_CAPTION].data = STR_VEH_WITH_SHARED_ORDERS_LIST;
+ break;
+ case VLW_STANDARD: /* Company Name - standard widget setup */
+ switch (this->vehicle_type) {
+ case VEH_TRAIN: this->widget[VLW_WIDGET_CAPTION].data = STR_881B_TRAINS; break;
+ case VEH_ROAD: this->widget[VLW_WIDGET_CAPTION].data = STR_9001_ROAD_VEHICLES; break;
+ case VEH_SHIP: this->widget[VLW_WIDGET_CAPTION].data = STR_9805_SHIPS; break;
+ case VEH_AIRCRAFT: this->widget[VLW_WIDGET_CAPTION].data = STR_A009_AIRCRAFT; break;
+ default: NOT_REACHED(); break;
+ }
+ break;
+ case VLW_STATION_LIST: /* Station Name */
+ switch (this->vehicle_type) {
+ case VEH_TRAIN: this->widget[VLW_WIDGET_CAPTION].data = STR_SCHEDULED_TRAINS; break;
+ case VEH_ROAD: this->widget[VLW_WIDGET_CAPTION].data = STR_SCHEDULED_ROAD_VEHICLES; break;
+ case VEH_SHIP: this->widget[VLW_WIDGET_CAPTION].data = STR_SCHEDULED_SHIPS; break;
+ case VEH_AIRCRAFT: this->widget[VLW_WIDGET_CAPTION].data = STR_SCHEDULED_AIRCRAFT; break;
+ default: NOT_REACHED(); break;
+ }
+ break;
+
+ case VLW_DEPOT_LIST:
+ switch (this->vehicle_type) {
+ case VEH_TRAIN: this->widget[VLW_WIDGET_CAPTION].data = STR_VEHICLE_LIST_TRAIN_DEPOT; break;
+ case VEH_ROAD: this->widget[VLW_WIDGET_CAPTION].data = STR_VEHICLE_LIST_ROADVEH_DEPOT; break;
+ case VEH_SHIP: this->widget[VLW_WIDGET_CAPTION].data = STR_VEHICLE_LIST_SHIP_DEPOT; break;
+ case VEH_AIRCRAFT: this->widget[VLW_WIDGET_CAPTION].data = STR_VEHICLE_LIST_AIRCRAFT_DEPOT; break;
+ default: NOT_REACHED(); break;
+ }
+ break;
+ default: NOT_REACHED(); break;
+ }
+
+ switch (this->vehicle_type) {
+ case VEH_TRAIN:
+ this->resize.step_width = 1;
+ /* Fallthrough */
+ case VEH_ROAD:
+ this->vscroll.cap = 7;
+ this->resize.step_height = PLY_WND_PRC__SIZE_OF_ROW_SMALL;
+ this->resize.height = 220 - (PLY_WND_PRC__SIZE_OF_ROW_SMALL * 3); // Minimum of 4 vehicles
+ break;
+ case VEH_SHIP:
+ case VEH_AIRCRAFT:
+ this->vscroll.cap = 4;
+ this->resize.step_height = PLY_WND_PRC__SIZE_OF_ROW_BIG;
+ break;
+ default: NOT_REACHED();
+ }
+
+
+ this->widget[VLW_WIDGET_LIST].data = (this->vscroll.cap << 8) + 1;
+
+ /* Set up sorting. Make the window-specific _sorting variable
+ * point to the correct global _sorting struct so we are freed
+ * from having conditionals during window operation */
+ switch (this->vehicle_type) {
+ case VEH_TRAIN: this->sorting = &_sorting.train; break;
+ case VEH_ROAD: this->sorting = &_sorting.roadveh; break;
+ case VEH_SHIP: this->sorting = &_sorting.ship; break;
+ case VEH_AIRCRAFT: this->sorting = &_sorting.aircraft; break;
+ default: NOT_REACHED(); break;
+ }
+
+ this->vehicles.flags = VL_REBUILD | (this->sorting->order ? VL_DESC : VL_NONE);
+ this->vehicles.sort_type = this->sorting->criteria;
+ this->vehicles.resort_timer = DAY_TICKS * PERIODIC_RESORT_DAYS; // Set up resort timer
+
+ this->FindWindowPlacementAndResize(desc);
+ }
+
+ ~VehicleListWindow()
+ {
+ free((void*)this->vehicles.sort_list);
+ }
+
+ virtual void OnPaint()
+ {
+ int x = 2;
+ int y = PLY_WND_PRC__OFFSET_TOP_WIDGET;
+ int max;
+ int i;
+ const PlayerID owner = (PlayerID)this->caption_color;
+ const uint16 window_type = this->window_number & VLW_MASK;
+ const uint16 index = GB(this->window_number, 16, 16);
+
+ BuildVehicleList(this, owner, index, window_type);
+ SortVehicleList(this);
+ SetVScrollCount(this, this->vehicles.list_length);
+
+ /* draw the widgets */
+ switch (window_type) {
+ case VLW_SHARED_ORDERS: /* Shared Orders */
+ if (this->vehicles.list_length == 0) {
+ /* We can't open this window without vehicles using this order
+ * and we should close the window when deleting the order */
+ NOT_REACHED();
+ }
+ SetDParam(0, this->vscroll.count);
+ break;
+
+ case VLW_STANDARD: /* Company Name */
+ SetDParam(0, owner);
+ SetDParam(1, this->vscroll.count);
+ break;
+
+ case VLW_STATION_LIST: /* Station Name */
+ SetDParam(0, index);
+ SetDParam(1, this->vscroll.count);
+ break;
+
+ case VLW_DEPOT_LIST:
+ switch (this->vehicle_type) {
+ case VEH_TRAIN: SetDParam(0, STR_8800_TRAIN_DEPOT); break;
+ case VEH_ROAD: SetDParam(0, STR_9003_ROAD_VEHICLE_DEPOT); break;
+ case VEH_SHIP: SetDParam(0, STR_9803_SHIP_DEPOT); break;
+ case VEH_AIRCRAFT: SetDParam(0, STR_A002_AIRCRAFT_HANGAR); break;
+ default: NOT_REACHED(); break;
+ }
+ if (this->vehicle_type == VEH_AIRCRAFT) {
+ SetDParam(1, index); // Airport name
+ } else {
+ SetDParam(1, GetDepot(index)->town_index);
+ }
+ SetDParam(2, this->vscroll.count);
+ break;
+ default: NOT_REACHED(); break;
+ }
+
+ this->SetWidgetsDisabledState(this->vehicles.list_length == 0,
+ VLW_WIDGET_MANAGE_VEHICLES_DROPDOWN,
+ VLW_WIDGET_STOP_ALL,
+ VLW_WIDGET_START_ALL,
+ WIDGET_LIST_END);
+
+ DrawWindowWidgets(this);
+
+ /* draw sorting criteria string */
+ DrawString(85, 15, _vehicle_sort_listing[this->vehicles.sort_type], TC_BLACK);
+ /* draw arrow pointing up/down for ascending/descending sorting */
+ DrawSortButtonState(this, VLW_WIDGET_SORT_ORDER, this->vehicles.flags & VL_DESC ? SBS_DOWN : SBS_UP);
+
+ max = min(this->vscroll.pos + this->vscroll.cap, this->vehicles.list_length);
+ for (i = this->vscroll.pos; i < max; ++i) {
+ const Vehicle *v = this->vehicles.sort_list[i];
+ StringID str;
+
+ SetDParam(0, v->GetDisplayProfitThisYear());
+ SetDParam(1, v->GetDisplayProfitLastYear());
+
+ DrawVehicleImage(v, x + 19, y + 6, INVALID_VEHICLE, this->widget[VLW_WIDGET_LIST].right - this->widget[VLW_WIDGET_LIST].left - 20, 0);
+ DrawString(x + 19, y + this->resize.step_height - 8, STR_0198_PROFIT_THIS_YEAR_LAST_YEAR, TC_FROMSTRING);
+
+ if (v->name != NULL) {
+ /* The vehicle got a name so we will print it */
+ SetDParam(0, v->index);
+ DrawString(x + 19, y, STR_01AB, TC_FROMSTRING);
}
- w->SetDirty();
- break;
-
- case WE_DESTROY:
- free((void*)vl->sort_list);
- break;
-
- case WE_TICK: /* resort the list every 20 seconds orso (10 days) */
- if (_pause_game != 0) break;
- if (--vl->l.resort_timer == 0) {
- StationID station = ((w->window_number & VLW_MASK) == VLW_STATION_LIST) ? GB(w->window_number, 16, 16) : INVALID_STATION;
- PlayerID owner = (PlayerID)w->caption_color;
- DEBUG(misc, 3, "Periodic resort %d list player %d at station %d", vl->vehicle_type, owner, station);
- vl->l.resort_timer = DAY_TICKS * PERIODIC_RESORT_DAYS;
- vl->l.flags |= VL_RESORT;
- w->SetDirty();
+ if (this->resize.step_height == PLY_WND_PRC__SIZE_OF_ROW_BIG) DrawSmallOrderList(v, x + 138, y);
+
+ if (v->IsInDepot()) {
+ str = STR_021F;
+ } else {
+ str = (v->age > v->max_age - 366) ? STR_00E3 : STR_00E2;
}
- break;
- case WE_RESIZE: /* Update the scroll + matrix */
- w->vscroll.cap += e->we.sizing.diff.y / (int)w->resize.step_height;
- w->widget[VLW_WIDGET_LIST].data = (w->vscroll.cap << 8) + 1;
- break;
+ SetDParam(0, v->unitnumber);
+ DrawString(x, y + 2, str, TC_FROMSTRING);
+
+ DrawVehicleProfitButton(v, x, y + 13);
+
+ y += this->resize.step_height;
+ }
}
-}
+
+ virtual void OnClick(Point pt, int widget)
+ {
+ switch (widget) {
+ case VLW_WIDGET_SORT_ORDER: /* Flip sorting method ascending/descending */
+ this->vehicles.flags ^= VL_DESC;
+ this->vehicles.flags |= VL_RESORT;
+
+ this->sorting->order = !!(this->vehicles.flags & VL_DESC);
+ this->SetDirty();
+ break;
+ case VLW_WIDGET_SORT_BY_PULLDOWN:/* Select sorting criteria dropdown menu */
+ ShowDropDownMenu(this, _vehicle_sort_listing, this->vehicles.sort_type, VLW_WIDGET_SORT_BY_PULLDOWN, 0, (this->vehicle_type == VEH_TRAIN || this->vehicle_type == VEH_ROAD) ? 0 : (1 << 10));
+ return;
+ case VLW_WIDGET_LIST: { /* Matrix to show vehicles */
+ uint32 id_v = (pt.y - PLY_WND_PRC__OFFSET_TOP_WIDGET) / this->resize.step_height;
+ const Vehicle *v;
+
+ if (id_v >= this->vscroll.cap) return; // click out of bounds
+
+ id_v += this->vscroll.pos;
+
+ if (id_v >= this->vehicles.list_length) return; // click out of list bound
+
+ v = this->vehicles.sort_list[id_v];
+
+ ShowVehicleViewWindow(v);
+ } break;
+
+ case VLW_WIDGET_AVAILABLE_VEHICLES:
+ ShowBuildVehicleWindow(0, this->vehicle_type);
+ break;
+
+ case VLW_WIDGET_MANAGE_VEHICLES_DROPDOWN: {
+ static StringID action_str[] = {
+ STR_REPLACE_VEHICLES,
+ STR_SEND_FOR_SERVICING,
+ STR_NULL,
+ INVALID_STRING_ID
+ };
+
+ static const StringID depot_name[] = {
+ STR_SEND_TRAIN_TO_DEPOT,
+ STR_SEND_ROAD_VEHICLE_TO_DEPOT,
+ STR_SEND_SHIP_TO_DEPOT,
+ STR_SEND_AIRCRAFT_TO_HANGAR
+ };
+
+ /* XXX - Substite string since the dropdown cannot handle dynamic strings */
+ action_str[2] = depot_name[this->vehicle_type];
+ ShowDropDownMenu(this, action_str, 0, VLW_WIDGET_MANAGE_VEHICLES_DROPDOWN, 0, (this->window_number & VLW_MASK) == VLW_STANDARD ? 0 : 1);
+ break;
+ }
+
+ case VLW_WIDGET_STOP_ALL:
+ case VLW_WIDGET_START_ALL:
+ DoCommandP(0, GB(this->window_number, 16, 16), (this->window_number & VLW_MASK) | (1 << 6) | (widget == VLW_WIDGET_START_ALL ? (1 << 5) : 0) | this->vehicle_type, NULL, CMD_MASS_START_STOP);
+ break;
+ }
+ }
+
+ virtual void OnDropdownSelect(int widget, int index)
+ {
+ switch (widget) {
+ case VLW_WIDGET_SORT_BY_PULLDOWN:
+ if (this->vehicles.sort_type != index) {
+ /* value has changed -> resort */
+ this->vehicles.flags |= VL_RESORT;
+ this->vehicles.sort_type = index;
+ this->sorting->criteria = this->vehicles.sort_type;
+ }
+ break;
+ case VLW_WIDGET_MANAGE_VEHICLES_DROPDOWN:
+ assert(this->vehicles.list_length != 0);
+
+ switch (index) {
+ case 0: /* Replace window */
+ ShowReplaceGroupVehicleWindow(DEFAULT_GROUP, this->vehicle_type);
+ break;
+ case 1: /* Send for servicing */
+ DoCommandP(0, GB(this->window_number, 16, 16) /* StationID or OrderID (depending on VLW) */,
+ (this->window_number & VLW_MASK) | DEPOT_MASS_SEND | DEPOT_SERVICE,
+ NULL,
+ GetCmdSendToDepot(this->vehicle_type));
+ break;
+ case 2: /* Send to Depots */
+ DoCommandP(0, GB(this->window_number, 16, 16) /* StationID or OrderID (depending on VLW) */,
+ (this->window_number & VLW_MASK) | DEPOT_MASS_SEND,
+ NULL,
+ GetCmdSendToDepot(this->vehicle_type));
+ break;
+
+ default: NOT_REACHED();
+ }
+ break;
+ default: NOT_REACHED();
+ }
+ this->SetDirty();
+ }
+
+ virtual void OnTick()
+ {
+ if (_pause_game != 0) return;
+ if (--this->vehicles.resort_timer == 0) {
+ StationID station = ((this->window_number & VLW_MASK) == VLW_STATION_LIST) ? GB(this->window_number, 16, 16) : INVALID_STATION;
+ PlayerID owner = (PlayerID)this->caption_color;
+
+ DEBUG(misc, 3, "Periodic resort %d list player %d at station %d", this->vehicle_type, owner, station);
+ this->vehicles.resort_timer = DAY_TICKS * PERIODIC_RESORT_DAYS;
+ this->vehicles.flags |= VL_RESORT;
+ this->SetDirty();
+ }
+ }
+
+ virtual void OnResize(Point new_size, Point delta)
+ {
+ this->vscroll.cap += delta.y / (int)this->resize.step_height;
+ this->widget[VLW_WIDGET_LIST].data = (this->vscroll.cap << 8) + 1;
+ }
+};
static const WindowDesc _player_vehicle_list_train_desc = {
WDP_AUTO, WDP_AUTO, 260, 182, 260, 182,
WC_TRAINS_LIST, WC_NONE,
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON | WDF_RESIZABLE,
_vehicle_list_widgets,
- PlayerVehWndProc
+ NULL
};
static const WindowDesc _player_vehicle_list_road_veh_desc = {
@@ -1210,7 +1202,7 @@
WC_ROADVEH_LIST, WC_NONE,
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON | WDF_RESIZABLE,
_vehicle_list_widgets,
- PlayerVehWndProc
+ NULL
};
static const WindowDesc _player_vehicle_list_ship_desc = {
@@ -1218,7 +1210,7 @@
WC_SHIPS_LIST, WC_NONE,
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON | WDF_RESIZABLE,
_vehicle_list_widgets,
- PlayerVehWndProc
+ NULL
};
static const WindowDesc _player_vehicle_list_aircraft_desc = {
@@ -1226,12 +1218,12 @@
WC_AIRCRAFT_LIST, WC_NONE,
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON | WDF_RESIZABLE,
_vehicle_list_widgets,
- PlayerVehWndProc
+ NULL
};
static void ShowVehicleListWindowLocal(PlayerID player, uint16 VLW_flag, VehicleType vehicle_type, uint16 unique_number)
{
- Window *w;
+ VehicleListWindow *w;
WindowNumber num;
if (!IsValidPlayer(player)) return;
@@ -1244,18 +1236,18 @@
switch (vehicle_type) {
default: NOT_REACHED();
case VEH_TRAIN:
- w = AllocateWindowDescFront(&_player_vehicle_list_train_desc, num);
+ w = AllocateWindowDescFront<VehicleListWindow>(&_player_vehicle_list_train_desc, num);
if (w != NULL) ResizeWindow(w, 65, 38);
break;
case VEH_ROAD:
- w = AllocateWindowDescFront(&_player_vehicle_list_road_veh_desc, num);
+ w = AllocateWindowDescFront<VehicleListWindow>(&_player_vehicle_list_road_veh_desc, num);
if (w != NULL) ResizeWindow(w, 0, 38);
break;
case VEH_SHIP:
- w = AllocateWindowDescFront(&_player_vehicle_list_ship_desc, num);
+ w = AllocateWindowDescFront<VehicleListWindow>(&_player_vehicle_list_ship_desc, num);
break;
case VEH_AIRCRAFT:
- w = AllocateWindowDescFront(&_player_vehicle_list_aircraft_desc, num);
+ w = AllocateWindowDescFront<VehicleListWindow>(&_player_vehicle_list_aircraft_desc, num);
break;
}
@@ -1671,7 +1663,7 @@
{
DeleteWindowById(WC_VEHICLE_ORDERS, v->index);
DeleteWindowById(WC_VEHICLE_DETAILS, v->index);
- AllocateWindowDescFront(&_vehicle_details_desc, v->index);
+ AllocateWindowDescFront<Window>(&_vehicle_details_desc, v->index);
}
@@ -1747,7 +1739,7 @@
/** Shows the vehicle view window of the given vehicle. */
void ShowVehicleViewWindow(const Vehicle *v)
{
- Window *w = AllocateWindowDescFront((v->type == VEH_TRAIN) ? &_train_view_desc : &_vehicle_view_desc, v->index);
+ Window *w = AllocateWindowDescFront<Window>((v->type == VEH_TRAIN) ? &_train_view_desc : &_vehicle_view_desc, v->index);
if (w != NULL) {
w->caption_color = v->owner;
@@ -2099,7 +2091,7 @@
const Window *mainwindow = FindWindowById(WC_MAIN_WINDOW, 0);
/* code to allow the main window to 'follow' the vehicle if the ctrl key is pressed */
if (_ctrl_pressed && mainwindow->viewport->zoom == ZOOM_LVL_NORMAL) {
- WP(mainwindow, vp_d).follow_vehicle = v->index;
+ mainwindow->viewport->follow_vehicle = v->index;
} else {
ScrollMainWindowTo(v->x_pos, v->y_pos);
}
@@ -2152,7 +2144,7 @@
DeleteWindowById(WC_VEHICLE_TIMETABLE, w->window_number);
break;
- case WE_MOUSELOOP: {
+ case WE_TICK: {
const Vehicle *v = GetVehicle(w->window_number);
bool veh_stopped = v->IsStoppedInDepot();
--- a/src/vehicle_gui.h Wed May 07 21:09:51 2008 +0000
+++ b/src/vehicle_gui.h Sun May 11 20:09:34 2008 +0000
@@ -14,13 +14,6 @@
void DrawVehicleProfitButton(const Vehicle *v, int x, int y);
void ShowVehicleRefitWindow(const Vehicle *v, VehicleOrderID order);
-void InitializeVehiclesGuiList();
-
-/* sorter stuff */
-void RebuildVehicleLists();
-void ResortVehicleLists();
-void SortVehicleList(vehiclelist_d *vl);
-void BuildVehicleList(vehiclelist_d *vl, PlayerID owner, uint16 index, uint16 window_type);
#define PERIODIC_RESORT_DAYS 10
@@ -70,8 +63,6 @@
return (flags == VLW_STANDARD || flags == VLW_SHARED_ORDERS || flags == VLW_STATION_LIST || flags == VLW_DEPOT_LIST || flags == VLW_GROUP_LIST);
}
-void PlayerVehWndProc(Window *w, WindowEvent *e);
-
int DrawVehiclePurchaseInfo(int x, int y, uint w, EngineID engine_number);
void DrawTrainImage(const Vehicle *v, int x, int y, VehicleID selection, int count, int skip);
@@ -137,6 +128,29 @@
/* Unified window procedure */
void ShowVehicleViewWindow(const Vehicle *v);
-Vehicle *CheckClickOnVehicle(const ViewPort *vp, int x, int y);
+Vehicle *CheckClickOnVehicle(const struct ViewPort *vp, int x, int y);
+
+typedef GUIList<const Vehicle*> GUIVehicleList;
+
+struct VehicleListBase {
+ GUIVehicleList vehicles; ///< The list of vehicles
+ Listing *sorting; ///< Pointer to the vehicle type related sorting.
+ VehicleType vehicle_type; ///< The vehicle type that is sorted
+};
+
+struct Sorting {
+ Listing aircraft;
+ Listing roadveh;
+ Listing ship;
+ Listing train;
+};
+
+extern Sorting _sorting;
+
+/* sorter stuff */
+void RebuildVehicleLists();
+void ResortVehicleLists();
+void SortVehicleList(VehicleListBase *vl);
+void BuildVehicleList(VehicleListBase *vl, PlayerID owner, uint16 index, uint16 window_type);
#endif /* VEHICLE_GUI_H */
--- a/src/viewport.cpp Wed May 07 21:09:51 2008 +0000
+++ b/src/viewport.cpp Sun May 11 20:09:34 2008 +0000
@@ -144,8 +144,6 @@
static TileInfo *_cur_ti;
bool _draw_bounding_boxes = false;
-extern void SmallMapCenterOnCurrentPos(Window *w);
-
static Point MapXYZToViewport(const ViewPort *vp, uint x, uint y, uint z)
{
Point p = RemapCoords(x, y, z);
@@ -156,7 +154,7 @@
void DeleteWindowViewport(Window *w)
{
- w->viewport->width = 0;
+ free(w->viewport);
w->viewport = NULL;
}
@@ -177,7 +175,7 @@
{
assert(w->viewport == NULL);
- ViewPort *vp = &(WP(w, vp_d).vp_data);
+ ViewportData *vp = CallocT<ViewportData>(1);
vp->left = x + w->left;
vp->top = y + w->top;
@@ -194,21 +192,21 @@
if (follow_flags & 0x80000000) {
const Vehicle *veh;
- WP(w, vp_d).follow_vehicle = (VehicleID)(follow_flags & 0xFFFF);
- veh = GetVehicle(WP(w, vp_d).follow_vehicle);
+ vp->follow_vehicle = (VehicleID)(follow_flags & 0xFFFF);
+ veh = GetVehicle(vp->follow_vehicle);
pt = MapXYZToViewport(vp, veh->x_pos, veh->y_pos, veh->z_pos);
} else {
uint x = TileX(follow_flags) * TILE_SIZE;
uint y = TileY(follow_flags) * TILE_SIZE;
- WP(w, vp_d).follow_vehicle = INVALID_VEHICLE;
+ vp->follow_vehicle = INVALID_VEHICLE;
pt = MapXYZToViewport(vp, x, y, GetSlopeZ(x, y));
}
- WP(w, vp_d).scrollpos_x = pt.x;
- WP(w, vp_d).scrollpos_y = pt.y;
- WP(w, vp_d).dest_scrollpos_x = pt.x;
- WP(w, vp_d).dest_scrollpos_y = pt.y;
+ vp->scrollpos_x = pt.x;
+ vp->scrollpos_y = pt.y;
+ vp->dest_scrollpos_x = pt.x;
+ vp->dest_scrollpos_y = pt.y;
w->viewport = vp;
vp->virtual_left = 0;//pt.x;
@@ -426,9 +424,7 @@
Point GetTileZoomCenterWindow(bool in, Window * w)
{
int x, y;
- ViewPort * vp;
-
- vp = w->viewport;
+ ViewPort *vp = w->viewport;
if (in) {
x = ((_cursor.pos.x - vp->left) >> 1) + (vp->width >> 2);
@@ -1581,33 +1577,33 @@
{
const ViewPort *vp = w->viewport;
- if (WP(w, vp_d).follow_vehicle != INVALID_VEHICLE) {
- const Vehicle* veh = GetVehicle(WP(w, vp_d).follow_vehicle);
+ if (w->viewport->follow_vehicle != INVALID_VEHICLE) {
+ const Vehicle* veh = GetVehicle(w->viewport->follow_vehicle);
Point pt = MapXYZToViewport(vp, veh->x_pos, veh->y_pos, veh->z_pos);
SetViewportPosition(w, pt.x, pt.y);
} else {
/* Ensure the destination location is within the map */
- ClampViewportToMap(vp, WP(w, vp_d).dest_scrollpos_x, WP(w, vp_d).dest_scrollpos_y);
-
- int delta_x = WP(w, vp_d).dest_scrollpos_x - WP(w, vp_d).scrollpos_x;
- int delta_y = WP(w, vp_d).dest_scrollpos_y - WP(w, vp_d).scrollpos_y;
+ ClampViewportToMap(vp, w->viewport->dest_scrollpos_x, w->viewport->dest_scrollpos_y);
+
+ int delta_x = w->viewport->dest_scrollpos_x - w->viewport->scrollpos_x;
+ int delta_y = w->viewport->dest_scrollpos_y - w->viewport->scrollpos_y;
if (delta_x != 0 || delta_y != 0) {
if (_patches.smooth_scroll) {
int max_scroll = ScaleByMapSize1D(512);
/* Not at our desired positon yet... */
- WP(w, vp_d).scrollpos_x += Clamp(delta_x / 4, -max_scroll, max_scroll);
- WP(w, vp_d).scrollpos_y += Clamp(delta_y / 4, -max_scroll, max_scroll);
+ w->viewport->scrollpos_x += Clamp(delta_x / 4, -max_scroll, max_scroll);
+ w->viewport->scrollpos_y += Clamp(delta_y / 4, -max_scroll, max_scroll);
} else {
- WP(w, vp_d).scrollpos_x = WP(w, vp_d).dest_scrollpos_x;
- WP(w, vp_d).scrollpos_y = WP(w, vp_d).dest_scrollpos_y;
+ w->viewport->scrollpos_x = w->viewport->dest_scrollpos_x;
+ w->viewport->scrollpos_y = w->viewport->dest_scrollpos_y;
}
}
- ClampViewportToMap(vp, WP(w, vp_d).scrollpos_x, WP(w, vp_d).scrollpos_y);
-
- SetViewportPosition(w, WP(w, vp_d).scrollpos_x, WP(w, vp_d).scrollpos_y);
+ ClampViewportToMap(vp, w->viewport->scrollpos_x, w->viewport->scrollpos_y);
+
+ SetViewportPosition(w, w->viewport->scrollpos_x, w->viewport->scrollpos_y);
}
}
@@ -2057,14 +2053,7 @@
_tile_fract_coords.y = pt.y & 0xF;
w = GetCallbackWnd();
- if (w != NULL) {
- WindowEvent e;
-
- e.event = WE_PLACE_OBJ;
- e.we.place.pt = pt;
- e.we.place.tile = TileVirtXY(pt.x, pt.y);
- w->HandleWindowEvent(&e);
- }
+ if (w != NULL) w->OnPlaceObject(pt, TileVirtXY(pt.x, pt.y));
}
@@ -2073,42 +2062,21 @@
{
/* The slope cannot be acquired outside of the map, so make sure we are always within the map. */
Point pt = MapXYZToViewport(w->viewport, x, y, GetSlopeZ(Clamp(x, 0, MapSizeX()), Clamp(y, 0, MapSizeY())));
- WP(w, vp_d).follow_vehicle = INVALID_VEHICLE;
-
- if (WP(w, vp_d).dest_scrollpos_x == pt.x && WP(w, vp_d).dest_scrollpos_y == pt.y)
+ w->viewport->follow_vehicle = INVALID_VEHICLE;
+
+ if (w->viewport->dest_scrollpos_x == pt.x && w->viewport->dest_scrollpos_y == pt.y)
return false;
if (instant) {
- WP(w, vp_d).scrollpos_x = pt.x;
- WP(w, vp_d).scrollpos_y = pt.y;
+ w->viewport->scrollpos_x = pt.x;
+ w->viewport->scrollpos_y = pt.y;
}
- WP(w, vp_d).dest_scrollpos_x = pt.x;
- WP(w, vp_d).dest_scrollpos_y = pt.y;
+ w->viewport->dest_scrollpos_x = pt.x;
+ w->viewport->dest_scrollpos_y = pt.y;
return true;
}
-
-bool ScrollMainWindowTo(int x, int y, bool instant)
-{
- Window *w;
- bool res = ScrollWindowTo(x, y, FindWindowById(WC_MAIN_WINDOW, 0), instant);
-
- /* If a user scrolls to a tile (via what way what so ever) and already is on
- * that tile (e.g.: pressed twice), move the smallmap to that location,
- * so you directly see where you are on the smallmap. */
-
- if (res) return res;
-
- w = FindWindowById(WC_SMALLMAP, 0);
- if (w == NULL) return res;
-
- SmallMapCenterOnCurrentPos(w);
-
- return res;
-}
-
-
bool ScrollMainWindowToTile(TileIndex tile, bool instant)
{
return ScrollMainWindowTo(TileX(tile) * TILE_SIZE + TILE_SIZE / 2, TileY(tile) * TILE_SIZE + TILE_SIZE / 2, instant);
@@ -2228,7 +2196,7 @@
}
/** highlighting tiles while only going over them with the mouse */
-void VpStartPlaceSizing(TileIndex tile, ViewportPlaceMethod method, byte process)
+void VpStartPlaceSizing(TileIndex tile, ViewportPlaceMethod method, ViewportDragDropSelectionProcess process)
{
_thd.select_method = method;
_thd.select_proc = process;
@@ -2695,16 +2663,10 @@
/** while dragging */
bool VpHandlePlaceSizingDrag()
{
- Window *w;
- WindowEvent e;
-
if (_special_mouse_mode != WSM_SIZING) return true;
- e.we.place.select_method = _thd.select_method;
- e.we.place.select_proc = _thd.select_proc;
-
/* stop drag mode if the window has been closed */
- w = FindWindowById(_thd.window_class, _thd.window_number);
+ Window *w = FindWindowById(_thd.window_class, _thd.window_number);
if (w == NULL) {
ResetObjectToPlace();
return false;
@@ -2712,9 +2674,7 @@
/* while dragging execute the drag procedure of the corresponding window (mostly VpSelectTilesWithMethod() ) */
if (_left_button_down) {
- e.event = WE_PLACE_DRAG;
- e.we.place.pt = GetTileBelowCursor();
- w->HandleWindowEvent(&e);
+ w->OnPlaceDrag(_thd.select_method, _thd.select_proc, GetTileBelowCursor());
return false;
}
@@ -2723,7 +2683,7 @@
_special_mouse_mode = WSM_NONE;
if (_thd.next_drawstyle == HT_RECT) {
_thd.place_mode = VHM_RECT;
- } else if (e.we.place.select_method == VPM_SIGNALDIRS) { // some might call this a hack... -- Dominik
+ } else if (_thd.select_method == VPM_SIGNALDIRS) { // some might call this a hack... -- Dominik
_thd.place_mode = VHM_RECT;
} else if (_thd.next_drawstyle & HT_LINE) {
_thd.place_mode = VHM_RAIL;
@@ -2734,12 +2694,7 @@
}
SetTileSelectSize(1, 1);
- /* and call the mouseup event. */
- e.event = WE_PLACE_MOUSEUP;
- e.we.place.pt = _thd.selend;
- e.we.place.tile = TileVirtXY(e.we.place.pt.x, e.we.place.pt.y);
- e.we.place.starttile = TileVirtXY(_thd.selstart.x, _thd.selstart.y);
- w->HandleWindowEvent(&e);
+ w->OnPlaceMouseUp(_thd.select_method, _thd.select_proc, _thd.selend, TileVirtXY(_thd.selstart.x, _thd.selstart.y), TileVirtXY(_thd.selend.x, _thd.selend.y));
return false;
}
@@ -2758,7 +2713,7 @@
/* undo clicking on button and drag & drop */
if (_thd.place_mode != VHM_NONE || _special_mouse_mode == WSM_DRAGDROP) {
w = FindWindowById(_thd.window_class, _thd.window_number);
- if (w != NULL) CallWindowEventNP(w, WE_ABORT_PLACE_OBJ);
+ if (w != NULL) w->OnPlaceObjectAbort();
}
SetTileSelectSize(1, 1);
--- a/src/viewport_func.h Wed May 07 21:09:51 2008 +0000
+++ b/src/viewport_func.h Sun May 11 20:09:34 2008 +0000
@@ -51,15 +51,8 @@
Vehicle *CheckMouseOverVehicle();
-void VpSelectTilesWithMethod(int x, int y, ViewportPlaceMethod method);
-void VpStartPlaceSizing(TileIndex tile, ViewportPlaceMethod method, byte process);
-void VpSetPresizeRange(TileIndex from, TileIndex to);
-void VpSetPlaceSizingLimit(int limit);
-
void ViewportDoDraw(const ViewPort *vp, int left, int top, int right, int bottom);
-void ResetObjectToPlace();
-
bool ScrollWindowTo(int x, int y, Window *w, bool instant = false);
bool ScrollMainWindowToTile(TileIndex tile, bool instant = false);
--- a/src/viewport_type.h Wed May 07 21:09:51 2008 +0000
+++ b/src/viewport_type.h Sun May 11 20:09:34 2008 +0000
@@ -58,4 +58,33 @@
VPM_SIGNALDIRS = 6, ///< similiar to VMP_RAILDIRS, but with different cursor
};
+/** Drag and drop selection process, or, what to do with an area of land when
+ * you've selected it. */
+enum ViewportDragDropSelectionProcess {
+ DDSP_DEMOLISH_AREA,
+ DDSP_RAISE_AND_LEVEL_AREA,
+ DDSP_LOWER_AND_LEVEL_AREA,
+ DDSP_LEVEL_AREA,
+ DDSP_CREATE_DESERT,
+ DDSP_CREATE_ROCKS,
+ DDSP_CREATE_WATER,
+ DDSP_CREATE_RIVER,
+ DDSP_PLANT_TREES,
+ DDSP_BUILD_BRIDGE,
+
+ /* Rail specific actions */
+ DDSP_PLACE_RAIL_NE,
+ DDSP_PLACE_RAIL_NW,
+ DDSP_PLACE_AUTORAIL,
+ DDSP_BUILD_SIGNALS,
+ DDSP_BUILD_STATION,
+ DDSP_REMOVE_STATION,
+ DDSP_CONVERT_RAIL,
+
+ /* Road specific actions */
+ DDSP_PLACE_ROAD_X_DIR,
+ DDSP_PLACE_ROAD_Y_DIR,
+ DDSP_PLACE_AUTOROAD,
+};
+
#endif /* VIEWPORT_TYPE_H */
--- a/src/widgets/dropdown.cpp Wed May 07 21:09:51 2008 +0000
+++ b/src/widgets/dropdown.cpp Sun May 11 20:09:34 2008 +0000
@@ -56,7 +56,13 @@
delete list;
}
-struct dropdown_d {
+static const Widget _dropdown_menu_widgets[] = {
+{ WWT_PANEL, RESIZE_NONE, 0, 0, 0, 0, 0, 0x0, STR_NULL},
+{ WWT_SCROLLBAR, RESIZE_NONE, 0, 0, 0, 0, 0, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST},
+{ WIDGETS_END},
+};
+
+struct DropdownWindow : Window {
WindowClass parent_wnd_class;
WindowNumber parent_wnd_num;
byte parent_button;
@@ -65,164 +71,157 @@
byte click_delay;
bool drag_mode;
int scrolling;
-};
-assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(dropdown_d));
-
-static const Widget _dropdown_menu_widgets[] = {
-{ WWT_PANEL, RESIZE_NONE, 0, 0, 0, 0, 0, 0x0, STR_NULL},
-{ WWT_SCROLLBAR, RESIZE_NONE, 0, 0, 0, 0, 0, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST},
-{ WIDGETS_END},
-};
-
-static int GetDropDownItem(const Window *w)
-{
- if (GetWidgetFromPos(w, _cursor.pos.x - w->left, _cursor.pos.y - w->top) < 0) return -1;
- int y = _cursor.pos.y - w->top - 2;
- int width = w->widget[0].right - 3;
- int pos = w->vscroll.pos;
-
- const DropDownList *list = WP(w, dropdown_d).list;
-
- for (DropDownList::const_iterator it = list->begin(); it != list->end(); ++it) {
- /* Skip items that are scrolled up */
- if (--pos >= 0) continue;
-
- const DropDownListItem *item = *it;
- int item_height = item->Height(width);
-
- if (y < item_height) {
- if (item->masked || item->String() == STR_NULL) return -1;
- return item->result;
- }
-
- y -= item_height;
+ DropdownWindow(int x, int y, int width, int height, const Widget *widget) : Window(x, y, width, height, NULL, WC_DROPDOWN_MENU, widget)
+ {
}
- return -1;
-}
-
-static void DropDownMenuWndProc(Window *w, WindowEvent *e)
-{
- switch (e->event) {
- case WE_PAINT: {
- DrawWindowWidgets(w);
-
- int x = 1;
- int y = 2;
-
- int sel = WP(w, dropdown_d).selected_index;
- int width = w->widget[0].right - 3;
- int height = w->widget[0].bottom;
- int pos = w->vscroll.pos;
-
- DropDownList *list = WP(w, dropdown_d).list;
-
- for (DropDownList::const_iterator it = list->begin(); it != list->end(); ++it) {
- const DropDownListItem *item = *it;
- int item_height = item->Height(width);
-
- /* Skip items that are scrolled up */
- if (--pos >= 0) continue;
-
- if (y + item_height < height) {
- if (item->String() != STR_NULL) {
- if (sel == item->result) GfxFillRect(x + 1, y, x + width, y + item_height - 1, 0);
-
- item->Draw(x, y, width, 10, sel == item->result);
+ ~DropdownWindow()
+ {
+ Window *w2 = FindWindowById(this->parent_wnd_class, this->parent_wnd_num);
+ if (w2 != NULL) {
+ w2->RaiseWidget(this->parent_button);
+ w2->InvalidateWidget(this->parent_button);
+ }
- if (item->masked) {
- GfxFillRect(x, y, x + width, y + item_height - 1,
- (1 << PALETTE_MODIFIER_GREYOUT) | _colour_gradient[w->widget[0].color][5]
- );
- }
- } else {
- int c1 = _colour_gradient[w->widget[0].color][3];
- int c2 = _colour_gradient[w->widget[0].color][7];
-
- GfxFillRect(x + 1, y + 3, x + w->width - 5, y + 3, c1);
- GfxFillRect(x + 1, y + 4, x + w->width - 5, y + 4, c2);
- }
- }
- y += item_height;
- }
- } break;
+ DeleteDropDownList(this->list);
+ }
- case WE_CLICK: {
- if (e->we.click.widget != 0) break;
- int item = GetDropDownItem(w);
- if (item >= 0) {
- WP(w, dropdown_d).click_delay = 4;
- WP(w, dropdown_d).selected_index = item;
- SetWindowDirty(w);
- }
- } break;
+ int GetDropDownItem()
+ {
+ if (GetWidgetFromPos(this, _cursor.pos.x - this->left, _cursor.pos.y - this->top) < 0) return -1;
- case WE_TICK:
- if (WP(w, dropdown_d).scrolling == -1) {
- w->vscroll.pos = max(0, w->vscroll.pos - 1);
- SetWindowDirty(w);
- } else if (WP(w, dropdown_d).scrolling == 1) {
- w->vscroll.pos = min(w->vscroll.count - w->vscroll.cap, w->vscroll.pos + 1);
- SetWindowDirty(w);
- }
- WP(w, dropdown_d).scrolling = 0;
- break;
+ int y = _cursor.pos.y - this->top - 2;
+ int width = this->widget[0].right - 3;
+ int pos = this->vscroll.pos;
- case WE_MOUSELOOP: {
- Window *w2 = FindWindowById(WP(w, dropdown_d).parent_wnd_class, WP(w,dropdown_d).parent_wnd_num);
- if (w2 == NULL) {
- delete w;
- return;
+ const DropDownList *list = this->list;
+
+ for (DropDownList::const_iterator it = list->begin(); it != list->end(); ++it) {
+ /* Skip items that are scrolled up */
+ if (--pos >= 0) continue;
+
+ const DropDownListItem *item = *it;
+ int item_height = item->Height(width);
+
+ if (y < item_height) {
+ if (item->masked || item->String() == STR_NULL) return -1;
+ return item->result;
}
- if (WP(w, dropdown_d).click_delay != 0 && --WP(w,dropdown_d).click_delay == 0) {
- WindowEvent e;
- e.event = WE_DROPDOWN_SELECT;
- e.we.dropdown.button = WP(w, dropdown_d).parent_button;
- e.we.dropdown.index = WP(w, dropdown_d).selected_index;
- w2->HandleWindowEvent(&e);
- delete w;
- return;
+ y -= item_height;
+ }
+
+ return -1;
+ }
+
+ virtual void OnPaint()
+ {
+ DrawWindowWidgets(this);
+
+ int x = 1;
+ int y = 2;
+
+ int sel = this->selected_index;
+ int width = this->widget[0].right - 3;
+ int height = this->widget[0].bottom;
+ int pos = this->vscroll.pos;
+
+ DropDownList *list = this->list;
+
+ for (DropDownList::const_iterator it = list->begin(); it != list->end(); ++it) {
+ const DropDownListItem *item = *it;
+ int item_height = item->Height(width);
+
+ /* Skip items that are scrolled up */
+ if (--pos >= 0) continue;
+
+ if (y + item_height < height) {
+ if (item->String() != STR_NULL) {
+ if (sel == item->result) GfxFillRect(x + 1, y, x + width, y + item_height - 1, 0);
+
+ item->Draw(x, y, width, 10, sel == item->result);
+
+ if (item->masked) {
+ GfxFillRect(x, y, x + width, y + item_height - 1,
+ (1 << PALETTE_MODIFIER_GREYOUT) | _colour_gradient[this->widget[0].color][5]
+ );
+ }
+ } else {
+ int c1 = _colour_gradient[this->widget[0].color][3];
+ int c2 = _colour_gradient[this->widget[0].color][7];
+
+ GfxFillRect(x + 1, y + 3, x + this->width - 5, y + 3, c1);
+ GfxFillRect(x + 1, y + 4, x + this->width - 5, y + 4, c2);
+ }
+ }
+ y += item_height;
+ }
+ };
+
+ virtual void OnClick(Point pt, int widget)
+ {
+ if (widget != 0) return;
+ int item = GetDropDownItem();
+ if (item >= 0) {
+ this->click_delay = 4;
+ this->selected_index = item;
+ this->SetDirty();
+ }
+ }
+
+ virtual void OnTick()
+ {
+ if (this->scrolling == -1) {
+ this->vscroll.pos = max(0, this->vscroll.pos - 1);
+ this->SetDirty();
+ } else if (this->scrolling == 1) {
+ this->vscroll.pos = min(this->vscroll.count - this->vscroll.cap, this->vscroll.pos + 1);
+ this->SetDirty();
+ }
+ this->scrolling = 0;
+ }
+
+ virtual void OnMouseLoop()
+ {
+ Window *w2 = FindWindowById(this->parent_wnd_class, this->parent_wnd_num);
+ if (w2 == NULL) {
+ delete this;
+ return;
+ }
+
+ if (this->click_delay != 0 && --this->click_delay == 0) {
+ w2->OnDropdownSelect(this->parent_button, this->selected_index);
+ delete this;
+ return;
+ }
+
+ if (this->drag_mode) {
+ int item = GetDropDownItem();
+
+ if (!_left_button_clicked) {
+ this->drag_mode = false;
+ if (item < 0) return;
+ this->click_delay = 2;
+ } else {
+ if (_cursor.pos.y <= this->top + 2) {
+ /* Cursor is above the list, set scroll up */
+ this->scrolling = -1;
+ return;
+ } else if (_cursor.pos.y >= this->top + this->height - 2) {
+ /* Cursor is below list, set scroll down */
+ this->scrolling = 1;
+ return;
+ }
+
+ if (item < 0) return;
}
- if (WP(w, dropdown_d).drag_mode) {
- int item = GetDropDownItem(w);
-
- if (!_left_button_clicked) {
- WP(w, dropdown_d).drag_mode = false;
- if (item < 0) return;
- WP(w, dropdown_d).click_delay = 2;
- } else {
- if (_cursor.pos.y <= w->top + 2) {
- /* Cursor is above the list, set scroll up */
- WP(w, dropdown_d).scrolling = -1;
- return;
- } else if (_cursor.pos.y >= w->top + w->height - 2) {
- /* Cursor is below list, set scroll down */
- WP(w, dropdown_d).scrolling = 1;
- return;
- }
-
- if (item < 0) return;
- }
-
- WP(w, dropdown_d).selected_index = item;
- SetWindowDirty(w);
- }
- } break;
-
- case WE_DESTROY: {
- Window *w2 = FindWindowById(WP(w, dropdown_d).parent_wnd_class, WP(w,dropdown_d).parent_wnd_num);
- if (w2 != NULL) {
- w2->RaiseWidget(WP(w, dropdown_d).parent_button);
- w2->InvalidateWidget(WP(w, dropdown_d).parent_button);
- }
-
- DeleteDropDownList(WP(w, dropdown_d).list);
- } break;
+ this->selected_index = item;
+ this->SetDirty();
+ }
}
-}
+};
void ShowDropDownList(Window *w, DropDownList *list, int selected, int button, uint width)
{
@@ -282,13 +281,11 @@
if (width == 0) width = wi->right - wi->left + 1;
- Window *dw = AllocateWindow(
+ DropdownWindow *dw = new DropdownWindow(
w->left + wi->left,
top,
width,
height + 4,
- DropDownMenuWndProc,
- WC_DROPDOWN_MENU,
_dropdown_menu_widgets);
dw->widget[0].color = wi->color;
@@ -314,13 +311,13 @@
dw->desc_flags = WDF_DEF_WIDGET;
dw->flags4 &= ~WF_WHITE_BORDER_MASK;
- WP(dw, dropdown_d).parent_wnd_class = w->window_class;
- WP(dw, dropdown_d).parent_wnd_num = w->window_number;
- WP(dw, dropdown_d).parent_button = button;
- WP(dw, dropdown_d).list = list;
- WP(dw, dropdown_d).selected_index = selected;
- WP(dw, dropdown_d).click_delay = 0;
- WP(dw, dropdown_d).drag_mode = true;
+ dw->parent_wnd_class = w->window_class;
+ dw->parent_wnd_num = w->window_number;
+ dw->parent_button = button;
+ dw->list = list;
+ dw->selected_index = selected;
+ dw->click_delay = 0;
+ dw->drag_mode = true;
}
void ShowDropDownMenu(Window *w, const StringID *strings, int selected, int button, uint32 disabled_mask, uint32 hidden_mask, uint width)
@@ -360,9 +357,10 @@
FOR_ALL_WINDOWS(wz) {
if ((*wz)->window_class != WC_DROPDOWN_MENU) continue;
- if (pw->window_class == WP(*wz, dropdown_d).parent_wnd_class &&
- pw->window_number == WP(*wz, dropdown_d).parent_wnd_num) {
- delete *wz;
+ DropdownWindow *dw = dynamic_cast<DropdownWindow*>(*wz);
+ if (pw->window_class == dw->parent_wnd_class &&
+ pw->window_number == dw->parent_wnd_num) {
+ delete dw;
break;
}
}
--- a/src/win32.cpp Wed May 07 21:09:51 2008 +0000
+++ b/src/win32.cpp Sun May 11 20:09:34 2008 +0000
@@ -206,16 +206,15 @@
HMODULE modules[100];
DWORD needed;
BOOL res;
- int count, i;
HANDLE proc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessId());
if (proc != NULL) {
res = EnumProcessModules(proc, modules, sizeof(modules), &needed);
CloseHandle(proc);
if (res) {
- count = min(needed / sizeof(HMODULE), lengthof(modules));
+ size_t count = min(needed / sizeof(HMODULE), lengthof(modules));
- for (i = 0; i != count; i++) output = PrintModuleInfo(output, modules[i]);
+ for (size_t i = 0; i != count; i++) output = PrintModuleInfo(output, modules[i]);
return output;
}
}
@@ -1091,7 +1090,7 @@
const char *ptr;
WChar c;
- uint16 width, length;
+ size_t width, length;
if (IsClipboardFormatAvailable(CF_UNICODETEXT)) {
OpenClipboard(NULL);
@@ -1124,7 +1123,7 @@
if (!IsPrintable(c)) break;
size_t len = Utf8CharLen(c);
- if (tb->length + length >= tb->maxlength - (uint16)len) break;
+ if (tb->length + length >= tb->maxlength - len) break;
byte charwidth = GetCharacterWidth(FS_NORMAL, c);
if (tb->maxwidth != 0 && width + tb->width + charwidth > tb->maxwidth) break;
@@ -1254,7 +1253,7 @@
* @return pointer to utf8_buf. If conversion fails the string is of zero-length */
char *convert_from_fs(const wchar_t *name, char *utf8_buf, size_t buflen)
{
- int len = WideCharToMultiByte(CP_UTF8, 0, name, -1, utf8_buf, buflen, NULL, NULL);
+ int len = WideCharToMultiByte(CP_UTF8, 0, name, -1, utf8_buf, (int)buflen, NULL, NULL);
if (len == 0) {
DEBUG(misc, 0, "[utf8] W2M error converting wide-string. Errno %d", GetLastError());
utf8_buf[0] = '\0';
@@ -1273,7 +1272,7 @@
* @return pointer to utf16_buf. If conversion fails the string is of zero-length */
wchar_t *convert_to_fs(const char *name, wchar_t *utf16_buf, size_t buflen)
{
- int len = MultiByteToWideChar(CP_UTF8, 0, name, -1, utf16_buf, buflen);
+ int len = MultiByteToWideChar(CP_UTF8, 0, name, -1, utf16_buf, (int)buflen);
if (len == 0) {
DEBUG(misc, 0, "[utf8] M2W error converting '%s'. Errno %d", name, GetLastError());
utf16_buf[0] = '\0';
--- a/src/window.cpp Wed May 07 21:09:51 2008 +0000
+++ b/src/window.cpp Sun May 11 20:09:34 2008 +0000
@@ -44,13 +44,16 @@
bool _scrolling_scrollbar;
bool _scrolling_viewport;
-bool _popup_menu_active;
byte _special_mouse_mode;
/**
- * Call the window event handler for handling event \a e
+ * Call the window event handler for handling event \a e.
+ * This is a temporary helper functions that will be removed
+ * once all windows that still rely on WindowEvent and
+ * WindowEventCodes have been rewritten to use the 'OnXXX'
+ * event handlers.
* @param e Window event to handle
*/
void Window::HandleWindowEvent(WindowEvent *e)
@@ -58,6 +61,208 @@
if (wndproc != NULL) wndproc(this, e);
}
+void Window::OnPaint()
+{
+ WindowEvent e;
+ e.event = WE_PAINT;
+ this->HandleWindowEvent(&e);
+}
+
+bool Window::OnKeyPress(uint16 key, uint16 keycode)
+{
+ WindowEvent e;
+ e.event = WE_KEYPRESS;
+ e.we.keypress.key = key;
+ e.we.keypress.keycode = keycode;
+ e.we.keypress.cont = true;
+ this->HandleWindowEvent(&e);
+
+ return e.we.keypress.cont;
+}
+
+bool Window::OnCTRLStateChange()
+{
+ WindowEvent e;
+ e.event = WE_CTRL_CHANGED;
+ e.we.ctrl.cont = true;
+ this->HandleWindowEvent(&e);
+
+ return e.we.ctrl.cont;
+}
+
+void Window::OnClick(Point pt, int widget)
+{
+ WindowEvent e;
+ e.event = WE_CLICK;
+ e.we.click.pt = pt;
+ e.we.click.widget = widget;
+ this->HandleWindowEvent(&e);
+}
+
+void Window::OnDoubleClick(Point pt, int widget)
+{
+ WindowEvent e;
+ e.event = WE_DOUBLE_CLICK;
+ e.we.click.pt = pt;
+ e.we.click.widget = widget;
+ this->HandleWindowEvent(&e);
+}
+
+void Window::OnRightClick(Point pt, int widget)
+{
+ WindowEvent e;
+ e.event = WE_RCLICK;
+ e.we.click.pt = pt;
+ e.we.click.widget = widget;
+ this->HandleWindowEvent(&e);
+}
+
+void Window::OnDragDrop(Point pt, int widget)
+{
+ WindowEvent e;
+ e.event = WE_DRAGDROP;
+ e.we.click.pt = pt;
+ e.we.click.widget = widget;
+ this->HandleWindowEvent(&e);
+}
+
+void Window::OnScroll(Point delta)
+{
+ WindowEvent e;
+ e.event = WE_SCROLL;
+ e.we.scroll.delta = delta;
+ this->HandleWindowEvent(&e);
+}
+
+void Window::OnMouseOver(Point pt, int widget)
+{
+ WindowEvent e;
+ e.event = WE_MOUSEOVER;
+ e.we.click.pt = pt;
+ e.we.click.widget = widget;
+ this->HandleWindowEvent(&e);
+}
+
+void Window::OnMouseWheel(int wheel)
+{
+ WindowEvent e;
+ e.event = WE_MOUSEWHEEL;
+ e.we.wheel.wheel = wheel;
+ this->HandleWindowEvent(&e);
+}
+
+void Window::OnMouseLoop()
+{
+ WindowEvent e;
+ e.event = WE_MOUSELOOP;
+ this->HandleWindowEvent(&e);
+}
+
+void Window::OnTick()
+{
+ WindowEvent e;
+ e.event = WE_TICK;
+ this->HandleWindowEvent(&e);
+}
+
+void Window::OnHundredthTick()
+{
+ WindowEvent e;
+ e.event = WE_100_TICKS;
+ this->HandleWindowEvent(&e);
+}
+
+void Window::OnTimeout()
+{
+ WindowEvent e;
+ e.event = WE_TIMEOUT;
+ this->HandleWindowEvent(&e);
+}
+
+void Window::OnResize(Point new_size, Point delta)
+{
+ WindowEvent e;
+ e.event = WE_RESIZE;
+ e.we.sizing.size = new_size;
+ e.we.sizing.diff = delta;
+ this->HandleWindowEvent(&e);
+}
+
+void Window::OnDropdownSelect(int widget, int index)
+{
+ WindowEvent e;
+ e.event = WE_DROPDOWN_SELECT;
+ e.we.dropdown.button = widget;
+ e.we.dropdown.index = index;
+ this->HandleWindowEvent(&e);
+}
+
+void Window::OnQueryTextFinished(char *str)
+{
+ WindowEvent e;
+ e.event = WE_ON_EDIT_TEXT;
+ e.we.edittext.str = str;
+ this->HandleWindowEvent(&e);
+}
+
+void Window::OnInvalidateData(int data)
+{
+ WindowEvent e;
+ e.event = WE_INVALIDATE_DATA;
+ e.we.invalidate.data = data;
+ this->HandleWindowEvent(&e);
+}
+
+void Window::OnPlaceObject(Point pt, TileIndex tile)
+{
+ WindowEvent e;
+ e.event = WE_PLACE_OBJ;
+ e.we.place.pt = pt;
+ e.we.place.tile = tile;
+ this->HandleWindowEvent(&e);
+}
+
+void Window::OnPlaceObjectAbort()
+{
+ WindowEvent e;
+ e.event = WE_ABORT_PLACE_OBJ;
+ this->HandleWindowEvent(&e);
+}
+
+
+void Window::OnPlaceDrag(ViewportPlaceMethod select_method, byte select_proc, Point pt)
+{
+ WindowEvent e;
+ e.event = WE_PLACE_DRAG;
+ e.we.place.select_method = select_method;
+ e.we.place.select_proc = select_proc;
+ e.we.place.pt = pt;
+ this->HandleWindowEvent(&e);
+}
+
+void Window::OnPlaceMouseUp(ViewportPlaceMethod select_method, byte select_proc, Point pt, TileIndex start_tile, TileIndex end_tile)
+{
+ WindowEvent e;
+ e.event = WE_PLACE_MOUSEUP;
+ e.we.place.select_method = select_method;
+ e.we.place.select_proc = select_proc;
+ e.we.place.pt = pt;
+ e.we.place.tile = end_tile;
+ e.we.place.starttile = start_tile;
+ this->HandleWindowEvent(&e);
+}
+
+void Window::OnPlacePresize(Point pt, TileIndex tile)
+{
+ WindowEvent e;
+ e.event = WE_PLACE_PRESIZE;
+ e.we.place.pt = pt;
+ e.we.place.tile = tile;
+ this->HandleWindowEvent(&e);
+}
+
+
+
void CDECL Window::SetWidgetsDisabledState(bool disab_stat, int widgets, ...)
{
va_list wdg_list;
@@ -139,19 +344,15 @@
*/
static void DispatchLeftClickEvent(Window *w, int x, int y, bool double_click)
{
- WindowEvent e;
- e.we.click.pt.x = x;
- e.we.click.pt.y = y;
- e.event = double_click ? WE_DOUBLE_CLICK : WE_CLICK;
-
+ int widget = 0;
if (w->desc_flags & WDF_DEF_WIDGET) {
- e.we.click.widget = GetWidgetFromPos(w, x, y);
- if (e.we.click.widget < 0) return; // exit if clicked outside of widgets
+ widget = GetWidgetFromPos(w, x, y);
+ if (widget < 0) return; // exit if clicked outside of widgets
/* don't allow any interaction if the button has been disabled */
- if (w->IsWidgetDisabled(e.we.click.widget)) return;
+ if (w->IsWidgetDisabled(widget)) return;
- const Widget *wi = &w->widget[e.we.click.widget];
+ const Widget *wi = &w->widget[widget];
if (wi->type & WWB_MASK) {
/* special widget handling for buttons*/
@@ -159,20 +360,20 @@
case WWT_PANEL | WWB_PUSHBUTTON: /* WWT_PUSHBTN */
case WWT_IMGBTN | WWB_PUSHBUTTON: /* WWT_PUSHIMGBTN */
case WWT_TEXTBTN | WWB_PUSHBUTTON: /* WWT_PUSHTXTBTN */
- w->HandleButtonClick(e.we.click.widget);
+ w->HandleButtonClick(widget);
break;
}
} else if (wi->type == WWT_SCROLLBAR || wi->type == WWT_SCROLL2BAR || wi->type == WWT_HSCROLLBAR) {
- ScrollbarClickHandler(w, wi, e.we.click.pt.x, e.we.click.pt.y);
+ ScrollbarClickHandler(w, wi, x, y);
}
if (w->desc_flags & WDF_STD_BTN) {
- if (e.we.click.widget == 0) { /* 'X' */
+ if (widget == 0) { /* 'X' */
delete w;
return;
}
- if (e.we.click.widget == 1) { /* 'Title bar' */
+ if (widget == 1) { /* 'Title bar' */
StartWindowDrag(w);
return;
}
@@ -180,18 +381,24 @@
if (w->desc_flags & WDF_RESIZABLE && wi->type == WWT_RESIZEBOX) {
StartWindowSizing(w);
- w->InvalidateWidget(e.we.click.widget);
+ w->InvalidateWidget(widget);
return;
}
if (w->desc_flags & WDF_STICKY_BUTTON && wi->type == WWT_STICKYBOX) {
w->flags4 ^= WF_STICKY;
- w->InvalidateWidget(e.we.click.widget);
+ w->InvalidateWidget(widget);
return;
}
}
- w->HandleWindowEvent(&e);
+ Point pt = { x, y };
+
+ if (double_click) {
+ w->OnDoubleClick(pt, widget);
+ } else {
+ w->OnClick(pt, widget);
+ }
}
/**
@@ -202,23 +409,21 @@
*/
static void DispatchRightClickEvent(Window *w, int x, int y)
{
- WindowEvent e;
+ int widget = 0;
/* default tooltips handler? */
if (w->desc_flags & WDF_STD_TOOLTIPS) {
- e.we.click.widget = GetWidgetFromPos(w, x, y);
- if (e.we.click.widget < 0) return; // exit if clicked outside of widgets
+ widget = GetWidgetFromPos(w, x, y);
+ if (widget < 0) return; // exit if clicked outside of widgets
- if (w->widget[e.we.click.widget].tooltips != 0) {
- GuiShowTooltips(w->widget[e.we.click.widget].tooltips);
+ if (w->widget[widget].tooltips != 0) {
+ GuiShowTooltips(w->widget[widget].tooltips);
return;
}
}
- e.event = WE_RCLICK;
- e.we.click.pt.x = x;
- e.we.click.pt.y = y;
- w->HandleWindowEvent(&e);
+ Point pt = { x, y };
+ w->OnRightClick(pt, widget);
}
/**
@@ -316,7 +521,7 @@
dp->pitch = _screen.pitch;
dp->dst_ptr = BlitterFactoryBase::GetCurrentBlitter()->MoveTo(_screen.dst_ptr, left, top);
dp->zoom = ZOOM_LVL_NORMAL;
- CallWindowEventNP(*wz, WE_PAINT);
+ (*wz)->OnPaint();
}
/**
@@ -346,20 +551,6 @@
}
/**
- * Dispatch an event to a possibly non-existing window.
- * If the window pointer w is \c NULL, the event is not dispatched
- * @param w Window to dispatch the event to, may be \c NULL
- * @param event Event to dispatch
- */
-void CallWindowEventNP(Window *w, int event)
-{
- WindowEvent e;
-
- e.event = event;
- w->HandleWindowEvent(&e);
-}
-
-/**
* Mark entire window as dirty (in need of re-paint)
* @param w Window to redraw
* @ingroup dirty
@@ -438,7 +629,9 @@
/* Delete any children a window might have in a head-recursive manner */
delete FindChildWindow(this);
- CallWindowEventNP(this, WE_DESTROY);
+ WindowEvent e;
+ e.event = WE_DESTROY;
+ this->HandleWindowEvent(&e);
if (this->viewport != NULL) DeleteWindowViewport(this);
this->SetDirty();
@@ -656,10 +849,18 @@
return (w->original_widget == widget);
}
-/** Copies 'widget' to 'w->widget' to allow for resizable windows
+/**
+ * Assign widgets to a new window by initialising its widget pointers, and by
+ * copying the widget array \a widget to \c w->widget to allow for resizable
+ * windows.
* @param w Window on which to attach the widget array
- * @param widget pointer of widget array to fill the window with */
-void AssignWidgetToWindow(Window *w, const Widget *widget)
+ * @param widget pointer of widget array to fill the window with
+ *
+ * @post \c w->widget points to allocated memory and contains the copied widget array except for the terminating widget,
+ * \c w->original_widget points to the original widgets,
+ * \c w->widget_count contains number of widgets in the allocated memory.
+ */
+static void AssignWidgetToWindow(Window *w, const Widget *widget)
{
w->original_widget = widget;
@@ -668,7 +869,7 @@
for (const Widget *wi = widget; wi->type != WWT_LAST; wi++) index++;
- w->widget = ReallocT(w->widget, index);
+ w->widget = MallocT<Widget>(index);
memcpy(w->widget, widget, sizeof(*w->widget) * index);
w->widget_count = index - 1;
} else {
@@ -677,88 +878,88 @@
}
}
-/** Open a new window.
- * This function is called from AllocateWindow() or AllocateWindowDesc()
+/**
+ * Initializes a new Window.
+ * This function is called the constructors.
* See descriptions for those functions for usage
- * See AllocateWindow() for description of arguments.
* Only addition here is window_number, which is the window_number being assigned to the new window
* @param x offset in pixels from the left of the screen
* @param y offset in pixels from the top of the screen
* @param min_width minimum width in pixels of the window
* @param min_height minimum height in pixels of the window
- * @param def_width default width in pixels of the window
- * @param def_height default height in pixels of the window
* @param *proc see WindowProc function to call when any messages/updates happen to the window
* @param cls see WindowClass class of the window, used for identification and grouping
* @param *widget see Widget pointer to the window layout and various elements
* @param window_number number being assigned to the new window
* @param data the data to be given during the WE_CREATE message
* @return Window pointer of the newly created window */
-static Window *LocalAllocateWindow(int x, int y, int min_width, int min_height, int def_width, int def_height,
+void Window::Initialize(int x, int y, int min_width, int min_height,
WindowProc *proc, WindowClass cls, const Widget *widget, int window_number, void *data)
{
- Window *w;
-
/* We have run out of windows, close one and use that as the place for our new one */
if (_last_z_window == endof(_z_windows)) {
- w = FindDeletableWindow();
+ Window *w = FindDeletableWindow();
if (w == NULL) w = ForceFindDeletableWindow();
delete w;
}
- w = new Window(proc);
-
/* Set up window properties */
- w->window_class = cls;
- w->flags4 = WF_WHITE_BORDER_MASK; // just opened windows have a white border
- w->caption_color = 0xFF;
- w->left = x;
- w->top = y;
- w->width = min_width;
- w->height = min_height;
- AssignWidgetToWindow(w, widget);
- w->resize.width = min_width;
- w->resize.height = min_height;
- w->resize.step_width = 1;
- w->resize.step_height = 1;
- w->window_number = window_number;
-
- {
- Window **wz = _last_z_window;
+ this->window_class = cls;
+ this->flags4 = WF_WHITE_BORDER_MASK; // just opened windows have a white border
+ this->caption_color = 0xFF;
+ this->left = x;
+ this->top = y;
+ this->width = min_width;
+ this->height = min_height;
+ this->wndproc = proc;
+ AssignWidgetToWindow(this, widget);
+ this->resize.width = min_width;
+ this->resize.height = min_height;
+ this->resize.step_width = 1;
+ this->resize.step_height = 1;
+ this->window_number = window_number;
- /* Hacky way of specifying always-on-top windows. These windows are
- * always above other windows because they are moved below them.
- * status-bar is above news-window because it has been created earlier.
- * Also, as the chat-window is excluded from this, it will always be
- * the last window, thus always on top.
- * XXX - Yes, ugly, probably needs something like w->always_on_top flag
- * to implement correctly, but even then you need some kind of distinction
- * between on-top of chat/news and status windows, because these conflict */
- if (wz != _z_windows && w->window_class != WC_SEND_NETWORK_MSG && w->window_class != WC_HIGHSCORE && w->window_class != WC_ENDSCREEN) {
- if (FindWindowById(WC_MAIN_TOOLBAR, 0) != NULL) wz--;
- if (FindWindowById(WC_STATUS_BAR, 0) != NULL) wz--;
- if (FindWindowById(WC_NEWS_WINDOW, 0) != NULL) wz--;
- if (FindWindowById(WC_SEND_NETWORK_MSG, 0) != NULL) wz--;
+ /* Hacky way of specifying always-on-top windows. These windows are
+ * always above other windows because they are moved below them.
+ * status-bar is above news-window because it has been created earlier.
+ * Also, as the chat-window is excluded from this, it will always be
+ * the last window, thus always on top.
+ * XXX - Yes, ugly, probably needs something like w->always_on_top flag
+ * to implement correctly, but even then you need some kind of distinction
+ * between on-top of chat/news and status windows, because these conflict */
+ Window **wz = _last_z_window;
+ if (wz != _z_windows && this->window_class != WC_SEND_NETWORK_MSG && this->window_class != WC_HIGHSCORE && this->window_class != WC_ENDSCREEN) {
+ if (FindWindowById(WC_MAIN_TOOLBAR, 0) != NULL) wz--;
+ if (FindWindowById(WC_STATUS_BAR, 0) != NULL) wz--;
+ if (FindWindowById(WC_NEWS_WINDOW, 0) != NULL) wz--;
+ if (FindWindowById(WC_SEND_NETWORK_MSG, 0) != NULL) wz--;
- assert(wz >= _z_windows);
- if (wz != _last_z_window) memmove(wz + 1, wz, (byte*)_last_z_window - (byte*)wz);
- }
+ assert(wz >= _z_windows);
+ if (wz != _last_z_window) memmove(wz + 1, wz, (byte*)_last_z_window - (byte*)wz);
+ }
- *wz = w;
- _last_z_window++;
- }
+ *wz = this;
+ _last_z_window++;
WindowEvent e;
e.event = WE_CREATE;
e.we.create.data = data;
- w->HandleWindowEvent(&e);
+ this->HandleWindowEvent(&e);
+}
+/**
+ * Find a nice spot for this window and resize it towards the default size.
+ * @param def_width default width in pixels of the window
+ * @param def_height default height in pixels of the window
+ */
+void Window::FindWindowPlacementAndResize(int def_width, int def_height)
+{
/* Try to make windows smaller when our window is too small.
* w->(width|height) is normally the same as min_(width|height),
* but this way the GUIs can be made a little more dynamic;
* one can use the same spec for multiple windows and those
* can then determine the real minimum size of the window. */
- if (w->width != def_width || w->height != def_height) {
+ if (this->width != def_width || this->height != def_height) {
/* Think about the overlapping toolbars when determining the minimum window size */
int free_height = _screen.height;
const Window *wt = FindWindowById(WC_STATUS_BAR, 0);
@@ -766,45 +967,48 @@
wt = FindWindowById(WC_MAIN_TOOLBAR, 0);
if (wt != NULL) free_height -= wt->height;
- int enlarge_x = max(min(def_width - w->width, _screen.width - w->width), 0);
- int enlarge_y = max(min(def_height - w->height, free_height - w->height), 0);
+ int enlarge_x = max(min(def_width - this->width, _screen.width - this->width), 0);
+ int enlarge_y = max(min(def_height - this->height, free_height - this->height), 0);
/* X and Y has to go by step.. calculate it.
* The cast to int is necessary else x/y are implicitly casted to
* unsigned int, which won't work. */
- if (w->resize.step_width > 1) enlarge_x -= enlarge_x % (int)w->resize.step_width;
- if (w->resize.step_height > 1) enlarge_y -= enlarge_y % (int)w->resize.step_height;
-
- ResizeWindow(w, enlarge_x, enlarge_y);
+ if (this->resize.step_width > 1) enlarge_x -= enlarge_x % (int)this->resize.step_width;
+ if (this->resize.step_height > 1) enlarge_y -= enlarge_y % (int)this->resize.step_height;
- WindowEvent e;
- e.event = WE_RESIZE;
- e.we.sizing.size.x = w->width;
- e.we.sizing.size.y = w->height;
- e.we.sizing.diff.x = enlarge_x;
- e.we.sizing.diff.y = enlarge_y;
- w->HandleWindowEvent(&e);
+ ResizeWindow(this, enlarge_x, enlarge_y);
+
+ Point size;
+ Point diff;
+ size.x = this->width;
+ size.y = this->height;
+ diff.x = enlarge_x;
+ diff.y = enlarge_y;
+ this->OnResize(size, diff);
}
- int nx = w->left;
- int ny = w->top;
+ int nx = this->left;
+ int ny = this->top;
- if (nx + w->width > _screen.width) nx -= (nx + w->width - _screen.width);
+ if (nx + this->width > _screen.width) nx -= (nx + this->width - _screen.width);
const Window *wt = FindWindowById(WC_MAIN_TOOLBAR, 0);
- ny = max(ny, (wt == NULL || w == wt || y == 0) ? 0 : wt->height);
+ ny = max(ny, (wt == NULL || this == wt || this->top == 0) ? 0 : wt->height);
nx = max(nx, 0);
- if (w->viewport != NULL) {
- w->viewport->left += nx - w->left;
- w->viewport->top += ny - w->top;
+ if (this->viewport != NULL) {
+ this->viewport->left += nx - this->left;
+ this->viewport->top += ny - this->top;
}
- w->left = nx;
- w->top = ny;
+ this->left = nx;
+ this->top = ny;
- w->SetDirty();
+ this->SetDirty();
+}
- return w;
+void Window::FindWindowPlacementAndResize(const WindowDesc *desc)
+{
+ this->FindWindowPlacementAndResize(desc->default_width, desc->default_height);
}
/**
@@ -821,10 +1025,11 @@
* @param *widget see Widget pointer to the window layout and various elements
* @return Window pointer of the newly created window
*/
-Window *AllocateWindow(int x, int y, int width, int height,
- WindowProc *proc, WindowClass cls, const Widget *widget, void *data)
+Window::Window(int x, int y, int width, int height, WindowProc *proc, WindowClass cls, const Widget *widget, void *data)
{
- return LocalAllocateWindow(x, y, width, height, width, height, proc, cls, widget, 0, data);
+ this->Initialize(x, y, width, height, proc, cls, widget, 0, data);
+
+ if (proc != NULL) this->FindWindowPlacementAndResize(width, height);
}
@@ -1014,37 +1219,13 @@
*
* @return Window pointer of the newly created window
*/
-static Window *LocalAllocateWindowDesc(const WindowDesc *desc, int window_number, void *data)
+Window::Window(const WindowDesc *desc, void *data, WindowNumber window_number)
{
Point pt = LocalGetWindowPlacement(desc, window_number);
- Window *w = LocalAllocateWindow(pt.x, pt.y, desc->minimum_width, desc->minimum_height, desc->default_width, desc->default_height, desc->proc, desc->cls, desc->widgets, window_number, data);
- w->desc_flags = desc->flags;
-
- return w;
-}
+ this->Initialize(pt.x, pt.y, desc->minimum_width, desc->minimum_height, desc->proc, desc->cls, desc->widgets, window_number, data);
+ this->desc_flags = desc->flags;
-/**
- * Open a new window.
- * @param *desc The pointer to the WindowDesc to be created
- * @param data arbitrary data that is send with the WE_CREATE message
- * @return Window pointer of the newly created window
- */
-Window *AllocateWindowDesc(const WindowDesc *desc, void *data)
-{
- return LocalAllocateWindowDesc(desc, 0, data);
-}
-
-/**
- * Open a new window.
- * @param *desc The pointer to the WindowDesc to be created
- * @param window_number the window number of the new window
- * @param data arbitrary data that is send with the WE_CREATE message
- * @return see Window pointer of the newly created window
- */
-Window *AllocateWindowDescFront(const WindowDesc *desc, int window_number, void *data)
-{
- if (BringWindowToFrontById(desc->cls, window_number)) return NULL;
- return LocalAllocateWindowDesc(desc, window_number, data);
+ if (desc->proc != NULL) this->FindWindowPlacementAndResize(desc->default_width, desc->default_height);
}
/** Do a search for a window at specific coordinates. For this we start
@@ -1108,14 +1289,14 @@
w->flags4 &= ~(WF_SCROLL_DOWN | WF_SCROLL_UP);
w->SetDirty();
}
- CallWindowEventNP(w, WE_MOUSELOOP);
+ w->OnMouseLoop();
}
for (wz = _last_z_window; wz != _z_windows;) {
Window *w = *--wz;
if (w->flags4 & WF_TIMEOUT_MASK && !(--w->flags4 & WF_TIMEOUT_MASK)) {
- CallWindowEventNP(w, WE_TIMEOUT);
+ w->OnTimeout();
if (w->desc_flags & WDF_UNCLICK_BUTTONS) w->RaiseButtons();
}
}
@@ -1133,15 +1314,13 @@
Window *w = GetCallbackWnd();
if (w == NULL) return;
- WindowEvent e;
- e.we.place.pt = GetTileBelowCursor();
- if (e.we.place.pt.x == -1) {
+ Point pt = GetTileBelowCursor();
+ if (pt.x == -1) {
_thd.selend.x = -1;
return;
}
- e.we.place.tile = TileVirtXY(e.we.place.pt.x, e.we.place.pt.y);
- e.event = WE_PLACE_PRESIZE;
- w->HandleWindowEvent(&e);
+
+ w->OnPlacePresize(pt, TileVirtXY(pt.x, pt.y));
}
static bool HandleDragDrop()
@@ -1153,12 +1332,10 @@
if (w != NULL) {
/* send an event in client coordinates. */
- WindowEvent e;
- e.event = WE_DRAGDROP;
- e.we.dragdrop.pt.x = _cursor.pos.x - w->left;
- e.we.dragdrop.pt.y = _cursor.pos.y - w->top;
- e.we.dragdrop.widget = GetWidgetFromPos(w, e.we.dragdrop.pt.x, e.we.dragdrop.pt.y);
- w->HandleWindowEvent(&e);
+ Point pt;
+ pt.x = _cursor.pos.x - w->left;
+ pt.y = _cursor.pos.y - w->top;
+ w->OnDragDrop(pt, GetWidgetFromPos(w, pt.x, pt.y));
}
ResetObjectToPlace();
@@ -1166,31 +1343,6 @@
return false;
}
-static bool HandlePopupMenu()
-{
- if (!_popup_menu_active) return true;
-
- Window *w = FindWindowById(WC_TOOLBAR_MENU, 0);
- if (w == NULL) {
- _popup_menu_active = false;
- return false;
- }
-
- WindowEvent e;
- if (_left_button_down) {
- e.event = WE_POPUPMENU_OVER;
- e.we.popupmenu.pt = _cursor.pos;
- } else {
- _popup_menu_active = false;
- e.event = WE_POPUPMENU_SELECT;
- e.we.popupmenu.pt = _cursor.pos;
- }
-
- w->HandleWindowEvent(&e);
-
- return false;
-}
-
static bool HandleMouseOver()
{
Window *w = FindWindowFromPt(_cursor.pos.x, _cursor.pos.y);
@@ -1198,11 +1350,8 @@
/* We changed window, put a MOUSEOVER event to the last window */
if (_mouseover_last_w != NULL && _mouseover_last_w != w) {
/* Reset mouse-over coordinates of previous window */
- WindowEvent e;
- e.event = WE_MOUSEOVER;
- e.we.mouseover.pt.x = -1;
- e.we.mouseover.pt.y = -1;
- _mouseover_last_w->HandleWindowEvent(&e);
+ Point pt = { -1, -1 };
+ _mouseover_last_w->OnMouseOver(pt, 0);
}
/* _mouseover_last_w will get reset when the window is deleted, see DeleteWindow() */
@@ -1210,14 +1359,12 @@
if (w != NULL) {
/* send an event in client coordinates. */
- WindowEvent e;
- e.event = WE_MOUSEOVER;
- e.we.mouseover.pt.x = _cursor.pos.x - w->left;
- e.we.mouseover.pt.y = _cursor.pos.y - w->top;
+ Point pt = { _cursor.pos.x - w->left, _cursor.pos.y - w->top };
+ int widget = 0;
if (w->widget != NULL) {
- e.we.mouseover.widget = GetWidgetFromPos(w, e.we.mouseover.pt.x, e.we.mouseover.pt.y);
+ widget = GetWidgetFromPos(w, pt.x, pt.y);
}
- w->HandleWindowEvent(&e);
+ w->OnMouseOver(pt, widget);
}
/* Mouseover never stops execution */
@@ -1421,7 +1568,6 @@
w->SetDirty();
return false;
} else if (w->flags4 & WF_SIZING) {
- WindowEvent e;
int x, y;
/* Stop the sizing if the left mouse button was released */
@@ -1458,12 +1604,13 @@
/* ResizeWindow sets both pre- and after-size to dirty for redrawal */
ResizeWindow(w, x, y);
- e.event = WE_RESIZE;
- e.we.sizing.size.x = x + w->width;
- e.we.sizing.size.y = y + w->height;
- e.we.sizing.diff.x = x;
- e.we.sizing.diff.y = y;
- w->HandleWindowEvent(&e);
+ Point size;
+ Point diff;
+ size.x = x + w->width;
+ size.y = y + w->height;
+ diff.x = x;
+ diff.y = y;
+ w->OnResize(size, diff);
return false;
}
}
@@ -1554,8 +1701,6 @@
static bool HandleViewportScroll()
{
- WindowEvent e;
-
bool scrollwheel_scrolling = _patches.scrollwheel_scrolling == 1 && (_cursor.v_wheel != 0 || _cursor.h_wheel != 0);
if (!_scrolling_viewport) return true;
@@ -1568,32 +1713,32 @@
return true;
}
- if (WP(w, vp_d).follow_vehicle != INVALID_VEHICLE && w == FindWindowById(WC_MAIN_WINDOW, 0)) {
+ if (w == FindWindowById(WC_MAIN_WINDOW, 0) && w->viewport->follow_vehicle != INVALID_VEHICLE) {
/* If the main window is following a vehicle, then first let go of it! */
- const Vehicle *veh = GetVehicle(WP(w, vp_d).follow_vehicle);
+ const Vehicle *veh = GetVehicle(w->viewport->follow_vehicle);
ScrollMainWindowTo(veh->x_pos, veh->y_pos, true); /* This also resets follow_vehicle */
return true;
}
+ Point delta;
if (_patches.reverse_scroll) {
- e.we.scroll.delta.x = -_cursor.delta.x;
- e.we.scroll.delta.y = -_cursor.delta.y;
+ delta.x = -_cursor.delta.x;
+ delta.y = -_cursor.delta.y;
} else {
- e.we.scroll.delta.x = _cursor.delta.x;
- e.we.scroll.delta.y = _cursor.delta.y;
+ delta.x = _cursor.delta.x;
+ delta.y = _cursor.delta.y;
}
if (scrollwheel_scrolling) {
/* We are using scrollwheels for scrolling */
- e.we.scroll.delta.x = _cursor.h_wheel;
- e.we.scroll.delta.y = _cursor.v_wheel;
+ delta.x = _cursor.h_wheel;
+ delta.y = _cursor.v_wheel;
_cursor.v_wheel = 0;
_cursor.h_wheel = 0;
}
/* Create a scroll-event and send it to the window */
- e.event = WE_SCROLL;
- w->HandleWindowEvent(&e);
+ w->OnScroll(delta);
_cursor.delta.x = 0;
_cursor.delta.y = 0;
@@ -1652,59 +1797,11 @@
return true;
}
-/** Send a message from one window to another. The receiving window is found by
- * @param w Window pointer pointing to the other window
- * @param msg Specifies the message to be sent
- * @param wparam Specifies additional message-specific information
- * @param lparam Specifies additional message-specific information
- */
-static void SendWindowMessageW(Window *w, uint msg, uint wparam, uint lparam)
-{
- WindowEvent e;
-
- e.event = WE_MESSAGE;
- e.we.message.msg = msg;
- e.we.message.wparam = wparam;
- e.we.message.lparam = lparam;
-
- w->HandleWindowEvent(&e);
-}
-
-/** Send a message from one window to another. The receiving window is found by
- * @param wnd_class see WindowClass class AND
- * @param wnd_num see WindowNumber number, mostly 0
- * @param msg Specifies the message to be sent
- * @param wparam Specifies additional message-specific information
- * @param lparam Specifies additional message-specific information
+/** Handle keyboard input.
+ * @param raw_key Lower 8 bits contain the ASCII character, the higher 16 bits the keycode
*/
-void SendWindowMessage(WindowClass wnd_class, WindowNumber wnd_num, int msg, int wparam, int lparam)
+void HandleKeypress(uint32 raw_key)
{
- Window *w = FindWindowById(wnd_class, wnd_num);
- if (w != NULL) SendWindowMessageW(w, msg, wparam, lparam);
-}
-
-/** Send a message from one window to another. The message will be sent
- * to ALL windows of the windowclass specified in the first parameter
- * @param wnd_class see WindowClass class
- * @param msg Specifies the message to be sent
- * @param wparam Specifies additional message-specific information
- * @param lparam Specifies additional message-specific information
- */
-void SendWindowMessageClass(WindowClass wnd_class, int msg, int wparam, int lparam)
-{
- Window* const *wz;
-
- FOR_ALL_WINDOWS(wz) {
- if ((*wz)->window_class == wnd_class) SendWindowMessageW(*wz, msg, wparam, lparam);
- }
-}
-
-/** Handle keyboard input.
- * @param key Lower 8 bits contain the ASCII character, the higher 16 bits the keycode
- */
-void HandleKeypress(uint32 key)
-{
- WindowEvent e;
/* Stores if a window with a textfield for typing is open
* If this is the case, keypress events are only passed to windows with text fields and
* to thein this main toolbar. */
@@ -1722,10 +1819,8 @@
if (!IsGeneratingWorld()) _current_player = _local_player;
/* Setup event */
- e.event = WE_KEYPRESS;
- e.we.keypress.key = GB(key, 0, 16);
- e.we.keypress.keycode = GB(key, 16, 16);
- e.we.keypress.cont = true;
+ uint16 key = GB(raw_key, 0, 16);
+ uint16 keycode = GB(raw_key, 16, 16);
/*
* The Unicode standard defines an area called the private use area. Code points in this
@@ -1734,12 +1829,12 @@
* on a system running OS X. We don't want these keys to show up in text fields and such,
* and thus we have to clear the unicode character when we encounter such a key.
*/
- if (e.we.keypress.key >= 0xE000 && e.we.keypress.key <= 0xF8FF) e.we.keypress.key = 0;
+ if (key >= 0xE000 && key <= 0xF8FF) key = 0;
/*
* If both key and keycode is zero, we don't bother to process the event.
*/
- if (e.we.keypress.key == 0 && e.we.keypress.keycode == 0) return;
+ if (key == 0 && keycode == 0) return;
/* check if we have a query string window open before allowing hotkeys */
if (FindWindowById(WC_QUERY_STRING, 0) != NULL ||
@@ -1765,15 +1860,13 @@
w->window_class != WC_COMPANY_PASSWORD_WINDOW) {
continue;
}
- w->HandleWindowEvent(&e);
- if (!e.we.keypress.cont) break;
+ ;
+ if (!w->OnKeyPress(key, keycode)) return;
}
- if (e.we.keypress.cont) {
- Window *w = FindWindowById(WC_MAIN_TOOLBAR, 0);
- /* When there is no toolbar w is null, check for that */
- if (w != NULL) w->HandleWindowEvent(&e);
- }
+ Window *w = FindWindowById(WC_MAIN_TOOLBAR, 0);
+ /* When there is no toolbar w is null, check for that */
+ if (w != NULL) w->OnKeyPress(key, keycode);
}
/**
@@ -1781,16 +1874,10 @@
*/
void HandleCtrlChanged()
{
- WindowEvent e;
-
- e.event = WE_CTRL_CHANGED;
- e.we.ctrl.cont = true;
-
/* Call the event, start with the uppermost window. */
for (Window* const *wz = _last_z_window; wz != _z_windows;) {
Window *w = *--wz;
- w->HandleWindowEvent(&e);
- if (!e.we.ctrl.cont) break;
+ if (!w->OnCTRLStateChange()) break;
}
}
@@ -1828,14 +1915,14 @@
/* here allows scrolling in both x and y axis */
#define scrollspeed 3
if (x - 15 < 0) {
- WP(w, vp_d).dest_scrollpos_x += ScaleByZoom((x - 15) * scrollspeed, vp->zoom);
+ w->viewport->dest_scrollpos_x += ScaleByZoom((x - 15) * scrollspeed, vp->zoom);
} else if (15 - (vp->width - x) > 0) {
- WP(w, vp_d).dest_scrollpos_x += ScaleByZoom((15 - (vp->width - x)) * scrollspeed, vp->zoom);
+ w->viewport->dest_scrollpos_x += ScaleByZoom((15 - (vp->width - x)) * scrollspeed, vp->zoom);
}
if (y - 15 < 0) {
- WP(w, vp_d).dest_scrollpos_y += ScaleByZoom((y - 15) * scrollspeed, vp->zoom);
+ w->viewport->dest_scrollpos_y += ScaleByZoom((y - 15) * scrollspeed, vp->zoom);
} else if (15 - (vp->height - y) > 0) {
- WP(w, vp_d).dest_scrollpos_y += ScaleByZoom((15 - (vp->height - y)) * scrollspeed, vp->zoom);
+ w->viewport->dest_scrollpos_y += ScaleByZoom((15 - (vp->height - y)) * scrollspeed, vp->zoom);
}
#undef scrollspeed
}
@@ -1862,7 +1949,6 @@
UpdateTileSelection();
if (!VpHandlePlaceSizingDrag()) return;
if (!HandleDragDrop()) return;
- if (!HandlePopupMenu()) return;
if (!HandleWindowDragging()) return;
if (!HandleScrollbarScrolling()) return;
if (!HandleViewportScroll()) return;
@@ -1884,13 +1970,8 @@
if (mousewheel != 0) {
if (_patches.scrollwheel_scrolling == 0) {
- /* Scrollwheel is in zoom mode. Make the zoom event. */
- WindowEvent e;
-
/* Send WE_MOUSEWHEEL event to window */
- e.event = WE_MOUSEWHEEL;
- e.we.wheel.wheel = mousewheel;
- w->HandleWindowEvent(&e);
+ w->OnMouseWheel(mousewheel);
}
/* Dispatch a MouseWheelEvent for widgets if it is not a viewport */
@@ -1931,9 +2012,14 @@
}
} else {
switch (click) {
- case MC_DOUBLE_LEFT: DispatchLeftClickEvent(w, x - w->left, y - w->top, true);
- /* fallthough, and also give a single-click for backwards compatible */
- case MC_LEFT: DispatchLeftClickEvent(w, x - w->left, y - w->top, false); break;
+ case MC_DOUBLE_LEFT:
+ DispatchLeftClickEvent(w, x - w->left, y - w->top, true);
+ if (_mouseover_last_w == NULL) break; // The window got removed.
+ /* fallthough, and also give a single-click for backwards compatibility */
+ case MC_LEFT:
+ DispatchLeftClickEvent(w, x - w->left, y - w->top, false);
+ break;
+
default:
if (!scrollwheel_scrolling || w == NULL || w->window_class != WC_SMALLMAP) break;
/* We try to use the scrollwheel to scroll since we didn't touch any of the buttons.
@@ -2014,7 +2100,7 @@
if (t >= 100) {
for (wz = _last_z_window; wz != _z_windows;) {
- CallWindowEventNP(*--wz, WE_4);
+ (*--wz)->OnHundredthTick();
}
t = 0;
}
@@ -2039,27 +2125,6 @@
DrawMouseCursor();
}
-
-/**
- * In a window with menu_d custom extension, retrieve the menu item number from a position
- * @param w Window holding the menu items
- * @param x X coordinate of the position
- * @param y Y coordinate of the position
- * @return Index number of the menu item, or \c -1 if no valid selection under position
- */
-int GetMenuItemIndex(const Window *w, int x, int y)
-{
- if ((x -= w->left) >= 0 && x < w->width && (y -= w->top + 1) >= 0) {
- y /= 10;
-
- if (y < WP(w, const menu_d).item_count &&
- !HasBit(WP(w, const menu_d).disabled_items, y)) {
- return y;
- }
- }
- return -1;
-}
-
/**
* Mark window as dirty (in need of repainting)
* @param cls Window class
@@ -2110,9 +2175,9 @@
* Mark window data as invalid (in need of re-computing)
* @param w Window with invalid data
*/
-void InvalidateThisWindowData(Window *w)
+void InvalidateThisWindowData(Window *w, int data)
{
- CallWindowEventNP(w, WE_INVALIDATE_DATA);
+ w->OnInvalidateData(data);
w->SetDirty();
}
@@ -2121,13 +2186,13 @@
* @param cls Window class
* @param number Window number within the class
*/
-void InvalidateWindowData(WindowClass cls, WindowNumber number)
+void InvalidateWindowData(WindowClass cls, WindowNumber number, int data)
{
Window* const *wz;
FOR_ALL_WINDOWS(wz) {
Window *w = *wz;
- if (w->window_class == cls && w->window_number == number) InvalidateThisWindowData(w);
+ if (w->window_class == cls && w->window_number == number) InvalidateThisWindowData(w, data);
}
}
@@ -2135,12 +2200,12 @@
* Mark window data of all windows of a given class as invalid (in need of re-computing)
* @param cls Window class
*/
-void InvalidateWindowClassesData(WindowClass cls)
+void InvalidateWindowClassesData(WindowClass cls, int data)
{
Window* const *wz;
FOR_ALL_WINDOWS(wz) {
- if ((*wz)->window_class == cls) InvalidateThisWindowData(*wz);
+ if ((*wz)->window_class == cls) InvalidateThisWindowData(*wz, data);
}
}
@@ -2150,7 +2215,7 @@
void CallWindowTickEvent()
{
for (Window * const *wz = _last_z_window; wz != _z_windows;) {
- CallWindowEventNP(*--wz, WE_TICK);
+ (*--wz)->OnTick();
}
}
@@ -2267,13 +2332,13 @@
if (neww - w->width != 0) {
ResizeWindow(w, min(neww, 640) - w->width, 0);
- WindowEvent e;
- e.event = WE_RESIZE;
- e.we.sizing.size.x = w->width;
- e.we.sizing.size.y = w->height;
- e.we.sizing.diff.x = neww - w->width;
- e.we.sizing.diff.y = 0;
- w->HandleWindowEvent(&e);
+ Point size;
+ Point delta;
+ size.x = w->width;
+ size.y = w->height;
+ delta.x = neww - w->width;
+ delta.y = 0;
+ w->OnResize(size, delta);
}
top = w->top;
--- a/src/window_func.h Wed May 07 21:09:51 2008 +0000
+++ b/src/window_func.h Sun May 11 20:09:34 2008 +0000
@@ -9,8 +9,6 @@
#include "player_type.h"
void SetWindowDirty(const Window *w);
-void SendWindowMessage(WindowClass wnd_class, WindowNumber wnd_num, int msg, int wparam, int lparam);
-void SendWindowMessageClass(WindowClass wnd_class, int msg, int wparam, int lparam);
Window *FindWindowById(WindowClass cls, WindowNumber number);
void ChangeWindowOwner(PlayerID old_player, PlayerID new_player);
@@ -23,18 +21,20 @@
void ResetWindowSystem();
void SetupColorsAndInitialWindow();
void InputLoop();
-void InvalidateThisWindowData(Window *w);
-void InvalidateWindowData(WindowClass cls, WindowNumber number);
+
+void InvalidateThisWindowData(Window *w, int data = 0);
+void InvalidateWindowData(WindowClass cls, WindowNumber number, int data = 0);
+void InvalidateWindowClassesData(WindowClass cls, int data = 0);
void DeleteNonVitalWindows();
void DeleteAllNonVitalWindows();
void HideVitalWindows();
void ShowVitalWindows();
-void InvalidateWindow(WindowClass cls, WindowNumber number);
void InvalidateWindowWidget(WindowClass cls, WindowNumber number, byte widget_index);
+void InvalidateWindow(WindowClass cls, WindowNumber number);
void InvalidateWindowClasses(WindowClass cls);
-void InvalidateWindowClassesData(WindowClass cls);
+
void DeleteWindowById(WindowClass cls, WindowNumber number);
void DeleteWindowByClass(WindowClass cls);
--- a/src/window_gui.h Wed May 07 21:09:51 2008 +0000
+++ b/src/window_gui.h Sun May 11 20:09:34 2008 +0000
@@ -117,24 +117,20 @@
WE_DOUBLE_CLICK, ///< Left mouse button double click
WE_RCLICK, ///< Right mouse button click
WE_MOUSEOVER,
- WE_MOUSELOOP,
WE_MOUSEWHEEL,
- WE_TICK, ///< Regularly occurring event (about once every 20 seconds orso, 10 days) for slowly changing content (typically list sorting)
- WE_4, ///< Regularly occurring event for updating continuously changing window content (other than view ports), or timer expiring
+ WE_MOUSELOOP, ///< Event for each mouse event in the game (at least once every game tick)
+ WE_TICK, ///< Regularly occurring event (every game tick)
+ WE_100_TICKS, ///< Regularly occurring event (every 100 game ticks, approximatelly 3 seconds)
WE_TIMEOUT,
WE_PLACE_OBJ,
WE_ABORT_PLACE_OBJ,
WE_ON_EDIT_TEXT,
- WE_ON_EDIT_TEXT_CANCEL,
- WE_POPUPMENU_SELECT,
- WE_POPUPMENU_OVER,
WE_DRAGDROP,
WE_PLACE_DRAG,
WE_PLACE_MOUSEUP,
WE_PLACE_PRESIZE,
WE_DROPDOWN_SELECT,
WE_RESIZE, ///< Request to resize the window, @see WindowEvent.we.resize
- WE_MESSAGE, ///< Receipt of a message from another window. @see WindowEvent.we.message, SendWindowMessage(), SendWindowMessageClass()
WE_SCROLL,
WE_INVALIDATE_DATA, ///< Notification that data displayed by the window is obsolete
WE_CTRL_CHANGED, ///< CTRL key has changed state
@@ -179,10 +175,6 @@
} edittext;
struct {
- Point pt;
- } popupmenu;
-
- struct {
int button;
int index;
} dropdown;
@@ -199,10 +191,8 @@
} keypress;
struct {
- int msg; ///< message to be sent
- int wparam; ///< additional message-specific information
- int lparam; ///< additional message-specific information
- } message;
+ int data;
+ } invalidate;
struct {
Point delta; ///< delta position against position of last call
@@ -281,24 +271,34 @@
};
/**
- * Message data structure for messages sent between winodows
- * @see SendWindowMessageW()
+ * Data structure for a window viewport
*/
-struct WindowMessage {
- int msg;
- int wparam;
- int lparam;
+struct ViewportData : ViewPort {
+ VehicleID follow_vehicle;
+ int32 scrollpos_x;
+ int32 scrollpos_y;
+ int32 dest_scrollpos_x;
+ int32 dest_scrollpos_y;
};
-/**
+ /**
* Data structure for an opened window
*/
struct Window : ZeroedMemoryAllocator {
private:
WindowProc *wndproc; ///< Event handler function for the window. Do not use directly, call HandleWindowEvent() instead.
+ void HandleWindowEvent(WindowEvent *e);
+
+protected:
+ void Initialize(int x, int y, int min_width, int min_height,
+ WindowProc *proc, WindowClass cls, const Widget *widget, int window_number, void *data);
+ void FindWindowPlacementAndResize(int def_width, int def_height);
+ void FindWindowPlacementAndResize(const WindowDesc *desc);
public:
- Window(WindowProc *proc) : wndproc(proc) {}
+ Window(int x, int y, int width, int height, WindowProc *proc, WindowClass cls, const Widget *widget, void *data = NULL);
+ Window(const WindowDesc *desc, void *data = NULL, WindowNumber number = 0);
+
virtual ~Window();
uint16 flags4; ///< Window flags, @see WindowFlags
@@ -317,13 +317,12 @@
byte caption_color; ///< Background color of the window caption, contains PlayerID
- ViewPort *viewport; ///< Pointer to viewport, if present
+ ViewportData *viewport; ///< Pointer to viewport data, if present
const Widget *original_widget; ///< Original widget layout, copied from WindowDesc
Widget *widget; ///< Widgets of the window
uint widget_count; ///< Number of widgets of the window
uint32 desc_flags; ///< Window/widgets default flags setting, @see WindowDefaultFlag
- WindowMessage message; ///< Buffer for storing received messages (for communication between different window events)
Window *parent; ///< Parent window
byte custom[WINDOW_CUSTOM_SIZE]; ///< Additional data depending on window type
@@ -351,7 +350,173 @@
void SetDirty() const;
- virtual void HandleWindowEvent(WindowEvent *e);
+ /*** Event handling ***/
+
+ /**
+ * This window is currently being repainted.
+ */
+ virtual void OnPaint();
+
+
+ /**
+ * A key has been pressed.
+ * @param key the Unicode value of the key.
+ * @param keycode the untranslated key code including shift state.
+ * @return true if the key press has been handled and no other
+ * window should receive the event.
+ */
+ virtual bool OnKeyPress(uint16 key, uint16 keycode);
+
+ /**
+ * The state of the control key has changed
+ * @return true if the change has been handled and no other
+ * window should receive the event.
+ */
+ virtual bool OnCTRLStateChange();
+
+
+ /**
+ * A click with the left mouse button has been made on the window.
+ * @param pt the point inside the window that has been clicked.
+ * @param widget the clicked widget.
+ */
+ virtual void OnClick(Point pt, int widget);
+
+ /**
+ * A double click with the left mouse button has been made on the window.
+ * @param pt the point inside the window that has been clicked.
+ * @param widget the clicked widget.
+ */
+ virtual void OnDoubleClick(Point pt, int widget);
+
+ /**
+ * A click with the right mouse button has been made on the window.
+ * @param pt the point inside the window that has been clicked.
+ * @param widget the clicked widget.
+ */
+ virtual void OnRightClick(Point pt, int widget);
+
+ /**
+ * A dragged 'object' has been released.
+ * @param pt the point inside the window where the release took place.
+ * @param widget the widget where the release took place.
+ */
+ virtual void OnDragDrop(Point pt, int widget);
+
+ /**
+ * Handle the request for (viewport) scrolling.
+ * @param delta the amount the viewport must be scrolled.
+ */
+ virtual void OnScroll(Point delta);
+
+ /**
+ * The mouse is currently moving over the window or has just moved outside
+ * of the window. In the latter case pt is (-1, -1).
+ * @param pt the point inside the window that the mouse hovers over.
+ * @param widget the widget the mouse hovers over.
+ */
+ virtual void OnMouseOver(Point pt, int widget);
+
+ /**
+ * The mouse wheel has been turned.
+ * @param wheel the amount of movement of the mouse wheel.
+ */
+ virtual void OnMouseWheel(int wheel);
+
+
+ /**
+ * Called for every mouse loop run, which is at least once per (game) tick.
+ */
+ virtual void OnMouseLoop();
+
+ /**
+ * Called once per (game) tick.
+ */
+ virtual void OnTick();
+
+ /**
+ * Called once every 100 (game) ticks.
+ */
+ virtual void OnHundredthTick();
+
+ /**
+ * Called when this window's timeout has been reached.
+ */
+ virtual void OnTimeout();
+
+
+ /**
+ * Called when the window got resized.
+ * @param new_size the new size of the window.
+ * @param delta the amount of which the window size changed.
+ */
+ virtual void OnResize(Point new_size, Point delta);
+
+ /**
+ * A dropdown option associated to this window has been selected.
+ * @param widget the widget (button) that the dropdown is associated with.
+ * @param index the element in the dropdown that is selected.
+ */
+ virtual void OnDropdownSelect(int widget, int index);
+
+ /**
+ * The query window opened from this window has closed.
+ * @param str the new value of the string or NULL if the window
+ * was cancelled.
+ */
+ virtual void OnQueryTextFinished(char *str);
+
+ /**
+ * Some data on this window has become invalid.
+ * @param data information about the changed data.
+ */
+ virtual void OnInvalidateData(int data = 0);
+
+
+ /**
+ * The user clicked some place on the map when a tile highlight mode
+ * has been set.
+ * @param pt the exact point on the map that has been clicked.
+ * @param tile the tile on the map that has been clicked.
+ */
+ virtual void OnPlaceObject(Point pt, TileIndex tile);
+
+ /**
+ * The user cancelled a tile highlight mode that has been set.
+ */
+ virtual void OnPlaceObjectAbort();
+
+
+ /**
+ * The user is dragging over the map when the tile highlight mode
+ * has been set.
+ * @param select_method the method of selection (allowed directions)
+ * @param select_proc what will be created when the drag is over.
+ * @param pt the exact point on the map where the mouse is.
+ */
+ virtual void OnPlaceDrag(ViewportPlaceMethod select_method, byte select_proc, Point pt);
+
+ /**
+ * The user has dragged over the map when the tile highlight mode
+ * has been set.
+ * @param select_method the method of selection (allowed directions)
+ * @param select_proc what should be created.
+ * @param pt the exact point on the map where the mouse was released.
+ * @param start_tile the begin tile of the drag.
+ * @param end_tile the end tile of the drag.
+ */
+ virtual void OnPlaceMouseUp(ViewportPlaceMethod select_method, byte select_proc, Point pt, TileIndex start_tile, TileIndex end_tile);
+
+ /**
+ * The user moves over the map when a tile highlight mode has been set
+ * when the special mouse mode has been set to 'PRESIZE' mode. An
+ * example of this is the tile highlight for dock building.
+ * @param pt the exact point on the map where the mouse is.
+ * @param tile the tile on the map where the mouse is.
+ */
+ virtual void OnPlacePresize(Point pt, TileIndex tile);
+
+ /*** End of the event handling ***/
};
struct menu_d {
@@ -373,71 +538,6 @@
};
assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(def_d));
-struct void_d {
- void *data;
-};
-assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(void_d));
-
-struct tree_d {
- uint16 base;
- uint16 count;
-};
-assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(tree_d));
-
-struct tooltips_d {
- StringID string_id;
- byte paramcount;
- uint64 params[5];
-};
-assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(tooltips_d));
-
-struct depot_d {
- VehicleID sel;
- VehicleType type;
- bool generate_list;
- uint16 engine_list_length;
- uint16 wagon_list_length;
- uint16 engine_count;
- uint16 wagon_count;
- Vehicle **vehicle_list;
- Vehicle **wagon_list;
-};
-assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(depot_d));
-
-struct vehicledetails_d {
- byte tab;
-};
-assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(vehicledetails_d));
-
-struct smallmap_d {
- int32 scroll_x;
- int32 scroll_y;
- int32 subscroll;
-};
-assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(smallmap_d));
-
-struct vp_d {
- VehicleID follow_vehicle;
- int32 scrollpos_x;
- int32 scrollpos_y;
- int32 dest_scrollpos_x;
- int32 dest_scrollpos_y;
- ViewPort vp_data; ///< Screen position and zoom of the viewport
-};
-assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(vp_d));
-
-struct highscore_d {
- uint32 background_img;
- int8 rank;
-};
-assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(highscore_d));
-
-struct scroller_d {
- int height;
- uint16 counter;
-};
-assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(scroller_d));
-
enum SortListFlags {
VL_NONE = 0, ///< no sort
VL_DESC = 1 << 0, ///< sort descending or ascending
@@ -445,7 +545,6 @@
VL_REBUILD = 1 << 2, ///< create sort-listing to use for qsort and friends
VL_END = 1 << 3,
};
-
DECLARE_ENUM_AS_BIT_SET(SortListFlags);
struct Listing {
@@ -453,29 +552,14 @@
byte criteria; ///< Sorting criteria
};
-struct list_d {
+template <typename T>
+struct GUIList {
+ T* sort_list; ///< The items to sort.
+ SortListFlags flags; ///< used to control sorting/resorting/etc.
uint16 list_length; ///< length of the list being sorted
+ uint16 resort_timer; ///< resort list after a given amount of ticks if set
byte sort_type; ///< what criteria to sort on
- SortListFlags flags; ///< used to control sorting/resorting/etc.
- uint16 resort_timer; ///< resort list after a given amount of ticks if set
};
-assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(list_d));
-
-struct message_d {
- int msg;
- int wparam;
- int lparam;
-};
-assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(message_d));
-
-struct vehiclelist_d {
- const Vehicle** sort_list; // List of vehicles (sorted)
- Listing *_sorting; // pointer to the appropiate subcategory of _sorting
- uint16 length_of_sort_list; // Keeps track of how many vehicle pointers sort list got space for
- VehicleType vehicle_type; // The vehicle type that is sorted
- list_d l; // General list struct
-};
-assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(vehiclelist_d));
/****************** THESE ARE NOT WIDGET TYPES!!!!! *******************/
enum WindowWidgetBehaviours {
@@ -545,25 +629,27 @@
WF_SCROLL2 = 1 << 13,
};
-/* window.cpp */
-void CallWindowEventNP(Window *w, int event);
-void CallWindowTickEvent();
-
Window *BringWindowToFrontById(WindowClass cls, WindowNumber number);
Window *FindWindowFromPt(int x, int y);
bool IsWindowOfPrototype(const Window *w, const Widget *widget);
-void AssignWidgetToWindow(Window *w, const Widget *widget);
-Window *AllocateWindow(int x, int y, int width, int height,
- WindowProc *proc, WindowClass cls, const Widget *widget,
- void *data = NULL);
-Window *AllocateWindowDesc(const WindowDesc *desc, void *data = NULL);
-Window *AllocateWindowDescFront(const WindowDesc *desc, int window_number, void *data = NULL);
+/**
+ * Open a new window.
+ * @param *desc The pointer to the WindowDesc to be created
+ * @param window_number the window number of the new window
+ * @param data arbitrary data that is send with the WE_CREATE message
+ * @return see Window pointer of the newly created window
+ */
+template <typename Wcls>
+Wcls *AllocateWindowDescFront(const WindowDesc *desc, int window_number, void *data = NULL)
+{
+ if (BringWindowToFrontById(desc->cls, window_number)) return NULL;
+ return new Wcls(desc, data, window_number);
+}
void DrawWindowViewport(const Window *w);
-int GetMenuItemIndex(const Window *w, int x, int y);
void RelocateAllWindows(int neww, int newh);
/* misc_gui.cpp */
@@ -600,7 +686,6 @@
extern bool _scrolling_scrollbar;
extern bool _scrolling_viewport;
-extern bool _popup_menu_active;
extern byte _special_mouse_mode;
enum SpecialMouseMode {