Commit 0a8a2dd8 authored by Florian Blasius's avatar Florian Blasius 🤘

[#166] move theme to window widget.

parent 7e622a57
......@@ -80,13 +80,12 @@ impl ThemeBuilder {
}
/// `Theme` is the representation of a css styling.
#[derive(Debug, Clone)]
#[derive(Clone, PartialEq, Default, Debug)]
pub struct Theme {
parent: Option<Arc<Theme>>,
rules: Vec<Rule>,
}
impl Theme {
/// Creates a new `ThemeBuilder` object with default theme as base.
pub fn create() -> ThemeBuilder {
......@@ -191,20 +190,20 @@ impl Theme {
}
}
#[derive(Clone, Debug)]
#[derive(Clone, Default, PartialEq, Debug)]
pub struct Rule {
pub selectors: Vec<Selector>,
pub declarations: Vec<Declaration>,
}
#[derive(Clone, Debug)]
#[derive(Clone, Default, PartialEq, Debug)]
pub struct Declaration {
pub property: String,
pub value: Value,
pub important: bool,
}
#[derive(Clone, Debug)]
#[derive(Clone, PartialEq, Debug)]
pub enum Value {
UInt(u32),
Float(f32),
......@@ -212,6 +211,12 @@ pub enum Value {
Str(String),
}
impl Default for Value {
fn default() -> Self {
Value::UInt(0)
}
}
impl Value {
pub fn uint(&self) -> Option<u32> {
match *self {
......
......@@ -80,18 +80,19 @@ impl Template for MainView {
}
}
fn main() {
// let mut application = Application::default();
// application
// .create_window()
// .bounds((100.0, 100.0, 420.0, 730.0))
// .title("OrbTk - grid example")
// .theme(
// Theme::create()
// .extension_path("examples/res/grid.css")
// .build(),
// )
// .resizable(true)
// .build(MainView::create());
// application.run();
}
Application::new()
.window(|ctx| {
Window::create()
.title("OrbTk - grid example")
.position((100.0, 100.0))
.size(420.0, 730.0)
.theme(ThemeValue::create()
.extension_path("examples/res/grid.css")
.build())
.child(MainView::create().build(ctx))
.build(ctx)
})
.run();
}
\ No newline at end of file
use orbtk::prelude::*;
fn main() {
Application::new()
Application::new()
.window(|ctx| {
Window::create()
.title("OrbTk - minimal example")
......
......@@ -128,13 +128,15 @@ impl Template for MainView {
}
fn main() {
// let mut application = Application::default();
// application
// .create_window()
// .bounds((100.0, 100.0, 420.0, 730.0))
// .title("OrbTk - light theme example")
// .theme(light_theme())
// .build(MainView::create());
// application.run();
Application::new()
.window(|ctx| {
Window::create()
.title("OrbTk - light theme example")
.position((100.0, 100.0))
.size(420.0, 730.0)
.theme(light_theme())
.child(MainView::create().build(ctx))
.build(ctx)
})
.run();
}
use orbtk::prelude::*;
fn main() {
Application::new()
Application::new()
.window(|ctx| {
Window::create()
.title("OrbTk - minimal example")
......
......@@ -64,10 +64,8 @@ impl Application {
world.entity_component_manager().register_component(window, Global::default());
world.entity_component_manager().register_component(window, Bounds::from((0.0, 0.0, constraint.width(), constraint.height())));
// todo: theme
let (mut runner, backend) =
target_backend(&title.0, Bounds::from((position.0.x, position.0.y, constraint.width(), constraint.height())), false, default_theme());
target_backend(&title.0, Bounds::from((position.0.x, position.0.y, constraint.width(), constraint.height())), false);
world.register_init_system(InitSystem {
backend: backend.clone(),
......
......@@ -15,28 +15,15 @@ use orbgl_api::prelude::Canvas;
use crate::prelude::*;
/// Provides the context for the `InitSystem`.
pub struct InitContext<'a> {
pub theme: &'a Theme,
}
/// Is used to provides data from the `Backend` to the `RenderSystem`.
pub struct RenderContext<'a> {
pub canvas: &'a mut Canvas,
pub renderer: &'a mut dyn Renderer,
pub theme: &'a Theme,
pub event_queue: &'a RefCell<EventQueue>,
}
/// Is used to provides data from the `Backend` to the `LayoutSystem`.
pub struct LayoutContext<'a> {
pub window_size: (u32, u32),
pub theme: &'a Theme,
}
/// Is used to provides data from the `Backend` to the `StateSystem` and `PostLayoutStateSystem`.
pub struct StateContext<'a> {
pub theme: &'a Theme,
pub event_queue: &'a RefCell<EventQueue>,
pub messages: &'a RefCell<BTreeMap<Entity, Vec<MessageBox>>>,
}
......@@ -63,9 +50,7 @@ pub trait Renderer {
/// This trait is used to define a backend for OrbTk.
pub trait Backend {
fn drain_events(&mut self);
fn init_context(&mut self) -> InitContext<'_>;
fn render_context(&mut self) -> RenderContext<'_>;
fn layout_context(&mut self) -> LayoutContext<'_>;
fn event_context(&mut self) -> EventContext<'_>;
fn state_context(&mut self) -> StateContext<'_>;
}
......
......@@ -13,7 +13,6 @@ use crate::backend::*;
/// Implementation of the OrbClient based backend.
pub struct OrbitalBackend {
inner: OrbWindow,
theme: Theme,
mouse_buttons: (bool, bool, bool),
mouse_position: Point,
event_queue: RefCell<EventQueue>,
......@@ -22,7 +21,7 @@ pub struct OrbitalBackend {
}
impl OrbitalBackend {
pub fn new(theme: Theme, inner: OrbWindow) -> OrbitalBackend {
pub fn new(inner: OrbWindow) -> OrbitalBackend {
let mut inner = inner;
let surface = FramebufferSurface::new(
......@@ -37,7 +36,6 @@ impl OrbitalBackend {
OrbitalBackend {
inner,
theme,
mouse_buttons: (false, false, false),
mouse_position: Point::default(),
event_queue: RefCell::new(EventQueue::default()),
......@@ -151,26 +149,14 @@ impl Backend for OrbitalBackend {
}
}
fn init_context(&mut self) -> InitContext<'_> {
InitContext { theme: &self.theme }
}
fn render_context(&mut self) -> RenderContext<'_> {
RenderContext {
canvas: &mut self.canvas,
renderer: &mut self.inner,
theme: &self.theme,
event_queue: &self.event_queue,
}
}
fn layout_context(&mut self) -> LayoutContext<'_> {
LayoutContext {
window_size: (self.inner.width(), self.inner.height()),
theme: &self.theme,
}
}
fn event_context(&mut self) -> EventContext<'_> {
EventContext {
event_queue: &self.event_queue,
......@@ -179,7 +165,6 @@ impl Backend for OrbitalBackend {
fn state_context(&mut self) -> StateContext<'_> {
StateContext {
theme: &self.theme,
event_queue: &self.event_queue,
messages: &mut self.messages,
}
......
......@@ -17,7 +17,6 @@ pub fn target_backend(
title: &str,
bounds: Bounds,
resizable: bool,
theme: Theme,
) -> (Box<OrbitalBackendRunner>, Rc<RefCell<dyn Backend>>) {
let mut flags = vec![];
if resizable {
......@@ -25,7 +24,6 @@ pub fn target_backend(
}
let backend = Rc::new(RefCell::new(OrbitalBackend::new(
theme,
OrbWindow::new_flags(
bounds.x() as i32,
bounds.y() as i32,
......
......@@ -31,7 +31,7 @@ impl Layout for FixedSizeLayout {
ecm: &mut EntityComponentManager,
tree: &Tree,
layouts: &Rc<RefCell<BTreeMap<Entity, Box<dyn Layout>>>>,
theme: &Theme,
theme: &ThemeValue,
) -> DirtySize {
if Visibility::get(entity, ecm) == VisibilityValue::Collapsed {
self.desired_size.borrow_mut().set_size(0.0, 0.0);
......@@ -125,7 +125,7 @@ impl Layout for FixedSizeLayout {
ecm: &mut EntityComponentManager,
tree: &Tree,
layouts: &Rc<RefCell<BTreeMap<Entity, Box<dyn Layout>>>>,
theme: &Theme,
theme: &ThemeValue,
) -> (f64, f64) {
if !self.desired_size.borrow().dirty() {
return self.desired_size.borrow().size();
......
......@@ -92,7 +92,7 @@ impl Layout for GridLayout {
ecm: &mut EntityComponentManager,
tree: &Tree,
layouts: &Rc<RefCell<BTreeMap<Entity, Box<dyn Layout>>>>,
theme: &Theme,
theme: &ThemeValue,
) -> DirtySize {
if Visibility::get(entity, ecm) == VisibilityValue::Collapsed {
self.desired_size.borrow_mut().set_size(0.0, 0.0);
......@@ -145,7 +145,7 @@ impl Layout for GridLayout {
ecm: &mut EntityComponentManager,
tree: &Tree,
layouts: &Rc<RefCell<BTreeMap<Entity, Box<dyn Layout>>>>,
theme: &Theme,
theme: &ThemeValue,
) -> (f64, f64) {
if !self.desired_size.borrow().dirty() {
return self.desired_size.borrow().size();
......
......@@ -27,7 +27,7 @@ pub trait Layout: Any {
ecm: &mut EntityComponentManager,
tree: &Tree,
layouts: &Rc<RefCell<BTreeMap<Entity, Box<dyn Layout>>>>,
theme: &Theme,
theme: &ThemeValue,
) -> DirtySize;
/// Arranges an sizes the children.
......@@ -38,6 +38,6 @@ pub trait Layout: Any {
ecm: &mut EntityComponentManager,
tree: &Tree,
layouts: &Rc<RefCell<BTreeMap<Entity, Box<dyn Layout>>>>,
theme: &Theme,
theme: &ThemeValue,
) -> (f64, f64);
}
......@@ -30,7 +30,7 @@ impl Layout for PaddingLayout {
ecm: &mut EntityComponentManager,
tree: &Tree,
layouts: &Rc<RefCell<BTreeMap<Entity, Box<dyn Layout>>>>,
theme: &Theme,
theme: &ThemeValue,
) -> DirtySize {
if Visibility::get(entity, ecm) == VisibilityValue::Collapsed {
self.desired_size.borrow_mut().set_size(0.0, 0.0);
......@@ -100,7 +100,7 @@ impl Layout for PaddingLayout {
ecm: &mut EntityComponentManager,
tree: &Tree,
layouts: &Rc<RefCell<BTreeMap<Entity, Box<dyn Layout>>>>,
theme: &Theme,
theme: &ThemeValue,
) -> (f64, f64) {
if !self.desired_size.borrow().dirty() {
return self.desired_size.borrow().size();
......
......@@ -33,7 +33,7 @@ impl Layout for ScrollLayout {
ecm: &mut EntityComponentManager,
tree: &Tree,
layouts: &Rc<RefCell<BTreeMap<Entity, Box<dyn Layout>>>>,
theme: &Theme,
theme: &ThemeValue,
) -> DirtySize {
if Visibility::get(entity, ecm) == VisibilityValue::Collapsed {
self.desired_size.borrow_mut().set_size(0.0, 0.0);
......@@ -89,7 +89,7 @@ impl Layout for ScrollLayout {
ecm: &mut EntityComponentManager,
tree: &Tree,
layouts: &Rc<RefCell<BTreeMap<Entity, Box<dyn Layout>>>>,
theme: &Theme,
theme: &ThemeValue,
) -> (f64, f64) {
if !self.desired_size.borrow().dirty() {
return self.desired_size.borrow().size();
......
......@@ -30,7 +30,7 @@ impl Layout for StackLayout {
ecm: &mut EntityComponentManager,
tree: &Tree,
layouts: &Rc<RefCell<BTreeMap<Entity, Box<dyn Layout>>>>,
theme: &Theme,
theme: &ThemeValue,
) -> DirtySize {
if Visibility::get(entity, ecm) == VisibilityValue::Collapsed {
self.desired_size.borrow_mut().set_size(0.0, 0.0);
......@@ -98,7 +98,7 @@ impl Layout for StackLayout {
ecm: &mut EntityComponentManager,
tree: &Tree,
layouts: &Rc<RefCell<BTreeMap<Entity, Box<dyn Layout>>>>,
theme: &Theme,
theme: &ThemeValue,
) -> (f64, f64) {
if !self.desired_size.borrow().dirty() {
return self.desired_size.borrow().size();
......
......@@ -37,7 +37,7 @@ impl Layout for TextSelectionLayout {
ecm: &mut EntityComponentManager,
tree: &Tree,
layouts: &Rc<RefCell<BTreeMap<Entity, Box<dyn Layout>>>>,
theme: &Theme,
theme: &ThemeValue,
) -> DirtySize {
if Visibility::get(entity, ecm) == VisibilityValue::Collapsed {
self.desired_size.borrow_mut().set_size(0.0, 0.0);
......@@ -94,7 +94,7 @@ impl Layout for TextSelectionLayout {
ecm: &mut EntityComponentManager,
tree: &Tree,
layouts: &Rc<RefCell<BTreeMap<Entity, Box<dyn Layout>>>>,
theme: &Theme,
theme: &ThemeValue,
) -> (f64, f64) {
if !self.desired_size.borrow().dirty() {
return self.desired_size.borrow().size();
......
......@@ -19,6 +19,6 @@ pub use crate::{
widgets::*,
widget,
property,
css_engine::{Selector as SelectorValue, Theme, ThemeBuilder, SelectorRelation},
css_engine::{Selector as SelectorValue, Theme as ThemeValue, ThemeBuilder, SelectorRelation},
tree::*,
};
\ No newline at end of file
......@@ -12,6 +12,7 @@ pub use self::icon_font::*;
pub use self::icon_size::*;
pub use self::opacity::*;
pub use self::selector::*;
pub use self::theme::*;
mod background;
mod border_brush;
......@@ -25,6 +26,7 @@ mod icon_font;
mod icon_size;
mod opacity;
mod selector;
mod theme;
#[cfg(test)]
mod tests;
use crate::prelude::*;
property!(
/// `Theme` describes the css theme of a window.
Theme(ThemeValue)
);
......@@ -42,6 +42,8 @@ impl System<Tree> for InitSystem {
let mut backend = self.backend.borrow_mut();
let state_context = backend.state_context();
let theme = ecm.borrow_component::<Theme>(tree.root).unwrap().0.clone();
#[cfg(feature = "debug")]
let debug = true;
#[cfg(not(feature = "debug"))]
......@@ -54,6 +56,7 @@ impl System<Tree> for InitSystem {
println!("\n------ Widget tree ------\n");
}
// init css ids
for node in tree.into_iter() {
......@@ -64,7 +67,7 @@ impl System<Tree> for InitSystem {
ecm,
tree,
&state_context.event_queue,
&state_context.theme,
&theme,
None,
);
......@@ -72,7 +75,6 @@ impl System<Tree> for InitSystem {
state.init(&mut context);
}
self.read_init_from_theme(&mut context);
}
}
......
......@@ -35,17 +35,16 @@ impl System<Tree> for LayoutSystem {
let root = tree.children[&tree.root][0];
let mut backend = self.backend.borrow_mut();
let render_context = backend.render_context();
let theme = ecm.borrow_component::<Theme>(tree.root).unwrap().0.clone();
self.layouts.borrow()[&root].measure(root, ecm, tree, &self.layouts, &render_context.theme);
self.layouts.borrow()[&root].measure(root, ecm, tree, &self.layouts, &theme);
self.layouts.borrow()[&root].arrange(
window_size,
root,
ecm,
tree,
&self.layouts,
&render_context.theme,
&theme,
);
// if self.debug_flag.get() {
......
......@@ -31,6 +31,8 @@ impl System<Tree> for RenderSystem {
let mut backend = self.backend.borrow_mut();
let render_context = backend.render_context();
let theme = ecm.borrow_component::<Theme>(tree.root).unwrap().0.clone();
let mut hidden_parents: HashSet<Entity> = HashSet::new();
let mut offsets = BTreeMap::new();
......@@ -76,7 +78,7 @@ impl System<Tree> for RenderSystem {
ecm,
tree,
&render_context.event_queue,
&render_context.theme,
&theme,
None,
),
&global_position,
......@@ -88,7 +90,7 @@ impl System<Tree> for RenderSystem {
if let Ok(bounds) = ecm.borrow_component::<Bounds>(node) {
let selector = Selector::from("debug-border");
let brush = render_context.theme.brush("border-color", &selector.0).unwrap();
let brush = theme.brush("border-color", &selector.0).unwrap();
match brush {
Brush::SolidColor(color) => render_context.canvas.set_stroke_style(color),
......
......@@ -84,12 +84,14 @@ impl System<Tree> for StateSystem {
let mut backend = self.backend.borrow_mut();
let state_context = backend.state_context();
let theme = ecm.borrow_component::<Theme>(tree.root).unwrap().0.clone();
let mut context = Context::new(
tree.root,
ecm,
tree,
&state_context.event_queue,
&state_context.theme,
&theme,
Some(&state_context.messages),
);
......@@ -134,6 +136,8 @@ impl System<Tree> for PostLayoutStateSystem {
return;
}
let theme = ecm.borrow_component::<Theme>(tree.root).unwrap().0.clone();
let mut backend = self.backend.borrow_mut();
let state_context = backend.state_context();
let mut context = Context::new(
......@@ -141,7 +145,7 @@ impl System<Tree> for PostLayoutStateSystem {
ecm,
tree,
&state_context.event_queue,
&state_context.theme,
&theme,
None,
);
......
......@@ -13,7 +13,7 @@ pub struct Context<'a> {
event_queue: &'a RefCell<EventQueue>,
messages: Option<&'a RefCell<BTreeMap<Entity, Vec<MessageBox>>>>,
pub entity: Entity,
pub theme: &'a Theme,
pub theme: &'a ThemeValue,
}
impl<'a> Context<'a> {
......@@ -23,7 +23,7 @@ impl<'a> Context<'a> {
ecm: &'a mut EntityComponentManager,
tree: &'a Tree,
event_queue: &'a RefCell<EventQueue>,
theme: &'a Theme,
theme: &'a ThemeValue,
messages: Option<&'a RefCell<BTreeMap<Entity, Vec<MessageBox>>>>,
) -> Self {
Context {
......@@ -43,7 +43,7 @@ impl<'a> Context<'a> {
/// Returns the window widget.
pub fn window(&mut self) -> WidgetContainer<'_> {
WidgetContainer::new(0, &mut self.ecm)
WidgetContainer::new(self.tree.root, &mut self.ecm)
}
/// Returns a child of the widget of the current state referenced by css `id`.
......
......@@ -19,7 +19,10 @@ widget!(
resizeable: Resizeable,
/// Sets or shares the position property.
position: Pos
position: Pos,
/// Sets or shares the theme property.
theme: Theme
}
);
......@@ -30,6 +33,7 @@ impl Template for Window {
.size(100.0, 100.0)
.selector("window")
.title("Window")
.theme(default_theme())
.resizeable(false)
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment