Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a5fba370b8 | |||
| 3e544c134f | |||
| f4e580638d | |||
| 504225631a | |||
| fb70636437 |
@@ -9,6 +9,7 @@
|
||||
- [Getting Started](ch01-00-getting-started.md)
|
||||
- [Installation](ch01-01-installation.md)
|
||||
- [Hello OrbTK!](ch01-02-hello-orbtk.md)
|
||||
- [The Composition System](ch01-03-composition-system.md)
|
||||
|
||||
- [OrbTK The Structure](ch02-00-crates.md)
|
||||
- [Crate: API](ch02-01-crate-api.md)
|
||||
|
||||
@@ -284,4 +284,9 @@ On Windows, you need to use `backslash` as a path delimeter:
|
||||
> ..\target\release\hello_orbtk.exe
|
||||
```
|
||||
|
||||
If you like to get debug feedback you can call the build process like this
|
||||
|
||||
```console
|
||||
$ cargo build --features debug --bin hello_orbtk.rs
|
||||
```
|
||||
[troubleshooting]: ch01-01-installation.html#troubleshooting
|
||||
|
||||
79
src/ch01-03-composition-system.md
Normal file
79
src/ch01-03-composition-system.md
Normal file
@@ -0,0 +1,79 @@
|
||||
# The Composition System
|
||||
|
||||
WIP: introduce a graphical representation of the structure
|
||||
|
||||
Everything is build on top of DECS, the unterlying entity compontent
|
||||
system.
|
||||
|
||||
|
||||
## GUI Elements
|
||||
|
||||
* Layouts
|
||||
* Events
|
||||
* Behaviors
|
||||
* Messages
|
||||
|
||||
### Layouts
|
||||
|
||||
At the GUI Element level, we do have a basic concept for implementing
|
||||
the layout of all involved entities. THis concept is following a two
|
||||
phase model and will run in two passes:
|
||||
|
||||
* `Measuring`
|
||||
* `Arranging`
|
||||
|
||||
`Measuring` allows a component to determine how much size it can take
|
||||
inside GUI. The `Arranging` is following in a separate run. Imagine
|
||||
the request of a parent entity that will ask a child to measure
|
||||
several times before it can determine the optimal position and the
|
||||
concrete size of this entity.
|
||||
|
||||
This leads us to one of the major concept decisions inside the
|
||||
toolkit:
|
||||
|
||||
* Size the content
|
||||
|
||||
What does that mean? Well, lets take an obvious example that will be
|
||||
visible in every modern application. You want to support
|
||||
localization, where the idioms will differ for all lables within the
|
||||
GUI. What would happen, if we would size the entities statically (e.g
|
||||
a button). If we wouldn't take into account the content of a child
|
||||
entity (e.g. the lable centered inside the button frame) that will be
|
||||
placed in the center of its parent? You as the programmer would need
|
||||
to adapt the GUI views for every supported language and adapt the
|
||||
sizes as needed. That is nonsense. We have to define and render the
|
||||
stuff the other way arround!
|
||||
|
||||
All controls in `OrbTK` support the ability to size to the natural
|
||||
size of their content. This allows the toolkit to dynamically layout
|
||||
the entities. No matter if things resizes, or application logic will
|
||||
need to add or subdivide other entities in the tree.
|
||||
|
||||
The Arrange phase allows a parent to position and determine the final
|
||||
size of each child.
|
||||
|
||||
|
||||
### Events
|
||||
|
||||
* bottom-up
|
||||
|
||||
if the events traverse from a leaf entity up to the root entity.
|
||||
|
||||
* top-down
|
||||
|
||||
if the events traverse from the root entity down to the leaf entities.
|
||||
|
||||
### Behaviours
|
||||
|
||||
Specialized event handling based on logical grouped methods
|
||||
(e.g. mouse, keyboard, focus, text).
|
||||
|
||||
### Messages
|
||||
|
||||
An itelligent messaging infrastucture that instatiates subs. The
|
||||
concept enables the toolkit to send and receive messages between the
|
||||
linked entities (m senders -> n receivers).
|
||||
|
||||
## Framework Elements
|
||||
|
||||
They are organised as cartes inside the API subtree.
|
||||
79
src/ch01-03-compositon-system.md
Normal file
79
src/ch01-03-compositon-system.md
Normal file
@@ -0,0 +1,79 @@
|
||||
# The Composition System
|
||||
|
||||
WIP: introduce a graphical representation of the structure
|
||||
|
||||
Everything is build on top of DECS, the unterlying entity compontent
|
||||
system.
|
||||
|
||||
|
||||
## GUI Elements
|
||||
|
||||
* Layouts
|
||||
* Events
|
||||
* Behaviors
|
||||
* Messages
|
||||
|
||||
### Layouts
|
||||
|
||||
At the GUI Element level, we do have a basic concept for implementing
|
||||
the layout of all involved entities. THis concept is following a two
|
||||
phase model and will run in two passes:
|
||||
|
||||
* `Measuring`
|
||||
* `Arranging`
|
||||
|
||||
`Measuring` allows a component to determine how much size it can take
|
||||
inside GUI. The `Arranging` is following in a separate run. Imagine
|
||||
the request of a parent entity that will ask a child to measure
|
||||
several times before it can determine the optimal position and the
|
||||
concrete size of this entity.
|
||||
|
||||
This leads us to one of the major concept decisions inside the
|
||||
toolkit:
|
||||
|
||||
* Size the content
|
||||
|
||||
What does that mean? Well, lets take an obvious example that will be
|
||||
visible in every modern application. You want to support
|
||||
localization, where the idioms will differ for all lables within the
|
||||
GUI. What would happen, if we would size the entities statically (e.g
|
||||
a button). If we wouldn't take into account the content of a child
|
||||
entity (e.g. the lable centered inside the button frame) that will be
|
||||
placed in the center of its parent? You as the programmer would need
|
||||
to adapt the GUI views for every supported language and adapt the
|
||||
sizes as needed. That is nonsense. We have to define and render the
|
||||
stuff the other way arround!
|
||||
|
||||
All controls in `OrbTK` support the ability to size to the natural
|
||||
size of their content. This allows the toolkit to dynamically layout
|
||||
the entities. No matter if things resizes, or application logic will
|
||||
need to add or subdivide other entities in the tree.
|
||||
|
||||
The Arrange phase allows a parent to position and determine the final
|
||||
size of each child.
|
||||
|
||||
|
||||
### Events
|
||||
|
||||
* bottom-up
|
||||
|
||||
if the events traverse from a leaf entity up to the root entity.
|
||||
|
||||
* top-down
|
||||
|
||||
if the events traverse from the root entity down to the leaf entities.
|
||||
|
||||
### Behaviours
|
||||
|
||||
Specialized event handling based on logical grouped methods
|
||||
(e.g. mouse, keyboard, focus, text).
|
||||
|
||||
### Messages
|
||||
|
||||
An itelligent messaging infrastucture that instatiates subs. The
|
||||
concept enables the toolkit to send and receive messages between the
|
||||
linked entities (m senders -> n receivers).
|
||||
|
||||
## Framework Elements
|
||||
|
||||
They are organised as cartes inside the API subtree.
|
||||
@@ -1,3 +1,108 @@
|
||||
# The Localization Crate
|
||||
|
||||
WIP: all about the OrbTK localization
|
||||
Localization is a research task by itself, if you want to resolve all syntactic
|
||||
rules that are found when writing prose in different languages.
|
||||
OrbTK's localization crate isn't ready to resolve all this complexity, but
|
||||
this may improve in further releases.
|
||||
|
||||
Starting with the given implementation, `localization` can offer methods, that
|
||||
are able to match and replace text strings. The usage of the `localization` crate is
|
||||
optional. If you don't need any multi lingual adaptions inside your widgets, simply
|
||||
do not include the `localization` sugar.
|
||||
|
||||
## The building blocks of `localization`
|
||||
|
||||
If you want to enable the users to select and change the desired display
|
||||
languare of the GUI at runtime, the toolkit needs to match up a requested
|
||||
text strings (the key) that should be presented inside the view and substitute
|
||||
it with the corresponding translation string (the target value). Dictionaries
|
||||
are used to organize the keys as word lists.
|
||||
|
||||
OrbTK's `localization` implementation has choosen to persitently store the
|
||||
translation strings inside a `ron` file. When introducing the new syntax
|
||||
structure used inside a `ron` filetype, it was one goal of the authors to
|
||||
easily match rust types to ron types.
|
||||
|
||||
You can save each supported language in its individual ron file. The language
|
||||
files need to be destinctable. A natural way to implement this requirement
|
||||
is the usage of unique `language ids`. Most **operating systems* take advantage
|
||||
of a `locale subsystem`, and save the identification of the active language in
|
||||
the `lang` enviroment variable. It's good practice to include the language id in
|
||||
the corresponding ron file name.
|
||||
|
||||
When you include the `localization` functionality in your OrbTK code, you
|
||||
should define constants for each supported `language id`, that will reference the
|
||||
ron file in question.
|
||||
|
||||
When calling the `RonLocalization` methods addressing the combination of a language
|
||||
id and the corresponding dictionary you are able to store the result in `language`
|
||||
variable. The crate methods will handle all the havy lifting to substitute the
|
||||
source values of the text attributes inside the views with their matching translation
|
||||
strings in the addressed dictionary.
|
||||
|
||||
## The ron file structure
|
||||
|
||||
In OrbTK, the structure `RonLocalizationBuilder` is defined to take values for
|
||||
the following parameters
|
||||
|
||||
* language: a String
|
||||
* dictionaries: a HashMap
|
||||
|
||||
The ron filename representing a language localization should include the language
|
||||
identifier to ease its distiction from another.
|
||||
|
||||
Dictionaries itself are stored
|
||||
The dictionary is represended by a key value pair
|
||||
|
||||
A class `Dictionary` will include a `map` named **words**.
|
||||
The ron type `map` is like a type `struct**, but keys are also values instead of
|
||||
just beenig identifiers.
|
||||
|
||||
** using a ron file
|
||||
|
||||
Activationg the `localization` crate inside your source code boils down this
|
||||
short example code.
|
||||
|
||||
```rust
|
||||
pub const EN_US: &str = include_str!("../assets/dictionary_en_US.ron");
|
||||
pub const DE_DE: &str = include_str!("../assets/dictionary_de_DE.ron");
|
||||
pub const ES_ES: &str = include_str!("../assets/dictionary_es_ES.ron");
|
||||
|
||||
let mut localization = RonLocalization::create()
|
||||
.language("en_US")
|
||||
.dictionary("en_US", EN_US)
|
||||
.build();
|
||||
if let Some(text) = localization.text("hello") {
|
||||
println!("{}", text);
|
||||
}
|
||||
|
||||
let mut localization = RonLocalization::create()
|
||||
.language("en_US")
|
||||
.dictionary("en_US", EN_US)
|
||||
.build();
|
||||
if let Some(text) = localization.text("hello") {
|
||||
println!("{}", text);
|
||||
}
|
||||
|
||||
let localization = RonLocalization::create()
|
||||
.language("de_DE")
|
||||
.dictionary("de_DE", DE_DE)
|
||||
.build();
|
||||
if let Some(text) = localization.text("hello") {
|
||||
println!("{}", text);
|
||||
}
|
||||
|
||||
let localization = RonLocalization::create()
|
||||
.language("es_ES")
|
||||
.dictionary("es_ES", ES_ES)
|
||||
.build();
|
||||
if let Some(text) = localization.text("hello") {
|
||||
println!("{}", text);
|
||||
}
|
||||
```
|
||||
|
||||
Sure, this code isn't elegant nor will it suite a real applications demands.
|
||||
What is does show is the logic, to bind a ron file (storing the translations
|
||||
of a given language) to a const. When calling `RonLocalization`, the `text`
|
||||
method will resolve text attributes inside a view or any rust primitive with
|
||||
the translation text resolved in the language dictionary.
|
||||
|
||||
@@ -1,3 +1,46 @@
|
||||
# The Render Crate
|
||||
# Render Crates
|
||||
|
||||
WIP: all about the OrbTK rendering services
|
||||
Rendering is a key component of the toolkit. Everybody is expecting state
|
||||
of the art presentation of implemented widgets. User interaction that will
|
||||
result in layout and entity changes inside the GUI should be updated as
|
||||
soon as possible. A comfortable users experience is mainly influenced by
|
||||
fast rendering tasks. New rendering of layouts should only take place, if
|
||||
constraint changes will need to do so. Entities and it attributes will
|
||||
only require new rendering, if a user interaction will change their state
|
||||
to be dirty.
|
||||
|
||||
Lets summarize the main goals of `OrbTK` rendering infrastructure:
|
||||
|
||||
* API encapsulated access to all renderer functions
|
||||
|
||||
This design decision is taken to keep freedom for further development of
|
||||
OrbTK when it comes to support different renderer. We are able to support
|
||||
|
||||
* different versions of a given renderer
|
||||
* support different renderer for different target platforms
|
||||
|
||||
* 2D rendering fast and complete implementation of all rendering functions
|
||||
used in the OrbTK toolkit.provided functions
|
||||
|
||||
* Pixmaps
|
||||
* Canvas
|
||||
* Path
|
||||
* geometry primitives
|
||||
* Blending modes
|
||||
* Path filling
|
||||
* Anti-aliased Path filling
|
||||
* Path stroking
|
||||
* Path hairline stroking
|
||||
* Anti-aliased Path hairline stroking
|
||||
* Stroke dashing
|
||||
* Gradients (linear and radial)
|
||||
* Pixmaps blending (image on image rendering)
|
||||
* Patterns
|
||||
* Fill rect
|
||||
* Stroke rect
|
||||
* Rectangular clipping
|
||||
* Clipping
|
||||
* Anti-aliased clipping
|
||||
* Analytical anti-aliased Path filling
|
||||
* Dithering
|
||||
* Blending modes
|
||||
|
||||
@@ -1,24 +1,35 @@
|
||||
# The Widgets Crate
|
||||
# The Widgets Crates
|
||||
|
||||
As an UI developer consuming OrbTK, you most probably will get in touch with
|
||||
the `widget` crate. If you get comfortable with the terminology of `views` and
|
||||
their `states`, it's quite easy to implement even complex structures. The GUI
|
||||
components are declarative and you will code them inside the `view` blocks. All
|
||||
callbacks that will handle the functional processing are coded inside the
|
||||
`state` blocks. User input (e.g. mouse events, keyboard input) as well as event
|
||||
handler generated feedback is handled and processed from methods of the
|
||||
associated `state` blocks.
|
||||
As an UI developer consuming OrbTK, you most probably will get in
|
||||
touch with the `widget` crate. If you get comfortable with the
|
||||
terminology of `views` and their `states`, it's quite easy to
|
||||
implement even complex structures. The GUI components are declarative
|
||||
and you will code them inside the `view` blocks. All callbacks that
|
||||
will handle the functional processing are coded inside the `state`
|
||||
blocks. User input (e.g. mouse events, keyboard input) as well as
|
||||
event handler generated feedback is handled and processed from methods
|
||||
of the associated `state` blocks.
|
||||
|
||||
The `behavior modules` are separated to handle specialized cases. If
|
||||
an event is emitted that belongs to a behavior class, the associated
|
||||
action is handled by a behavior method. In particular you will
|
||||
recognize modules for the following behaviors:
|
||||
|
||||
* focus
|
||||
* mouse
|
||||
* selection
|
||||
* text
|
||||
|
||||
## Views
|
||||
|
||||
When you create a `view` block inside an OrbTK application, it is required to insert
|
||||
definitions that declare what elements are going to be present inside the user
|
||||
interface.
|
||||
When you create a `view` block inside an OrbTK application, it is
|
||||
required to insert definitions that declare what elements are going to
|
||||
be present inside the user interface.
|
||||
|
||||
### What is a View
|
||||
|
||||
If you take the Rust code that makes a `view` in a structural way, it will
|
||||
answers to the following questions:
|
||||
If you take the Rust code that makes a `view` in a structural way, it
|
||||
will answers to the following questions:
|
||||
|
||||
* Which entities are used?
|
||||
* What is the entities tree formed?
|
||||
@@ -27,40 +38,43 @@ answers to the following questions:
|
||||
|
||||
### What is the code structure of a View
|
||||
|
||||
First, the inside the source code that takes your `view` needs to call the
|
||||
`widget!` macro. This macro automatically implements the `Widget` trait. When
|
||||
instantiated, it will inherits all default properties from a base widget,
|
||||
which gets you started with consistent preset values.
|
||||
First, the inside the source code that takes your `view` needs to call
|
||||
the `widget!` macro. This macro automatically implements the `Widget`
|
||||
trait. When instantiated, it will inherits all default properties from
|
||||
a base widget, which gets you started with consistent preset values.
|
||||
|
||||
The syntax of this macro call will require you, to select
|
||||
|
||||
* the desired `view-name` (e.g: "NavigationView")
|
||||
* optional: the name of the associated `state-structure` (e.g: "<NavigationState>")
|
||||
* optional: the name of the associated `state-structure` (e.g:
|
||||
"<NavigationState>")
|
||||
|
||||
If you like to assign property names inside the view, go ahead and introduce
|
||||
an extensible list of the property-variables. Each variable will take a name
|
||||
and define its associated type.
|
||||
If you like to assign property names inside the view, go ahead and
|
||||
introduce an extensible list of the property-variables. Each variable
|
||||
will take a name and define its associated type.
|
||||
|
||||
In a next step you enhance the `Template` trait with an implementation
|
||||
of your new widget. You are required to code a function called `template`.
|
||||
The syntax of this function will take the following arguments
|
||||
of your new widget. You are required to code a function called
|
||||
`template`. The syntax of this function will take the following
|
||||
arguments
|
||||
|
||||
* `self`, the implementation of your view-name
|
||||
* the `Id` of the entity
|
||||
* the `Context`, as a mutual reference to the BuildContext
|
||||
|
||||
All the widget structures you are going to use inside of `template` will be
|
||||
coded as child's of `self`.
|
||||
All the widget structures you are going to use inside of `template`
|
||||
will be coded as child's of `self`.
|
||||
|
||||
## States
|
||||
|
||||
When you create a `state` block inside an OrbTK application, it is required to
|
||||
define the structures you want to work on in the `State` implementation.
|
||||
When you create a `state` block inside an OrbTK application, it is
|
||||
required to define the structures you want to work on in the `State`
|
||||
implementation.
|
||||
|
||||
### What is a State
|
||||
|
||||
The Rust code that makes a `state` is associated to the `view` block of your
|
||||
widget. Go and ask yourself:
|
||||
The Rust code that makes a `state` is associated to the `view` block
|
||||
of your widget. Go and ask yourself:
|
||||
|
||||
* What actions should be processed on a given event?
|
||||
* How should we handled user input?
|
||||
@@ -69,23 +83,24 @@ widget. Go and ask yourself:
|
||||
### What is the structure of a State
|
||||
|
||||
First, inside the source code that takes your `state`, you will go and
|
||||
declare its structure name. This name corresponds to the parameter value you did
|
||||
choose inside the `widget!` macro call of your widgets view (e.g
|
||||
"NavigationState").
|
||||
declare its structure name. This name corresponds to the parameter
|
||||
value you did choose inside the `widget!` macro call of your widgets
|
||||
view (e.g "NavigationState").
|
||||
|
||||
In a next step you enhance the `State` trait with an implementation of your state
|
||||
structure. Most probable, you create and adapt the following functions:
|
||||
In a next step you enhance the `State` trait with an implementation of
|
||||
your state structure. Most probable, you create and adapt the
|
||||
following functions:
|
||||
|
||||
#### The `init` function
|
||||
|
||||
This function is called to initialize the widget state. You can preset attributes
|
||||
**before** the view is activated and presented to the user.
|
||||
This function is called to initialize the widget state. You can preset
|
||||
attributes **before** the view is activated and presented to the user.
|
||||
|
||||
#### The `message` function
|
||||
|
||||
The `message subsystem` is offering methods to chain events, that can be
|
||||
interchanged and accessed from any defined `state`. You will code a `message`
|
||||
function to take advantage of this functionality.
|
||||
The `message subsystem` is offering methods to chain events, that can
|
||||
be interchanged and accessed from any defined `state`. You will code a
|
||||
`message` function to take advantage of this functionality.
|
||||
|
||||
The syntax of this function will take the following arguments
|
||||
|
||||
@@ -93,21 +108,22 @@ The syntax of this function will take the following arguments
|
||||
* the mutable `messages` variable, referencing the MessageReader
|
||||
* the `Context`, as a mutual reference to the BuildContext
|
||||
|
||||
As already explained, you should define an action enumeration,
|
||||
(e.g "NavigationAction"), that will code the values that are possible or
|
||||
desired (e.g "SaveSettings", "LoadSettings"). Inside the `message` function
|
||||
you will loop through the `messages` and match the action values you are
|
||||
interested in.
|
||||
As already explained, you should define an action enumeration, (e.g
|
||||
"NavigationAction"), that will code the values that are possible or
|
||||
desired (e.g "SaveSettings", "LoadSettings"). Inside the `message`
|
||||
function you will loop through the `messages` and match the action
|
||||
values you are interested in.
|
||||
|
||||
#### The `update` function
|
||||
|
||||
Whenever the attribute of an entity is changed, OrbTK will render it dirty. The
|
||||
`update` function is taking care to react on any triggered dirty state. You will
|
||||
probably define an `Action` enumeration that will name and list all action states
|
||||
you are interested in. Now, if you match an `action` in the `update` function,
|
||||
you can react on this with all the Rust syntax flexibility.
|
||||
Whenever the attribute of an entity is changed, OrbTK will render it
|
||||
dirty. The `update` function is taking care to react on any triggered
|
||||
dirty state. You will probably define an `Action` enumeration that
|
||||
will name and list all action states you are interested in. Now, if
|
||||
you match an `action` in the `update` function, you can react on this
|
||||
with all the Rust syntax flexibility.
|
||||
|
||||
#### The `update_post_layout` function
|
||||
|
||||
OrbTK will run this function **after** the rendering crate has processed the new
|
||||
layout for your view.
|
||||
OrbTK will run this function **after** the rendering crate has
|
||||
processed the new layout for your view.
|
||||
|
||||
Reference in New Issue
Block a user