diff --git a/src/command.cpp b/src/command.cpp index 2891a06af6..9b965faab3 100644 --- a/src/command.cpp +++ b/src/command.cpp @@ -26,6 +26,7 @@ #include "signal_func.h" #include "core/backup_type.hpp" #include "object_base.h" +#include "string_func.h" #include "table/strings.h" @@ -525,6 +526,79 @@ bool DoCommandP(const CommandContainer *container, bool my_cmd) return DoCommandP(container->tile, container->p1, container->p2, container->cmd, container->callback, container->text, my_cmd); } +/* Stored data for a command that is waiting for user confirmation. */ +bool _is_queued_command; +bool _my_cmd; +CommandContainer _queued_command; + +/** + * Store a command that needs user confirmation. + * If current mode doesn't need confirmation, execute it immediately via DoCommandP. + * @param tile The tile to perform a command on (see #CommandProc) + * @param p1 Additional data for the command (see #CommandProc) + * @param p2 Additional data for the command (see #CommandProc) + * @param cmd The command to execute (a CMD_* value) + * @param callback A callback function to call after the command is finished + * @param text The text to pass + * @param my_cmd indicator if the command is from a company or server (to display error messages for a user) + * @return \c true if the command succeeded or is stored, else \c false. + */ +bool TouchCommandP(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, CommandCallback *callback, const char *text, bool my_cmd) +{ + if (_settings_client.gui.touchscreen_mode == TSC_CONFIRM && !_shift_pressed) { + _queued_command.tile = tile; + _queued_command.p1 = p1; + _queued_command.p2 = p2; + _queued_command.cmd = cmd; + _queued_command.callback = callback; + if (text != NULL) ttd_strlcpy(_queued_command.text, text, 32 * MAX_CHAR_LENGTH); + _my_cmd = my_cmd; + _is_queued_command = true; + extern void UpdateTouchscreenBar(); + UpdateTouchscreenBar(); + return true; + } else { + return DoCommandP(tile, p1, p2, cmd, callback, text, my_cmd); + } +} + +/** + * Shortcut for the long TouchCommandP when having a container with the data. + * Store a command that needs user confirmation. + * If current mode doesn't need confirmation, execute it immediately via DoCommandP. + * @param container the container with information. + * @param my_cmd indicator if the command is from a company or server (to display error messages for a user) + * @return true if the command succeeded or when it is stored, else false + */ +bool TouchCommandP(const CommandContainer *container, bool my_cmd) +{ + return TouchCommandP(container->tile, container->p1, container->p2, container->cmd, container->callback, container->text, my_cmd); +} + +/** Return whether there is a command stored waiting for confirmation. */ +bool IsQueuedTouchCommand() +{ + return _is_queued_command; +} + +/** Execute a stored command. Keep it when asking for estimated cost. */ +bool DoQueuedTouchCommand() +{ + bool result = DoCommandP(&_queued_command, _my_cmd); + if (!_shift_pressed && result) EraseQueuedTouchCommand(); + return result; +} + +/** Erase a stored command and update viewport and touchscreen bar. */ +void EraseQueuedTouchCommand() +{ + if (!IsQueuedTouchCommand()) return; + _is_queued_command = false; + extern void UpdateTouchscreenBar(); + UpdateTouchscreenBar(); + //reset selection of tiles +} + /*! * Toplevel network safe docommand function for the current company. Must not be called recursively. * The callback is called when the command succeeded or failed. The parameters diff --git a/src/command_func.h b/src/command_func.h index c4cc51e3da..ab9fb05d42 100644 --- a/src/command_func.h +++ b/src/command_func.h @@ -40,6 +40,12 @@ CommandCost DoCommand(const CommandContainer *container, DoCommandFlag flags); bool DoCommandP(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, CommandCallback *callback = NULL, const char *text = NULL, bool my_cmd = true); bool DoCommandP(const CommandContainer *container, bool my_cmd = true); +bool TouchCommandP(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, CommandCallback *callback = NULL, const char *text = NULL, bool my_cmd = true); +bool TouchCommandP(const CommandContainer *container, bool my_cmd = true); +bool IsQueuedTouchCommand(); +bool DoQueuedTouchCommand(); +void EraseQueuedTouchCommand(); + CommandCost DoCommandPInternal(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, CommandCallback *callback, const char *text, bool my_cmd, bool estimate_only); #ifdef ENABLE_NETWORK diff --git a/src/lang/english.txt b/src/lang/english.txt index 3a875fc014..ad4759305a 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -1188,6 +1188,7 @@ STR_CONFIG_SETTING_TOUCHSCREEN_MODE :Control mode fo STR_CONFIG_SETTING_TOUCHSCREEN_MODE_HELPTEXT :If playing with a mouse, choose no adaptation. Other modes are for touchscreen devices. Associated hotkey: N STR_CONFIG_SETTING_TOUCHSCREEN_NONE :no adaptation STR_CONFIG_SETTING_TOUCHSCREEN_SIMPLE :simple +STR_CONFIG_SETTING_TOUCHSCREEN_CONFIRM :confirm STR_CONFIG_SETTING_SHOWFINANCES :Show finances window at the end of the year: {STRING2} STR_CONFIG_SETTING_SHOWFINANCES_HELPTEXT :If enabled, the finances window pops up at the end of each year to allow easy inspection of the financial status of the company STR_CONFIG_SETTING_NONSTOP_BY_DEFAULT :New orders are 'non-stop' by default: {STRING2} @@ -2455,6 +2456,8 @@ STR_TABLET_CTRL :{BLACK}Ctrl STR_TABLET_CTRL_TOOLTIP :{BLACK}Use it for actions that use the "CTRL" key STR_TABLET_MOVE :{BLACK}Move STR_TABLET_MOVE_TOOLTIP :{BLACK}Press it to move around viewports. No action will be executed on viewports while this is active +STR_TABLET_CONFIRM :{BLACK}Do +STR_TABLET_CONFIRM_TOOLTIP :{BLACK}Press it to confirm an action # Object construction window STR_OBJECT_BUILD_CAPTION :{WHITE}Object Selection diff --git a/src/script/api/script_window.hpp b/src/script/api/script_window.hpp index 2fde7166dc..62570aa6fa 100644 --- a/src/script/api/script_window.hpp +++ b/src/script/api/script_window.hpp @@ -2412,6 +2412,7 @@ public: WID_TT_SHIFT = ::WID_TT_SHIFT, ///< Press SHIFT. WID_TT_CTRL = ::WID_TT_CTRL, ///< Press CTRL. WID_TT_MOVE = ::WID_TT_MOVE, ///< Click for moving around viewports. + WID_TT_CONFIRM = ::WID_TT_CONFIRM, ///< Confirm action. }; /* automatically generated from ../../widgets/town_widget.h */ diff --git a/src/table/settings.ini b/src/table/settings.ini index f3cca6dd2b..c742c0f657 100644 --- a/src/table/settings.ini +++ b/src/table/settings.ini @@ -2504,7 +2504,7 @@ type = SLE_UINT8 guiflags = SGF_MULTISTRING def = 0 min = 0 -max = 1 +max = 2 interval = 1 str = STR_CONFIG_SETTING_TOUCHSCREEN_MODE strval = STR_CONFIG_SETTING_TOUCHSCREEN_NONE diff --git a/src/toolbar_gui.cpp b/src/toolbar_gui.cpp index 74ff152444..20f66d98a4 100644 --- a/src/toolbar_gui.cpp +++ b/src/toolbar_gui.cpp @@ -2265,6 +2265,9 @@ struct TabletToolbar : Window { this->ToggleWidgetLoweredState(WID_TT_MOVE); this->SetWidgetDirty(WID_TT_MOVE); break; + case WID_TT_CONFIRM: + DoQueuedTouchCommand(); + break; default: NOT_REACHED(); } @@ -2283,7 +2286,10 @@ struct TabletToolbar : Window { if (HasBit(data, 2)) { UpdateTileSelection(); } /* This window is dirty. */ - if (HasBit(data, 3)) { this->SetDirty(); } + if (HasBit(data, 3)) { + SetWidgetDisabledState(WID_TT_CONFIRM, !IsQueuedTouchCommand()); + this->SetWidgetDirty(WID_TT_CONFIRM); + } } }; @@ -2297,6 +2303,17 @@ static const NWidgetPart _nested_tablet_simple_widgets[] = { EndContainer(), }; +static const NWidgetPart _nested_tablet_confirm_widgets[] = { + NWidget(NWID_VERTICAL), + NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_TT_X), SetDataTip(STR_TABLET_X, STR_TABLET_TOGGLE_TRANSPARENCY_TOOLTIP), + NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_TT_DELETE), SetDataTip(STR_TABLET_CLOSE, STR_TABLET_CLOSE_TOOLTIP), + NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_TT_SHIFT), SetDataTip(STR_TABLET_SHIFT, STR_TABLET_SHIFT_TOOLTIP), + NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_TT_CTRL), SetDataTip(STR_TABLET_CTRL, STR_TABLET_CTRL_TOOLTIP), + NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_TT_MOVE), SetDataTip(STR_TABLET_MOVE, STR_TABLET_MOVE_TOOLTIP), + NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_TT_CONFIRM), SetDataTip(STR_TABLET_CONFIRM, STR_TABLET_CONFIRM_TOOLTIP), + EndContainer(), +}; + static WindowDesc _toolbar_tablet_simple_desc( WDP_AUTO, NULL, 0, 0, WC_TABLET_BAR, WC_NONE, @@ -2304,11 +2321,19 @@ static WindowDesc _toolbar_tablet_simple_desc( _nested_tablet_simple_widgets, lengthof(_nested_tablet_simple_widgets) ); +static WindowDesc _toolbar_tablet_confirm_desc( + WDP_AUTO, NULL, 0, 0, + WC_TABLET_BAR, WC_NONE, + WDF_NO_FOCUS, + _nested_tablet_confirm_widgets, lengthof(_nested_tablet_confirm_widgets) +); + void ResetTabletWindow() { if (_game_mode == GM_MENU) return; DeleteWindowByClass(WC_TABLET_BAR); + EraseQueuedTouchCommand(); switch (_settings_client.gui.touchscreen_mode) { case TSC_NONE: @@ -2316,9 +2341,14 @@ void ResetTabletWindow() case TSC_SIMPLE: new TabletToolbar(&_toolbar_tablet_simple_desc); break; + case TSC_CONFIRM: + new TabletToolbar(&_toolbar_tablet_confirm_desc); + InvalidateWindowData(WC_TABLET_BAR, 0, 1 << 3); + break; default: NOT_REACHED(); - } + + MarkWholeScreenDirty(); } /** Allocate the toolbar. */ @@ -2335,3 +2365,8 @@ void AllocateToolbar() ResetTabletWindow(); } + +void UpdateTouchscreenBar() +{ + InvalidateWindowData(WC_TABLET_BAR, 0, 1 << 3); +} diff --git a/src/toolbar_type.h b/src/toolbar_type.h index cfde179dcc..682cf2f568 100644 --- a/src/toolbar_type.h +++ b/src/toolbar_type.h @@ -16,8 +16,9 @@ enum TouchscreenMode { TSC_NONE = 0, TSC_SIMPLE, + TSC_CONFIRM, }; -DECLARE_CYCLE(TouchscreenMode, TSC_NONE, TSC_SIMPLE) +DECLARE_CYCLE(TouchscreenMode, TSC_NONE, TSC_CONFIRM) typedef SimpleTinyEnumT TouchscreenModeByte; #endif /* TOOLBAR_TYPE_H */ diff --git a/src/widgets/toolbar_widget.h b/src/widgets/toolbar_widget.h index c7bac73b39..4399b5d10c 100644 --- a/src/widgets/toolbar_widget.h +++ b/src/widgets/toolbar_widget.h @@ -82,6 +82,7 @@ enum ToolbarTabletWidgets { WID_TT_SHIFT, ///< Press SHIFT. WID_TT_CTRL, ///< Press CTRL. WID_TT_MOVE, ///< Click for moving around viewports. + WID_TT_CONFIRM, ///< Confirm action. }; #endif /* WIDGETS_TOOLBAR_WIDGET_H */