Commit b070640a authored by Florian Blasius's avatar Florian Blasius 🤘

Merge branch '168-subcrate-shell' into 'master'

Resolve "subcrate - shell"

See merge request redox-os/orbtk!110
parents c12497b7 0d4979f6
......@@ -18,7 +18,8 @@
"group": {
"kind": "build",
"isDefault": true
}
},
"problemMatcher": []
},
{
"label": "build debug",
......
......@@ -468,13 +468,13 @@ name = "orbtk"
version = "0.3.0"
dependencies = [
"dces 0.1.6 (git+https://gitlab.redox-os.org/redox-os/dces-rust.git)",
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"orbclient 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
"orbfont 0.1.9 (git+https://gitlab.redox-os.org/redox-os/orbfont.git)",
"orbgl 0.1.0 (git+https://gitlab.redox-os.org/redox-os/orbgl.git)",
"orbgl_api 0.1.0 (git+https://gitlab.redox-os.org/redox-os/orbgl.git)",
"orbimage 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)",
"orbtk-css-engine 0.1.0",
"orbtk-shell 0.1.0",
"orbtk-theme 0.1.0",
"orbtk-tree 0.1.0",
"orbtk-utils 0.1.0",
......@@ -488,6 +488,18 @@ dependencies = [
"orbtk-utils 0.1.0",
]
[[package]]
name = "orbtk-shell"
version = "0.1.0"
dependencies = [
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"orbclient 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
"orbfont 0.1.9 (git+https://gitlab.redox-os.org/redox-os/orbfont.git)",
"orbgl 0.1.0 (git+https://gitlab.redox-os.org/redox-os/orbgl.git)",
"orbgl_api 0.1.0 (git+https://gitlab.redox-os.org/redox-os/orbgl.git)",
"orbtk-utils 0.1.0",
]
[[package]]
name = "orbtk-theme"
version = "0.1.0"
......
......@@ -29,10 +29,10 @@ orbclient = "0.3.22"
[dependencies]
orbtk-css-engine = { version = "0.1.0", path = "crates/css-engine" }
orbtk-shell = { version = "0.1.0", path = "crates/shell" }
orbtk-theme = { version = "0.1.0", path="crates/theme" }
orbtk-utils = { version = "0.1.0", path = "crates/utils" }
orbtk-tree = { version = "0.1.0", path="crates/tree" }
lazy_static = "1.3.0"
# dces = { path = "../dces-rust"}
dces = { git = "https://gitlab.redox-os.org/redox-os/dces-rust.git" }
# orbgl_api = { path = "../orbgl/orbgl_api" }
......@@ -45,6 +45,7 @@ debug = []
[workspace]
members = [
"crates/css-engine",
"crates/shell",
"crates/theme",
"crates/utils",
"crates/tree"
......
[package]
name = "orbtk-shell"
version = "0.1.0"
authors = ["Florian Blasius <flovanpt@posteo.de>"]
description = "Window shell crate used by OrbTk."
repository = "https://gitlab.redox-os.org/redox-os/orbtk"
license = "MIT"
keywords = ["shell", "window", "ui"]
edition = "2018"
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
orbgl = { git = "https://gitlab.redox-os.org/redox-os/orbgl.git" }
orbfont = { git = "https://gitlab.redox-os.org/redox-os/orbfont.git" }
orbclient = "0.3.22"
[dependencies]
orbgl_api = { git = "https://gitlab.redox-os.org/redox-os/orbgl.git" }
orbtk-utils = { version = "0.1.0", path = "../utils" }
lazy_static = "1.3.0"
\ No newline at end of file
//! This module contains elements to work with window events.
/// Represents a keyboard key.
#[derive(Copy, Clone, Debug, Hash, PartialEq)]
pub enum Key {
Unknown,
Backspace,
Up,
Down,
Left,
Right,
Space,
Enter,
A(bool),
B(bool),
C(bool),
D(bool),
E(bool),
F(bool),
G(bool),
H(bool),
I(bool),
J(bool),
K(bool),
L(bool),
M(bool),
N(bool),
O(bool),
P(bool),
Q(bool),
S(bool),
R(bool),
T(bool),
U(bool),
V(bool),
W(bool),
X(bool),
Y(bool),
Z(bool),
Zero,
One,
Two,
Three,
Four,
Five,
Six,
Seven,
Eight,
Nine,
Dot,
QuestionMark,
ExclamationMark,
}
impl From<Key> for &'static str {
fn from(key: Key) -> &'static str {
match key {
Key::A(false) => "a",
Key::B(false) => "b",
Key::C(false) => "c",
Key::D(false) => "d",
Key::E(false) => "e",
Key::F(false) => "f",
Key::G(false) => "g",
Key::H(false) => "h",
Key::I(false) => "i",
Key::J(false) => "j",
Key::K(false) => "k",
Key::L(false) => "l",
Key::M(false) => "m",
Key::N(false) => "n",
Key::O(false) => "o",
Key::P(false) => "p",
Key::Q(false) => "q",
Key::R(false) => "r",
Key::S(false) => "s",
Key::T(false) => "t",
Key::U(false) => "u",
Key::V(false) => "v",
Key::W(false) => "w",
Key::X(false) => "x",
Key::Y(false) => "y",
Key::Z(false) => "z",
Key::A(true) => "A",
Key::B(true) => "B",
Key::C(true) => "C",
Key::D(true) => "D",
Key::E(true) => "E",
Key::F(true) => "F",
Key::G(true) => "G",
Key::H(true) => "H",
Key::I(true) => "I",
Key::J(true) => "J",
Key::K(true) => "K",
Key::L(true) => "L",
Key::M(true) => "M",
Key::N(true) => "N",
Key::O(true) => "O",
Key::P(true) => "P",
Key::Q(true) => "Q",
Key::R(true) => "R",
Key::S(true) => "S",
Key::T(true) => "T",
Key::U(true) => "U",
Key::V(true) => "V",
Key::W(true) => "W",
Key::X(true) => "X",
Key::Y(true) => "Y",
Key::Z(true) => "Z",
Key::Zero => "0",
Key::One => "1",
Key::Two => "2",
Key::Three => "3",
Key::Four => "4",
Key::Five => "5",
Key::Six => "6",
Key::Seven => "7",
Key::Eight => "8",
Key::Nine => "9",
Key::Space => " ",
Key::Dot => ".",
Key::QuestionMark => "?",
Key::ExclamationMark => "!",
_ => "",
}
}
}
impl From<Key> for Option<u8> {
fn from(key: Key) -> Option<u8> {
match key {
Key::A(false) => Some(b'a'),
Key::B(false) => Some(b'b'),
Key::C(false) => Some(b'c'),
Key::D(false) => Some(b'd'),
Key::E(false) => Some(b'e'),
Key::F(false) => Some(b'f'),
Key::G(false) => Some(b'g'),
Key::H(false) => Some(b'h'),
Key::I(false) => Some(b'i'),
Key::J(false) => Some(b'j'),
Key::K(false) => Some(b'k'),
Key::L(false) => Some(b'l'),
Key::M(false) => Some(b'm'),
Key::N(false) => Some(b'n'),
Key::O(false) => Some(b'o'),
Key::P(false) => Some(b'p'),
Key::Q(false) => Some(b'q'),
Key::R(false) => Some(b'r'),
Key::S(false) => Some(b's'),
Key::T(false) => Some(b't'),
Key::U(false) => Some(b'u'),
Key::V(false) => Some(b'v'),
Key::W(false) => Some(b'w'),
Key::X(false) => Some(b'x'),
Key::Y(false) => Some(b'y'),
Key::Z(false) => Some(b'z'),
Key::A(true) => Some(b'A'),
Key::B(true) => Some(b'B'),
Key::C(true) => Some(b'C'),
Key::D(true) => Some(b'D'),
Key::E(true) => Some(b'E'),
Key::F(true) => Some(b'F'),
Key::G(true) => Some(b'G'),
Key::H(true) => Some(b'H'),
Key::I(true) => Some(b'I'),
Key::J(true) => Some(b'J'),
Key::K(true) => Some(b'K'),
Key::L(true) => Some(b'L'),
Key::M(true) => Some(b'M'),
Key::N(true) => Some(b'N'),
Key::O(true) => Some(b'O'),
Key::P(true) => Some(b'P'),
Key::Q(true) => Some(b'Q'),
Key::R(true) => Some(b'R'),
Key::S(true) => Some(b'S'),
Key::T(true) => Some(b'T'),
Key::U(true) => Some(b'U'),
Key::V(true) => Some(b'V'),
Key::W(true) => Some(b'W'),
Key::X(true) => Some(b'X'),
Key::Y(true) => Some(b'Y'),
Key::Z(true) => Some(b'Z'),
Key::Zero => Some(b'0'),
Key::One => Some(b'1'),
Key::Two => Some(b'2'),
Key::Three => Some(b'3'),
Key::Four => Some(b'4'),
Key::Five => Some(b'5'),
Key::Six => Some(b'6'),
Key::Seven => Some(b'7'),
Key::Eight => Some(b'8'),
Key::Nine => Some(b'9'),
Key::Space => Some(b' '),
Key::Dot => Some(b'.'),
Key::QuestionMark => Some(b'?'),
Key::ExclamationMark => Some(b'!'),
_ => None,
}
}
}
impl ToString for Key {
fn to_string(&self) -> String {
<&'static str>::from(*self).to_owned()
}
}
impl From<char> for Key {
fn from(sight: char) -> Self {
match sight {
'a' => Key::A(false),
'b' => Key::B(false),
'c' => Key::C(false),
'd' => Key::D(false),
'e' => Key::E(false),
'f' => Key::F(false),
'g' => Key::G(false),
'h' => Key::H(false),
'i' => Key::I(false),
'j' => Key::J(false),
'k' => Key::K(false),
'l' => Key::L(false),
'm' => Key::M(false),
'n' => Key::N(false),
'o' => Key::O(false),
'p' => Key::P(false),
'q' => Key::Q(false),
'r' => Key::R(false),
's' => Key::S(false),
't' => Key::T(false),
'u' => Key::U(false),
'v' => Key::V(false),
'w' => Key::W(false),
'x' => Key::X(false),
'y' => Key::Y(false),
'z' => Key::Z(false),
'A' => Key::A(true),
'B' => Key::B(true),
'C' => Key::C(true),
'D' => Key::D(true),
'E' => Key::E(true),
'F' => Key::F(true),
'G' => Key::G(true),
'H' => Key::H(true),
'I' => Key::I(true),
'J' => Key::J(true),
'K' => Key::K(true),
'L' => Key::L(true),
'M' => Key::M(true),
'N' => Key::N(true),
'O' => Key::O(true),
'P' => Key::P(true),
'Q' => Key::Q(true),
'R' => Key::R(true),
'S' => Key::S(true),
'T' => Key::T(true),
'U' => Key::U(true),
'V' => Key::V(true),
'W' => Key::W(true),
'X' => Key::X(true),
'Y' => Key::Y(true),
'Z' => Key::Z(true),
'0' => Key::Zero,
'1' => Key::One,
'2' => Key::Two,
'3' => Key::Three,
'4' => Key::Four,
'5' => Key::Five,
'6' => Key::Six,
'7' => Key::Seven,
'8' => Key::Eight,
'9' => Key::Nine,
' ' => Key::Space,
'.' => Key::Dot,
'?' => Key::QuestionMark,
'!' => Key::ExclamationMark,
_ => Key::Unknown,
}
}
}
/// Describes a specific mouse button.
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
pub enum MouseButton {
Left,
Middle,
Right,
}
/// Describes the position / state of a button.
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
pub enum ButtonState {
Down,
Up
}
/// Represents a mouse event.
#[derive(Debug)]
pub struct MouseEvent {
pub x: f64,
pub y: f64,
pub button: MouseButton,
pub state: ButtonState
}
/// Represents a keyboard key event.
#[derive(Debug)]
pub struct KeyEvent {
pub key: Key,
pub state: ButtonState
}
\ No newline at end of file
/*!
Window shell abstraction layer used by OrbTk. Provides support for desktop and web.
# Example
Basic usage of the shell:
```rust,no_run
use orbtk_shell::prelude::*;
let shell = WindowBuilder::new(MyCustomWindowAdapter::new())
.title("Window")
.bounds((0.0, 0.0, 100.0, 100.0))
.build();
let runner = ShellRunner {
shell,
update: Rc::new(Cell::new(true)),
running: Rc::new(Cell:new(true)),
updater: Box::new(MyCustomUpdater::new())
};
runner.run()
```
*/
#[macro_use]
extern crate lazy_static;
pub mod event;
pub mod obsolete;
pub mod prelude;
pub mod window;
#[cfg(not(target_arch = "wasm32"))]
#[path = "orbclient/mod.rs"]
pub mod platform;
// !!! The complete components of this module will be deleted after OrbGL supports text rendering !!!
use orbfont::Font;
use orbtk_utils::prelude::*;
pub trait Renderer {
fn render_text(
&mut self,
text: &str,
bounds: &Rect,
parent_bounds: &Rect,
global_position: &Point,
font_size: u32,
color: Color,
font: &Font,
);
}
pub trait FontMeasure {
fn measure(&self, text: &str, font: &Font, font_size: u32) -> (u32, u32);
}
\ No newline at end of file
use orbfont::Font;
/// Reference to the material icon font.
pub static MATERIAL_ICONS_REGULAR_FONT: &'static [u8; 128180] =
include_bytes!("MaterialIcons-Regular.ttf");
pub static ROBOTO_REGULAR_FONT: &'static [u8; 145348] = include_bytes!("Roboto-Regular.ttf");
pub fn font_by_key(key: &str) -> Option<Font> {
match key {
"Roboto Regular" => {
return Some(Font::from_data(font_into_box(ROBOTO_REGULAR_FONT)).unwrap());
}
"Material Icons Regular" => {
return Some(Font::from_data(font_into_box(MATERIAL_ICONS_REGULAR_FONT)).unwrap());
}
_ => return None,
}
}
pub fn font_into_box(font: &[u8]) -> Box<[u8]> {
font.to_vec().into_boxed_slice()
}
\ No newline at end of file
pub use crate::{
event::*,
obsolete::*,
window::*,
platform::*,
};
\ No newline at end of file
//! This module contains traits to inject custom logic into the window shell.
use orbgl_api::Canvas;
use crate::event::*;
/// The window adapter is used to work with the window shell.ButtonState
///
/// It handles updates from the shell and provides method to update and render
/// its content.
pub trait WindowAdapter {
/// Renders the content.
fn render(&mut self, _canvas: &mut Canvas) {}
/// Updates the content.
fn update(&mut self) {}
/// Is called after the window is resized.
fn resize(&mut self, _width: f64, _height: f64) {}
/// Is called after the mouse was moved.
fn mouse(&mut self, _x: f64, _y: f64) {}
/// Is called after the state of a mouse button is changed.
fn mouse_event(&mut self, _event: MouseEvent) {}
/// Is called after the state of a keyboard key is changed.
fn key_event(&mut self, _event: KeyEvent) {}
/// Is called after the quite event of the window is called.
fn quite_event(&mut self) {}
}
/// Used to define an additional updater for the window shell.
pub trait Updater {
/// Called to update the content.
fn update(&mut self);
}
......@@ -9,7 +9,7 @@ use std::{
use dces::prelude::{Entity, World};
use crate::prelude::*;
use crate::backend::*;
use crate::shell::{WindowBuilder, ShellRunner};
use crate::systems::*;
pub use self::global::*;
......@@ -21,7 +21,7 @@ mod window;
/// The `Application` represents the entry point of an OrbTk based application.
#[derive(Default)]
pub struct Application {
windows: Vec<WindowShell>,
runners: Vec<ShellRunner<WindowAdapter>>,
}
impl Application {
......@@ -64,17 +64,23 @@ 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())));
let (mut runner, backend) =
target_backend(&title.0, Bounds::from((position.0.x, position.0.y, constraint.width(), constraint.height())), false);
let window_shell = Rc::new(RefCell::new(WindowBuilder::new(WindowAdapter {
root: window,
render_objects: render_objects.clone(),
layouts: layouts.clone(),
handlers: handlers.clone(),
states: states.clone(),
..Default::default()
}).title(&(title.0)[..]).bounds(Bounds::from((position.0.x, position.0.y, constraint.width(), constraint.height()))).resizeable(resizeable.0).build()));
world.register_init_system(InitSystem {
backend: backend.clone(),
backend: window_shell.clone(),
states: states.clone(),
});
world
.create_system(EventSystem {
backend: backend.clone(),
backend: window_shell.clone(),
handlers: handlers.clone(),
update: update.clone(),
running: running.clone(),
......@@ -84,7 +90,7 @@ impl Application {
world
.create_system(StateSystem {
backend: backend.clone(),
backend: window_shell.clone(),
states: states.clone(),
update: update.clone(),
running: running.clone(),
......@@ -94,7 +100,7 @@ impl Application {
world
.create_system(LayoutSystem {
backend: backend.clone(),
backend: window_shell.clone(),
layouts: layouts.clone(),
update: update.clone(),
running: running.clone(),
......@@ -104,7 +110,7 @@ impl Application {
world
.create_system(PostLayoutStateSystem {
backend: backend.clone(),
backend: window_shell.clone(),
states: states.clone(),
update: update.clone(),
running: running.clone(),
......@@ -114,7 +120,7 @@ impl Application {
world
.create_system(RenderSystem {
backend: backend.clone(),
backend: window_shell.clone(),
render_objects: render_objects.clone(),
update: update.clone(),
running: running.clone(),
......@@ -122,17 +128,20 @@ impl Application {
.with_priority(4)
.build();
runner.world(world);
self.windows.push(WindowShell {
backend_runner: runner,
render_objects,
layouts,
handlers,
states,
// backend_runner: ShellRunner {
// world: Some(world),
// window_shell
// },
self.runners.push(ShellRunner {
updater: Box::new(WorldWrapper {
world
}),
window_shell,
update,
running,
resizable: resizeable.0,
});
self
......@@ -140,8 +149,8 @@ impl Application {
/// Starts the application and run it until quit is requested.
pub fn run(&mut self) {
for window in &mut self.windows {
window.run();
for runner in &mut self.runners {
runner.run();
}
}
}
use std::{
cell::{Cell, RefCell},
collections::BTreeMap,
rc::Rc,
};
use std::{cell::RefCell, collections::BTreeMap, rc::Rc};
use dces::prelude::Entity;
use dces::prelude::{Entity, World};
use crate::prelude::*;
use crate::backend::*;
/// Represents a window. Each window has its own tree, event pipeline and backend.
pub struct WindowShell {
pub backend_runner: Box<dyn BackendRunner>,
use crate::shell;
/// Represents a window. Each window has its own tree, event pipeline and shell.
#[derive(Default)]
pub struct WindowAdapter {
pub render_objects: Rc<RefCell<BTreeMap<Entity, Box<dyn RenderObject>>>>,
pub layouts: Rc<RefCell<BTreeMap<Entity, Box<dyn Layout>>>>,
pub handlers: Rc<RefCell<BTreeMap<Entity, Vec<Rc<dyn EventHandler>>>>>,
pub states: Rc<RefCell<BTreeMap<Entity, Rc<dyn State>>>>,
pub update: Rc<Cell<bool>>,
pub running: Rc<Cell<bool>>,
pub resizable: bool,
pub event_queue: EventQueue,
pub messages: BTreeMap<Entity, Vec<MessageBox>>,
pub root: Entity,
}
// todo: remove all render_objects etc. from system, handle all with window adapter
// todo: remove rc refcell..
// impl WindowAdapter {
// pub fn context_provider(&mut self) -> &mut ContextProvider {
// &mut self.context_provider
// }
// }
pub struct WorldWrapper {
pub world: World<Tree>,
}
impl WindowShell {
/// Executes the given window until quit is requested.
pub fn run(&mut self) {