From 08f9a4003989659ee577bddc4b301af2de0e3478 Mon Sep 17 00:00:00 2001 From: Reinder Feenstra Date: Thu, 25 Apr 2024 00:14:08 +0200 Subject: [PATCH] board: added label tile --- client/src/board/boardareawidget.cpp | 26 +++++++- client/src/board/tilepainter.cpp | 31 ++++++++- client/src/board/tilepainter.hpp | 5 +- client/src/enum/textalign.hpp | 66 +++++++++++++++++++ client/src/utils/enum.cpp | 2 + server/src/board/tile/misc/labeltile.cpp | 48 ++++++++++++++ server/src/board/tile/misc/labeltile.hpp | 45 +++++++++++++ server/src/board/tile/tiles.cpp | 6 +- shared/src/traintastic/board/tileid.hpp | 4 +- shared/src/traintastic/enum/textalign.hpp | 77 +++++++++++++++++++++++ shared/translations/en-us.json | 66 ++++++++++++++++++- 11 files changed, 370 insertions(+), 6 deletions(-) create mode 100644 client/src/enum/textalign.hpp create mode 100644 server/src/board/tile/misc/labeltile.cpp create mode 100644 server/src/board/tile/misc/labeltile.hpp create mode 100644 shared/src/traintastic/enum/textalign.hpp diff --git a/client/src/board/boardareawidget.cpp b/client/src/board/boardareawidget.cpp index 1a251e78..9b0c3d0c 100644 --- a/client/src/board/boardareawidget.cpp +++ b/client/src/board/boardareawidget.cpp @@ -3,7 +3,7 @@ * * This file is part of the traintastic source code. * - * Copyright (C) 2020-2023 Reinder Feenstra + * Copyright (C) 2020-2024 Reinder Feenstra * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -30,6 +30,7 @@ #include "getboardcolorscheme.hpp" #include "tilepainter.hpp" #include "../network/board.hpp" +#include "../network/object.tpp" #include "../network/object/blockrailtile.hpp" #include "../network/object/nxbuttonrailtile.hpp" #include "../network/abstractproperty.hpp" @@ -184,6 +185,13 @@ void BoardAreaWidget::tileObjectAdded(int16_t x, int16_t y, const ObjectPtr& obj case TileId::RailLink: case TileId::ReservedForFutureExpension: break; + + case TileId::Label: + tryConnect("background_color"); + tryConnect("text"); + tryConnect("text_align"); + tryConnect("text_color"); + break; } } @@ -598,6 +606,22 @@ void BoardAreaWidget::paintEvent(QPaintEvent* event) tilePainter.drawRailNX(r, a, isReserved, getNXButtonEnabled(it.first), getNXButtonPressed(it.first)); break; + case TileId::Label: + { + if(auto label = m_board.board().getTileObject(it.first)) /*[[likely]]*/ + { + tilePainter.drawLabel(r, a, + label->getPropertyValueString("text"), + label->getPropertyValueEnum("text_align", TextAlign::Center), + label->getPropertyValueEnum("text_color", Color::None), + label->getPropertyValueEnum("background_color", Color::None)); + } + else + { + tilePainter.drawLabel(r, a); + } + break; + } case TileId::None: case TileId::ReservedForFutureExpension: default: diff --git a/client/src/board/tilepainter.cpp b/client/src/board/tilepainter.cpp index cebe22b6..f3491b7d 100644 --- a/client/src/board/tilepainter.cpp +++ b/client/src/board/tilepainter.cpp @@ -3,7 +3,7 @@ * * This file is part of the traintastic source code. * - * Copyright (C) 2020-2023 Reinder Feenstra + * Copyright (C) 2020-2024 Reinder Feenstra * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -168,6 +168,10 @@ void TilePainter::draw(TileId id, const QRectF& r, TileRotate rotate, bool isRes drawRailNX(r, rotate, isReserved); break; + case TileId::Label: + drawLabel(r, rotate); + break; + case TileId::None: case TileId::ReservedForFutureExpension: break; @@ -1295,3 +1299,28 @@ void TilePainter::drawRailNX(const QRectF& r, TileRotate rotate, bool isReserved drawStraight(r, rotate); drawPushButton(r, pressed ? Color::White : (isEnabled ? Color::Blue : Color::Gray)); } + +void TilePainter::drawLabel(const QRectF& r, TileRotate rotate, const QString& text, TextAlign textAlign, Color textColor, Color backgroundColor) +{ + m_painter.save(); + + m_painter.setPen(Qt::NoPen); + m_painter.setBrush(backgroundColor == Color::None ? m_colorScheme.background : toQColor(backgroundColor)); + m_painter.drawRect(r.adjusted(1, 1, -1, -1)); + + if(!text.isEmpty()) + { + m_painter.translate(r.center()); + m_painter.rotate(toDeg(rotate)); + m_painter.setPen(textColor == Color::None ? m_colorScheme.foreground : toQColor(textColor)); + QRectF textRect{r}; + if(rotate == TileRotate::Deg90 || rotate == TileRotate::Deg270) + { + textRect = textRect.transposed(); + } + textRect.moveCenter({0., 0.}); + m_painter.drawText(textRect, text, QTextOption(toAlignment(textAlign))); + } + + m_painter.restore(); +} diff --git a/client/src/board/tilepainter.hpp b/client/src/board/tilepainter.hpp index fea399c3..f016c7d7 100644 --- a/client/src/board/tilepainter.hpp +++ b/client/src/board/tilepainter.hpp @@ -3,7 +3,7 @@ * * This file is part of the traintastic source code. * - * Copyright (C) 2020-2023 Reinder Feenstra + * Copyright (C) 2020-2024 Reinder Feenstra * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -37,6 +37,7 @@ #include #include #include "../enum/color.hpp" +#include "../enum/textalign.hpp" #include "../network/objectptr.hpp" struct BoardColorScheme; @@ -111,6 +112,8 @@ class TilePainter void drawRailDecoupler(const QRectF& r, TileRotate rotate, bool isReserved = false, DecouplerState active = DecouplerState::Deactivated); void drawRailNX(const QRectF& r, TileRotate rotate, bool isReserved = false, bool isEnabled = false, bool pressed = false); + + void drawLabel(const QRectF& r, TileRotate rotate, const QString& text = "txt", TextAlign textAlign = TextAlign::Center, Color textColor = Color::None, Color backgroundColor = Color::None); }; #endif diff --git a/client/src/enum/textalign.hpp b/client/src/enum/textalign.hpp new file mode 100644 index 00000000..6725e0f1 --- /dev/null +++ b/client/src/enum/textalign.hpp @@ -0,0 +1,66 @@ +/** + * client/src/enum/textalign.hpp + * + * This file is part of the traintastic source code. + * + * Copyright (C) 2024 Reinder Feenstra + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef TRAINTASTIC_CLIENT_ENUM_TEXTALIGN_HPP +#define TRAINTASTIC_CLIENT_ENUM_TEXTALIGN_HPP + +#include +#include + +constexpr Qt::Alignment toAlignment(TextAlign value) +{ + switch(value) + { + case TextAlign::TopLeft: + return Qt::AlignTop | Qt::AlignLeft; + + case TextAlign::TopCenter: + return Qt::AlignTop | Qt::AlignHCenter; + + case TextAlign::TopRight: + return Qt::AlignTop | Qt::AlignRight; + + case TextAlign::CenterLeft: + return Qt::AlignVCenter | Qt::AlignLeft; + + case TextAlign::Center: + return Qt::AlignCenter; + + case TextAlign::CenterRight: + return Qt::AlignVCenter | Qt::AlignRight; + + case TextAlign::BottomLeft: + return Qt::AlignBottom | Qt::AlignLeft; + + case TextAlign::BottomCenter: + return Qt::AlignBottom | Qt::AlignHCenter; + + case TextAlign::BottomRight: + return Qt::AlignBottom | Qt::AlignRight; + + default: + break; + } + return Qt::Alignment(); +} + +#endif diff --git a/client/src/utils/enum.cpp b/client/src/utils/enum.cpp index a9bd2453..fa8cd53e 100644 --- a/client/src/utils/enum.cpp +++ b/client/src/utils/enum.cpp @@ -49,6 +49,7 @@ #include #include #include +#include #include #include #include @@ -117,6 +118,7 @@ QString translateEnum(const QString& enumName, qint64 value) TRANSLATE_ENUM(SingleOutputAction) TRANSLATE_ENUM(SignalAspect) TRANSLATE_ENUM(SpeedUnit) + TRANSLATE_ENUM(TextAlign) TRANSLATE_ENUM(TrainMode) TRANSLATE_ENUM(TraintasticDIYInterfaceType) TRANSLATE_ENUM(TurnoutPosition) diff --git a/server/src/board/tile/misc/labeltile.cpp b/server/src/board/tile/misc/labeltile.cpp new file mode 100644 index 00000000..3e670ccd --- /dev/null +++ b/server/src/board/tile/misc/labeltile.cpp @@ -0,0 +1,48 @@ +/** + * server/src/board/tile/misc/labeltile.cpp + * + * This file is part of the traintastic source code. + * + * Copyright (C) 2024 Reinder Feenstra + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "labeltile.hpp" +#include "../../../core/attributes.hpp" + +CREATE_IMPL(LabelTile) + +LabelTile::LabelTile(World& world, std::string_view _id) + : Tile(world, _id, TileId::Label) + , backgroundColor{this, "background_color", Color::None, PropertyFlags::ReadWrite | PropertyFlags::Store | PropertyFlags::ScriptReadWrite} + , text{this, "text", id, PropertyFlags::ReadWrite | PropertyFlags::Store | PropertyFlags::ScriptReadWrite} + , textAlign{this, "text_align", TextAlign::Center, PropertyFlags::ReadWrite | PropertyFlags::Store | PropertyFlags::ScriptReadWrite} + , textColor{this, "text_color", Color::None, PropertyFlags::ReadWrite | PropertyFlags::Store | PropertyFlags::ScriptReadWrite} +{ + Attributes::setMax(height, 16); + Attributes::setMax(width, 16); + + m_interfaceItems.add(text); + + Attributes::addValues(textAlign, textAlignValues); + m_interfaceItems.add(textAlign); + + Attributes::addValues(textColor, colorValues); + m_interfaceItems.add(textColor); + + Attributes::addValues(backgroundColor, colorValues); + m_interfaceItems.add(backgroundColor); +} diff --git a/server/src/board/tile/misc/labeltile.hpp b/server/src/board/tile/misc/labeltile.hpp new file mode 100644 index 00000000..26a6af1c --- /dev/null +++ b/server/src/board/tile/misc/labeltile.hpp @@ -0,0 +1,45 @@ +/** + * server/src/board/tile/misc/labeltile.hpp + * + * This file is part of the traintastic source code. + * + * Copyright (C) 2024 Reinder Feenstra + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef TRAINTASTIC_SERVER_BOARD_TILE_MISC_LABELTILE_HPP +#define TRAINTASTIC_SERVER_BOARD_TILE_MISC_LABELTILE_HPP + +#include "../tile.hpp" +#include "../../../enum/color.hpp" +#include + +class LabelTile : public Tile +{ + CLASS_ID("board_tile.misc.label") + DEFAULT_ID("label") + CREATE_DEF(LabelTile) + + public: + Property backgroundColor; + Property text; + Property textAlign; + Property textColor; + + LabelTile(World& world, std::string_view _id); +}; + +#endif diff --git a/server/src/board/tile/tiles.cpp b/server/src/board/tile/tiles.cpp index 180d20b9..d01c1a33 100644 --- a/server/src/board/tile/tiles.cpp +++ b/server/src/board/tile/tiles.cpp @@ -3,7 +3,7 @@ * * This file is part of the traintastic source code. * - * Copyright (C) 2020-2023 Reinder Feenstra + * Copyright (C) 2020-2024 Reinder Feenstra * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -24,6 +24,7 @@ #include "rail/decouplerrailtile.hpp" #include "rail/linkrailtile.hpp" #include "rail/nxbuttonrailtile.hpp" +#include "misc/labeltile.hpp" #include "../../utils/ifclassidcreate.hpp" #include "../../world/world.hpp" @@ -59,6 +60,7 @@ std::shared_ptr Tiles::create(World& world, std::string_view classId, std: IF_CLASSID_CREATE(PushButtonTile) IF_CLASSID_CREATE(DecouplerRailTile) IF_CLASSID_CREATE(NXButtonRailTile) + IF_CLASSID_CREATE(LabelTile) return std::shared_ptr(); } @@ -69,6 +71,7 @@ const std::vector& Tiles::getInfo() static constexpr uint8_t rotate0and90 = 0x05; //!< only 0 or 90 deg static constexpr uint8_t rotateHalf = 0x0F; //!< only 0, 45, 90 or 135 deg static constexpr uint8_t rotateFull = 0xFF; + static constexpr uint8_t rotateFull90 = 0x55; //!< only 0, 90, 180, 270 deg static constexpr std::string_view straight = "tile_menu:straight"; static constexpr std::string_view curve = "tile_menu:curve"; @@ -115,6 +118,7 @@ const std::vector& Tiles::getInfo() Info{Signal3AspectRailTile::classId, TileId::RailSignal3Aspect, rotateFull, {signal}}, Info{PushButtonTile::classId, TileId::PushButton, rotateNone, {miscellaneous}}, + Info{LabelTile::classId, TileId::Label, rotateFull90, {miscellaneous}}, }}; return info; diff --git a/shared/src/traintastic/board/tileid.hpp b/shared/src/traintastic/board/tileid.hpp index 914cdc84..b46dfaae 100644 --- a/shared/src/traintastic/board/tileid.hpp +++ b/shared/src/traintastic/board/tileid.hpp @@ -3,7 +3,7 @@ * * This file is part of the traintastic source code. * - * Copyright (C) 2020-2023 Reinder Feenstra + * Copyright (C) 2020-2024 Reinder Feenstra * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -58,6 +58,7 @@ enum class TileId : uint16_t // 10 bit RailLink = 28, RailDecoupler = 29, RailNXButton = 30, + Label = 31, ReservedForFutureExpension = 1023 }; @@ -191,6 +192,7 @@ constexpr bool isActive(TileId id) case TileId::RailLink: case TileId::RailDecoupler: case TileId::RailNXButton: + case TileId::Label: return true; default: diff --git a/shared/src/traintastic/enum/textalign.hpp b/shared/src/traintastic/enum/textalign.hpp new file mode 100644 index 00000000..6711744f --- /dev/null +++ b/shared/src/traintastic/enum/textalign.hpp @@ -0,0 +1,77 @@ +/** + * shared/src/traintastic/enum/textalign.hpp + * + * This file is part of the traintastic source code. + * + * Copyright (C) 2024 Reinder Feenstra + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef TRAINTASTIC_SHARED_TRAINTASTIC_ENUM_TEXTALIGN_HPP +#define TRAINTASTIC_SHARED_TRAINTASTIC_ENUM_TEXTALIGN_HPP + +#include +#include +#include "enum.hpp" + +enum class TextAlign : uint8_t +{ + // Horizontal: + Left = 0x01, + HCenter = 0x02, + Right = 0x04, + // Vertical: + Top = 0x10, + VCenter = 0x20, + Bottom = 0x40, + // Combinations: + TopLeft = Top | Left, + TopCenter = Top | HCenter, + TopRight = Top | Right, + CenterLeft = VCenter | Left, + Center = VCenter | HCenter, + CenterRight = VCenter | Right, + BottomLeft = Bottom | Left, + BottomCenter = Bottom | HCenter, + BottomRight = Bottom | Right, +}; + +TRAINTASTIC_ENUM(TextAlign, "text_align", 9, +{ + {TextAlign::TopLeft, "top_left"}, + {TextAlign::TopCenter, "top_center"}, + {TextAlign::TopRight, "top_right"}, + {TextAlign::CenterLeft, "center_left"}, + {TextAlign::Center, "center"}, + {TextAlign::CenterRight, "center_right"}, + {TextAlign::BottomLeft, "bottom_left"}, + {TextAlign::BottomCenter, "bottom_center"}, + {TextAlign::BottomRight, "bottom_right"}, +}); + +inline constexpr std::array textAlignValues{{ + TextAlign::TopLeft, + TextAlign::TopCenter, + TextAlign::TopRight, + TextAlign::CenterLeft, + TextAlign::Center, + TextAlign::CenterRight, + TextAlign::BottomLeft, + TextAlign::BottomCenter, + TextAlign::BottomRight, +}}; + +#endif diff --git a/shared/translations/en-us.json b/shared/translations/en-us.json index 27d01dd8..bc827d41 100644 --- a/shared/translations/en-us.json +++ b/shared/translations/en-us.json @@ -4698,5 +4698,69 @@ { "term": "output_map:address_x", "definition": "Address %1" + }, + { + "term": "class_id:board_tile.rail.nx_button", + "definition": "NX button" + }, + { + "term": "class_id:board_tile.misc.label", + "definition": "Label" + }, + { + "term": "board_tile.misc.label:text", + "definition": "Text" + }, + { + "term": "board_tile.misc.label:text_align", + "definition": "Text align" + }, + { + "term": "board_tile.misc.label:text_color", + "definition": "Text color" + }, + { + "term": "color:none", + "definition": "None" + }, + { + "term": "board_tile.misc.label:background_color", + "definition": "Background color" + }, + { + "term": "text_align:top_left", + "definition": "Top left" + }, + { + "term": "text_align:top_center", + "definition": "Top center" + }, + { + "term": "text_align:top_right", + "definition": "Top right" + }, + { + "term": "text_align:center_left", + "definition": "Center left" + }, + { + "term": "text_align:center", + "definition": "Center" + }, + { + "term": "text_align:center_right", + "definition": "Center right" + }, + { + "term": "text_align:bottom_left", + "definition": "Bottom left" + }, + { + "term": "text_align:bottom_center", + "definition": "Bottom center" + }, + { + "term": "text_align:bottom_right", + "definition": "Bottom right" } -] +] \ No newline at end of file