Skip to content

Commit

Permalink
editor: reusable property table
Browse files Browse the repository at this point in the history
  • Loading branch information
barsoosayque committed Nov 30, 2024
1 parent 4f3391c commit 690c7ea
Show file tree
Hide file tree
Showing 7 changed files with 179 additions and 145 deletions.
5 changes: 3 additions & 2 deletions crates/opensi-core/src/components.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,9 @@ pub struct Authors {
pub struct Round {
#[serde(rename = "@name")]
pub name: String,
// TODO: Actual enum of kinds
#[serde(rename = "@type", skip_serializing_if = "Option::is_none")]
pub variant: Option<String>,
pub kind: Option<String>,
#[serde(rename = "@info", skip_serializing_if = "Option::is_none")]
pub info: Option<Info>,
#[serde(with = "serde_impl::themes")]
Expand All @@ -45,7 +46,7 @@ pub struct Theme {
}

impl Theme {
/// Try to guess a price for the next question:
/// Try to guess price for the next question:
/// - Either a difference between the last two question prices;
/// - Or the last question's price plus 100;
///
Expand Down
63 changes: 21 additions & 42 deletions crates/opensi-editor/src/app/package_tab.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
use itertools::Itertools;
use opensi_core::prelude::*;

use crate::element::{danger_button, simple_row, unselectable_heading, unselectable_label};
use crate::element::{
danger_button, string_list, unselectable_heading, unselectable_label, PropertyTable,
};

/// Workarea tab to edit package info.
pub fn package_tab(package: &mut Package, selected: &mut Option<PackageNode>, ui: &mut egui::Ui) {
Expand Down Expand Up @@ -35,51 +37,28 @@ pub fn package_tab(package: &mut Package, selected: &mut Option<PackageNode>, ui
}

fn package_info_edit(package: &mut Package, ui: &mut egui::Ui) {
egui_extras::TableBuilder::new(ui)
.id_salt("package-info-edit")
.vscroll(false)
.column(egui_extras::Column::auto())
.column(egui_extras::Column::remainder())
.cell_layout(egui::Layout::left_to_right(egui::Align::Min))
.striped(false)
.body(|mut body| {
simple_row("Название", 20.0, &mut body, |ui| {
ui.text_edit_singleline(&mut package.name);
});
simple_row("Сложность", 20.0, &mut body, |ui| {
ui.add(egui::DragValue::new(&mut package.difficulty).range(0..=10));
});
simple_row("Ограничения", 20.0, &mut body, |ui| {
ui.text_edit_singleline(&mut package.restriction);
});
simple_row("Дата создания", 20.0, &mut body, |ui| {
ui.text_edit_singleline(&mut package.date);
});
simple_row("Издатель", 20.0, &mut body, |ui| {
ui.text_edit_singleline(&mut package.publisher);
});
simple_row("Язык", 20.0, &mut body, |ui| {
ui.text_edit_singleline(&mut package.language);
});
PropertyTable::new("package-info-properties").show(ui, |mut properties| {
properties.row("Название", |ui| ui.text_edit_singleline(&mut package.name));
properties.row("Сложность", |ui| {
ui.add(egui::DragValue::new(&mut package.difficulty).range(0..=10))
});
properties
.row("Ограничения", |ui| ui.text_edit_singleline(&mut package.restriction));
properties
.row("Дата создания", |ui| ui.text_edit_singleline(&mut package.date));
properties.row("Издатель", |ui| ui.text_edit_singleline(&mut package.publisher));
properties.row("Язык", |ui| ui.text_edit_singleline(&mut package.language));
properties
.multiline_row("Тэги", 2, |ui| string_list("package-tags", &mut package.tags, ui))
});
}

fn package_metadata_edit(package: &Package, ui: &mut egui::Ui) {
egui_extras::TableBuilder::new(ui)
.id_salt("package-metadata-edit")
.vscroll(false)
.column(egui_extras::Column::auto())
.column(egui_extras::Column::remainder())
.cell_layout(egui::Layout::left_to_right(egui::Align::Min))
.striped(true)
.body(|mut body| {
simple_row("ID пакета", 20.0, &mut body, |ui| {
ui.label(&package.id);
});
simple_row("Версия пакета", 20.0, &mut body, |ui| {
ui.label(format!("{:.1}", package.version));
});
});
PropertyTable::new("package-metadata-properties").readonly(true).show(ui, |mut properties| {
properties.row("ID пакета", |ui| ui.label(&package.id));
properties
.row("Версия пакета", |ui| ui.label(format!("{:.1}", package.version)));
});
}

fn package_rounds(package: &mut Package, selected: &mut Option<PackageNode>, ui: &mut egui::Ui) {
Expand Down
23 changes: 6 additions & 17 deletions crates/opensi-editor/src/app/round_tab.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
use opensi_core::prelude::*;

use crate::element::{
error_label, info_edit, simple_row, unselectable_heading, unselectable_label, Card,
};
use crate::element::{error_label, info_edit, unselectable_heading, Card, PropertyTable};

/// Workarea tab to edit round info and its themes.
pub fn round_tab(
Expand Down Expand Up @@ -47,21 +45,12 @@ pub fn round_tab(
}

fn round_edit(round: &mut Round, ui: &mut egui::Ui) {
egui_extras::TableBuilder::new(ui)
.id_salt("round-edit")
.column(egui_extras::Column::auto())
.column(egui_extras::Column::remainder())
.cell_layout(egui::Layout::left_to_right(egui::Align::Min))
.striped(false)
.body(|mut body| {
simple_row("Название", 20.0, &mut body, |ui| {
ui.text_edit_singleline(&mut round.name);
});
simple_row("Вариант", 20.0, &mut body, |ui| {
// TODO: variant enum
unselectable_label(format!("TODO: {:?}", round.variant), ui);
});
PropertyTable::new("round-properties").show(ui, |mut properties| {
properties.row("Название", |ui| ui.text_edit_singleline(&mut round.name));
properties.row("Тип", |ui| {
ui.add_enabled_ui(false, |ui| ui.label(format!("{:?}?", round.kind))).inner
});
});
}

fn round_themes(
Expand Down
16 changes: 4 additions & 12 deletions crates/opensi-editor/src/app/theme_tab.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use opensi_core::prelude::*;

use crate::element::{error_label, info_edit, simple_row, unselectable_heading, Card};
use crate::element::{error_label, info_edit, unselectable_heading, Card, PropertyTable};

pub fn theme_tab(
package: &mut Package,
Expand Down Expand Up @@ -44,17 +44,9 @@ pub fn theme_tab(
}

fn theme_edit(theme: &mut Theme, ui: &mut egui::Ui) {
egui_extras::TableBuilder::new(ui)
.id_salt("theme-edit")
.column(egui_extras::Column::auto())
.column(egui_extras::Column::remainder())
.cell_layout(egui::Layout::left_to_right(egui::Align::Min))
.striped(false)
.body(|mut body| {
simple_row("Название", 20.0, &mut body, |ui| {
ui.text_edit_singleline(&mut theme.name);
});
});
PropertyTable::new("theme-properties").show(ui, |mut properties| {
properties.row("Название", |ui| ui.text_edit_singleline(&mut theme.name));
});
}

fn theme_questions(
Expand Down
142 changes: 70 additions & 72 deletions crates/opensi-editor/src/element/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ use std::{borrow::Cow, fmt::Display};

use opensi_core::prelude::*;

use super::PropertyTable;

/// A generic error label.
pub fn error_label(error: impl Display, ui: &mut egui::Ui) {
let text =
Expand Down Expand Up @@ -60,67 +62,73 @@ pub fn unselectable_label(text: impl Into<egui::WidgetText>, ui: &mut egui::Ui)
ui.add(egui::Label::new(text).selectable(false))
}

pub fn string_list(id: impl Into<egui::Id>, list: &mut Vec<String>, ui: &mut egui::Ui) {
pub fn string_list(
id: impl Into<egui::Id>,
list: &mut Vec<String>,
ui: &mut egui::Ui,
) -> egui::Response {
ui.push_id(id.into(), |ui| {
ui.vertical(|ui| {
if list.is_empty() {
unselectable_label("Пусто...", ui);
} else {
ui.horizontal(|ui| {
let mut deleted_index = None;

for (index, item) in list.iter().enumerate() {
egui::Frame::none()
.rounding(4.0)
.inner_margin(egui::Margin { left: 4.0, ..Default::default() })
.fill(ui.style().visuals.widgets.inactive.bg_fill)
.show(ui, |ui| {
ui.horizontal(|ui| {
ui.label(item);
if ui.small_button("❌").clicked() {
deleted_index = Some(index);
}
ui.with_layout(
egui::Layout::top_down(egui::Align::Min)
.with_cross_justify(true)
.with_main_align(egui::Align::Center),
|ui| {
if list.is_empty() {
unselectable_label("Пусто...", ui);
} else {
ui.horizontal(|ui| {
let mut deleted_index = None;

for (index, item) in list.iter().enumerate() {
egui::Frame::none()
.rounding(4.0)
.inner_margin(egui::Margin { left: 4.0, ..Default::default() })
.fill(ui.style().visuals.widgets.inactive.bg_fill)
.show(ui, |ui| {
ui.horizontal(|ui| {
ui.label(item);
if ui.small_button("❌").clicked() {
deleted_index = Some(index);
}
});
});
});
}
}

if let Some(index) = deleted_index {
list.remove(index);
}
});
}
if let Some(index) = deleted_index {
list.remove(index);
}
});
}

ui.spacing();

ui.horizontal(|ui| {
let new_item_id = ui.id().with("new");
let mut text = ui.memory_mut(|memory| {
memory.data.get_temp_mut_or_default::<String>(new_item_id).clone()
});

if ui.button("➕").clicked() && !text.is_empty() {
list.push(text.clone());
ui.memory_mut(|memory| memory.data.remove_temp::<String>(new_item_id));
}

if ui.text_edit_singleline(&mut text).changed() {
ui.memory_mut(|memory| memory.data.insert_temp(new_item_id, text));
}
});
});
});
}

pub fn simple_row(
label: impl AsRef<str>,
height: f32,
body: &mut egui_extras::TableBody,
content: impl FnOnce(&mut egui::Ui),
) {
body.row(height, |mut row| {
row.col(|ui| {
ui.label(label.as_ref());
});
row.col(content);
});
egui_extras::StripBuilder::new(ui)
.size(egui_extras::Size::exact(22.0))
.size(egui_extras::Size::remainder())
.horizontal(|mut strip| {
strip.cell(|ui| {
if ui.button("➕").clicked() && !text.is_empty() {
list.push(text.clone());
ui.memory_mut(|memory| {
memory.data.remove_temp::<String>(new_item_id)
});
}
});

strip.cell(|ui| {
if ui.text_edit_singleline(&mut text).changed() {
ui.memory_mut(|memory| memory.data.insert_temp(new_item_id, text));
}
});
});
},
);
})
.response
}

pub fn info_edit(info: &mut Option<Info>, ui: &mut egui::Ui) {
Expand All @@ -131,24 +139,14 @@ pub fn info_edit(info: &mut Option<Info>, ui: &mut egui::Ui) {
return;
};

egui_extras::TableBuilder::new(ui)
.id_salt("round-info-edit")
.column(egui_extras::Column::auto())
.column(egui_extras::Column::remainder())
.cell_layout(egui::Layout::left_to_right(egui::Align::Min))
.striped(true)
.body(|mut body| {
simple_row("Авторы", 40.0, &mut body, |ui| {
string_list("round-authors", &mut info.authors, ui);
});
simple_row("Источники", 40.0, &mut body, |ui| {
string_list("round-sources", &mut info.sources, ui);
});
simple_row("Комментарий", 20.0, &mut body, |ui| {
ui.text_edit_singleline(&mut info.comments);
});
simple_row("Расширения", 20.0, &mut body, |ui| {
ui.text_edit_singleline(&mut info.extension);
});
PropertyTable::new("info-properties").show(ui, |mut properties| {
properties.multiline_row("Авторы", 2, |ui| {
string_list("info-properties-authors", &mut info.authors, ui)
});
properties.multiline_row("Источники", 2, |ui| {
string_list("info-properties-sources", &mut info.sources, ui)
});
properties.row("Комментарий", |ui| ui.text_edit_singleline(&mut info.comments));
properties.row("Расширения", |ui| ui.text_edit_singleline(&mut info.extension));
});
}
2 changes: 2 additions & 0 deletions crates/opensi-editor/src/element/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
pub mod card;
pub mod common;
pub mod property;

pub use card::Card;
pub use common::*;
pub use property::PropertyTable;
Loading

0 comments on commit 690c7ea

Please sign in to comment.