feat(dashboard): Implement Vector control

This commit is contained in:
Riccardo Zaglia 2023-09-12 15:10:24 +08:00
parent 0f4aca4094
commit a06232a4a6
8 changed files with 207 additions and 54 deletions

View File

@ -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() {

View File

@ -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()),

View File

@ -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
}

View File

@ -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"));

View File

@ -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| {

View File

@ -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();

View File

@ -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| {

View File

@ -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
}
}