mirror of
https://github.com/OpenSpace/OpenSpace.git
synced 2026-05-08 12:30:00 -05:00
Merge branch 'feature/guisorting'
# Conflicts: # modules/imgui/include/guipropertycomponent.h # modules/imgui/src/guipropertycomponent.cpp
This commit is contained in:
@@ -28,6 +28,8 @@
|
||||
#include <modules/imgui/include/guicomponent.h>
|
||||
|
||||
#include <openspace/properties/property.h>
|
||||
#include <openspace/properties/stringlistproperty.h>
|
||||
#include <openspace/properties/scalar/boolproperty.h>
|
||||
|
||||
#include <ghoul/misc/boolean.h>
|
||||
|
||||
@@ -72,8 +74,10 @@ protected:
|
||||
/// are regular, i.e., not containing wildcards, regex, or groups
|
||||
/// This variable only has an impact on which \c setPropertyValue function is called
|
||||
bool _hasOnlyRegularProperties = false;
|
||||
UseTreeLayout _useTreeLayout;
|
||||
bool _currentUseTreeLayout;
|
||||
|
||||
properties::BoolProperty _useTreeLayout;
|
||||
properties::StringListProperty _treeOrdering;
|
||||
|
||||
bool _showHelpTooltip;
|
||||
};
|
||||
|
||||
|
||||
@@ -57,6 +57,10 @@ void renderStringProperty(properties::Property* prop, const std::string& ownerNa
|
||||
IsRegularProperty isRegular = IsRegularProperty::Yes,
|
||||
ShowToolTip showTooltip = ShowToolTip::Yes);
|
||||
|
||||
void renderStringListProperty(properties::Property* prop, const std::string& ownerName,
|
||||
IsRegularProperty isRegular = IsRegularProperty::Yes,
|
||||
ShowToolTip showTooltip = ShowToolTip::Yes);
|
||||
|
||||
void renderDoubleProperty(properties::Property* prop, const std::string& ownerName,
|
||||
IsRegularProperty isRegular = IsRegularProperty::Yes,
|
||||
ShowToolTip showTooltip = ShowToolTip::Yes);
|
||||
|
||||
@@ -626,11 +626,6 @@ void GUI::startFrame(float deltaTime, const glm::vec2& windowSize,
|
||||
}
|
||||
|
||||
void GUI::endFrame() {
|
||||
LINFOC("Enabled", _isEnabled);
|
||||
LINFOC("Collapsed", _isCollapsed);
|
||||
LINFOC("Hidden", _allHidden);
|
||||
|
||||
|
||||
if (_program->isDirty()) {
|
||||
_program->rebuildFromFile();
|
||||
}
|
||||
|
||||
@@ -37,6 +37,22 @@
|
||||
namespace {
|
||||
const ImVec2 size = ImVec2(350, 500);
|
||||
|
||||
static const openspace::properties::Property::PropertyInfo UseTreeInfo = {
|
||||
"TreeLayout",
|
||||
"Use Tree Layout",
|
||||
"If this value is checked, this component will display the properties using a "
|
||||
"tree layout, rather than using a flat map. This value should only be set on "
|
||||
"property windows that display SceneGraphNodes, or the application might crash."
|
||||
};
|
||||
|
||||
static const openspace::properties::Property::PropertyInfo OrderingInfo = {
|
||||
"Ordering",
|
||||
"Tree Ordering",
|
||||
"This list determines the order of the first tree layer if it is used. Elements "
|
||||
"present in this list will be shown first, with an alphabetical ordering for "
|
||||
"elements not listed."
|
||||
};
|
||||
|
||||
int nVisibleProperties(const std::vector<openspace::properties::Property*>& props,
|
||||
openspace::properties::Property::Visibility visibility)
|
||||
{
|
||||
@@ -148,9 +164,12 @@ namespace openspace::gui {
|
||||
|
||||
GuiPropertyComponent::GuiPropertyComponent(std::string name, UseTreeLayout useTree)
|
||||
: GuiComponent(std::move(name))
|
||||
, _useTreeLayout(useTree)
|
||||
, _currentUseTreeLayout(useTree)
|
||||
{}
|
||||
, _useTreeLayout(UseTreeInfo, useTree)
|
||||
, _treeOrdering(OrderingInfo)
|
||||
{
|
||||
addProperty(_useTreeLayout);
|
||||
addProperty(_treeOrdering);
|
||||
}
|
||||
|
||||
void GuiPropertyComponent::setSource(SourceFunction function) {
|
||||
_function = std::move(function);
|
||||
@@ -241,13 +260,9 @@ void GuiPropertyComponent::render() {
|
||||
_isEnabled = v;
|
||||
|
||||
_isCollapsed = ImGui::IsWindowCollapsed();
|
||||
using namespace properties;
|
||||
|
||||
if (_function) {
|
||||
if (_useTreeLayout) {
|
||||
ImGui::Checkbox("Use Tree layout", &_currentUseTreeLayout);
|
||||
}
|
||||
|
||||
|
||||
std::vector<properties::PropertyOwner*> owners = _function();
|
||||
|
||||
std::sort(
|
||||
@@ -258,7 +273,7 @@ void GuiPropertyComponent::render() {
|
||||
}
|
||||
);
|
||||
|
||||
if (_currentUseTreeLayout) {
|
||||
if (_useTreeLayout) {
|
||||
for (properties::PropertyOwner* owner : owners) {
|
||||
ghoul_assert(
|
||||
dynamic_cast<SceneGraphNode*>(owner),
|
||||
@@ -268,12 +283,14 @@ void GuiPropertyComponent::render() {
|
||||
}
|
||||
|
||||
// Sort:
|
||||
// if guigrouping, sort by name and shortest first
|
||||
// if guigrouping, sort by name and shortest first, but respect the user
|
||||
// specified ordering
|
||||
// then all w/o guigroup
|
||||
const std::vector<std::string>& ordering = _treeOrdering;
|
||||
std::stable_sort(
|
||||
owners.begin(),
|
||||
owners.end(),
|
||||
[](properties::PropertyOwner* lhs, properties::PropertyOwner* rhs) {
|
||||
[&ordering](PropertyOwner* lhs, PropertyOwner* rhs) {
|
||||
std::string lhsGroup = static_cast<SceneGraphNode*>(lhs)->guiPath();
|
||||
std::string rhsGroup = static_cast<SceneGraphNode*>(rhs)->guiPath();
|
||||
|
||||
@@ -283,7 +300,40 @@ void GuiPropertyComponent::render() {
|
||||
if (rhsGroup.empty()) {
|
||||
return true;
|
||||
}
|
||||
return lhsGroup < rhsGroup;
|
||||
|
||||
if (ordering.empty()) {
|
||||
return lhsGroup < rhsGroup;
|
||||
}
|
||||
|
||||
std::vector<std::string> lhsToken = ghoul::tokenizeString(
|
||||
lhsGroup,
|
||||
'/'
|
||||
);
|
||||
// The first token is always empty
|
||||
auto lhsIt = std::find(ordering.begin(), ordering.end(), lhsToken[1]);
|
||||
|
||||
std::vector<std::string> rhsToken = ghoul::tokenizeString(
|
||||
rhsGroup,
|
||||
'/'
|
||||
);
|
||||
// The first token is always empty
|
||||
auto rhsIt = std::find(ordering.begin(), ordering.end(), rhsToken[1]);
|
||||
|
||||
if (lhsIt != ordering.end() && rhsIt != ordering.end()) {
|
||||
// If both top-level groups are in the ordering list, the order
|
||||
// of the iterators gives us the order of the groups
|
||||
return lhsIt < rhsIt;
|
||||
}
|
||||
else if (lhsIt != ordering.end() && rhsIt == ordering.end()) {
|
||||
// If only one of them is in the list, we have a sorting
|
||||
return true;
|
||||
}
|
||||
else if (lhsIt == ordering.end() && rhsIt != ordering.end()) {
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
return lhsGroup < rhsGroup;
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
@@ -326,7 +376,7 @@ void GuiPropertyComponent::render() {
|
||||
}
|
||||
};
|
||||
|
||||
if (!_currentUseTreeLayout || noGuiGroups) {
|
||||
if (!_useTreeLayout || noGuiGroups) {
|
||||
std::for_each(owners.begin(), owners.end(), renderProp);
|
||||
}
|
||||
else { // _useTreeLayout && gui groups exist
|
||||
@@ -395,6 +445,7 @@ void GuiPropertyComponent::renderProperty(properties::Property* prop,
|
||||
{ "DMat3Property", &renderDMat3Property },
|
||||
{ "DMat4Property", &renderDMat4Property },
|
||||
{ "StringProperty", &renderStringProperty },
|
||||
{ "StringListProperty", &renderStringListProperty },
|
||||
{ "OptionProperty", &renderOptionProperty },
|
||||
{ "TriggerProperty", &renderTriggerProperty },
|
||||
{ "SelectionProperty", &renderSelectionProperty }
|
||||
|
||||
@@ -32,10 +32,12 @@
|
||||
#include <openspace/properties/optionproperty.h>
|
||||
#include <openspace/properties/selectionproperty.h>
|
||||
#include <openspace/properties/stringproperty.h>
|
||||
#include <openspace/properties/stringlistproperty.h>
|
||||
#include <openspace/properties/vectorproperty.h>
|
||||
#include <openspace/scripting/scriptengine.h>
|
||||
|
||||
#include <ghoul/filesystem/filesystem.h>
|
||||
#include <ghoul/misc/misc.h>
|
||||
|
||||
namespace openspace {
|
||||
|
||||
@@ -244,6 +246,56 @@ void renderStringProperty(Property* prop, const std::string& ownerName,
|
||||
ImGui::PopID();
|
||||
}
|
||||
|
||||
void renderStringListProperty(Property* prop, const std::string& ownerName,
|
||||
IsRegularProperty isRegular, ShowToolTip showTooltip)
|
||||
{
|
||||
ghoul_assert(prop, "prop must not be nullptr");
|
||||
StringListProperty* p = static_cast<StringListProperty*>(prop);
|
||||
std::string name = p->guiName();
|
||||
ImGui::PushID((ownerName + "." + name).c_str());
|
||||
|
||||
std::string value;
|
||||
p->getStringValue(value);
|
||||
// const std::string value = p->value();
|
||||
|
||||
static const int bufferSize = 512;
|
||||
static char buffer[bufferSize];
|
||||
#ifdef _MSC_VER
|
||||
strcpy_s(buffer, value.length() + 1, value.c_str());
|
||||
#else
|
||||
strcpy(buffer, value.c_str());
|
||||
#endif
|
||||
bool hasNewValue = ImGui::InputText(
|
||||
name.c_str(),
|
||||
buffer,
|
||||
bufferSize,
|
||||
ImGuiInputTextFlags_EnterReturnsTrue
|
||||
);
|
||||
if (showTooltip) {
|
||||
renderTooltip(prop);
|
||||
}
|
||||
|
||||
if (hasNewValue) {
|
||||
std::vector<std::string> tokens = ghoul::tokenizeString(std::string(buffer), ',');
|
||||
std::string script = "{";
|
||||
for (std::string& token : tokens) {
|
||||
if (!token.empty()) {
|
||||
ghoul::trimWhitespace(token);
|
||||
script += "[[" + token + "]],";
|
||||
}
|
||||
}
|
||||
script += "}";
|
||||
|
||||
executeScript(
|
||||
p->fullyQualifiedIdentifier(),
|
||||
std::move(script),
|
||||
isRegular
|
||||
);
|
||||
}
|
||||
|
||||
ImGui::PopID();
|
||||
}
|
||||
|
||||
void renderDoubleProperty(properties::Property* prop, const std::string& ownerName,
|
||||
IsRegularProperty isRegular, ShowToolTip showTooltip)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user