Skip to content
Snippets Groups Projects
Unverified Commit c2494886 authored by John's avatar John Committed by GitHub
Browse files

Merge pull request #81 from StarArawn/style-qol

Added QoL improvements to styling
parents fbaa2518 13670c2a
No related branches found
No related tags found
No related merge requests found
Showing
with 561 additions and 118 deletions
......@@ -4,6 +4,7 @@ use bevy::{
sprite::Rect,
};
use kayak_core::render_primitive::RenderPrimitive;
use kayak_core::styles::Corner;
use kayak_font::{Alignment, CoordinateSystem, KayakFont};
use crate::{
......@@ -77,7 +78,7 @@ pub fn extract_texts(
z_index: layout.z_index,
quad_type: UIQuadType::Text,
type_index: 0,
border_radius: (0.0, 0.0, 0.0, 0.0),
border_radius: Corner::default(),
image: None,
uv_max: None,
uv_min: None,
......
......@@ -9,7 +9,7 @@ use bevy::{
sprite::Rect,
window::Windows,
};
use kayak_core::{render_primitive::RenderPrimitive, Binding, Bound};
use kayak_core::{render_primitive::RenderPrimitive, styles::Corner, Binding, Bound};
use kayak_font::KayakFont;
use crate::{
......@@ -129,7 +129,7 @@ pub fn extract(
font_handle: None,
quad_type: UIQuadType::Clip,
type_index: 0,
border_radius: (0.0, 0.0, 0.0, 0.0),
border_radius: Corner::default(),
image: None,
uv_min: None,
uv_max: None,
......
......@@ -5,6 +5,7 @@ use bevy::{
sprite::Rect,
};
use kayak_core::render_primitive::RenderPrimitive;
use kayak_core::styles::Corner;
use crate::{
render::unified::pipeline::{ExtractQuadBundle, ExtractedQuad, UIQuadType},
......@@ -60,7 +61,7 @@ pub fn extract_nine_patch(
font_handle: None,
quad_type: UIQuadType::Image,
type_index: 0,
border_radius: (0.0, 0.0, 0.0, 0.0),
border_radius: Corner::default(),
image: image_handle,
uv_max: None,
uv_min: None,
......
......@@ -39,6 +39,7 @@ use kayak_font::{
use super::{Dpi, UNIFIED_SHADER_HANDLE};
use crate::{render::ui_pass::TransparentUI, WindowSize};
use kayak_core::styles::Corner;
pub struct UnifiedPipeline {
view_layout: BindGroupLayout,
......@@ -51,12 +52,12 @@ pub struct UnifiedPipeline {
}
const QUAD_VERTEX_POSITIONS: &[Vec3] = &[
const_vec3!([0.0, 0.0, 0.0]),
const_vec3!([1.0, 1.0, 0.0]),
const_vec3!([0.0, 1.0, 0.0]),
const_vec3!([0.0, 0.0, 0.0]),
const_vec3!([1.0, 0.0, 0.0]),
const_vec3!([0.0, 0.0, 0.0]),
const_vec3!([0.0, 1.0, 0.0]),
const_vec3!([1.0, 1.0, 0.0]),
const_vec3!([1.0, 0.0, 0.0]),
];
impl FontRenderingPipeline for UnifiedPipeline {
......@@ -320,7 +321,7 @@ pub struct ExtractedQuad {
pub font_handle: Option<Handle<KayakFont>>,
pub quad_type: UIQuadType,
pub type_index: u32,
pub border_radius: (f32, f32, f32, f32),
pub border_radius: Corner<f32>,
pub image: Option<Handle<Image>>,
pub uv_min: Option<Vec2>,
pub uv_max: Option<Vec2>,
......@@ -411,27 +412,27 @@ pub fn prepare_quads(
let bottom_left = Vec4::new(
uv_min.x,
uv_max.y,
uv_min.y,
extracted_sprite.char_id as f32,
extracted_sprite.border_radius.0,
extracted_sprite.border_radius.bottom_left,
);
let top_left = Vec4::new(
uv_min.x,
uv_min.y,
uv_max.y,
extracted_sprite.char_id as f32,
extracted_sprite.border_radius.1,
extracted_sprite.border_radius.top_left,
);
let top_right = Vec4::new(
uv_max.x,
uv_min.y,
uv_max.y,
extracted_sprite.char_id as f32,
extracted_sprite.border_radius.2,
extracted_sprite.border_radius.top_right,
);
let bottom_right = Vec4::new(
uv_max.x,
uv_max.y,
uv_min.y,
extracted_sprite.char_id as f32,
extracted_sprite.border_radius.3,
extracted_sprite.border_radius.bottom_right,
);
let uvs: [[f32; 4]; 6] = [
......
......@@ -25,12 +25,7 @@ pub fn extract_quads(render_primitive: &RenderPrimitive, dpi: f32) -> Vec<Extrac
_ => panic!(""),
};
border = (
border.0 * dpi,
border.1 * dpi,
border.2 * dpi,
border.3 * dpi,
);
border *= dpi;
vec![
// Border
......@@ -59,10 +54,10 @@ pub fn extract_quads(render_primitive: &RenderPrimitive, dpi: f32) -> Vec<Extrac
ExtractQuadBundle {
extracted_quad: ExtractedQuad {
rect: Rect {
min: Vec2::new(layout.posx + border.3, layout.posy + border.0),
min: Vec2::new(layout.posx + border.left, layout.posy + border.top),
max: Vec2::new(
(layout.posx + (layout.width * dpi)) - border.1,
(layout.posy + (layout.height * dpi)) - border.2,
(layout.posx + (layout.width * dpi)) - border.right,
(layout.posy + (layout.height * dpi)) - border.bottom,
),
},
color: to_bevy_color(&background_color),
......
......@@ -5,9 +5,8 @@ use bevy::{
};
use kayak_ui::bevy::{BevyContext, BevyKayakUIPlugin, FontMapping, ImageManager, UICameraBundle};
use kayak_ui::core::{
layout_cache::Space,
render,
styles::{Style, StyleProp, Units},
styles::{Edge, Style, StyleProp, Units},
Index,
};
use kayak_ui::widgets::{App, Clip, NinePatch, Text};
......@@ -29,14 +28,8 @@ fn startup(
let nine_patch_styles = Style {
width: StyleProp::Value(Units::Pixels(512.0)),
height: StyleProp::Value(Units::Pixels(512.0)),
left: StyleProp::Value(Units::Stretch(1.0)),
right: StyleProp::Value(Units::Stretch(1.0)),
top: StyleProp::Value(Units::Stretch(1.0)),
bottom: StyleProp::Value(Units::Stretch(1.0)),
padding_left: StyleProp::Value(Units::Pixels(25.0)),
padding_right: StyleProp::Value(Units::Pixels(25.0)),
padding_top: StyleProp::Value(Units::Pixels(25.0)),
padding_bottom: StyleProp::Value(Units::Pixels(25.0)),
offset: StyleProp::Value(Edge::all(Units::Stretch(1.0))),
padding: StyleProp::Value(Edge::all(Units::Pixels(25.0))),
..Style::default()
};
......@@ -58,12 +51,7 @@ Vestibulum rutrum imperdiet nisl, et consequat massa porttitor vel. Ut velit jus
<App>
<NinePatch
styles={Some(nine_patch_styles)}
border={Space {
left: 30.0,
right: 30.0,
top: 30.0,
bottom: 30.0,
}}
border={Edge::all(30.0)}
handle={panel_brown_handle}
>
<Clip styles={Some(clip_styles)}>
......
......@@ -5,9 +5,8 @@ use bevy::{
};
use kayak_ui::bevy::{BevyContext, BevyKayakUIPlugin, FontMapping, ImageManager, UICameraBundle};
use kayak_ui::core::{
layout_cache::Space,
render, rsx,
styles::{LayoutType, Style, StyleProp, Units},
styles::{Edge, LayoutType, Style, StyleProp, Units},
widget, Bound, Children, EventType, Index, MutableBound, OnEvent, WidgetProps,
};
use kayak_ui::widgets::{App, NinePatch, Text};
......@@ -52,10 +51,7 @@ fn BlueButton(props: BlueButtonProps) {
let button_styles = Style {
width: StyleProp::Value(Units::Pixels(200.0)),
height: StyleProp::Value(Units::Pixels(50.0)),
padding_left: StyleProp::Value(Units::Stretch(1.0)),
padding_right: StyleProp::Value(Units::Stretch(1.0)),
padding_top: StyleProp::Value(Units::Stretch(1.0)),
padding_bottom: StyleProp::Value(Units::Stretch(1.0)),
padding: StyleProp::Value(Edge::all(Units::Stretch(1.0))),
..props.styles.clone().unwrap_or_default()
};
......@@ -73,12 +69,7 @@ fn BlueButton(props: BlueButtonProps) {
let children = props.get_children();
rsx! {
<NinePatch
border={Space {
left: 10.0,
right: 10.0,
top: 10.0,
bottom: 10.0,
}}
border={Edge::all(10.0)}
handle={current_button_handle.get()}
styles={Some(button_styles)}
on_event={Some(on_event)}
......@@ -112,10 +103,7 @@ fn startup(
right: StyleProp::Value(Units::Stretch(1.0)),
top: StyleProp::Value(Units::Stretch(1.0)),
bottom: StyleProp::Value(Units::Stretch(1.0)),
padding_left: StyleProp::Value(Units::Stretch(1.0)),
padding_right: StyleProp::Value(Units::Stretch(1.0)),
padding_top: StyleProp::Value(Units::Stretch(1.0)),
padding_bottom: StyleProp::Value(Units::Stretch(1.0)),
padding: StyleProp::Value(Edge::all(Units::Stretch(1.0))),
..Style::default()
};
......@@ -135,12 +123,7 @@ fn startup(
<App>
<NinePatch
styles={Some(nine_patch_styles)}
border={Space {
left: 30.0,
right: 30.0,
top: 30.0,
bottom: 30.0,
}}
border={Edge::all(30.0)}
handle={panel_brown_handle}
>
<Text
......
......@@ -7,7 +7,7 @@ use kayak_core::styles::PositionType;
use kayak_ui::bevy::{BevyContext, BevyKayakUIPlugin, ImageManager, UICameraBundle};
use kayak_ui::core::{
render,
styles::{Style, StyleProp, Units},
styles::{Corner, Style, StyleProp, Units},
Index,
};
use kayak_ui::widgets::{App, Image};
......@@ -27,7 +27,7 @@ fn startup(
position_type: StyleProp::Value(PositionType::SelfDirected),
left: StyleProp::Value(Units::Pixels(10.0)),
top: StyleProp::Value(Units::Pixels(10.0)),
border_radius: StyleProp::Value((500.0, 500.0, 500.0, 500.0)),
border_radius: StyleProp::Value(Corner::all(500.0)),
width: StyleProp::Value(Units::Pixels(200.0)),
height: StyleProp::Value(Units::Pixels(182.0)),
..Style::default()
......
......@@ -5,9 +5,8 @@ use bevy::{
};
use kayak_ui::bevy::{BevyContext, BevyKayakUIPlugin, ImageManager, UICameraBundle};
use kayak_ui::core::{
layout_cache::Space,
render,
styles::{Style, StyleProp, Units},
styles::{Edge, Style, StyleProp, Units},
Index,
};
use kayak_ui::widgets::{App, NinePatch};
......@@ -56,12 +55,7 @@ fn startup(
<App>
<NinePatch
styles={Some(nine_patch_styles)}
border={Space {
left: 15.0,
right: 15.0,
top: 15.0,
bottom: 15.0,
}}
border={Edge::all(15.0)}
handle={ui_image_handle}
/>
</App>
......
......@@ -18,7 +18,7 @@ use kayak_ui::{
bevy::{BevyContext, BevyKayakUIPlugin, FontMapping, UICameraBundle},
core::{
render, rsx,
styles::{LayoutType, Style, StyleProp, Units},
styles::{Edge, LayoutType, Style, StyleProp, Units},
widget, Bound, Color, EventType, Index, MutableBound, OnEvent, WidgetProps,
},
widgets::{App, Background, Element, If, Text, TooltipConsumer, TooltipProvider, Window},
......@@ -219,10 +219,7 @@ fn ThemeDemo(props: ThemeDemoProps) {
top: StyleProp::Value(Units::Pixels(5.0)),
left: StyleProp::Value(Units::Stretch(1.0)),
right: StyleProp::Value(Units::Stretch(1.0)),
padding_bottom: StyleProp::Value(Units::Stretch(1.0)),
padding_left: StyleProp::Value(Units::Stretch(1.0)),
padding_right: StyleProp::Value(Units::Stretch(1.0)),
padding_top: StyleProp::Value(Units::Stretch(1.0)),
padding: StyleProp::Value(Edge::all(Units::Stretch(1.0))),
..Default::default()
};
......
......@@ -2,7 +2,7 @@ use kayak_ui::{
core::{
render_command::RenderCommand,
rsx,
styles::{LayoutType, Style, StyleProp, Units},
styles::{Edge, LayoutType, Style, StyleProp, Units},
use_state, widget, Bound, EventType, OnEvent, WidgetProps,
},
widgets::{Background, Text},
......@@ -86,10 +86,7 @@ pub fn Tab(props: TabProps) {
} else {
StyleProp::Value(tab_color)
},
padding_left: StyleProp::Value(border_width),
padding_right: StyleProp::Value(border_width),
padding_top: StyleProp::Value(border_width),
padding_bottom: StyleProp::Value(border_width),
padding: StyleProp::Value(Edge::all(border_width)),
layout_type: StyleProp::Value(LayoutType::Row),
..Default::default()
};
......
......@@ -3,7 +3,7 @@ use kayak_ui::core::{
color::Color,
render_command::RenderCommand,
rsx,
styles::{Style, StyleProp, Units},
styles::{Corner, Style, StyleProp, Units},
use_state, widget, EventType, OnEvent, WidgetProps,
};
......@@ -30,7 +30,7 @@ pub fn AddButton(props: AddButtonProps) {
});
let background_styles = Some(Style {
border_radius: StyleProp::Value((5.0, 5.0, 5.0, 5.0)),
border_radius: StyleProp::Value(Corner::all(5.0)),
background_color: StyleProp::Value(color),
cursor: CursorIcon::Hand.into(),
padding_left: StyleProp::Value(Units::Pixels(9.0)),
......
......@@ -27,10 +27,7 @@ pub fn Card(props: CardProps) {
height: StyleProp::Value(Units::Auto),
min_height: StyleProp::Value(Units::Pixels(26.0)),
top: StyleProp::Value(Units::Pixels(10.0)),
padding_left: StyleProp::Value(Units::Pixels(5.0)),
padding_right: StyleProp::Value(Units::Pixels(5.0)),
padding_top: StyleProp::Value(Units::Pixels(5.0)),
padding_bottom: StyleProp::Value(Units::Pixels(5.0)),
padding: StyleProp::Value(Edge::all(Units::Pixels(5.0))),
..Style::default()
};
......
......@@ -3,7 +3,7 @@ use kayak_ui::core::{
color::Color,
render_command::RenderCommand,
rsx,
styles::{Style, StyleProp, Units},
styles::{Corner, Style, StyleProp, Units},
use_state, widget, EventType, OnEvent, WidgetProps,
};
......@@ -31,7 +31,7 @@ pub fn DeleteButton(props: DeleteButtonProps) {
});
let background_styles = Some(Style {
border_radius: StyleProp::Value((5.0, 5.0, 5.0, 5.0)),
border_radius: StyleProp::Value(Corner::all(5.0)),
background_color: StyleProp::Value(color),
cursor: CursorIcon::Hand.into(),
padding_left: StyleProp::Value(Units::Pixels(8.0)),
......
......@@ -19,7 +19,7 @@ use kayak_ui::{
bevy::{BevyContext, BevyKayakUIPlugin, FontMapping, UICameraBundle},
core::{
render, rsx,
styles::{Style, StyleProp, Units},
styles::{Edge, Style, StyleProp, Units},
use_state, widget, EventType, Index, OnEvent,
},
widgets::{App, Button, Text, Window},
......@@ -80,10 +80,7 @@ fn ControlPanel() {
right: StyleProp::Value(Units::Stretch(1.0)),
top: StyleProp::Value(Units::Pixels(16.0)),
bottom: StyleProp::Value(Units::Pixels(8.0)),
padding_top: StyleProp::Value(Units::Pixels(8.0)),
padding_bottom: StyleProp::Value(Units::Pixels(8.0)),
padding_left: StyleProp::Value(Units::Pixels(48.0)),
padding_right: StyleProp::Value(Units::Pixels(48.0)),
padding: StyleProp::Value(Edge::axis(Units::Pixels(8.0), Units::Pixels(48.0))),
..Default::default()
};
......
......@@ -175,7 +175,11 @@ impl<'a> morphorm::Node<'a> for Index {
if let Some(node) = store.get(*self) {
if let Some(node) = node {
return match node.resolved_styles.left {
StyleProp::Default => Some(morphorm::Units::Auto),
StyleProp::Default => match node.resolved_styles.offset {
StyleProp::Default => Some(morphorm::Units::Auto),
StyleProp::Value(prop) => Some(prop.left),
_ => Some(morphorm::Units::Auto),
},
StyleProp::Value(prop) => Some(prop),
_ => Some(morphorm::Units::Auto),
};
......@@ -188,7 +192,11 @@ impl<'a> morphorm::Node<'a> for Index {
if let Some(node) = store.get(*self) {
if let Some(node) = node {
return match node.resolved_styles.right {
StyleProp::Default => Some(morphorm::Units::Auto),
StyleProp::Default => match node.resolved_styles.offset {
StyleProp::Default => Some(morphorm::Units::Auto),
StyleProp::Value(prop) => Some(prop.right),
_ => Some(morphorm::Units::Auto),
},
StyleProp::Value(prop) => Some(prop),
_ => Some(morphorm::Units::Auto),
};
......@@ -201,7 +209,11 @@ impl<'a> morphorm::Node<'a> for Index {
if let Some(node) = store.get(*self) {
if let Some(node) = node {
return match node.resolved_styles.top {
StyleProp::Default => Some(morphorm::Units::Auto),
StyleProp::Default => match node.resolved_styles.offset {
StyleProp::Default => Some(morphorm::Units::Auto),
StyleProp::Value(prop) => Some(prop.top),
_ => Some(morphorm::Units::Auto),
},
StyleProp::Value(prop) => Some(prop),
_ => Some(morphorm::Units::Auto),
};
......@@ -214,7 +226,11 @@ impl<'a> morphorm::Node<'a> for Index {
if let Some(node) = store.get(*self) {
if let Some(node) = node {
return match node.resolved_styles.bottom {
StyleProp::Default => Some(morphorm::Units::Auto),
StyleProp::Default => match node.resolved_styles.offset {
StyleProp::Default => Some(morphorm::Units::Auto),
StyleProp::Value(prop) => Some(prop.bottom),
_ => Some(morphorm::Units::Auto),
},
StyleProp::Value(prop) => Some(prop),
_ => Some(morphorm::Units::Auto),
};
......@@ -259,7 +275,11 @@ impl<'a> morphorm::Node<'a> for Index {
if let Some(node) = store.get(*self) {
if let Some(node) = node {
return match node.resolved_styles.padding_left {
StyleProp::Default => Some(morphorm::Units::Auto),
StyleProp::Default => match node.resolved_styles.padding {
StyleProp::Default => Some(morphorm::Units::Auto),
StyleProp::Value(prop) => Some(prop.left),
_ => Some(morphorm::Units::Auto),
},
StyleProp::Value(prop) => Some(prop),
_ => Some(morphorm::Units::Auto),
};
......@@ -272,7 +292,11 @@ impl<'a> morphorm::Node<'a> for Index {
if let Some(node) = store.get(*self) {
if let Some(node) = node {
return match node.resolved_styles.padding_right {
StyleProp::Default => Some(morphorm::Units::Auto),
StyleProp::Default => match node.resolved_styles.padding {
StyleProp::Default => Some(morphorm::Units::Auto),
StyleProp::Value(prop) => Some(prop.right),
_ => Some(morphorm::Units::Auto),
},
StyleProp::Value(prop) => Some(prop),
_ => Some(morphorm::Units::Auto),
};
......@@ -285,7 +309,11 @@ impl<'a> morphorm::Node<'a> for Index {
if let Some(node) = store.get(*self) {
if let Some(node) = node {
return match node.resolved_styles.padding_top {
StyleProp::Default => Some(morphorm::Units::Auto),
StyleProp::Default => match node.resolved_styles.padding {
StyleProp::Default => Some(morphorm::Units::Auto),
StyleProp::Value(prop) => Some(prop.top),
_ => Some(morphorm::Units::Auto),
},
StyleProp::Value(prop) => Some(prop),
_ => Some(morphorm::Units::Auto),
};
......@@ -298,7 +326,11 @@ impl<'a> morphorm::Node<'a> for Index {
if let Some(node) = store.get(*self) {
if let Some(node) = node {
return match node.resolved_styles.padding_bottom {
StyleProp::Default => Some(morphorm::Units::Auto),
StyleProp::Default => match node.resolved_styles.padding {
StyleProp::Default => Some(morphorm::Units::Auto),
StyleProp::Value(prop) => Some(prop.bottom),
_ => Some(morphorm::Units::Auto),
},
StyleProp::Value(prop) => Some(prop),
_ => Some(morphorm::Units::Auto),
};
......@@ -307,11 +339,29 @@ impl<'a> morphorm::Node<'a> for Index {
return Some(morphorm::Units::Auto);
}
fn row_between(&self, _store: &'_ Self::Data) -> Option<morphorm::Units> {
fn row_between(&self, store: &'_ Self::Data) -> Option<morphorm::Units> {
if let Some(node) = store.get(*self) {
if let Some(node) = node {
return match node.resolved_styles.row_between {
StyleProp::Default => Some(morphorm::Units::Auto),
StyleProp::Value(prop) => Some(prop),
_ => Some(morphorm::Units::Auto),
};
}
}
Some(morphorm::Units::Auto)
}
fn col_between(&self, _store: &'_ Self::Data) -> Option<morphorm::Units> {
fn col_between(&self, store: &'_ Self::Data) -> Option<morphorm::Units> {
if let Some(node) = store.get(*self) {
if let Some(node) = node {
return match node.resolved_styles.col_between {
StyleProp::Default => Some(morphorm::Units::Auto),
StyleProp::Value(prop) => Some(prop),
_ => Some(morphorm::Units::Auto),
};
}
}
Some(morphorm::Units::Auto)
}
......@@ -344,7 +394,7 @@ impl<'a> morphorm::Node<'a> for Index {
if let Some(node) = node {
return match node.resolved_styles.border {
StyleProp::Default => Some(morphorm::Units::Auto),
StyleProp::Value(prop) => Some(morphorm::Units::Pixels(prop.3)),
StyleProp::Value(prop) => Some(morphorm::Units::Pixels(prop.left)),
_ => Some(morphorm::Units::Auto),
};
}
......@@ -357,7 +407,7 @@ impl<'a> morphorm::Node<'a> for Index {
if let Some(node) = node {
return match node.resolved_styles.border {
StyleProp::Default => Some(morphorm::Units::Auto),
StyleProp::Value(prop) => Some(morphorm::Units::Pixels(prop.1)),
StyleProp::Value(prop) => Some(morphorm::Units::Pixels(prop.right)),
_ => Some(morphorm::Units::Auto),
};
}
......@@ -370,7 +420,7 @@ impl<'a> morphorm::Node<'a> for Index {
if let Some(node) = node {
return match node.resolved_styles.border {
StyleProp::Default => Some(morphorm::Units::Auto),
StyleProp::Value(prop) => Some(morphorm::Units::Pixels(prop.0)),
StyleProp::Value(prop) => Some(morphorm::Units::Pixels(prop.top)),
_ => Some(morphorm::Units::Auto),
};
}
......@@ -383,7 +433,7 @@ impl<'a> morphorm::Node<'a> for Index {
if let Some(node) = node {
return match node.resolved_styles.border {
StyleProp::Default => Some(morphorm::Units::Auto),
StyleProp::Value(prop) => Some(morphorm::Units::Pixels(prop.2)),
StyleProp::Value(prop) => Some(morphorm::Units::Pixels(prop.bottom)),
_ => Some(morphorm::Units::Auto),
};
}
......
use crate::layout_cache::Space;
use crate::styles::Edge;
#[derive(Debug, Clone, PartialEq)]
pub enum RenderCommand {
......@@ -18,7 +18,7 @@ pub enum RenderCommand {
handle: u16,
},
NinePatch {
border: Space,
border: Edge<f32>,
handle: u16,
},
}
......
use crate::{
color::Color,
layout_cache::{Rect, Space},
layout_cache::Rect,
render_command::RenderCommand,
styles::{Style, StyleProp},
styles::{Corner, Edge, Style, StyleProp},
};
#[derive(Debug, Clone, PartialEq)]
......@@ -15,8 +15,8 @@ pub enum RenderPrimitive {
layout: Rect,
background_color: Color,
border_color: Color,
border: (f32, f32, f32, f32),
border_radius: (f32, f32, f32, f32),
border: Edge<f32>,
border_radius: Corner<f32>,
},
Text {
color: Color,
......@@ -28,12 +28,12 @@ pub enum RenderPrimitive {
size: f32,
},
Image {
border_radius: (f32, f32, f32, f32),
border_radius: Corner<f32>,
layout: Rect,
handle: u16,
},
NinePatch {
border: Space,
border: Edge<f32>,
layout: Rect,
handle: u16,
},
......
use std::ops::{Mul, MulAssign};
/// A struct for defining properties related to the corners of widgets
///
/// This is useful for things like border radii, etc.
#[derive(Debug, Default, Copy, Clone, PartialEq)]
pub struct Corner<T>
where
T: Copy + Default + PartialEq,
{
/// The value of the top-left corner
pub top_left: T,
/// The value of the top-right corner
pub top_right: T,
/// The value of the bottom-left corner
pub bottom_left: T,
/// The value of the bottom-right corner
pub bottom_right: T,
}
impl<T> Corner<T>
where
T: Copy + Default + PartialEq,
{
/// Creates a new `Corner` with values individually specified for each corner
///
/// # Arguments
///
/// * `top_left`: The top-left corner value
/// * `top_right`: The top_-right corner value
/// * `bottom_left`: The bottom_-left corner value
/// * `bottom_right`: The bottom_-right corner value
///
pub fn new(top_left: T, top_right: T, bottom_left: T, bottom_right: T) -> Self {
Self {
top_left,
top_right,
bottom_left,
bottom_right,
}
}
/// Creates a new `Corner` with matching top corners and matching bottom corners
///
/// # Arguments
///
/// * `top`: The value of the top corners
/// * `bottom`: The value of the bottom corners
///
/// ```
/// # use kayak_core::styles::Corner;
/// // Creates a `Corner` with only the top corners rounded
/// let corner_radius = Corner::vertical(10.0, 0.0);
///
/// // Creates a `Corner` with only the bottom corners rounded
/// let corner_radius = Corner::vertical(0.0, 10.0);
/// ```
pub fn vertical(top: T, bottom: T) -> Self {
Self {
top_left: top,
top_right: top,
bottom_left: bottom,
bottom_right: bottom,
}
}
/// Creates a new `Corner` with matching left corners and matching right corners
///
/// # Arguments
///
/// * `left`: The value of the left corners
/// * `right`: The value of the right corners
///
/// ```
/// # use kayak_core::styles::Corner;
/// // Creates a `Corner` with only the left corners rounded
/// let corner_radius = Corner::horizontal(10.0, 0.0);
///
/// // Creates a `Corner` with only the right corners rounded
/// let corner_radius = Corner::horizontal(0.0, 10.0);
/// ```
pub fn horizontal(left: T, right: T) -> Self {
Self {
top_left: left,
top_right: right,
bottom_left: left,
bottom_right: right,
}
}
/// Creates a new `Corner` with all corners having the same value
///
/// # Arguments
///
/// * `value`: The value of all corners
///
pub fn all(value: T) -> Self {
Self {
top_left: value,
top_right: value,
bottom_left: value,
bottom_right: value,
}
}
/// Converts this `Corner` into a tuple matching `(Top Left, Top Right, Bottom Left, Bottom Right)`
pub fn into_tuple(self) -> (T, T, T, T) {
(
self.top_left,
self.top_right,
self.bottom_left,
self.bottom_right,
)
}
}
impl<T> From<Corner<T>> for (T, T, T, T)
where
T: Copy + Default + PartialEq,
{
/// Creates a tuple matching the pattern: `(Top Left, Top Right, Bottom Left, Bottom Right)`
fn from(edge: Corner<T>) -> Self {
edge.into_tuple()
}
}
impl<T> From<T> for Corner<T>
where
T: Copy + Default + PartialEq,
{
fn from(value: T) -> Self {
Corner::all(value)
}
}
impl<T> From<(T, T, T, T)> for Corner<T>
where
T: Copy + Default + PartialEq,
{
/// Converts the tuple according to the pattern: `(Top Left, Top Right, Bottom Left, Bottom Right)`
fn from(value: (T, T, T, T)) -> Self {
Corner::new(value.0, value.1, value.2, value.3)
}
}
impl<T> Mul<T> for Corner<T>
where
T: Copy + Default + PartialEq + Mul<Output = T>,
{
type Output = Self;
fn mul(self, rhs: T) -> Self::Output {
Self {
top_left: self.top_left * rhs,
top_right: self.top_right * rhs,
bottom_left: self.bottom_left * rhs,
bottom_right: self.bottom_right * rhs,
}
}
}
impl<T> Mul<Corner<T>> for Corner<T>
where
T: Copy + Default + PartialEq + Mul<Output = T>,
{
type Output = Self;
fn mul(self, rhs: Corner<T>) -> Self::Output {
Self {
top_left: rhs.top_left * self.top_left,
top_right: rhs.top_right * self.top_right,
bottom_left: rhs.bottom_left * self.bottom_left,
bottom_right: rhs.bottom_right * self.bottom_right,
}
}
}
impl<T> MulAssign<T> for Corner<T>
where
T: Copy + Default + PartialEq + MulAssign,
{
fn mul_assign(&mut self, rhs: T) {
self.top_left *= rhs;
self.top_right *= rhs;
self.bottom_left *= rhs;
self.bottom_right *= rhs;
}
}
impl<T> MulAssign<Corner<T>> for Corner<T>
where
T: Copy + Default + PartialEq + MulAssign,
{
fn mul_assign(&mut self, rhs: Corner<T>) {
self.top_left *= rhs.top_left;
self.top_right *= rhs.top_right;
self.bottom_left *= rhs.bottom_left;
self.bottom_right *= rhs.bottom_right;
}
}
#[cfg(test)]
mod tests {
use super::Corner;
#[test]
fn tuples_should_convert_to_corner() {
let expected = (1.0, 2.0, 3.0, 4.0);
let corner: Corner<f32> = expected.into();
assert_eq!(expected, corner.into_tuple());
let expected = (1.0, 1.0, 1.0, 1.0);
let corner: Corner<f32> = (expected.0).into();
assert_eq!(expected, corner.into_tuple());
let expected = (1.0, 1.0, 1.0, 1.0);
let corner: Corner<f32> = expected.0.into();
assert_eq!(expected, corner.into_tuple());
}
#[test]
fn multiplication_should_work_on_corners() {
let expected = (10.0, 20.0, 30.0, 40.0);
let mut corner = Corner::new(1.0, 2.0, 3.0, 4.0);
// Basic multiplication
let multiplied = corner * 10.0;
assert_eq!(expected, multiplied.into_tuple());
// Multiply and assign
corner *= 10.0;
assert_eq!(expected, corner.into_tuple());
}
}
use std::ops::{Mul, MulAssign};
/// A struct for defining properties related to the edges of widgets
///
/// This is useful for things like borders, padding, etc.
#[derive(Debug, Default, Copy, Clone, PartialEq)]
pub struct Edge<T>
where
T: Copy + Default + PartialEq,
{
/// The value of the top edge
pub top: T,
/// The value of the right edge
pub right: T,
/// The value of the bottom edge
pub bottom: T,
/// The value of the left edge
pub left: T,
}
impl<T> Edge<T>
where
T: Copy + Default + PartialEq,
{
/// Creates a new `Edge` with values individually specified for each edge
///
/// # Arguments
///
/// * `top`: The top edge value
/// * `right`: The right edge value
/// * `bottom`: The bottom edge value
/// * `left`: The left edge value
///
pub fn new(top: T, right: T, bottom: T, left: T) -> Self {
Self {
top,
right,
bottom,
left,
}
}
/// Creates a new `Edge` with matching vertical edges and matching horizontal edges
///
/// # Arguments
///
/// * `vertical`: The value of the vertical edges
/// * `horizontal`: The value of the horizontal edges
///
pub fn axis(vertical: T, horizontal: T) -> Self {
Self {
top: vertical,
right: horizontal,
bottom: vertical,
left: horizontal,
}
}
/// Creates a new `Edge` with all edges having the same value
///
/// # Arguments
///
/// * `value`: The value of all edges
///
pub fn all(value: T) -> Self {
Self {
top: value,
right: value,
bottom: value,
left: value,
}
}
/// Converts this `Edge` into a tuple matching `(Top, Right, Bottom, Left)`
pub fn into_tuple(self) -> (T, T, T, T) {
(self.top, self.right, self.bottom, self.left)
}
}
impl<T> From<Edge<T>> for (T, T, T, T)
where
T: Copy + Default + PartialEq,
{
fn from(edge: Edge<T>) -> Self {
edge.into_tuple()
}
}
impl<T> From<T> for Edge<T>
where
T: Copy + Default + PartialEq,
{
fn from(value: T) -> Self {
Edge::all(value)
}
}
impl<T> From<(T, T)> for Edge<T>
where
T: Copy + Default + PartialEq,
{
fn from(value: (T, T)) -> Self {
Edge::axis(value.0, value.1)
}
}
impl<T> From<(T, T, T, T)> for Edge<T>
where
T: Copy + Default + PartialEq,
{
fn from(value: (T, T, T, T)) -> Self {
Edge::new(value.0, value.1, value.2, value.3)
}
}
impl<T> Mul<T> for Edge<T>
where
T: Copy + Default + PartialEq + Mul<Output = T>,
{
type Output = Self;
fn mul(self, rhs: T) -> Self::Output {
Self {
top: self.top * rhs,
right: self.right * rhs,
bottom: self.bottom * rhs,
left: self.left * rhs,
}
}
}
impl<T> Mul<Edge<T>> for Edge<T>
where
T: Copy + Default + PartialEq + Mul<Output = T>,
{
type Output = Self;
fn mul(self, rhs: Edge<T>) -> Self::Output {
Self {
top: rhs.top * self.top,
right: rhs.right * self.right,
bottom: rhs.bottom * self.bottom,
left: rhs.left * self.left,
}
}
}
impl<T> MulAssign<T> for Edge<T>
where
T: Copy + Default + PartialEq + MulAssign,
{
fn mul_assign(&mut self, rhs: T) {
self.top *= rhs;
self.right *= rhs;
self.bottom *= rhs;
self.left *= rhs;
}
}
impl<T> MulAssign<Edge<T>> for Edge<T>
where
T: Copy + Default + PartialEq + MulAssign,
{
fn mul_assign(&mut self, rhs: Edge<T>) {
self.top *= rhs.top;
self.right *= rhs.right;
self.bottom *= rhs.bottom;
self.left *= rhs.left;
}
}
#[cfg(test)]
mod tests {
use super::Edge;
#[test]
fn tuples_should_convert_to_edge() {
let expected = (1.0, 2.0, 3.0, 4.0);
let edge: Edge<f32> = expected.into();
assert_eq!(expected, edge.into_tuple());
let expected = (1.0, 2.0, 1.0, 2.0);
let edge: Edge<f32> = (expected.0, expected.1).into();
assert_eq!(expected, edge.into_tuple());
let expected = (1.0, 1.0, 1.0, 1.0);
let edge: Edge<f32> = (expected.0).into();
assert_eq!(expected, edge.into_tuple());
let expected = (1.0, 1.0, 1.0, 1.0);
let edge: Edge<f32> = expected.0.into();
assert_eq!(expected, edge.into_tuple());
}
#[test]
fn multiplication_should_work_on_edges() {
let expected = (10.0, 20.0, 30.0, 40.0);
let mut corner = Edge::new(1.0, 2.0, 3.0, 4.0);
// Basic multiplication
let multiplied = corner * 10.0;
assert_eq!(expected, multiplied.into_tuple());
// Multiply and assign
corner *= 10.0;
assert_eq!(expected, corner.into_tuple());
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment