feat(dashboard): ✨ Implement Vector control
This commit is contained in:
parent
0f4aca4094
commit
a06232a4a6
|
@ -1,4 +1,4 @@
|
|||
use super::{NestingInfo, SettingControl};
|
||||
use super::{collapsible, NestingInfo, SettingControl};
|
||||
use alvr_packets::PathValuePair;
|
||||
use alvr_session::settings_schema::SchemaNode;
|
||||
use eframe::egui::Ui;
|
||||
|
@ -37,24 +37,12 @@ impl Control {
|
|||
) -> Option<PathValuePair> {
|
||||
super::grid_flow_inline(ui, allow_inline);
|
||||
|
||||
let json::Value::Bool(collapsed_state_mut) = &mut session_fragment["gui_collapsed"] else {
|
||||
unreachable!()
|
||||
};
|
||||
|
||||
let mut request = None;
|
||||
|
||||
if (*collapsed_state_mut && ui.small_button("Expand").clicked())
|
||||
|| (!*collapsed_state_mut && ui.small_button("Collapse").clicked())
|
||||
{
|
||||
*collapsed_state_mut = !*collapsed_state_mut;
|
||||
request = super::set_single_value(
|
||||
&self.nesting_info,
|
||||
"gui_collapsed".into(),
|
||||
json::Value::Bool(*collapsed_state_mut),
|
||||
);
|
||||
}
|
||||
let collapsed =
|
||||
collapsible::collapsible_button(ui, &self.nesting_info, session_fragment, &mut request);
|
||||
|
||||
if !*collapsed_state_mut {
|
||||
if !collapsed {
|
||||
let session_array_mut = session_fragment["content"].as_array_mut().unwrap();
|
||||
|
||||
for (idx, control) in self.controls.iter_mut().enumerate() {
|
||||
|
|
|
@ -113,7 +113,7 @@ impl Control {
|
|||
};
|
||||
|
||||
fn get_request(nesting_info: &NestingInfo, variant: &str) -> Option<PathValuePair> {
|
||||
super::set_single_value(
|
||||
super::get_single_value(
|
||||
nesting_info,
|
||||
"variant".into(),
|
||||
json::Value::String(variant.to_owned()),
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
use super::NestingInfo;
|
||||
use alvr_packets::PathValuePair;
|
||||
use eframe::egui::Ui;
|
||||
use serde_json as json;
|
||||
|
||||
pub fn collapsible_button(
|
||||
ui: &mut Ui,
|
||||
nesting_info: &NestingInfo,
|
||||
session_fragment: &mut json::Value,
|
||||
request: &mut Option<PathValuePair>,
|
||||
) -> bool {
|
||||
let json::Value::Bool(state_mut) = &mut session_fragment["gui_collapsed"] else {
|
||||
unreachable!()
|
||||
};
|
||||
|
||||
if (*state_mut && ui.small_button("Expand").clicked())
|
||||
|| (!*state_mut && ui.small_button("Collapse").clicked())
|
||||
{
|
||||
*state_mut = !*state_mut;
|
||||
*request = super::get_single_value(
|
||||
nesting_info,
|
||||
"gui_collapsed".into(),
|
||||
json::Value::Bool(*state_mut),
|
||||
);
|
||||
}
|
||||
|
||||
*state_mut
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
pub mod array;
|
||||
pub mod boolean;
|
||||
pub mod choice;
|
||||
pub mod collapsible;
|
||||
pub mod dictionary;
|
||||
pub mod help;
|
||||
pub mod notice;
|
||||
|
@ -21,7 +22,7 @@ use std::collections::HashMap;
|
|||
|
||||
pub const INDENTATION_STEP: f32 = 20.0;
|
||||
|
||||
fn set_single_value(
|
||||
fn get_single_value(
|
||||
nesting_info: &NestingInfo,
|
||||
leaf: PathSegment,
|
||||
new_value: json::Value,
|
||||
|
@ -65,6 +66,7 @@ pub enum SettingControl {
|
|||
Text(text::Control),
|
||||
Numeric(number::Control),
|
||||
Array(array::Control),
|
||||
Vector(vector::Control),
|
||||
None,
|
||||
}
|
||||
|
||||
|
@ -109,7 +111,14 @@ impl SettingControl {
|
|||
SchemaNode::Array(schema_array) => {
|
||||
Self::Array(array::Control::new(nesting_info, schema_array))
|
||||
}
|
||||
// SchemaNode::Vector { default_element, default } => todo!(),
|
||||
SchemaNode::Vector {
|
||||
default_element,
|
||||
default,
|
||||
} => Self::Vector(vector::Control::new(
|
||||
nesting_info,
|
||||
*default_element,
|
||||
default,
|
||||
)),
|
||||
// SchemaNode::Dictionary { default_key, default_value, default } => todo!(),
|
||||
_ => Self::None,
|
||||
}
|
||||
|
@ -131,6 +140,7 @@ impl SettingControl {
|
|||
Self::Text(control) => control.ui(ui, session_fragment, allow_inline),
|
||||
Self::Numeric(control) => control.ui(ui, session_fragment, allow_inline),
|
||||
Self::Array(control) => control.ui(ui, session_fragment, allow_inline),
|
||||
Self::Vector(control) => control.ui(ui, session_fragment, allow_inline),
|
||||
Self::None => {
|
||||
grid_flow_inline(ui, allow_inline);
|
||||
ui.add_enabled_ui(false, |ui| ui.label("Unimplemented UI"));
|
||||
|
|
|
@ -54,7 +54,7 @@ impl Control {
|
|||
let mut request = None;
|
||||
|
||||
fn get_request(nesting_info: &NestingInfo, enabled: bool) -> Option<PathValuePair> {
|
||||
super::set_single_value(nesting_info, "set".into(), json::Value::Bool(enabled))
|
||||
super::get_single_value(nesting_info, "set".into(), json::Value::Bool(enabled))
|
||||
}
|
||||
|
||||
ui.with_layout(Layout::left_to_right(Align::Center), |ui| {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use super::{NestingInfo, SettingControl, INDENTATION_STEP};
|
||||
use super::{collapsible, NestingInfo, SettingControl, INDENTATION_STEP};
|
||||
use crate::dashboard::DisplayString;
|
||||
use alvr_gui_common::theme::{
|
||||
log_colors::{INFO_LIGHT, WARNING_LIGHT},
|
||||
|
@ -78,26 +78,18 @@ impl Control {
|
|||
let collapsed = if self.gui_collapsible {
|
||||
super::grid_flow_inline(ui, allow_inline);
|
||||
|
||||
let json::Value::Bool(state_mut) = &mut session_fragment["gui_collapsed"] else {
|
||||
unreachable!()
|
||||
};
|
||||
let collapsed = collapsible::collapsible_button(
|
||||
ui,
|
||||
&self.nesting_info,
|
||||
session_fragment,
|
||||
&mut request,
|
||||
);
|
||||
|
||||
if (*state_mut && ui.small_button("Expand").clicked())
|
||||
|| (!*state_mut && ui.small_button("Collapse").clicked())
|
||||
{
|
||||
*state_mut = !*state_mut;
|
||||
request = super::set_single_value(
|
||||
&self.nesting_info,
|
||||
"gui_collapsed".into(),
|
||||
json::Value::Bool(*state_mut),
|
||||
);
|
||||
}
|
||||
|
||||
if !*state_mut {
|
||||
if !collapsed {
|
||||
ui.end_row();
|
||||
}
|
||||
|
||||
*state_mut
|
||||
collapsed
|
||||
} else {
|
||||
if allow_inline {
|
||||
ui.end_row();
|
||||
|
|
|
@ -59,7 +59,7 @@ impl Control {
|
|||
let mut request = None;
|
||||
|
||||
fn get_request(nesting_info: &NestingInfo, enabled: bool) -> Option<PathValuePair> {
|
||||
super::set_single_value(nesting_info, "enabled".into(), json::Value::Bool(enabled))
|
||||
super::get_single_value(nesting_info, "enabled".into(), json::Value::Bool(enabled))
|
||||
}
|
||||
|
||||
ui.with_layout(Layout::left_to_right(Align::Center), |ui| {
|
||||
|
|
|
@ -1,18 +1,153 @@
|
|||
// use super::{SettingContainer, SettingsContext, SettingsResponse};
|
||||
// use crate::dashboard::DashboardResponse;
|
||||
// use egui::Ui;
|
||||
// use serde_json as json;
|
||||
// use settings_schema::VectorDefault;
|
||||
use crate::dashboard::components::collapsible;
|
||||
|
||||
// pub struct Vector {}
|
||||
use super::{reset, NestingInfo, SettingControl, INDENTATION_STEP};
|
||||
use alvr_packets::PathValuePair;
|
||||
use alvr_session::settings_schema::SchemaNode;
|
||||
use eframe::{
|
||||
egui::{self, Layout, Ui},
|
||||
emath::Align,
|
||||
};
|
||||
use serde_json as json;
|
||||
|
||||
// impl SettingContainer for Vector {
|
||||
// fn ui(
|
||||
// &mut self,
|
||||
// ui: &mut Ui,
|
||||
// session_fragment: json::Value,
|
||||
// context: &SettingsContext,
|
||||
// ) -> Option<SettingsResponse> {
|
||||
// None
|
||||
// }
|
||||
// }
|
||||
pub struct Control {
|
||||
nesting_info: NestingInfo,
|
||||
default_element: SchemaNode,
|
||||
default: Vec<json::Value>,
|
||||
controls: Vec<SettingControl>,
|
||||
}
|
||||
|
||||
impl Control {
|
||||
pub fn new(
|
||||
nesting_info: NestingInfo,
|
||||
default_element: SchemaNode,
|
||||
default: Vec<json::Value>,
|
||||
) -> Self {
|
||||
Self {
|
||||
nesting_info,
|
||||
default_element,
|
||||
default,
|
||||
controls: vec![],
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ui(
|
||||
&mut self,
|
||||
ui: &mut Ui,
|
||||
session_fragment: &mut json::Value,
|
||||
allow_inline: bool,
|
||||
) -> Option<PathValuePair> {
|
||||
super::grid_flow_inline(ui, allow_inline);
|
||||
|
||||
let mut request = None;
|
||||
let collapsed = ui
|
||||
.with_layout(Layout::left_to_right(Align::Center), |ui| {
|
||||
let collapsed = collapsible::collapsible_button(
|
||||
ui,
|
||||
&self.nesting_info,
|
||||
session_fragment,
|
||||
&mut request,
|
||||
);
|
||||
|
||||
if reset::reset_button(ui, true, "default list").clicked() {
|
||||
request = get_content_request(&self.nesting_info, self.default.clone())
|
||||
}
|
||||
|
||||
collapsed
|
||||
})
|
||||
.inner;
|
||||
|
||||
{
|
||||
let session_array_mut = session_fragment["content"].as_array().unwrap();
|
||||
|
||||
while session_array_mut.len() > self.controls.len() {
|
||||
let mut nesting_info = self.nesting_info.clone();
|
||||
nesting_info.path.push("content".into());
|
||||
nesting_info.path.push(self.controls.len().into());
|
||||
|
||||
self.controls.push(SettingControl::new(
|
||||
nesting_info,
|
||||
self.default_element.clone(),
|
||||
))
|
||||
}
|
||||
while session_array_mut.len() < self.controls.len() {
|
||||
self.controls.pop();
|
||||
}
|
||||
}
|
||||
|
||||
fn get_content_request(
|
||||
nesting_info: &NestingInfo,
|
||||
elements: Vec<json::Value>,
|
||||
) -> Option<PathValuePair> {
|
||||
super::get_single_value(nesting_info, "content".into(), json::Value::Array(elements))
|
||||
}
|
||||
|
||||
if !collapsed {
|
||||
ui.end_row();
|
||||
|
||||
let mut idx = 0;
|
||||
while idx < self.controls.len() {
|
||||
let response = ui
|
||||
.horizontal(|ui| {
|
||||
ui.add_space(INDENTATION_STEP * self.nesting_info.indentation_level as f32);
|
||||
|
||||
let response = ui.button("❌");
|
||||
|
||||
ui.with_layout(Layout::top_down(Align::LEFT), |ui| {
|
||||
let session_content =
|
||||
session_fragment["content"].as_array_mut().unwrap();
|
||||
|
||||
ui.spacing_mut().item_spacing = egui::vec2(0.0, 0.0);
|
||||
|
||||
let up_clicked = ui
|
||||
.add_visible_ui(idx > 0, |ui| ui.small_button("⬆"))
|
||||
.inner
|
||||
.clicked();
|
||||
let down_clicked = ui
|
||||
.add_visible_ui(idx < self.controls.len() - 1, |ui| {
|
||||
ui.small_button("⬇")
|
||||
})
|
||||
.inner
|
||||
.clicked();
|
||||
|
||||
if up_clicked || down_clicked {
|
||||
let mut session_content = session_content.clone();
|
||||
session_content
|
||||
.swap(idx, if up_clicked { idx - 1 } else { idx + 1 });
|
||||
|
||||
request = get_content_request(&self.nesting_info, session_content);
|
||||
}
|
||||
});
|
||||
|
||||
response
|
||||
})
|
||||
.inner;
|
||||
|
||||
let session_array_mut = session_fragment["content"].as_array_mut().unwrap();
|
||||
|
||||
if response.clicked() {
|
||||
session_array_mut.remove(idx);
|
||||
self.controls.remove(idx);
|
||||
} else {
|
||||
request = self.controls[idx]
|
||||
.ui(ui, &mut session_array_mut[idx], true)
|
||||
.or(request);
|
||||
}
|
||||
|
||||
ui.end_row();
|
||||
|
||||
idx += 1;
|
||||
}
|
||||
|
||||
ui.label(" ");
|
||||
if ui.button("Add element").clicked() {
|
||||
let mut session_content =
|
||||
session_fragment["content"].as_array_mut().unwrap().clone();
|
||||
session_content.push(session_fragment["element"].clone());
|
||||
|
||||
request = get_content_request(&self.nesting_info, session_content);
|
||||
}
|
||||
}
|
||||
|
||||
request
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue