switch to element defined span lens + better size fn
This commit is contained in:
883
Cargo.lock
generated
883
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -11,7 +11,7 @@ winit = "0.30.12"
|
|||||||
wgpu = "27.0.1"
|
wgpu = "27.0.1"
|
||||||
bytemuck = "1.23.1"
|
bytemuck = "1.23.1"
|
||||||
image = "0.25.6"
|
image = "0.25.6"
|
||||||
cosmic-text = "0.14.2"
|
cosmic-text = "0.15.0"
|
||||||
unicode-segmentation = "1.12.0"
|
unicode-segmentation = "1.12.0"
|
||||||
fxhash = "0.2.1"
|
fxhash = "0.2.1"
|
||||||
arboard = { version = "3.6.1", features = ["wayland-data-control"] }
|
arboard = { version = "3.6.1", features = ["wayland-data-control"] }
|
||||||
|
|||||||
@@ -10,8 +10,8 @@ impl Widget for Image {
|
|||||||
painter.texture(&self.handle);
|
painter.texture(&self.handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn desired_size(&mut self, _: &mut SizeCtx) -> UiVec2 {
|
fn desired_size(&mut self, _: &mut SizeCtx) -> Size {
|
||||||
UiVec2::abs(self.handle.size())
|
Size::abs(self.handle.size())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,11 +7,12 @@ pub struct Aligned {
|
|||||||
|
|
||||||
impl Widget for Aligned {
|
impl Widget for Aligned {
|
||||||
fn draw(&mut self, painter: &mut Painter) {
|
fn draw(&mut self, painter: &mut Painter) {
|
||||||
let region = UiRegion::from_ui_size_align(painter.size(&self.inner), self.align);
|
let region =
|
||||||
|
UiRegion::from_ui_size_align(painter.size(&self.inner).to_uivec2(), self.align);
|
||||||
painter.widget_within(&self.inner, region);
|
painter.widget_within(&self.inner, region);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn desired_size(&mut self, ctx: &mut SizeCtx) -> UiVec2 {
|
fn desired_size(&mut self, ctx: &mut SizeCtx) -> Size {
|
||||||
ctx.size(&self.inner)
|
ctx.size(&self.inner)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ impl Widget for Offset {
|
|||||||
painter.widget_within(&self.inner, region);
|
painter.widget_within(&self.inner, region);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn desired_size(&mut self, ctx: &mut SizeCtx) -> UiVec2 {
|
fn desired_size(&mut self, ctx: &mut SizeCtx) -> Size {
|
||||||
ctx.size(&self.inner)
|
ctx.size(&self.inner)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,30 +1,22 @@
|
|||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
pub struct Padded {
|
pub struct Pad {
|
||||||
pub padding: Padding,
|
pub padding: Padding,
|
||||||
pub inner: WidgetId,
|
pub inner: WidgetId,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Widget for Padded {
|
impl Widget for Pad {
|
||||||
fn draw(&mut self, painter: &mut Painter) {
|
fn draw(&mut self, painter: &mut Painter) {
|
||||||
painter.widget_within(&self.inner, self.padding.region());
|
painter.widget_within(&self.inner, self.padding.region());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn desired_size(&mut self, ctx: &mut SizeCtx) -> UiVec2 {
|
fn desired_size(&mut self, ctx: &mut SizeCtx) -> Size {
|
||||||
let mut size = ctx.size(&self.inner);
|
let mut size = ctx.size(&self.inner);
|
||||||
// TODO: this is currently a hack
|
if size.x.rest == 0.0 {
|
||||||
// the correct solution is that the position is not linear
|
size.x.abs += self.padding.left + self.padding.right;
|
||||||
// becauase if you have 0.5 rel + 100 abs, it's linear
|
|
||||||
// until you fill up parent rel (in abs units) and then 1.0 rel (piecewise linear)
|
|
||||||
// so I guess yet another detection system is needed
|
|
||||||
// to determine when abs translated to rel + rel > 1.0
|
|
||||||
// hopefully find a way to get working on gpu so no cpu changing needed
|
|
||||||
// eg by sending size to calculate above and then doing... something?
|
|
||||||
if size.rel.x != 1.0 {
|
|
||||||
size.abs.x += self.padding.left + self.padding.right;
|
|
||||||
}
|
}
|
||||||
if size.rel.y != 1.0 {
|
if size.y.rest == 0.0 {
|
||||||
size.abs.y += self.padding.top + self.padding.bottom;
|
size.y.abs += self.padding.top + self.padding.bottom;
|
||||||
}
|
}
|
||||||
size
|
size
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,8 @@ use crate::prelude::*;
|
|||||||
|
|
||||||
pub struct Sized {
|
pub struct Sized {
|
||||||
pub inner: WidgetId,
|
pub inner: WidgetId,
|
||||||
pub size: Vec2,
|
pub x: Option<Len>,
|
||||||
|
pub y: Option<Len>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Widget for Sized {
|
impl Widget for Sized {
|
||||||
@@ -10,7 +11,10 @@ impl Widget for Sized {
|
|||||||
painter.widget(&self.inner);
|
painter.widget(&self.inner);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn desired_size(&mut self, _: &mut SizeCtx) -> UiVec2 {
|
fn desired_size(&mut self, ctx: &mut SizeCtx) -> Size {
|
||||||
UiVec2::abs(self.size)
|
Size {
|
||||||
|
x: self.x.unwrap_or_else(|| ctx.size(&self.inner).x),
|
||||||
|
y: self.y.unwrap_or_else(|| ctx.size(&self.inner).y),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,36 +1,26 @@
|
|||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
pub struct Span {
|
pub struct Span {
|
||||||
pub children: Vec<(WidgetId, SpanLen)>,
|
pub children: Vec<WidgetId>,
|
||||||
pub dir: Dir,
|
pub dir: Dir,
|
||||||
pub spacing: f32,
|
pub spacing: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Widget for Span {
|
impl Widget for Span {
|
||||||
fn draw(&mut self, painter: &mut Painter) {
|
fn draw(&mut self, painter: &mut Painter) {
|
||||||
let total = self.setup(&mut painter.size_ctx());
|
let total = self.len_sum(&mut painter.size_ctx());
|
||||||
let mut start = UiScalar::rel_min();
|
let mut start = UiScalar::rel_min();
|
||||||
for (child, length) in &self.children {
|
for child in &self.children {
|
||||||
let mut child_region = UiRegion::full();
|
let mut child_region = UiRegion::full();
|
||||||
let mut axis = child_region.axis_mut(self.dir.axis);
|
let mut axis = child_region.axis_mut(self.dir.axis);
|
||||||
axis.top_left.set(start);
|
axis.top_left.set(start);
|
||||||
match *length {
|
let len = painter.size(child).axis(self.dir.axis);
|
||||||
SpanLen::Fixed(offset) => {
|
start.abs += len.abs;
|
||||||
start.abs += offset;
|
start.rel += len.rel;
|
||||||
}
|
if len.rest > 0.0 {
|
||||||
SpanLen::Ratio(ratio) => {
|
let offset = UiScalar::new(total.rel, total.abs);
|
||||||
let offset = UiScalar::new(total.rel, total.abs);
|
let rel_end = UiScalar::from_anchor(len.rest / total.rest);
|
||||||
let rel_end = UiScalar::from_anchor(ratio / total.ratio);
|
start = rel_end.within(start, (UiScalar::rel_max() + start) - offset);
|
||||||
start = rel_end.within(start, (UiScalar::rel_max() + start) - offset);
|
|
||||||
}
|
|
||||||
SpanLen::Relative(rel) => {
|
|
||||||
start.rel += rel;
|
|
||||||
}
|
|
||||||
SpanLen::Sized(size) => {
|
|
||||||
let size_axis = size.axis(self.dir.axis);
|
|
||||||
start.abs += size_axis.abs;
|
|
||||||
start.rel += size_axis.rel;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
axis.bot_right.set(start);
|
axis.bot_right.set(start);
|
||||||
if self.dir.sign == Sign::Neg {
|
if self.dir.sign == Sign::Neg {
|
||||||
@@ -41,33 +31,29 @@ impl Widget for Span {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn desired_size(&mut self, ctx: &mut SizeCtx) -> UiVec2 {
|
fn desired_size(&mut self, ctx: &mut SizeCtx) -> Size {
|
||||||
let total = self.setup(ctx);
|
let mut sums = self.len_sum(ctx);
|
||||||
let axis = self.dir.axis;
|
let dir_len = if sums.rest == 0.0 && sums.rel == 0.0 {
|
||||||
let dir_len = if total.ratio != 0.0 {
|
sums.abs += self.spacing * self.children.len().saturating_sub(1) as f32;
|
||||||
UiScalar::rel_max()
|
sums
|
||||||
} else {
|
} else {
|
||||||
UiScalar::new(
|
Len::default()
|
||||||
total.rel,
|
|
||||||
total.abs + self.spacing * self.children.len().saturating_sub(1) as f32,
|
|
||||||
)
|
|
||||||
};
|
};
|
||||||
let mut max_ortho = UiScalar::ZERO;
|
let mut max_ortho = Len::ZERO;
|
||||||
for (child, _) in &self.children {
|
for child in &self.children {
|
||||||
let size = ctx.size(child);
|
let len = ctx.size(child).axis(!self.dir.axis);
|
||||||
max_ortho = max_ortho.max(size.axis(!self.dir.axis));
|
// TODO: rel shouldn't do this, but no easy way before actually calculating pixels
|
||||||
|
if len.rel > 0.0 || len.rest > 0.0 {
|
||||||
|
max_ortho.rest = 1.0;
|
||||||
|
max_ortho.abs = 0.0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
max_ortho.abs = max_ortho.abs.max(len.abs);
|
||||||
}
|
}
|
||||||
UiVec2::from_axis(axis, dir_len, max_ortho)
|
Size::from_axis(self.dir.axis, dir_len, max_ortho)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
|
||||||
pub struct SpanLenSums {
|
|
||||||
pub abs: f32,
|
|
||||||
pub ratio: f32,
|
|
||||||
pub rel: f32,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Span {
|
impl Span {
|
||||||
pub fn empty(dir: Dir) -> Self {
|
pub fn empty(dir: Dir) -> Self {
|
||||||
Self {
|
Self {
|
||||||
@@ -82,61 +68,10 @@ impl Span {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setup(&mut self, ctx: &mut SizeCtx) -> SpanLenSums {
|
fn len_sum(&mut self, ctx: &mut SizeCtx) -> Len {
|
||||||
self.children
|
self.children.iter_mut().fold(Len::ZERO, |mut s, id| {
|
||||||
.iter_mut()
|
s += ctx.size(id).axis(self.dir.axis);
|
||||||
.fold(SpanLenSums::default(), |mut s, (id, l)| {
|
s
|
||||||
match l {
|
})
|
||||||
SpanLen::Fixed(v) => s.abs += *v,
|
|
||||||
SpanLen::Ratio(v) => s.ratio += *v,
|
|
||||||
SpanLen::Relative(v) => s.rel += *v,
|
|
||||||
SpanLen::Sized(v) => {
|
|
||||||
let size = ctx.size(id);
|
|
||||||
let len = size.axis(self.dir.axis);
|
|
||||||
*v = size;
|
|
||||||
s.abs += len.abs;
|
|
||||||
s.rel += len.rel;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
s
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
|
||||||
pub enum SpanLen {
|
|
||||||
/// exact (non dynamic) size
|
|
||||||
Fixed(f32),
|
|
||||||
/// relative to remaining free space and other ratios
|
|
||||||
/// eg. 1 and 2 would take up 1/3 and 2/3 of the remaining space (after others)
|
|
||||||
Ratio(f32),
|
|
||||||
/// relative to the total space (of the entire span)
|
|
||||||
/// eg. 0.5 means 1/2 of the total space
|
|
||||||
Relative(f32),
|
|
||||||
/// size determined by the child widget itself
|
|
||||||
/// the value is not used externally, I just don't wanna make a duplicate enum
|
|
||||||
/// there are util functions instead so
|
|
||||||
Sized(UiVec2),
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn fixed<N: UiNum>(x: N) -> SpanLen {
|
|
||||||
SpanLen::Fixed(x.to_f32())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn ratio<N: UiNum>(x: N) -> SpanLen {
|
|
||||||
SpanLen::Ratio(x.to_f32())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn relative<N: UiNum>(x: N) -> SpanLen {
|
|
||||||
SpanLen::Relative(x.to_f32())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn sized() -> SpanLen {
|
|
||||||
SpanLen::Sized(UiVec2::default())
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<N: UiNum> From<N> for SpanLen {
|
|
||||||
fn from(value: N) -> Self {
|
|
||||||
Self::Ratio(value.to_f32())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,9 +24,9 @@ impl Widget for Stack {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn desired_size(&mut self, ctx: &mut SizeCtx) -> UiVec2 {
|
fn desired_size(&mut self, ctx: &mut SizeCtx) -> Size {
|
||||||
match self.size {
|
match self.size {
|
||||||
StackSize::Full => UiVec2::MAX_SIZE,
|
StackSize::Default => Size::default(),
|
||||||
StackSize::Child(i) => ctx.size(&self.children[i]),
|
StackSize::Child(i) => ctx.size(&self.children[i]),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -35,7 +35,7 @@ impl Widget for Stack {
|
|||||||
#[derive(Default, Debug)]
|
#[derive(Default, Debug)]
|
||||||
pub enum StackSize {
|
pub enum StackSize {
|
||||||
#[default]
|
#[default]
|
||||||
Full,
|
Default,
|
||||||
Child(usize),
|
Child(usize),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -64,6 +64,7 @@ impl TextBuilderOutput for TextOutput {
|
|||||||
&builder.content,
|
&builder.content,
|
||||||
&Attrs::new(),
|
&Attrs::new(),
|
||||||
Shaping::Advanced,
|
Shaping::Advanced,
|
||||||
|
None,
|
||||||
);
|
);
|
||||||
let mut text = Text {
|
let mut text = Text {
|
||||||
content: builder.content.into(),
|
content: builder.content.into(),
|
||||||
@@ -94,6 +95,7 @@ impl TextBuilderOutput for TextEditOutput {
|
|||||||
&builder.content,
|
&builder.content,
|
||||||
&Attrs::new(),
|
&Attrs::new(),
|
||||||
Shaping::Advanced,
|
Shaping::Advanced,
|
||||||
|
None,
|
||||||
);
|
);
|
||||||
builder.attrs.apply(font_system, &mut text.buf, None);
|
builder.attrs.apply(font_system, &mut text.buf, None);
|
||||||
text
|
text
|
||||||
|
|||||||
@@ -41,8 +41,8 @@ impl Widget for TextEdit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn desired_size(&mut self, ctx: &mut SizeCtx) -> UiVec2 {
|
fn desired_size(&mut self, ctx: &mut SizeCtx) -> Size {
|
||||||
UiVec2::abs(self.view.draw(ctx).size())
|
Size::abs(self.view.draw(ctx).size())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,7 +96,7 @@ impl<'a> TextEditCtx<'a> {
|
|||||||
.join("\n");
|
.join("\n");
|
||||||
self.text
|
self.text
|
||||||
.buf
|
.buf
|
||||||
.set_text(self.font_system, "", &Attrs::new(), Shaping::Advanced);
|
.set_text(self.font_system, "", &Attrs::new(), Shaping::Advanced, None);
|
||||||
if let Some(cursor) = &mut self.text.cursor {
|
if let Some(cursor) = &mut self.text.cursor {
|
||||||
cursor.line = 0;
|
cursor.line = 0;
|
||||||
cursor.index = 0;
|
cursor.index = 0;
|
||||||
|
|||||||
@@ -75,6 +75,7 @@ impl Text {
|
|||||||
&self.content,
|
&self.content,
|
||||||
&Attrs::new().family(self.view.attrs.family),
|
&Attrs::new().family(self.view.attrs.family),
|
||||||
Shaping::Advanced,
|
Shaping::Advanced,
|
||||||
|
None,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
self.view.draw(ctx)
|
self.view.draw(ctx)
|
||||||
@@ -88,8 +89,8 @@ impl Widget for Text {
|
|||||||
painter.texture_within(&tex.handle, region);
|
painter.texture_within(&tex.handle, region);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn desired_size(&mut self, ctx: &mut SizeCtx) -> UiVec2 {
|
fn desired_size(&mut self, ctx: &mut SizeCtx) -> Size {
|
||||||
UiVec2::abs(self.update_buf(ctx).size())
|
Size::abs(self.update_buf(ctx).size())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,19 +2,21 @@ use super::*;
|
|||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
pub trait CoreWidget<W, Tag> {
|
pub trait CoreWidget<W, Tag> {
|
||||||
fn pad(self, padding: impl Into<Padding>) -> impl WidgetFn<Padded>;
|
fn pad(self, padding: impl Into<Padding>) -> impl WidgetFn<Pad>;
|
||||||
fn align(self, align: Align) -> impl WidgetFn<Aligned>;
|
fn align(self, align: Align) -> impl WidgetFn<Aligned>;
|
||||||
fn center(self) -> impl WidgetFn<Aligned>;
|
fn center(self) -> impl WidgetFn<Aligned>;
|
||||||
fn label(self, label: impl Into<String>) -> impl WidgetIdFn<W>;
|
fn label(self, label: impl Into<String>) -> impl WidgetIdFn<W>;
|
||||||
fn sized(self, size: impl Into<Vec2>) -> impl WidgetFn<Sized>;
|
fn sized(self, size: impl Into<Size>) -> impl WidgetFn<Sized>;
|
||||||
|
fn width(self, len: impl Into<Len>) -> impl WidgetFn<Sized>;
|
||||||
|
fn height(self, len: impl Into<Len>) -> impl WidgetFn<Sized>;
|
||||||
fn offset(self, amt: impl Into<UiVec2>) -> impl WidgetFn<Offset>;
|
fn offset(self, amt: impl Into<UiVec2>) -> impl WidgetFn<Offset>;
|
||||||
fn scroll(self) -> impl WidgetIdFn<Offset>;
|
fn scroll(self) -> impl WidgetIdFn<Offset>;
|
||||||
fn masked(self) -> impl WidgetFn<Masked>;
|
fn masked(self) -> impl WidgetFn<Masked>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<W: WidgetLike<Tag>, Tag> CoreWidget<W::Widget, Tag> for W {
|
impl<W: WidgetLike<Tag>, Tag> CoreWidget<W::Widget, Tag> for W {
|
||||||
fn pad(self, padding: impl Into<Padding>) -> impl WidgetFn<Padded> {
|
fn pad(self, padding: impl Into<Padding>) -> impl WidgetFn<Pad> {
|
||||||
|ui| Padded {
|
|ui| Pad {
|
||||||
padding: padding.into(),
|
padding: padding.into(),
|
||||||
inner: self.add(ui).any(),
|
inner: self.add(ui).any(),
|
||||||
}
|
}
|
||||||
@@ -39,10 +41,30 @@ impl<W: WidgetLike<Tag>, Tag> CoreWidget<W::Widget, Tag> for W {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sized(self, size: impl Into<Vec2>) -> impl WidgetFn<Sized> {
|
fn sized(self, size: impl Into<Size>) -> impl WidgetFn<Sized> {
|
||||||
|
let size = size.into();
|
||||||
move |ui| Sized {
|
move |ui| Sized {
|
||||||
inner: self.add(ui).any(),
|
inner: self.add(ui).any(),
|
||||||
size: size.into(),
|
x: Some(size.x),
|
||||||
|
y: Some(size.y),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn width(self, len: impl Into<Len>) -> impl WidgetFn<Sized> {
|
||||||
|
let len = len.into();
|
||||||
|
move |ui| Sized {
|
||||||
|
inner: self.add(ui).any(),
|
||||||
|
x: Some(len),
|
||||||
|
y: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn height(self, len: impl Into<Len>) -> impl WidgetFn<Sized> {
|
||||||
|
let len = len.into();
|
||||||
|
move |ui| Sized {
|
||||||
|
inner: self.add(ui).any(),
|
||||||
|
x: None,
|
||||||
|
y: Some(len),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,15 +90,14 @@ impl<W: WidgetLike<Tag>, Tag> CoreWidget<W::Widget, Tag> for W {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub trait CoreWidgetArr<const LEN: usize, Wa: WidgetArrLike<LEN, Tag>, Tag> {
|
pub trait CoreWidgetArr<const LEN: usize, Wa: WidgetArrLike<LEN, Tag>, Tag> {
|
||||||
fn span(self, dir: Dir, lengths: impl IntoSpanLens<LEN>) -> impl WidgetFn<Span>;
|
fn span(self, dir: Dir) -> impl WidgetFn<Span>;
|
||||||
fn stack(self) -> StackBuilder<LEN, Wa, Tag>;
|
fn stack(self) -> StackBuilder<LEN, Wa, Tag>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<const LEN: usize, Wa: WidgetArrLike<LEN, Tag>, Tag> CoreWidgetArr<LEN, Wa, Tag> for Wa {
|
impl<const LEN: usize, Wa: WidgetArrLike<LEN, Tag>, Tag> CoreWidgetArr<LEN, Wa, Tag> for Wa {
|
||||||
fn span(self, dir: Dir, lengths: impl IntoSpanLens<LEN>) -> impl WidgetFn<Span> {
|
fn span(self, dir: Dir) -> impl WidgetFn<Span> {
|
||||||
let lengths = lengths.into_lens();
|
|
||||||
move |ui| Span {
|
move |ui| Span {
|
||||||
children: self.ui(ui).arr.into_iter().zip(lengths).collect(),
|
children: self.ui(ui).arr.to_vec(),
|
||||||
dir,
|
dir,
|
||||||
spacing: 0.0,
|
spacing: 0.0,
|
||||||
}
|
}
|
||||||
@@ -85,19 +106,3 @@ impl<const LEN: usize, Wa: WidgetArrLike<LEN, Tag>, Tag> CoreWidgetArr<LEN, Wa,
|
|||||||
StackBuilder::new(self)
|
StackBuilder::new(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait IntoSpanLens<const LEN: usize> {
|
|
||||||
fn into_lens(self) -> [SpanLen; LEN];
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<const LEN: usize, T: Into<SpanLen>> IntoSpanLens<LEN> for [T; LEN] {
|
|
||||||
fn into_lens(self) -> [SpanLen; LEN] {
|
|
||||||
self.map(Into::into)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<const LEN: usize> IntoSpanLens<LEN> for SpanLen {
|
|
||||||
fn into_lens(self) -> [SpanLen; LEN] {
|
|
||||||
[self; LEN]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
use std::ops::Not;
|
use std::ops::Not;
|
||||||
|
|
||||||
use crate::layout::{Vec2, vec2};
|
use crate::{
|
||||||
|
layout::{UiNum, UiVec2, Vec2, vec2},
|
||||||
|
util::impl_op,
|
||||||
|
};
|
||||||
|
|
||||||
#[derive(Copy, Clone, Eq, PartialEq)]
|
#[derive(Copy, Clone, Eq, PartialEq)]
|
||||||
pub enum Axis {
|
pub enum Axis {
|
||||||
@@ -100,3 +103,172 @@ impl Align {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Default, Clone, Copy, PartialEq)]
|
||||||
|
pub struct Size {
|
||||||
|
pub x: Len,
|
||||||
|
pub y: Len,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, PartialEq)]
|
||||||
|
pub struct Len {
|
||||||
|
pub abs: f32,
|
||||||
|
pub rel: f32,
|
||||||
|
pub rest: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<N: UiNum> From<N> for Len {
|
||||||
|
fn from(value: N) -> Self {
|
||||||
|
Len::abs(value.to_f32())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<Nx: UiNum, Ny: UiNum> From<(Nx, Ny)> for Size {
|
||||||
|
fn from((x, y): (Nx, Ny)) -> Self {
|
||||||
|
Self {
|
||||||
|
x: x.into(),
|
||||||
|
y: y.into(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Size {
|
||||||
|
pub const ZERO: Self = Self {
|
||||||
|
x: Len::ZERO,
|
||||||
|
y: Len::ZERO,
|
||||||
|
};
|
||||||
|
pub fn abs(v: Vec2) -> Self {
|
||||||
|
Self {
|
||||||
|
x: Len::abs(v.x),
|
||||||
|
y: Len::abs(v.y),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_uivec2(self) -> UiVec2 {
|
||||||
|
UiVec2 {
|
||||||
|
rel: Vec2 {
|
||||||
|
x: self.x.total_rel(),
|
||||||
|
y: self.y.total_rel(),
|
||||||
|
},
|
||||||
|
abs: Vec2 {
|
||||||
|
x: self.x.abs,
|
||||||
|
y: self.y.abs,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_axis(axis: Axis, aligned: Len, ortho: Len) -> Self {
|
||||||
|
match axis {
|
||||||
|
Axis::X => Self {
|
||||||
|
x: aligned,
|
||||||
|
y: ortho,
|
||||||
|
},
|
||||||
|
Axis::Y => Self {
|
||||||
|
x: ortho,
|
||||||
|
y: aligned,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn axis(&self, axis: Axis) -> Len {
|
||||||
|
match axis {
|
||||||
|
Axis::X => self.x,
|
||||||
|
Axis::Y => self.y,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Len {
|
||||||
|
pub const ZERO: Self = Self {
|
||||||
|
abs: 0.0,
|
||||||
|
rel: 0.0,
|
||||||
|
rest: 0.0,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn total_rel(&self) -> f32 {
|
||||||
|
if self.rest > 0.0 {
|
||||||
|
self.rel.max(1.0)
|
||||||
|
} else {
|
||||||
|
self.rel
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn abs(abs: impl UiNum) -> Self {
|
||||||
|
Self {
|
||||||
|
abs: abs.to_f32(),
|
||||||
|
rel: 0.0,
|
||||||
|
rest: 0.0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn rel(rel: impl UiNum) -> Self {
|
||||||
|
Self {
|
||||||
|
abs: 0.0,
|
||||||
|
rel: rel.to_f32(),
|
||||||
|
rest: 0.0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn rest(ratio: impl UiNum) -> Self {
|
||||||
|
Self {
|
||||||
|
abs: 0.0,
|
||||||
|
rel: 0.0,
|
||||||
|
rest: ratio.to_f32(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub mod len_fns {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
pub fn abs(abs: impl UiNum) -> Len {
|
||||||
|
Len {
|
||||||
|
abs: abs.to_f32(),
|
||||||
|
rel: 0.0,
|
||||||
|
rest: 0.0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn rel(rel: impl UiNum) -> Len {
|
||||||
|
Len {
|
||||||
|
abs: 0.0,
|
||||||
|
rel: rel.to_f32(),
|
||||||
|
rest: 0.0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn rest(ratio: impl UiNum) -> Len {
|
||||||
|
Len {
|
||||||
|
abs: 0.0,
|
||||||
|
rel: 0.0,
|
||||||
|
rest: ratio.to_f32(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_op!(Len Add add; abs rel rest);
|
||||||
|
impl_op!(Len Sub sub; abs rel rest);
|
||||||
|
|
||||||
|
impl_op!(Size Add add; x y);
|
||||||
|
impl_op!(Size Sub sub; x y);
|
||||||
|
|
||||||
|
impl Default for Len {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::rest(1.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Display for Size {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(f, "({}, {})", self.x, self.y)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Display for Len {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
if self.abs != 0.0 {
|
||||||
|
write!(f, "{} abs;", self.abs)?;
|
||||||
|
}
|
||||||
|
if self.rel != 0.0 {
|
||||||
|
write!(f, "{} rel;", self.abs)?;
|
||||||
|
}
|
||||||
|
if self.rest != 0.0 {
|
||||||
|
write!(f, "{} leftover;", self.abs)?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
layout::{
|
layout::{
|
||||||
Layers, Modules, TextAttrs, TextBuffer, TextData, TextTexture, TextureHandle, Textures,
|
Layers, Modules, Size, TextAttrs, TextBuffer, TextData, TextTexture, TextureHandle,
|
||||||
UiRegion, UiVec2, Vec2, WidgetId, Widgets,
|
Textures, UiRegion, Vec2, WidgetId, Widgets,
|
||||||
},
|
},
|
||||||
render::{Mask, MaskIdx, Primitive, PrimitiveHandle, PrimitiveInst},
|
render::{Mask, MaskIdx, Primitive, PrimitiveHandle, PrimitiveInst},
|
||||||
util::{HashMap, HashSet, Id, TrackedArena},
|
util::{HashMap, HashSet, Id, TrackedArena},
|
||||||
@@ -14,7 +14,7 @@ pub struct Painter<'a, 'c> {
|
|||||||
textures: Vec<TextureHandle>,
|
textures: Vec<TextureHandle>,
|
||||||
primitives: Vec<PrimitiveHandle>,
|
primitives: Vec<PrimitiveHandle>,
|
||||||
children: Vec<Id>,
|
children: Vec<Id>,
|
||||||
sized_children: HashMap<Id, UiVec2>,
|
sized_children: HashMap<Id, Size>,
|
||||||
/// whether this widget depends on region's final pixel size or not
|
/// whether this widget depends on region's final pixel size or not
|
||||||
/// TODO: decide if point (pt) should be used here instead of px
|
/// TODO: decide if point (pt) should be used here instead of px
|
||||||
pub layer: usize,
|
pub layer: usize,
|
||||||
@@ -41,10 +41,10 @@ pub struct WidgetInstance {
|
|||||||
pub textures: Vec<TextureHandle>,
|
pub textures: Vec<TextureHandle>,
|
||||||
pub primitives: Vec<PrimitiveHandle>,
|
pub primitives: Vec<PrimitiveHandle>,
|
||||||
pub children: Vec<Id>,
|
pub children: Vec<Id>,
|
||||||
pub resize: Option<(Id, UiVec2)>,
|
pub resize: Option<(Id, Size)>,
|
||||||
pub mask: MaskIdx,
|
pub mask: MaskIdx,
|
||||||
pub layer: usize,
|
pub layer: usize,
|
||||||
pub desired_size: UiVec2,
|
pub desired_size: Size,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
@@ -348,7 +348,7 @@ impl<'a, 'c> Painter<'a, 'c> {
|
|||||||
self.region
|
self.region
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn size<W>(&mut self, id: &WidgetId<W>) -> UiVec2 {
|
pub fn size<W>(&mut self, id: &WidgetId<W>) -> Size {
|
||||||
self.size_ctx().size(id)
|
self.size_ctx().size(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -388,14 +388,14 @@ pub struct SizeCtx<'a> {
|
|||||||
pub textures: &'a mut Textures,
|
pub textures: &'a mut Textures,
|
||||||
widgets: &'a Widgets,
|
widgets: &'a Widgets,
|
||||||
px_dependent: &'a mut HashSet<Id>,
|
px_dependent: &'a mut HashSet<Id>,
|
||||||
checked: &'a mut HashMap<Id, UiVec2>,
|
checked: &'a mut HashMap<Id, Size>,
|
||||||
region: UiRegion,
|
region: UiRegion,
|
||||||
screen_size: Vec2,
|
screen_size: Vec2,
|
||||||
id: Id,
|
id: Id,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SizeCtx<'_> {
|
impl SizeCtx<'_> {
|
||||||
fn size_inner(&mut self, id: Id, region: UiRegion) -> UiVec2 {
|
fn size_inner(&mut self, id: Id, region: UiRegion) -> Size {
|
||||||
let self_region = self.region;
|
let self_region = self.region;
|
||||||
self.region = region;
|
self.region = region;
|
||||||
let size = self.widgets.get_dyn_dynamic(id).desired_size(self);
|
let size = self.widgets.get_dyn_dynamic(id).desired_size(self);
|
||||||
@@ -403,17 +403,17 @@ impl SizeCtx<'_> {
|
|||||||
self.checked.insert(id, size);
|
self.checked.insert(id, size);
|
||||||
size
|
size
|
||||||
}
|
}
|
||||||
pub fn size<W>(&mut self, id: &WidgetId<W>) -> UiVec2 {
|
pub fn size<W>(&mut self, id: &WidgetId<W>) -> Size {
|
||||||
// TODO: determine if this is useful
|
// TODO: determine if this is useful
|
||||||
// if let Some(size) = self.checked.get(&id.id) {
|
if let Some(&size) = self.checked.get(&id.id) {
|
||||||
// return Some(*size);
|
return size;
|
||||||
// }
|
}
|
||||||
self.size_inner(id.id, self.region)
|
self.size_inner(id.id, self.region)
|
||||||
}
|
}
|
||||||
fn size_raw(&mut self, id: Id) -> UiVec2 {
|
fn size_raw(&mut self, id: Id) -> Size {
|
||||||
self.size_inner(id, self.region)
|
self.size_inner(id, self.region)
|
||||||
}
|
}
|
||||||
pub fn size_within<W>(&mut self, id: &WidgetId<W>, region: UiRegion) -> UiVec2 {
|
pub fn size_within<W>(&mut self, id: &WidgetId<W>, region: UiRegion) -> Size {
|
||||||
self.size_inner(id.id, region.within(&self.region))
|
self.size_inner(id.id, region.within(&self.region))
|
||||||
}
|
}
|
||||||
pub fn px_size(&mut self) -> Vec2 {
|
pub fn px_size(&mut self) -> Vec2 {
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
use crate::layout::{Painter, SizeCtx, StaticWidgetId, Ui, UiVec2, WidgetId, WidgetIdFn};
|
use crate::layout::{Painter, SizeCtx, StaticWidgetId, Ui, Size, WidgetId, WidgetIdFn};
|
||||||
|
|
||||||
use std::{any::Any, marker::PhantomData};
|
use std::{any::Any, marker::PhantomData};
|
||||||
|
|
||||||
pub trait Widget: Any {
|
pub trait Widget: Any {
|
||||||
fn draw(&mut self, painter: &mut Painter);
|
fn draw(&mut self, painter: &mut Painter);
|
||||||
fn desired_size(&mut self, _: &mut SizeCtx) -> UiVec2 {
|
fn desired_size(&mut self, _: &mut SizeCtx) -> Size {
|
||||||
UiVec2::MAX_SIZE
|
Size::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ use ui::prelude::*;
|
|||||||
use winit::{event::WindowEvent, event_loop::ActiveEventLoop, window::Window};
|
use winit::{event::WindowEvent, event_loop::ActiveEventLoop, window::Window};
|
||||||
|
|
||||||
use crate::testing::input::Input;
|
use crate::testing::input::Input;
|
||||||
|
use len_fns::*;
|
||||||
|
|
||||||
mod app;
|
mod app;
|
||||||
mod input;
|
mod input;
|
||||||
@@ -42,39 +43,35 @@ impl Client {
|
|||||||
let pad_test = (
|
let pad_test = (
|
||||||
rrect.color(Color::BLUE),
|
rrect.color(Color::BLUE),
|
||||||
(
|
(
|
||||||
rrect.color(Color::RED).sized(100).center(),
|
rrect
|
||||||
|
.color(Color::RED)
|
||||||
|
.sized((100, 100))
|
||||||
|
.center()
|
||||||
|
.width(rest(2)),
|
||||||
(
|
(
|
||||||
rrect.color(Color::ORANGE),
|
rrect.color(Color::ORANGE),
|
||||||
rrect.color(Color::LIME).pad(10.0),
|
rrect.color(Color::LIME).pad(10.0),
|
||||||
)
|
)
|
||||||
.span(Dir::RIGHT, ratio(1)),
|
.span(Dir::RIGHT)
|
||||||
|
.width(rest(2)),
|
||||||
rrect.color(Color::YELLOW),
|
rrect.color(Color::YELLOW),
|
||||||
)
|
)
|
||||||
.span(Dir::RIGHT, [2, 2, 1])
|
.span(Dir::RIGHT)
|
||||||
.pad(10),
|
.pad(10)
|
||||||
|
.width(rest(3)),
|
||||||
)
|
)
|
||||||
.span(Dir::RIGHT, [1, 3])
|
.span(Dir::RIGHT)
|
||||||
.add_static(&mut ui);
|
.add_static(&mut ui);
|
||||||
|
|
||||||
let span_test = (
|
let span_test = (
|
||||||
rrect.color(Color::GREEN),
|
rrect.color(Color::GREEN).width(100),
|
||||||
rrect.color(Color::ORANGE),
|
rrect.color(Color::ORANGE),
|
||||||
rrect.color(Color::CYAN),
|
rrect.color(Color::CYAN),
|
||||||
rrect.color(Color::BLUE),
|
rrect.color(Color::BLUE).width(rel(0.5)),
|
||||||
rrect.color(Color::MAGENTA),
|
rrect.color(Color::MAGENTA).width(100),
|
||||||
rrect.color(Color::RED),
|
rrect.color(Color::RED).width(100),
|
||||||
)
|
)
|
||||||
.span(
|
.span(Dir::LEFT)
|
||||||
Dir::LEFT,
|
|
||||||
[
|
|
||||||
fixed(100),
|
|
||||||
ratio(1),
|
|
||||||
ratio(1),
|
|
||||||
relative(0.5),
|
|
||||||
fixed(100),
|
|
||||||
fixed(100),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
.add_static(&mut ui);
|
.add_static(&mut ui);
|
||||||
|
|
||||||
let span_add = Span::empty(Dir::RIGHT).add_static(&mut ui);
|
let span_add = Span::empty(Dir::RIGHT).add_static(&mut ui);
|
||||||
@@ -86,9 +83,9 @@ impl Client {
|
|||||||
.ui
|
.ui
|
||||||
.add(image(include_bytes!("assets/sungals.png")).center())
|
.add(image(include_bytes!("assets/sungals.png")).center())
|
||||||
.any();
|
.any();
|
||||||
ctx.ui[span_add].children.push((child, sized()));
|
ctx.ui[span_add].children.push(child);
|
||||||
})
|
})
|
||||||
.sized(150)
|
.sized((150, 150))
|
||||||
.align(Align::BotRight);
|
.align(Align::BotRight);
|
||||||
|
|
||||||
let del_button = rect(Color::RED)
|
let del_button = rect(Color::RED)
|
||||||
@@ -96,7 +93,7 @@ impl Client {
|
|||||||
.on(CursorSense::click(), move |ctx: &mut Client, _| {
|
.on(CursorSense::click(), move |ctx: &mut Client, _| {
|
||||||
ctx.ui[span_add].children.pop();
|
ctx.ui[span_add].children.pop();
|
||||||
})
|
})
|
||||||
.sized(150)
|
.sized((150, 150))
|
||||||
.align(Align::BotLeft);
|
.align(Align::BotLeft);
|
||||||
|
|
||||||
let span_add_test = (span_add, add_button, del_button)
|
let span_add_test = (span_add, add_button, del_button)
|
||||||
@@ -117,18 +114,18 @@ impl Client {
|
|||||||
btext("'").family(Family::Monospace).align(Align::Top),
|
btext("'").family(Family::Monospace).align(Align::Top),
|
||||||
btext("'").family(Family::Monospace),
|
btext("'").family(Family::Monospace),
|
||||||
btext(":gamer mode").family(Family::Monospace),
|
btext(":gamer mode").family(Family::Monospace),
|
||||||
rect(Color::CYAN).sized(10).center(),
|
rect(Color::CYAN).sized((10, 10)).center(),
|
||||||
rect(Color::RED).sized(100).center(),
|
rect(Color::RED).sized((100, 100)).center(),
|
||||||
rect(Color::PURPLE).sized(50).align(Align::Top),
|
rect(Color::PURPLE).sized((50, 50)).align(Align::Top),
|
||||||
)
|
)
|
||||||
.span(Dir::RIGHT, sized())
|
.span(Dir::RIGHT)
|
||||||
.center(),
|
.center(),
|
||||||
text("pretty cool right?").size(50),
|
text("pretty cool right?").size(50),
|
||||||
)
|
)
|
||||||
.span(Dir::DOWN, sized())
|
.span(Dir::DOWN)
|
||||||
.add_static(&mut ui);
|
.add_static(&mut ui);
|
||||||
|
|
||||||
let texts = Span::empty(Dir::DOWN).add_static(&mut ui);
|
let texts = Span::empty(Dir::DOWN).spacing(10).add_static(&mut ui);
|
||||||
let msg_area = (Rect::new(Color::SKY), texts.scroll().masked()).stack();
|
let msg_area = (Rect::new(Color::SKY), texts.scroll().masked()).stack();
|
||||||
let add_text = text("add")
|
let add_text = text("add")
|
||||||
.editable()
|
.editable()
|
||||||
@@ -153,7 +150,7 @@ impl Client {
|
|||||||
.stack()
|
.stack()
|
||||||
.size(StackSize::Child(1))
|
.size(StackSize::Child(1))
|
||||||
.add(&mut client.ui);
|
.add(&mut client.ui);
|
||||||
client.ui[texts].children.push((msg_box.any(), sized()));
|
client.ui[texts].children.push(msg_box.any());
|
||||||
})
|
})
|
||||||
.add(&mut ui);
|
.add(&mut ui);
|
||||||
let text_edit_scroll = (
|
let text_edit_scroll = (
|
||||||
@@ -161,14 +158,14 @@ impl Client {
|
|||||||
(
|
(
|
||||||
Rect::new(Color::WHITE.darker(0.9)),
|
Rect::new(Color::WHITE.darker(0.9)),
|
||||||
(
|
(
|
||||||
add_text.clone(),
|
add_text.clone().width(rest(1)),
|
||||||
Rect::new(Color::GREEN)
|
Rect::new(Color::GREEN)
|
||||||
.on(CursorSense::click(), move |client: &mut Client, _| {
|
.on(CursorSense::click(), move |client: &mut Client, _| {
|
||||||
client.run_event(&add_text, Submit, ());
|
client.run_event(&add_text, Submit, ());
|
||||||
})
|
})
|
||||||
.sized(40),
|
.sized((40, 40)),
|
||||||
)
|
)
|
||||||
.span(Dir::RIGHT, [ratio(1), sized()])
|
.span(Dir::RIGHT)
|
||||||
.pad(10),
|
.pad(10),
|
||||||
)
|
)
|
||||||
.stack()
|
.stack()
|
||||||
@@ -176,7 +173,7 @@ impl Client {
|
|||||||
.offset_layer(1)
|
.offset_layer(1)
|
||||||
.align(Align::Bot),
|
.align(Align::Bot),
|
||||||
)
|
)
|
||||||
.span(Dir::DOWN, [ratio(1), sized()])
|
.span(Dir::DOWN)
|
||||||
.add_static(&mut ui);
|
.add_static(&mut ui);
|
||||||
|
|
||||||
let switch_button = |color, to, label| {
|
let switch_button = |color, to, label| {
|
||||||
@@ -208,15 +205,12 @@ impl Client {
|
|||||||
"text edit scroll",
|
"text edit scroll",
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.span(Dir::RIGHT, ratio(1));
|
.span(Dir::RIGHT);
|
||||||
|
|
||||||
let info = text("").add(&mut ui);
|
let info = text("").add(&mut ui);
|
||||||
let info_sect = info.clone().pad(10).align(Align::Right);
|
let info_sect = info.clone().pad(10).align(Align::Right);
|
||||||
|
|
||||||
(
|
((tabs.height(40), main).span(Dir::DOWN), info_sect)
|
||||||
(tabs, main).span(Dir::DOWN, [fixed(40), ratio(1)]),
|
|
||||||
info_sect,
|
|
||||||
)
|
|
||||||
.stack()
|
.stack()
|
||||||
.set_root(&mut ui);
|
.set_root(&mut ui);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user