From 81acd2a5c5d4bcb1eaf38f72f20e460c5731b136 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matt=C3=A9o=20Delabre?= Date: Wed, 20 Apr 2016 14:48:24 +0200 Subject: [PATCH] =?UTF-8?q?Extension=20du=20bouton=20radio=20pour=20affich?= =?UTF-8?q?er=20l'ic=C3=B4ne=20des=20objets?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/object_button.hpp | 58 ++++++++++++++++++++++++++ src/object_button.cpp | 86 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 144 insertions(+) create mode 100644 include/object_button.hpp create mode 100644 src/object_button.cpp diff --git a/include/object_button.hpp b/include/object_button.hpp new file mode 100644 index 0000000..6adfdaa --- /dev/null +++ b/include/object_button.hpp @@ -0,0 +1,58 @@ +#ifndef __SKIZZLE_OBJECT_BUTTON_HPP__ +#define __SKIZZLE_OBJECT_BUTTON_HPP__ + +#include +#include +#include +#include +#include + +/** + * Widget personnalisé SFGUI. Il s'agit d'un widget héritant directement + * des boutons radio et qui affiche l'image donnée sur toute sa surface. + * Il est utilisé dans la toolbar pour choisir le type d'objet à + * sélectionner + * + * (note: cette classe suit les conventions de nommage de SFGUI, pas + * celles de Skizzle, pour plus de cohérence) + */ +class ObjectButton : public sfg::RadioButton { +public: + typedef std::shared_ptr Ptr; + typedef std::shared_ptr PtrConst; + + /** + * Crée un nouveau bouton d'objet. La convention pour les widgets + * SFGUI est de protéger le constructeur et de les construire uniquement + * avec la méthode statique ::Create() qui renvoie un pointeur partagé + */ + static Ptr Create( + sfg::Image::Ptr image, + sfg::RadioButtonGroup::Ptr group = sfg::RadioButtonGroup::Ptr() + ); + + /** + * Renvoie le nom de l'objet. Est utilisé par le parseur de styles + * pour obtenir la liste des propriétés s'appliquant au widget + */ + const std::string& GetName() const override; + +protected: + /** + * On utilise le constructeur par défaut, mais on est obligés de le + * déclarer explicitement pour qu'il soit protégé + */ + ObjectButton() = default; + + /** + * Recalcule la géométrie du widget + */ + std::unique_ptr InvalidateImpl() const override; + + /** + * Recalcule la place occupée par le widget + */ + sf::Vector2f CalculateRequisition() override; +}; + +#endif diff --git a/src/object_button.cpp b/src/object_button.cpp new file mode 100644 index 0000000..15ac684 --- /dev/null +++ b/src/object_button.cpp @@ -0,0 +1,86 @@ +#include +#include +#include +#include +#include +#include "object_button.hpp" + +ObjectButton::Ptr ObjectButton::Create( + sfg::Image::Ptr image, + std::shared_ptr group +) { + auto ptr = Ptr(new ObjectButton); + ptr->SetImage(image); + ptr->SetLabel(L""); + + // on définit le groupe de boutons d'objets tel que passé + // en paramètre, sinon on en crée un nouveau + if (group) { + ptr->SetGroup(group); + } else { + ptr->SetGroup(sfg::RadioButtonGroup::Create()); + } + + return ptr; +} + +const std::string& ObjectButton::GetName() const { + static const std::string name = "ObjectButton"; + return name; +} + +sf::Vector2f ObjectButton::CalculateRequisition() { + float padding = sfg::Context::Get().GetEngine().GetProperty( + "Padding", shared_from_this() + ); + + // le widget occupe la taille de l'image de l'objet contenue, + // plus deux fois le padding spécifié dans le style + sf::Vector2f child_req = GetChild()->GetRequisition(); + + child_req.x += 2 * padding; + child_req.y += 2 * padding; + + return child_req; +} + +std::unique_ptr ObjectButton::InvalidateImpl() const { + auto queue = std::unique_ptr(new sfg::RenderQueue); + + auto border_color = sfg::Context::Get().GetEngine().GetProperty( + "BorderColor", shared_from_this() + ); + + auto background_color = sfg::Context::Get().GetEngine().GetProperty( + "BackgroundColor", shared_from_this() + ); + + float padding = sfg::Context::Get().GetEngine().GetProperty( + "Padding", shared_from_this() + ); + + // si le bouton est sélectionné, on l'entoure + if (IsActive()) { + sf::Vector2f position; + sf::Vector2f size; + + position.x = GetAllocation().width / 2 - GetRequisition().x / 2; + position.y = GetAllocation().height / 2 - GetRequisition().y / 2; + size.x = std::min(GetAllocation().width, GetRequisition().x); + size.y = std::min(GetAllocation().height, GetRequisition().y); + + queue->Add(sfg::Renderer::Get().CreatePane( + position, size, 1.f, + background_color, border_color, 0 + )); + } + + // demande à l'image de recalculer sa géométrie + GetChild()->SetAllocation(sf::FloatRect( + padding, padding, GetAllocation().width - 2 * padding, + GetAllocation().height - 2 * padding + )); + + GetChild()->Invalidate(); + return queue; +}