Add visibility setting to the property classes (closing #166)

This commit is contained in:
Alexander Bock
2016-11-23 23:24:07 +01:00
parent 357a447435
commit 7ffcf81235
17 changed files with 200 additions and 84 deletions
@@ -33,12 +33,15 @@ namespace properties {
template <typename T>
class NumericalProperty : public TemplateProperty<T> {
public:
NumericalProperty(std::string identifier, std::string guiName);
NumericalProperty(std::string identifier, std::string guiName, T value);
NumericalProperty(std::string identifier, std::string guiName,
Visibility visibility = Visibility::User);
NumericalProperty(std::string identifier, std::string guiName, T value,
T minimumValue, T maximumValue);
Visibility visibility = Visibility::User);
NumericalProperty(std::string identifier, std::string guiName, T value,
T minimumValue, T maximumValue, T steppingValue);
T minimumValue, T maximumValue, Visibility visibility = Visibility::User);
NumericalProperty(std::string identifier, std::string guiName, T value,
T minimumValue, T maximumValue, T steppingValue,
Visibility visibility = Visibility::User);
bool getLuaValue(lua_State* state) const override;
bool setLuaValue(lua_State* state) override;
@@ -233,42 +233,50 @@ const std::string NumericalProperty<T>::SteppingValueKey = "SteppingValue";
// a single constructor
template <typename T>
NumericalProperty<T>::NumericalProperty(std::string identifier, std::string guiName)
NumericalProperty<T>::NumericalProperty(std::string identifier, std::string guiName,
Visibility visibility)
: NumericalProperty<T>(
std::move(identifier), std::move(guiName),
PropertyDelegate<NumericalProperty<T>>::template defaultValue<T>(),
PropertyDelegate<NumericalProperty<T>>::template defaultMinimumValue<T>(),
PropertyDelegate<NumericalProperty<T>>::template defaultMaximumValue<T>(),
PropertyDelegate<NumericalProperty<T>>::template defaultSteppingValue<T>()
)
{}
template <typename T>
NumericalProperty<T>::NumericalProperty(std::string identifier,
std::string guiName, T value)
: NumericalProperty<T>(
std::move(identifier), std::move(guiName), std::move(value),
PropertyDelegate<NumericalProperty<T>>::template defaultMinimumValue<T>(),
PropertyDelegate<NumericalProperty<T>>::template defaultMaximumValue<T>(),
PropertyDelegate<NumericalProperty<T>>::template defaultSteppingValue<T>()
)
{}
template <typename T>
NumericalProperty<T>::NumericalProperty(std::string identifier, std::string guiName,
T value, T minimumValue, T maximumValue)
: NumericalProperty<T>(
std::move(identifier) , std::move(guiName), std::move(value),
std::move(minimumValue), std::move(maximumValue),
PropertyDelegate<NumericalProperty<T>>::template defaultSteppingValue<T>()
PropertyDelegate<NumericalProperty<T>>::template defaultSteppingValue<T>(),
visibility
)
{}
template <typename T>
NumericalProperty<T>::NumericalProperty(std::string identifier,
std::string guiName, T value,
T minimumValue, T maximumValue, T steppingValue)
: TemplateProperty<T>(std::move(identifier), std::move(guiName), std::move(value))
Visibility visibility)
: NumericalProperty<T>(
std::move(identifier), std::move(guiName), std::move(value),
PropertyDelegate<NumericalProperty<T>>::template defaultMinimumValue<T>(),
PropertyDelegate<NumericalProperty<T>>::template defaultMaximumValue<T>(),
PropertyDelegate<NumericalProperty<T>>::template defaultSteppingValue<T>(),
visibility
)
{}
template <typename T>
NumericalProperty<T>::NumericalProperty(std::string identifier, std::string guiName,
T value, T minimumValue, T maximumValue,
Visibility visibility)
: NumericalProperty<T>(
std::move(identifier) , std::move(guiName), std::move(value),
std::move(minimumValue), std::move(maximumValue),
PropertyDelegate<NumericalProperty<T>>::template defaultSteppingValue<T>(),
visibility
)
{}
template <typename T>
NumericalProperty<T>::NumericalProperty(std::string identifier,
std::string guiName, T value,
T minimumValue, T maximumValue, T steppingValue,
Visibility visibility)
: TemplateProperty<T>(std::move(identifier), std::move(guiName), std::move(value),
visibility)
, _minimumValue(std::move(minimumValue))
, _maximumValue(std::move(maximumValue))
, _stepping(std::move(steppingValue))
@@ -61,7 +61,8 @@ public:
* \param identifier A unique identifier for this property
* \param guiName The GUI name that should be used to represent this property
*/
OptionProperty(std::string identifier, std::string guiName);
OptionProperty(std::string identifier, std::string guiName,
Visibility visibility = Visibility::User);
/**
* The constructor delegating the <code>identifier</code> and the <code>guiName</code>
@@ -70,7 +71,8 @@ public:
* \param guiName The GUI name that should be used to represent this property
* \param displayType Optional DisplayType for GUI (default RADIO)
*/
OptionProperty(std::string identifier, std::string guiName, DisplayType displayType);
OptionProperty(std::string identifier, std::string guiName, DisplayType displayType,
Visibility visibility = Visibility::User);
/**
* Returns the name of the class for reflection purposes.
+21 -11
View File
@@ -62,6 +62,17 @@ class PropertyOwner;
*/
class Property {
public:
/**
* The visibility classes for Property%s. The classes are strictly ordered as
* All > Developer > User > None
*/
enum class Visibility {
All = 3, ///< Visible for all types, no matter what
Developer = 2, ///< Visible in Developer mode
User = 1, ///< Visible in User mode
None = 0 ///< Never visible
};
/**
* The constructor for the property. The <code>identifier</code> needs to be unique
* for each PropertyOwner. The <code>guiName</code> will be stored in the metaData
@@ -74,7 +85,8 @@ public:
* \pre \p identifier must not be empty
* \pre \p guiName must not be empty
*/
Property(std::string identifier, std::string guiName);
Property(std::string identifier, std::string guiName,
Visibility visibility = Visibility::All);
/**
* The destructor taking care of deallocating all unused memory. This method will not
@@ -255,20 +267,18 @@ public:
std::string groupIdentifier() const;
/**
* Determines a hint if this Property should be visible, or hidden. Each application
* accessing the properties is free to ignore this hint. It is stored in the metaData
* Dictionary with the key: <code>isVisible</code>. The default value is
* <code>true</code>.
* \param state <code>true</code> if the Property should be visible,
* <code>false</code> otherwise.
* Sets a hint about the visibility of the Property. Each application accessing the
* properties is free to ignore this hint. It is stored in the metaData Dictionary
* with the key: <code>Visibility</code>.
* \param visibility The new visibility of the Property
*/
void setVisible(bool state);
void setVisibility(Visibility visibility);
/**
* Returns whether this Property is visible or not.
* \return Whether this Property is visible or hidden
* Returns this Property%'s visibility setting
* \return This Property%'s visibility setting
*/
bool isVisible() const;
Visibility visibility() const;
/**
* This method determines if this Property should be read-only in external
@@ -39,7 +39,8 @@ public:
std::string description;
};
SelectionProperty(std::string identifier, std::string guiName);
SelectionProperty(std::string identifier, std::string guiName,
Visibility visibility = Visibility::User);
void addOption(Option option);
void removeOptions();
@@ -63,14 +63,16 @@ public:
* \param identifier The identifier that is used for this TemplateProperty
* \param guiName The human-readable GUI name for this TemplateProperty
*/
TemplateProperty(std::string identifier, std::string guiName);
TemplateProperty(std::string identifier, std::string guiName,
Visibility visibility = Visibility::User);
/**
* The constructor initializing the TemplateProperty with the provided
* <code>identifier</code>, human-readable <code>guiName</code> and provided
* <code>value</code>.
*/
TemplateProperty(std::string identifier, std::string guiName, T value);
TemplateProperty(std::string identifier, std::string guiName, T value,
Visibility visibility = Visibility::User);
/**
* Returns the class name for this TemplateProperty. The default implementation makes
@@ -149,17 +149,20 @@ namespace properties {
// a single constructor
template <typename T>
TemplateProperty<T>::TemplateProperty(std::string identifier, std::string guiName)
TemplateProperty<T>::TemplateProperty(std::string identifier, std::string guiName,
Visibility visibility)
: TemplateProperty<T>(
std::move(identifier), std::move(guiName),
PropertyDelegate<TemplateProperty<T>>::template defaultValue<T>())
PropertyDelegate<TemplateProperty<T>>::template defaultValue<T>(),
visibility)
{
}
template <typename T>
TemplateProperty<T>::TemplateProperty(std::string identifier, std::string guiName,
T value)
: Property(std::move(identifier), std::move(guiName))
T value, Visibility visibility)
: Property(std::move(identifier), std::move(guiName), visibility)
, _value(std::move(value)) {
}
@@ -42,7 +42,8 @@ public:
* \param identifier The unique identifier used for this Property
* \param guiName The human-readable name of this Property
*/
TriggerProperty(std::string identifier, std::string guiName);
TriggerProperty(std::string identifier, std::string guiName,
Visibility visibility = Visibility::User);
/**
* Returns the class name <code>TriggerProperty</code>.
+5 -1
View File
@@ -130,7 +130,11 @@ RenderableStars::RenderableStars(const ghoul::Dictionary& dictionary)
, _colorTexturePath("colorTexture", "ColorBV Texture")
, _colorTexture(nullptr)
, _colorTextureIsDirty(true)
, _colorOption("colorOption", "Color Option")
, _colorOption(
"colorOption",
"Color Option",
properties::OptionProperty::DisplayType::Dropdown
)
, _dataIsDirty(true)
, _alphaValue("alphaValue", "Transparency", 1.f, 0.f, 1.f)
, _scaleFactor("scaleFactor", "Scale Factor", 1.f, 0.f, 10.f)
+7
View File
@@ -33,6 +33,7 @@
#include <modules/onscreengui/include/guitimecomponent.h>
#include <modules/onscreengui/include/guiiswacomponent.h>
#include <openspace/scripting/scriptengine.h>
#include <openspace/properties/property.h>
#include <openspace/util/keys.h>
#include <openspace/util/mouse.h>
@@ -70,6 +71,12 @@ public:
GuiPropertyComponent _screenSpaceProperty;
GuiTimeComponent _time;
GuiIswaComponent _iswa;
private:
void renderAndUpdatePropertyVisibility();
properties::Property::Visibility _currentVisibility;
};
} // namespace gui
@@ -27,6 +27,8 @@
#include <modules/onscreengui/include/guicomponent.h>
#include <openspace/properties/property.h>
#include <functional>
#include <string>
#include <vector>
@@ -50,12 +52,16 @@ public:
// component should render
void setSource(SourceFunction func);
void setVisibility(properties::Property::Visibility visibility);
void render();
protected:
void renderPropertyOwner(properties::PropertyOwner* owner);
void renderProperty(properties::Property* prop, properties::PropertyOwner* owner);
properties::Property::Visibility _visibility;
SourceFunction _function;
};
+19
View File
@@ -225,6 +225,7 @@ GUI::GUI()
, _globalProperty("Global")
, _property("Properties")
, _screenSpaceProperty("ScreenSpace Properties")
, _currentVisibility(properties::Property::Visibility::All)
{
addPropertySubOwner(_help);
addPropertySubOwner(_origin);
@@ -546,6 +547,8 @@ void GUI::render() {
ImGui::Checkbox("Help", &help);
_help.setEnabled(help);
renderAndUpdatePropertyVisibility();
static const int addImageBufferSize = 256;
static char addImageBuffer[addImageBufferSize];
@@ -576,5 +579,21 @@ void GUI::render() {
ImGui::End();
}
void GUI::renderAndUpdatePropertyVisibility() {
// Fragile! Keep this in sync with properties::Property::Visibility
using V = properties::Property::Visibility;
int t = static_cast<std::underlying_type_t<V>>(_currentVisibility);
// Array is sorted by importance
std::array<const char*, 4> items = { "None", "User", "Developer", "All"};
ImGui::Combo("PropertyVisibility", &t, items.data(), items.size());
_currentVisibility = static_cast<V>(t);
_globalProperty.setVisibility(_currentVisibility);
_property.setVisibility(_currentVisibility);
_screenSpaceProperty.setVisibility(_currentVisibility);
}
} // namespace gui
} // namespace openspace
@@ -28,6 +28,7 @@
#include <openspace/properties/propertyowner.h>
#include <algorithm>
#include "imgui.h"
namespace {
@@ -36,6 +37,24 @@ namespace {
}
namespace openspace {
namespace {
int nVisibleProperties(const std::vector<properties::Property*>& properties,
properties::Property::Visibility visibility)
{
return std::count_if(
properties.begin(),
properties.end(),
[visibility](properties::Property* p) {
using V = properties::Property::Visibility;
return
static_cast<std::underlying_type_t<V>>(visibility) >=
static_cast<std::underlying_type_t<V>>(p->visibility());
}
);
}
}
namespace gui {
GuiPropertyComponent::GuiPropertyComponent(std::string name)
@@ -46,6 +65,10 @@ void GuiPropertyComponent::setSource(SourceFunction function) {
_function = std::move(function);
}
void GuiPropertyComponent::setVisibility(properties::Property::Visibility visibility) {
_visibility = visibility;
}
void GuiPropertyComponent::renderPropertyOwner(properties::PropertyOwner* owner) {
if (owner->propertiesRecursive().empty()) {
return;
@@ -54,7 +77,9 @@ void GuiPropertyComponent::renderPropertyOwner(properties::PropertyOwner* owner)
ImGui::PushID(owner->name().c_str());
const auto& subOwners = owner->propertySubOwners();
for (properties::PropertyOwner* subOwner : subOwners) {
if (subOwner->propertiesRecursive().empty()) {
std::vector<properties::Property*> properties = subOwner->propertiesRecursive();
int count = nVisibleProperties(properties, _visibility);
if (count == 0) {
continue;
}
if (subOwners.size() == 1) {
@@ -96,9 +121,7 @@ void GuiPropertyComponent::renderPropertyOwner(properties::PropertyOwner* owner)
ImGui::Spacing();
for (properties::Property* prop : remainingProperies) {
if (prop->isVisible()) {
renderProperty(prop, owner);
}
renderProperty(prop, owner);
}
ImGui::PopID();
}
@@ -121,8 +144,11 @@ void GuiPropertyComponent::render() {
);
for (properties::PropertyOwner* pOwner : owners) {
if (pOwner->propertiesRecursive().empty())
int count = nVisibleProperties(pOwner->propertiesRecursive(), _visibility);
if (count == 0) {
continue;
}
auto header = [&]() -> bool {
if (owners.size() > 1) {
@@ -146,9 +172,11 @@ void GuiPropertyComponent::render() {
ImGui::End();
}
void GuiPropertyComponent::renderProperty(properties::Property* prop, properties::PropertyOwner* owner) {
void GuiPropertyComponent::renderProperty(properties::Property* prop,
properties::PropertyOwner* owner)
{
using Func = std::function<void(properties::Property*, const std::string&)>;
static std::map<std::string, Func> FunctionMapping = {
static const std::map<std::string, Func> FunctionMapping = {
{ "BoolProperty", &renderBoolProperty },
{ "DoubleProperty", &renderDoubleProperty},
{ "IntProperty", &renderIntProperty },
@@ -165,9 +193,15 @@ void GuiPropertyComponent::renderProperty(properties::Property* prop, properties
{ "SelectionProperty", &renderSelectionProperty }
};
auto it = FunctionMapping.find(prop->className());
if (it != FunctionMapping.end()) {
it->second(prop, owner->name());
// Check if the visibility of the property is high enough to be displayed
using V = properties::Property::Visibility;
auto v = static_cast<std::underlying_type_t<V>>(_visibility);
auto propV = static_cast<std::underlying_type_t<V>>(prop->visibility());
if (v >= propV) {
auto it = FunctionMapping.find(prop->className());
if (it != FunctionMapping.end()) {
it->second(prop, owner->name());
}
}
}
+6 -4
View File
@@ -33,13 +33,15 @@ namespace properties {
const std::string OptionProperty::OptionsKey = "Options";
OptionProperty::OptionProperty(std::string identifier, std::string guiName)
: IntProperty(std::move(identifier), std::move(guiName))
OptionProperty::OptionProperty(std::string identifier, std::string guiName,
Visibility visibility)
: IntProperty(std::move(identifier), std::move(guiName), visibility)
, _displayType(DisplayType::Radio)
{}
OptionProperty::OptionProperty(std::string identifier, std::string guiName, DisplayType displayType)
: IntProperty(std::move(identifier), std::move(guiName))
OptionProperty::OptionProperty(std::string identifier, std::string guiName,
DisplayType displayType, Visibility visibility)
: IntProperty(std::move(identifier), std::move(guiName), visibility)
, _displayType(displayType)
{}
+26 -15
View File
@@ -35,7 +35,7 @@ namespace {
const std::string _loggerCat = "Property";
const std::string MetaDataKeyGuiName = "guiName";
const std::string MetaDataKeyGroup = "Group";
const std::string MetaDataKeyVisible = "isVisible";
const std::string MetaDataKeyVisibility = "Visibility";
const std::string MetaDataKeyReadOnly = "isReadOnly";
const std::string _metaDataKeyViewPrefix = "view.";
@@ -51,14 +51,14 @@ const std::string Property::NameKey = "Name";
const std::string Property::TypeKey = "Type";
const std::string Property::MetaDataKey = "MetaData";
Property::Property(std::string identifier, std::string guiName)
Property::Property(std::string identifier, std::string guiName, Visibility visibility)
: _owner(nullptr)
, _identifier(std::move(identifier))
{
ghoul_assert(!_identifier.empty(), "Identifier must not be empty");
ghoul_assert(!guiName.empty(), "guiName must not be empty");
setVisible(true);
setVisibility(visibility);
_metaData.setValue(MetaDataKeyGuiName, std::move(guiName));
}
@@ -131,14 +131,18 @@ std::string Property::groupIdentifier() const {
return result;
}
void Property::setVisible(bool state) {
_metaData.setValue(MetaDataKeyVisible, state);
void Property::setVisibility(Visibility visibility) {
_metaData.setValue(
MetaDataKeyVisibility,
static_cast<std::underlying_type_t<Visibility>>(visibility)
);
}
bool Property::isVisible() const {
bool visible = true;
_metaData.getValue(MetaDataKeyVisible, visible);
return visible;
Property::Visibility Property::visibility() const {
return
static_cast<Visibility>(
_metaData.value<std::underlying_type_t<Visibility>>(MetaDataKeyVisibility)
);
}
void Property::setReadOnly(bool state) {
@@ -185,15 +189,22 @@ std::string Property::generateBaseDescription() const {
}
std::string Property::generateMetaDataDescription() const {
bool isVisible, isReadOnly;
_metaData.getValue(MetaDataKeyVisible, isVisible);
_metaData.getValue(MetaDataKeyReadOnly, isReadOnly);
static const std::map<Visibility, std::string> VisibilityConverter = {
{ Visibility::All, "All" },
{ Visibility::Developer, "Developer" },
{ Visibility::User, "User" },
{ Visibility::None, "None" }
};
Visibility visibility = _metaData.value<Visibility>(MetaDataKeyVisibility);
bool isReadOnly = _metaData.value<bool>(MetaDataKeyReadOnly);
std::string vis = VisibilityConverter.at(visibility);
return
MetaDataKey + " = {" +
MetaDataKeyGroup + " = '" + groupIdentifier() + "'," +
MetaDataKeyVisible + " = " + (isVisible ? "true" : "false") + "," +
MetaDataKeyReadOnly +" = " + (isReadOnly ? "true" : "false") + "}";
MetaDataKeyGroup + " = '" + groupIdentifier() + "'," +
MetaDataKeyVisibility + " = " + vis + "," +
MetaDataKeyReadOnly +" = " + (isReadOnly ? "true" : "false") + "}";
}
std::string Property::generateAdditionalDescription() const {
+4 -2
View File
@@ -35,8 +35,10 @@ namespace properties {
const std::string SelectionProperty::OptionsKey = "Options";
SelectionProperty::SelectionProperty(std::string identifier, std::string guiName)
: TemplateProperty(std::move(identifier), std::move(guiName), std::vector<int>())
SelectionProperty::SelectionProperty(std::string identifier, std::string guiName,
Visibility visibility)
: TemplateProperty(std::move(identifier), std::move(guiName), std::vector<int>(),
visibility)
{}
void SelectionProperty::addOption(Option option) {
+3 -2
View File
@@ -27,8 +27,9 @@
namespace openspace {
namespace properties {
TriggerProperty::TriggerProperty(std::string identifier, std::string guiName)
: Property(std::move(identifier), std::move(guiName))
TriggerProperty::TriggerProperty(std::string identifier, std::string guiName,
Visibility visibility)
: Property(std::move(identifier), std::move(guiName), visibility)
{}
std::string TriggerProperty::className() const {