From e46c8493bce6113175d5cb4cae16e284c4f36ba6 Mon Sep 17 00:00:00 2001 From: Florian Rival Date: Sun, 25 Feb 2018 22:17:04 +0100 Subject: [PATCH] Refactor Resource to use gd::PropertyDescriptor for custom properties --- .vscode/c_cpp_properties.json | 2 + Core/GDCore/IDE/Dialogs/ResourcesEditor.cpp | 59 ++++------ Core/GDCore/Project/ResourcesManager.cpp | 81 ++++--------- Core/GDCore/Project/ResourcesManager.h | 122 ++++++++------------ 4 files changed, 99 insertions(+), 165 deletions(-) diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json index 431e40acd3..b01cb94294 100644 --- a/.vscode/c_cpp_properties.json +++ b/.vscode/c_cpp_properties.json @@ -15,6 +15,8 @@ "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/9.0.0/include", "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include", "/usr/include", + "/usr/local/lib/wx/include/osx_cocoa-unicode-3.0", + "/usr/local/include/wx-3.0", "${workspaceRoot}" ], "defines": [ diff --git a/Core/GDCore/IDE/Dialogs/ResourcesEditor.cpp b/Core/GDCore/IDE/Dialogs/ResourcesEditor.cpp index cdadb12fef..663d0a1371 100644 --- a/Core/GDCore/IDE/Dialogs/ResourcesEditor.cpp +++ b/Core/GDCore/IDE/Dialogs/ResourcesEditor.cpp @@ -52,6 +52,7 @@ #include "GDCore/Tools/Log.h" #include "GDCore/IDE/Dialogs/DndResourcesEditor.h" #include "GDCore/IDE/wxTools/TreeItemStringData.h" +#include "GDCore/IDE/Dialogs/PropertyDescriptor.h" #ifdef __WXGTK__ #include @@ -635,7 +636,7 @@ void ResourcesEditor::OnresourcesTreeSelectionChanged( wxTreeEvent& event ) void ResourcesEditor::UpdatePropertyGrid() { - std::vector commonProperties; ///< The name of the properties to be displayed + std::map commonProperties; ///< The name of the properties to be displayed bool aFolderIsSelected = false; //First construct the list of common properties @@ -646,18 +647,29 @@ void ResourcesEditor::UpdatePropertyGrid() gd::TreeItemStringData * data = dynamic_cast(resourcesTree->GetItemData(selection[i])); if ( data && data->GetString() == "Image") { - std::vector properties = project.GetResourcesManager().GetResource(data->GetSecondString()).GetAllProperties(project); + const std::map & properties = + project.GetResourcesManager().GetResource(data->GetSecondString()).GetProperties(project); if ( i == 0 ) commonProperties = properties; else { - //Keep only properties that are common to all the selected resources - for (std::size_t j = 0;j::const_iterator it = properties.begin(); + it != properties.end();++it) { - if ( find(properties.begin(), properties.end(), commonProperties[j]) == properties.end() ) - commonProperties.erase(commonProperties.begin()+j); - else - ++j; + if ( commonProperties.find(it->first) == commonProperties.end() ) continue; + if ( commonProperties[it->first].GetValue() != it->second.GetValue() ) + commonProperties[it->first].SetValue(_("(Multiples values)")); + } + //Also erase properties which are not in common. + for(std::map::iterator it = commonProperties.begin(); + it != commonProperties.end();) + { + if ( properties.find(it->first) == properties.end() ) + commonProperties.erase(it++); + else ++it; } } } @@ -721,32 +733,11 @@ void ResourcesEditor::UpdatePropertyGrid() //Other properties if ( !commonProperties.empty() ) propertyGrid->Append( new wxPropertyCategory(_("Other properties")) ); - for (std::size_t j = 0;jAppend( new wxStringProperty("", commonProperties[j], "") ); - wxString commonValue; - - for (std::size_t i = 0;i(resourcesTree->GetItemData(selection[i])); - if ( data && data->GetString() == "Image") - { - //It is assumed that the description and the user friendly name - //are the same for all the properties with the same name. - gd::String propertyUserFriendlyName; - gd::String propertyDescription; - project.GetResourcesManager().GetResource(data->GetSecondString()).GetPropertyInformation(project, commonProperties[j], propertyUserFriendlyName, propertyDescription); - propertyGrid->SetPropertyLabel(property, propertyUserFriendlyName); - propertyGrid->SetPropertyHelpString(property, propertyDescription); - - //Values can be different though - gd::String propertyValue = project.GetResourcesManager().GetResource(data->GetSecondString()).GetProperty(project, commonProperties[j]); - if ( i == 0 ) commonValue = propertyValue; - else if ( commonValue != propertyValue ) commonValue = _("(Multiple values)"); - } - } - - propertyGrid->SetPropertyValue(property, commonValue); + // TODO: For now, all other properties are assumed to be booleans. + auto & propertyName = propertyIterator.first; + propertyGrid->Append(new wxBoolProperty(propertyName, propertyName, propertyIterator.second.GetValue() == "true")); } } } @@ -782,7 +773,7 @@ void ResourcesEditor::OnPropertyChanged(wxPropertyGridEvent& event) RenameInTree(resourcesTree->GetRootItem(), renamedItemOldName, propertyNewValue, "Image"); } else - project.GetResourcesManager().GetResource(data->GetSecondString()).ChangeProperty(project, propertyName, propertyNewValue); + project.GetResourcesManager().GetResource(data->GetSecondString()).UpdateProperty(propertyName, propertyNewValue, project); for ( std::size_t j = 0; j < project.GetUsedPlatforms().size();++j) project.GetUsedPlatforms()[j]->GetChangesNotifier().OnResourceModified(project, data->GetSecondString()); diff --git a/Core/GDCore/Project/ResourcesManager.cpp b/Core/GDCore/Project/ResourcesManager.cpp index 96df12028b..83c1bf8936 100644 --- a/Core/GDCore/Project/ResourcesManager.cpp +++ b/Core/GDCore/Project/ResourcesManager.cpp @@ -5,6 +5,7 @@ */ #include +#include #if defined(GD_IDE_ONLY) && !defined(GD_NO_WX_GUI) #include "GDCore/IDE/wxTools/CommonBitmapProvider.h" #include @@ -20,6 +21,7 @@ #include "GDCore/Serialization/SerializerElement.h" #include "GDCore/Tools/Log.h" #include "GDCore/Tools/Localization.h" +#include "GDCore/IDE/Dialogs/PropertyDescriptor.h" namespace gd { @@ -114,8 +116,30 @@ std::vector ResourcesManager::GetAllResourceNames() return allResources; } - #if defined(GD_IDE_ONLY) +std::map Resource::GetProperties(gd::Project & project) const +{ + std::map nothing; + return nothing; +} + +std::map ImageResource::GetProperties(gd::Project & project) const +{ + std::map properties; + properties[_("Smooth the image")].SetValue(smooth ? "true" : "false").SetType("Boolean"); + properties[_("Always loaded in memory")].SetValue(alwaysLoaded ? "true" : "false").SetType("Boolean"); + + return properties; +} + +bool ImageResource::UpdateProperty(const gd::String & name, const gd::String & value, gd::Project & project) +{ + if (name == _("Smooth the image")) smooth = value == "1"; + else if (name == _("Always loaded in memory")) alwaysLoaded = value == "1"; + + return true; +} + bool ResourcesManager::AddResource(const gd::Resource & resource) { if ( HasResource(resource.GetName()) ) return false; @@ -155,61 +179,6 @@ std::vector ResourceFolder::GetAllResourceNames() return allResources; } -bool ImageResource::EditProperty(gd::Project & project, const gd::String & property) -{ - return false; -} - -bool ImageResource::ChangeProperty(gd::Project & project, const gd::String & property, const gd::String & newValue) -{ - if ( property == "smooth" ) - smooth = (newValue == _("Yes")); - else if ( property == "alwaysLoaded" ) - alwaysLoaded = (newValue == _("Yes")); - - return true; -} - -void ImageResource::GetPropertyInformation(gd::Project & project, const gd::String & property, gd::String & userFriendlyName, gd::String & description) const -{ - if ( property == "smooth" ) - { - userFriendlyName = _("Smooth the image"); - description = _("Set this to \"Yes\" to set a smooth filter on the image"); - } - else if ( property == "alwaysLoaded" ) - { - userFriendlyName = _("Always loaded in memory"); - description = _("Set this to \"Yes\" to let the image always loaded in memory.\nUseful when the image is used by actions."); - } -} - -gd::String ImageResource::GetProperty(gd::Project & project, const gd::String & property) -{ - if ( property == "smooth" ) - { - return smooth ? _("Yes") : _("No"); - } - else if ( property == "alwaysLoaded" ) - { - return alwaysLoaded ? _("Yes") : _("No"); - } - - return ""; -} - -/** - * Return a vector containing the name of all the properties of the resource - */ -std::vector ImageResource::GetAllProperties(gd::Project & project) const -{ - std::vector allProperties; - allProperties.push_back("smooth"); - allProperties.push_back("alwaysLoaded"); - - return allProperties; -} - #if !defined(GD_NO_WX_GUI) void ImageResource::RenderPreview(wxPaintDC & dc, wxPanel & previewPanel, gd::Project & project) { diff --git a/Core/GDCore/Project/ResourcesManager.h b/Core/GDCore/Project/ResourcesManager.h index 63afbc4a4a..97d1909d44 100644 --- a/Core/GDCore/Project/ResourcesManager.h +++ b/Core/GDCore/Project/ResourcesManager.h @@ -6,11 +6,12 @@ #ifndef GDCORE_RESOURCESMANAGER_H #define GDCORE_RESOURCESMANAGER_H #include -#include "GDCore/String.h" #include +#include "GDCore/String.h" namespace gd { class Project; } namespace gd { class ResourceFolder; } namespace gd { class SerializerElement; } +namespace gd { class PropertyDescriptor; } class wxPaintDC; class wxPanel; @@ -83,37 +84,6 @@ public: */ gd::String GetAbsoluteFile(const gd::Project & game) const; - /** - * \brief Called when a property must be edited (i.e: it was double clicked in a property grid) - * - * \return true if the resource was changed - */ - virtual bool EditProperty(gd::Project & project, const gd::String & property) { return true; }; - - /** - * \brief Called when a property must be changed (i.e: its value was changed in a property grid) - * - * \return true if the resource was changed - */ - virtual bool ChangeProperty(gd::Project & project, const gd::String & property, const gd::String & newValue) { return true; }; - - /** - * \brief Must return a description of the main property provided by the resource (example : "Image file") - */ - virtual void GetPropertyInformation(gd::Project & project, const gd::String & property, gd::String & userFriendlyName, gd::String & description) const { return; }; - - /** - * \brief Called when a property must be changed ( i.e: its value was changed in the property grid ) - * - * \return the value of the property - */ - virtual gd::String GetProperty(gd::Project & project, const gd::String & property) { return ""; }; - - /** - * \brief Return a description of the main property provided by the resource ( Example : "Image file" ) - */ - virtual std::vector GetAllProperties(gd::Project & project) const { std::vector noProperties; return noProperties; }; - #if !defined(GD_NO_WX_GUI) /** * \brief Called when the resource must be rendered in a preview panel. @@ -121,6 +91,36 @@ public: virtual void RenderPreview(wxPaintDC & dc, wxPanel & previewPanel, gd::Project & game) {}; #endif + #if defined(GD_IDE_ONLY) + /** \name Resources properties + * Reading and updating resources properties + */ + ///@{ + /** + * \brief Called when the IDE wants to know about the custom properties of the resource. + * + * Usage example: + \code + std::map properties; + properties[ToString(_("Text"))].SetValue("Hello world!"); + + return properties; + \endcode + * + * \return a std::map with properties names as key. + * \see gd::PropertyDescriptor + */ + virtual std::map GetProperties(gd::Project & project) const; + + /** + * \brief Called when the IDE wants to update a custom property of the resource + * + * \return false if the new value cannot be set + */ + virtual bool UpdateProperty(const gd::String & name, const gd::String & value, gd::Project & project) {return false;}; + ///@} + #endif + /** * \brief Serialize the object */ @@ -150,69 +150,41 @@ class GD_CORE_API ImageResource : public Resource public: ImageResource() : Resource(), smooth(true), alwaysLoaded(false) { SetKind("image"); }; virtual ~ImageResource() {}; - virtual ImageResource* Clone() const { return new ImageResource(*this);} + virtual ImageResource* Clone() const override { return new ImageResource(*this);} /** * Return the file used by the resource. */ - virtual const gd::String & GetFile() const {return file;}; + virtual const gd::String & GetFile() const override {return file;}; /** * Change the file of the resource. */ - virtual void SetFile(const gd::String & newFile); + virtual void SetFile(const gd::String & newFile) override; #if defined(GD_IDE_ONLY) - virtual bool UseFile() { return true; } + virtual bool UseFile() override { return true; } #if !defined(GD_NO_WX_GUI) /** * Called when the resource must be rendered in a preview panel. */ - virtual void RenderPreview(wxPaintDC & dc, wxPanel & previewPanel, gd::Project & game); + virtual void RenderPreview(wxPaintDC & dc, wxPanel & previewPanel, gd::Project & game) override; #endif - /** - * Called when a property must be edited ( i.e: it was double clicked ) - * - * \return true if the resource was changed - */ - virtual bool EditProperty(gd::Project & project, const gd::String & property); - - /** - * Called when a property must be changed ( i.e: its value was changed in the property grid ) - * - * \return true if the resource was changed - */ - virtual bool ChangeProperty(gd::Project & project, const gd::String & property, const gd::String & newValue); - - /** - * Called when a property must be changed ( i.e: its value was changed in the property grid ) - * - * \return the value of the property - */ - virtual gd::String GetProperty(gd::Project & project, const gd::String & property); - - /** - * Return a description of the main property provided by the resource ( Example : "Image file" ) - */ - virtual void GetPropertyInformation(gd::Project & project, const gd::String & property, gd::String & userFriendlyName, gd::String & description) const; - - /** - * Return a vector containing the name of all the properties of the resource - */ - virtual std::vector GetAllProperties(gd::Project & project) const; + std::map GetProperties(gd::Project & project) const override; + bool UpdateProperty(const gd::String & name, const gd::String & value, gd::Project & project) override; /** * \brief Serialize the object */ - void SerializeTo(SerializerElement & element) const; + void SerializeTo(SerializerElement & element) const override; #endif /** * \brief Unserialize the objectt. */ - void UnserializeFrom(const SerializerElement & element); + void UnserializeFrom(const SerializerElement & element) override; /** * \brief Return true if the image should be smoothed. @@ -242,17 +214,17 @@ class GD_CORE_API AudioResource : public Resource public: AudioResource() : Resource() { SetKind("audio"); }; virtual ~AudioResource() {}; - virtual AudioResource* Clone() const { return new AudioResource(*this);} + virtual AudioResource* Clone() const override { return new AudioResource(*this);} - virtual const gd::String & GetFile() const {return file;}; - virtual void SetFile(const gd::String & newFile); + virtual const gd::String & GetFile() const override {return file;}; + virtual void SetFile(const gd::String & newFile) override; #if defined(GD_IDE_ONLY) - virtual bool UseFile() { return true; } - void SerializeTo(SerializerElement & element) const; + virtual bool UseFile() override { return true; } + void SerializeTo(SerializerElement & element) const override; #endif - void UnserializeFrom(const SerializerElement & element); + void UnserializeFrom(const SerializerElement & element) override; private: gd::String file;