Skip to content

Commit

Permalink
goryak: personal layer over yakui
Browse files Browse the repository at this point in the history
make my own UI framework over yakui with theme support and more
  • Loading branch information
Uriopass committed Dec 23, 2023
1 parent c358d70 commit 29dcca1
Show file tree
Hide file tree
Showing 13 changed files with 1,778 additions and 217 deletions.
18 changes: 18 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

424 changes: 242 additions & 182 deletions assets_gui/src/yakui_gui.rs

Large diffs are not rendered by default.

5 changes: 4 additions & 1 deletion goryak/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,7 @@ description = "Egregoria's yakui component library"

[dependencies]
yakui-core = { git = "https://github.com/SecondHalfGames/yakui" }
yakui-widgets = { git = "https://github.com/SecondHalfGames/yakui" }
yakui-widgets = { git = "https://github.com/SecondHalfGames/yakui" }
nanoserde = "0.1.35"
lazy_static = "1.4.0"
serde = { version = "1.0.193", features = ["derive"] }
11 changes: 6 additions & 5 deletions goryak/src/combo_box.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use yakui_core::geometry::{Color, Constraints, Dim2, Vec2};
use crate::{background, button_secondary};
use yakui_core::geometry::{Constraints, Dim2, Vec2};
use yakui_core::{Alignment, CrossAxisAlignment, MainAxisAlignment, MainAxisSize};
use yakui_widgets::widgets::{Layer, List, Pad};
use yakui_widgets::{button, colored_box_container, constrained, pad, reflow, use_state};
use yakui_widgets::{colored_box_container, constrained, pad, reflow, use_state};

pub fn combo_box(selected: &mut usize, items: &[&str], w: f32) -> bool {
let mut changed = false;
Expand All @@ -14,15 +15,15 @@ pub fn combo_box(selected: &mut usize, items: &[&str], w: f32) -> bool {
l.show(|| {
let open = use_state(|| false);

if button(items[*selected].to_string()).clicked {
if button_secondary(items[*selected].to_string()).clicked {
open.modify(|x| !x);
}

if open.get() {
Layer::new().show(|| {
reflow(Alignment::BOTTOM_LEFT, Dim2::ZERO, || {
constrained(Constraints::loose(Vec2::new(w, f32::INFINITY)), || {
colored_box_container(Color::GRAY.adjust(0.8), || {
colored_box_container(background(), || {
Pad::all(3.0).show(|| {
let mut l = List::column();
l.cross_axis_alignment = CrossAxisAlignment::Stretch;
Expand All @@ -33,7 +34,7 @@ pub fn combo_box(selected: &mut usize, items: &[&str], w: f32) -> bool {
continue;
}

if button(item.to_string()).clicked {
if button_secondary(item.to_string()).clicked {
*selected = i;
open.set(false);
changed = true;
Expand Down
1 change: 1 addition & 0 deletions goryak/src/count_grid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,7 @@ impl Widget for CountGridWidget {
MainAxisAlignItems::Start | MainAxisAlignItems::Stretch => cell_main_max,
_ => max_sizes[n_cross + main_id],
};
#[allow(unreachable_patterns)]
let offset_main = match self.props.main_axis_align_items {
MainAxisAlignItems::Start | MainAxisAlignItems::Stretch => 0.0,
MainAxisAlignItems::Center => ((cell_main_size - child_main_size) / 2.0).max(0.0),
Expand Down
131 changes: 116 additions & 15 deletions goryak/src/dragvalue.rs
Original file line number Diff line number Diff line change
@@ -1,38 +1,139 @@
use crate::stretch_width;
use yakui_widgets::pad;
use yakui_widgets::widgets::{Pad, Slider};
use yakui_core::geometry::Vec2;
use yakui_core::MainAxisAlignment;
use yakui_widgets::widgets::{List, Pad};
use yakui_widgets::{draggable, pad, use_state};

use crate::roundrect::RoundRect;
use crate::{labelc, on_primary, outline, secondary};

pub trait Draggable: Copy {
const DEFAULT_STEP: f64;
const DEFAULT_MIN: f64;
const DEFAULT_MAX: f64;

fn to_f64(self) -> f64;
fn from_f64(v: f64) -> Self;
fn default_step() -> f64;
}

macro_rules! impl_slidable {
($($t:ty),*) => {
($($t:ty; $step:expr),*) => {
$(
impl Draggable for $t {
const DEFAULT_STEP: f64 = $step;
const DEFAULT_MIN: f64 = <$t>::MIN as f64;
const DEFAULT_MAX: f64 = <$t>::MAX as f64;

fn to_f64(self) -> f64 {
self as f64
}

fn from_f64(v: f64) -> Self {
v as Self
}

fn default_step() -> f64 {
$step
}

}
)*
};
}

impl_slidable!(i32, u32, i64, u64, f32, f64);
impl_slidable!(i32; 1.0,
u32; 1.0,
i64; 1.0,
u64; 1.0,
f32; 0.01,
f64; 0.01);

pub fn drag_value<T: Draggable>(amount: &mut T) {
stretch_width(|| {
pad(Pad::horizontal(10.0), || {
let mut slider = Slider::new((*amount).to_f64(), 1.0, 10.0);
slider.step = Some(1.0);
if let Some(v) = slider.show().value {
*amount = Draggable::from_f64(v);
}
});
});
pub struct DragValue {
min: Option<f64>,
max: Option<f64>,
step: Option<f64>,
}

impl DragValue {
pub fn min(mut self, v: f64) -> Self {
self.min = Some(v);
self
}

pub fn max(mut self, v: f64) -> Self {
self.max = Some(v);
self
}
pub fn minmax(mut self, r: std::ops::Range<f64>) -> Self {
self.min = Some(r.start);
self.max = Some(r.end);
self
}

pub fn step(mut self, v: f64) -> Self {
self.step = Some(v);
self
}

/// Returns true if the value was changed.
pub fn show<T: Draggable>(self, value: &mut T) -> bool {
let mut changed = false;

RoundRect::new(2.0)
.outline(outline(), 2.0)
.color(secondary())
.show_children(|| {
let dragged = draggable_delta(|| {
pad(Pad::horizontal(10.0), || {
let mut l = List::row();
l.main_axis_alignment = MainAxisAlignment::Center;
l.show(|| {
labelc(on_primary(), format!("{}", T::to_f64(*value)));
});
});
});

if let Some(dragged) = dragged {
let oldv = T::to_f64(*value);
let newv = oldv + dragged.x as f64 * self.step.unwrap_or(T::default_step());

*value = T::from_f64(newv.clamp(
self.min.unwrap_or(T::DEFAULT_MIN),
self.max.unwrap_or(T::DEFAULT_MAX),
));
changed = true;
}
});

changed
}
}

fn draggable_delta(children: impl FnOnce()) -> Option<Vec2> {
let last_val_state = use_state(|| None);
let Some(mut d) = draggable(children).dragging else {
last_val_state.set(None);
return None;
};

let last_val = last_val_state.get().unwrap_or(d.current);
let mut delta = d.current - last_val;
if delta.x.abs() < 1.0 {
d.current.x = last_val.x;
delta.x = 0.0;
}
if delta.y.abs() < 1.0 {
d.current.y = last_val.y;
delta.y = 0.0;
}
last_val_state.set(Some(d.current));
Some(delta)
}

pub fn dragvalue() -> DragValue {
DragValue {
min: None,
max: None,
step: None,
}
}
5 changes: 3 additions & 2 deletions goryak/src/hovered.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
use yakui_core::event::{EventInterest, EventResponse, WidgetEvent};
use yakui_core::widget::{EventContext, Widget};
use yakui_core::Response;
use yakui_widgets::util::widget;

pub fn is_hovered() -> bool {
*widget::<IsHovered>(())
pub fn is_hovered() -> Response<bool> {
widget::<IsHovered>(())
}

#[derive(Debug)]
Expand Down
20 changes: 8 additions & 12 deletions goryak/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,18 @@ mod decoration;
mod dragvalue;
mod hovered;
mod layout;
mod roundrect;
mod scroll;
mod theme;
mod util;

pub use combo_box::*;
pub use count_grid::*;
pub use decoration::*;
pub use dragvalue::*;
pub use hovered::*;
pub use layout::*;

pub fn checkbox_value(v: &mut bool) {
*v = yakui_widgets::checkbox(*v).checked;
}

pub fn use_changed<T: Copy + PartialEq + 'static>(v: T, f: impl FnOnce()) {
let old_v = yakui_widgets::use_state(|| None);
if old_v.get() != Some(v) {
old_v.set(Some(v));
f();
}
}
pub use roundrect::*;
pub use scroll::*;
pub use theme::*;
pub use util::*;
Loading

0 comments on commit 29dcca1

Please sign in to comment.