Draft custom layout engine based on druid
This commit is contained in:
parent
2303111e09
commit
0240c3981b
38 changed files with 974 additions and 249 deletions
|
|
@ -1,7 +1,17 @@
|
|||
/// The strategy used to fill space in a specific dimension.
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Hash)]
|
||||
pub enum Length {
|
||||
Fill,
|
||||
Shrink,
|
||||
Units(u16),
|
||||
}
|
||||
|
||||
impl Length {
|
||||
pub fn fill_factor(&self) -> u16 {
|
||||
match self {
|
||||
Length::Fill => 1,
|
||||
Length::Shrink => 0,
|
||||
Length::Units(_) => 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use crate::Point;
|
||||
|
||||
/// A rectangle.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
|
||||
pub struct Rectangle<T = f32> {
|
||||
/// X coordinate of the top-left corner.
|
||||
pub x: T,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
use crate::{Align, Justify, Length};
|
||||
|
||||
use std::u32;
|
||||
|
||||
/// A container that distributes its contents vertically.
|
||||
///
|
||||
/// A [`Column`] will try to fill the horizontal space of its container.
|
||||
|
|
@ -10,8 +12,8 @@ pub struct Column<Element> {
|
|||
pub padding: u16,
|
||||
pub width: Length,
|
||||
pub height: Length,
|
||||
pub max_width: Length,
|
||||
pub max_height: Length,
|
||||
pub max_width: u32,
|
||||
pub max_height: u32,
|
||||
pub align_self: Option<Align>,
|
||||
pub align_items: Align,
|
||||
pub justify_content: Justify,
|
||||
|
|
@ -28,8 +30,8 @@ impl<Element> Column<Element> {
|
|||
padding: 0,
|
||||
width: Length::Fill,
|
||||
height: Length::Shrink,
|
||||
max_width: Length::Shrink,
|
||||
max_height: Length::Shrink,
|
||||
max_width: u32::MAX,
|
||||
max_height: u32::MAX,
|
||||
align_self: None,
|
||||
align_items: Align::Start,
|
||||
justify_content: Justify::Start,
|
||||
|
|
@ -74,7 +76,7 @@ impl<Element> Column<Element> {
|
|||
/// Sets the maximum width of the [`Column`].
|
||||
///
|
||||
/// [`Column`]: struct.Column.html
|
||||
pub fn max_width(mut self, max_width: Length) -> Self {
|
||||
pub fn max_width(mut self, max_width: u32) -> Self {
|
||||
self.max_width = max_width;
|
||||
self
|
||||
}
|
||||
|
|
@ -82,7 +84,7 @@ impl<Element> Column<Element> {
|
|||
/// Sets the maximum height of the [`Column`] in pixels.
|
||||
///
|
||||
/// [`Column`]: struct.Column.html
|
||||
pub fn max_height(mut self, max_height: Length) -> Self {
|
||||
pub fn max_height(mut self, max_height: u32) -> Self {
|
||||
self.max_height = max_height;
|
||||
self
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
use crate::{Align, Justify, Length};
|
||||
|
||||
use std::u32;
|
||||
|
||||
/// A container that distributes its contents horizontally.
|
||||
///
|
||||
/// A [`Row`] will try to fill the horizontal space of its container.
|
||||
|
|
@ -10,8 +12,8 @@ pub struct Row<Element> {
|
|||
pub padding: u16,
|
||||
pub width: Length,
|
||||
pub height: Length,
|
||||
pub max_width: Length,
|
||||
pub max_height: Length,
|
||||
pub max_width: u32,
|
||||
pub max_height: u32,
|
||||
pub align_self: Option<Align>,
|
||||
pub align_items: Align,
|
||||
pub justify_content: Justify,
|
||||
|
|
@ -28,8 +30,8 @@ impl<Element> Row<Element> {
|
|||
padding: 0,
|
||||
width: Length::Fill,
|
||||
height: Length::Shrink,
|
||||
max_width: Length::Shrink,
|
||||
max_height: Length::Shrink,
|
||||
max_width: u32::MAX,
|
||||
max_height: u32::MAX,
|
||||
align_self: None,
|
||||
align_items: Align::Start,
|
||||
justify_content: Justify::Start,
|
||||
|
|
@ -74,7 +76,7 @@ impl<Element> Row<Element> {
|
|||
/// Sets the maximum width of the [`Row`].
|
||||
///
|
||||
/// [`Row`]: struct.Row.html
|
||||
pub fn max_width(mut self, max_width: Length) -> Self {
|
||||
pub fn max_width(mut self, max_width: u32) -> Self {
|
||||
self.max_width = max_width;
|
||||
self
|
||||
}
|
||||
|
|
@ -82,7 +84,7 @@ impl<Element> Row<Element> {
|
|||
/// Sets the maximum height of the [`Row`].
|
||||
///
|
||||
/// [`Row`]: struct.Row.html
|
||||
pub fn max_height(mut self, max_height: Length) -> Self {
|
||||
pub fn max_height(mut self, max_height: u32) -> Self {
|
||||
self.max_height = max_height;
|
||||
self
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,12 @@
|
|||
use crate::{Align, Column, Length, Point, Rectangle};
|
||||
|
||||
use std::u32;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Scrollable<'a, Element> {
|
||||
pub state: &'a mut State,
|
||||
pub height: Length,
|
||||
pub max_height: Length,
|
||||
pub max_height: u32,
|
||||
pub align_self: Option<Align>,
|
||||
pub content: Column<Element>,
|
||||
}
|
||||
|
|
@ -14,7 +16,7 @@ impl<'a, Element> Scrollable<'a, Element> {
|
|||
Scrollable {
|
||||
state,
|
||||
height: Length::Shrink,
|
||||
max_height: Length::Shrink,
|
||||
max_height: u32::MAX,
|
||||
align_self: None,
|
||||
content: Column::new(),
|
||||
}
|
||||
|
|
@ -57,7 +59,7 @@ impl<'a, Element> Scrollable<'a, Element> {
|
|||
/// Sets the maximum width of the [`Scrollable`].
|
||||
///
|
||||
/// [`Scrollable`]: struct.Scrollable.html
|
||||
pub fn max_width(mut self, max_width: Length) -> Self {
|
||||
pub fn max_width(mut self, max_width: u32) -> Self {
|
||||
self.content = self.content.max_width(max_width);
|
||||
self
|
||||
}
|
||||
|
|
@ -65,7 +67,7 @@ impl<'a, Element> Scrollable<'a, Element> {
|
|||
/// Sets the maximum height of the [`Scrollable`] in pixels.
|
||||
///
|
||||
/// [`Scrollable`]: struct.Scrollable.html
|
||||
pub fn max_height(mut self, max_height: Length) -> Self {
|
||||
pub fn max_height(mut self, max_height: u32) -> Self {
|
||||
self.max_height = max_height;
|
||||
self
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use iced::{
|
||||
scrollable, text::HorizontalAlignment, text_input, Align, Application,
|
||||
Checkbox, Color, Column, Element, Length, Scrollable, Text, TextInput,
|
||||
Checkbox, Color, Column, Element, Scrollable, Text, TextInput,
|
||||
};
|
||||
|
||||
pub fn main() {
|
||||
|
|
@ -77,7 +77,7 @@ impl Application for Todos {
|
|||
);
|
||||
|
||||
let content = Column::new()
|
||||
.max_width(Length::Units(800))
|
||||
.max_width(800)
|
||||
.align_self(Align::Center)
|
||||
.spacing(20)
|
||||
.push(title)
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ impl Tour {
|
|||
scroll: scrollable::State::new(),
|
||||
back_button: button::State::new(),
|
||||
next_button: button::State::new(),
|
||||
debug: false,
|
||||
debug: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -79,7 +79,7 @@ impl Application for Tour {
|
|||
}
|
||||
|
||||
let element: Element<_> = Column::new()
|
||||
.max_width(Length::Units(540))
|
||||
.max_width(540)
|
||||
.spacing(20)
|
||||
.padding(20)
|
||||
.push(steps.view(self.debug).map(Message::StepMessage))
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
use crate::{layout, renderer, Color, Event, Hasher, Layout, Point, Widget};
|
||||
use crate::{
|
||||
layout, renderer, Color, Event, Hasher, Layout, Length, Point, Widget,
|
||||
};
|
||||
|
||||
/// A generic [`Widget`].
|
||||
///
|
||||
|
|
@ -39,18 +41,26 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
pub fn width(&self) -> Length {
|
||||
self.widget.width()
|
||||
}
|
||||
|
||||
pub fn height(&self) -> Length {
|
||||
self.widget.height()
|
||||
}
|
||||
|
||||
pub fn layout(
|
||||
&self,
|
||||
renderer: &Renderer,
|
||||
limits: &layout::Limits,
|
||||
) -> Layout {
|
||||
) -> layout::Node {
|
||||
self.widget.layout(renderer, limits)
|
||||
}
|
||||
|
||||
pub fn draw(
|
||||
&self,
|
||||
renderer: &mut Renderer,
|
||||
layout: &Layout,
|
||||
layout: Layout<'_>,
|
||||
cursor_position: Point,
|
||||
) -> Renderer::Output {
|
||||
self.widget.draw(renderer, layout, cursor_position)
|
||||
|
|
@ -285,14 +295,18 @@ where
|
|||
A: Clone,
|
||||
Renderer: crate::Renderer,
|
||||
{
|
||||
fn layout(&self, renderer: &Renderer, limits: &layout::Limits) -> Layout {
|
||||
fn layout(
|
||||
&self,
|
||||
renderer: &Renderer,
|
||||
limits: &layout::Limits,
|
||||
) -> layout::Node {
|
||||
self.widget.layout(renderer, limits)
|
||||
}
|
||||
|
||||
fn on_event(
|
||||
&mut self,
|
||||
event: Event,
|
||||
layout: &Layout,
|
||||
layout: Layout<'_>,
|
||||
cursor_position: Point,
|
||||
messages: &mut Vec<B>,
|
||||
renderer: &Renderer,
|
||||
|
|
@ -316,7 +330,7 @@ where
|
|||
fn draw(
|
||||
&self,
|
||||
renderer: &mut Renderer,
|
||||
layout: &Layout,
|
||||
layout: Layout<'_>,
|
||||
cursor_position: Point,
|
||||
) -> Renderer::Output {
|
||||
self.widget.draw(renderer, layout, cursor_position)
|
||||
|
|
@ -357,14 +371,18 @@ impl<'a, Message, Renderer> Widget<Message, Renderer>
|
|||
where
|
||||
Renderer: crate::Renderer + renderer::Debugger,
|
||||
{
|
||||
fn layout(&self, renderer: &Renderer, limits: &layout::Limits) -> Layout {
|
||||
fn layout(
|
||||
&self,
|
||||
renderer: &Renderer,
|
||||
limits: &layout::Limits,
|
||||
) -> layout::Node {
|
||||
self.element.widget.layout(renderer, limits)
|
||||
}
|
||||
|
||||
fn on_event(
|
||||
&mut self,
|
||||
event: Event,
|
||||
layout: &Layout,
|
||||
layout: Layout<'_>,
|
||||
cursor_position: Point,
|
||||
messages: &mut Vec<Message>,
|
||||
renderer: &Renderer,
|
||||
|
|
@ -381,7 +399,7 @@ where
|
|||
fn draw(
|
||||
&self,
|
||||
renderer: &mut Renderer,
|
||||
layout: &Layout,
|
||||
layout: Layout<'_>,
|
||||
cursor_position: Point,
|
||||
) -> Renderer::Output {
|
||||
renderer.explain(
|
||||
|
|
|
|||
|
|
@ -1,57 +1,50 @@
|
|||
use crate::Rectangle;
|
||||
|
||||
mod limits;
|
||||
mod node;
|
||||
|
||||
pub mod flex;
|
||||
|
||||
pub use limits::Limits;
|
||||
pub use node::Node;
|
||||
|
||||
/// The computed bounds of a [`Node`] and its children.
|
||||
///
|
||||
/// This type is provided by the GUI runtime to [`Widget::on_event`] and
|
||||
/// [`Widget::draw`], describing the layout of the [`Node`] produced by
|
||||
/// [`Widget::node`].
|
||||
///
|
||||
/// [`Node`]: struct.Node.html
|
||||
/// [`Widget::on_event`]: widget/trait.Widget.html#method.on_event
|
||||
/// [`Widget::draw`]: widget/trait.Widget.html#tymethod.draw
|
||||
/// [`Widget::node`]: widget/trait.Widget.html#tymethod.node
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Layout {
|
||||
bounds: Rectangle,
|
||||
children: Vec<Layout>,
|
||||
use crate::{Point, Rectangle, Vector};
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct Layout<'a> {
|
||||
position: Point,
|
||||
node: &'a Node,
|
||||
}
|
||||
|
||||
impl Layout {
|
||||
pub fn new(bounds: Rectangle) -> Self {
|
||||
Layout {
|
||||
bounds,
|
||||
children: Vec::new(),
|
||||
impl<'a> Layout<'a> {
|
||||
pub(crate) fn new(node: &'a Node) -> Self {
|
||||
Self::with_offset(Vector::new(0.0, 0.0), node)
|
||||
}
|
||||
|
||||
pub(crate) fn with_offset(offset: Vector, node: &'a Node) -> Self {
|
||||
let bounds = node.bounds();
|
||||
|
||||
Self {
|
||||
position: Point::new(bounds.x, bounds.y) + offset,
|
||||
node,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn push(&mut self, mut child: Layout) {
|
||||
child.bounds.x += self.bounds.x;
|
||||
child.bounds.y += self.bounds.y;
|
||||
|
||||
self.children.push(child);
|
||||
}
|
||||
|
||||
/// Gets the bounds of the [`Layout`].
|
||||
///
|
||||
/// The returned [`Rectangle`] describes the position and size of a
|
||||
/// [`Node`].
|
||||
///
|
||||
/// [`Layout`]: struct.Layout.html
|
||||
/// [`Rectangle`]: struct.Rectangle.html
|
||||
/// [`Node`]: struct.Node.html
|
||||
pub fn bounds(&self) -> Rectangle {
|
||||
self.bounds
|
||||
let bounds = self.node.bounds();
|
||||
|
||||
Rectangle {
|
||||
x: self.position.x,
|
||||
y: self.position.y,
|
||||
width: bounds.width,
|
||||
height: bounds.height,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns an iterator over the [`Layout`] of the children of a [`Node`].
|
||||
///
|
||||
/// [`Layout`]: struct.Layout.html
|
||||
/// [`Node`]: struct.Node.html
|
||||
pub fn children(&self) -> impl Iterator<Item = &Layout> {
|
||||
self.children.iter()
|
||||
pub fn children(&'a self) -> impl Iterator<Item = Layout<'a>> {
|
||||
self.node.children().iter().map(move |node| {
|
||||
Layout::with_offset(
|
||||
Vector::new(self.position.x, self.position.y),
|
||||
node,
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
202
native/src/layout/DRUID_LICENSE
Normal file
202
native/src/layout/DRUID_LICENSE
Normal file
|
|
@ -0,0 +1,202 @@
|
|||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
155
native/src/layout/flex.rs
Normal file
155
native/src/layout/flex.rs
Normal file
|
|
@ -0,0 +1,155 @@
|
|||
// This code is heavily inspired by the [`druid`] codebase.
|
||||
//
|
||||
// [`druid`]: https://github.com/xi-editor/druid
|
||||
//
|
||||
// Copyright 2018 The xi-editor Authors, Héctor Ramón
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
use crate::{
|
||||
layout::{Limits, Node},
|
||||
Element, Size,
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Axis {
|
||||
Horizontal,
|
||||
Vertical,
|
||||
}
|
||||
|
||||
impl Axis {
|
||||
fn main(&self, size: Size) -> f32 {
|
||||
match self {
|
||||
Axis::Horizontal => size.width,
|
||||
Axis::Vertical => size.height,
|
||||
}
|
||||
}
|
||||
|
||||
fn cross(&self, size: Size) -> f32 {
|
||||
match self {
|
||||
Axis::Horizontal => size.height,
|
||||
Axis::Vertical => size.width,
|
||||
}
|
||||
}
|
||||
|
||||
fn pack(&self, main: f32, cross: f32) -> (f32, f32) {
|
||||
match self {
|
||||
Axis::Horizontal => (main, cross),
|
||||
Axis::Vertical => (cross, main),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Remove `Message` type parameter
|
||||
pub fn resolve<Message, Renderer>(
|
||||
axis: Axis,
|
||||
renderer: &Renderer,
|
||||
limits: &Limits,
|
||||
padding: f32,
|
||||
spacing: f32,
|
||||
children: &[Element<'_, Message, Renderer>],
|
||||
) -> Node
|
||||
where
|
||||
Renderer: crate::Renderer,
|
||||
{
|
||||
let limits = limits.pad(padding);
|
||||
|
||||
let mut total_non_fill = spacing as f32 * (children.len() - 1) as f32;
|
||||
let mut fill_sum = 0;
|
||||
|
||||
let mut nodes: Vec<Node> = Vec::with_capacity(children.len());
|
||||
nodes.resize(children.len(), Node::default());
|
||||
|
||||
for (i, child) in children.iter().enumerate() {
|
||||
let fill_factor = match axis {
|
||||
Axis::Horizontal => child.width(),
|
||||
Axis::Vertical => child.height(),
|
||||
}
|
||||
.fill_factor();
|
||||
|
||||
if fill_factor == 0 {
|
||||
let child_limits = Limits::new(Size::ZERO, limits.max());
|
||||
|
||||
let layout = child.layout(renderer, &child_limits);
|
||||
|
||||
total_non_fill += axis.main(layout.size());
|
||||
|
||||
nodes[i] = layout;
|
||||
} else {
|
||||
fill_sum += fill_factor;
|
||||
}
|
||||
}
|
||||
|
||||
let available = axis.main(limits.max());
|
||||
let remaining = (available - total_non_fill).max(0.0);
|
||||
|
||||
for (i, child) in children.iter().enumerate() {
|
||||
let fill_factor = match axis {
|
||||
Axis::Horizontal => child.width(),
|
||||
Axis::Vertical => child.height(),
|
||||
}
|
||||
.fill_factor();
|
||||
|
||||
if fill_factor != 0 {
|
||||
let max_main = remaining * fill_factor as f32 / fill_sum as f32;
|
||||
let min_main = if max_main.is_infinite() {
|
||||
0.0
|
||||
} else {
|
||||
max_main
|
||||
};
|
||||
|
||||
let (min_main, min_cross) =
|
||||
axis.pack(min_main, axis.cross(limits.min()));
|
||||
|
||||
let (max_main, max_cross) =
|
||||
axis.pack(max_main, axis.cross(limits.max()));
|
||||
|
||||
let child_limits = Limits::new(
|
||||
Size::new(min_main, min_cross),
|
||||
Size::new(max_main, max_cross),
|
||||
);
|
||||
|
||||
let layout = child.layout(renderer, &child_limits);
|
||||
|
||||
nodes[i] = layout;
|
||||
}
|
||||
}
|
||||
|
||||
let mut main = padding;
|
||||
let mut cross = axis.cross(limits.min());
|
||||
|
||||
for (i, node) in nodes.iter_mut().enumerate() {
|
||||
if i > 0 {
|
||||
main += spacing;
|
||||
}
|
||||
|
||||
let (x, y) = axis.pack(main, padding);
|
||||
|
||||
node.bounds.x = x;
|
||||
node.bounds.y = y;
|
||||
|
||||
let size = node.size();
|
||||
|
||||
main += axis.main(size);
|
||||
cross = cross.max(axis.cross(size));
|
||||
}
|
||||
|
||||
let (width, height) = axis.pack(main, cross);
|
||||
let size = limits.resolve(Size::new(width, height));
|
||||
|
||||
let (padding_x, padding_y) = axis.pack(padding, padding * 2.0);
|
||||
|
||||
Node::with_children(
|
||||
Size::new(size.width + padding_x, size.height + padding_y),
|
||||
nodes,
|
||||
)
|
||||
}
|
||||
|
|
@ -1,6 +1,131 @@
|
|||
#[derive(Debug)]
|
||||
pub struct Limits {}
|
||||
use crate::{Length, Size};
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct Limits {
|
||||
min: Size,
|
||||
max: Size,
|
||||
fill: Size,
|
||||
}
|
||||
|
||||
impl Limits {
|
||||
pub const NONE: Limits = Limits {};
|
||||
pub const NONE: Limits = Limits {
|
||||
min: Size::ZERO,
|
||||
max: Size::INFINITY,
|
||||
fill: Size::INFINITY,
|
||||
};
|
||||
|
||||
pub fn new(min: Size, max: Size) -> Limits {
|
||||
Limits {
|
||||
min,
|
||||
max,
|
||||
fill: Size::INFINITY,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn width(mut self, width: Length) -> Limits {
|
||||
match width {
|
||||
Length::Shrink => {
|
||||
self.fill.width = self.min.width;
|
||||
}
|
||||
Length::Fill => {
|
||||
self.fill.width = self.fill.width.min(self.max.width);
|
||||
}
|
||||
Length::Units(units) => {
|
||||
let new_width =
|
||||
(units as f32).min(self.max.width).max(self.min.width);
|
||||
|
||||
self.min.width = new_width;
|
||||
self.max.width = new_width;
|
||||
self.fill.width = new_width;
|
||||
}
|
||||
}
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
pub fn height(mut self, height: Length) -> Limits {
|
||||
match height {
|
||||
Length::Shrink => {
|
||||
self.fill.height = self.min.height;
|
||||
}
|
||||
Length::Fill => {
|
||||
self.fill.height = self.fill.height.min(self.max.height);
|
||||
}
|
||||
Length::Units(units) => {
|
||||
let new_height =
|
||||
(units as f32).min(self.max.height).max(self.min.height);
|
||||
|
||||
self.min.height = new_height;
|
||||
self.max.height = new_height;
|
||||
self.fill.height = new_height;
|
||||
}
|
||||
}
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
pub fn min_width(mut self, min_width: u32) -> Limits {
|
||||
self.min.width =
|
||||
self.min.width.max(min_width as f32).min(self.max.width);
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
pub fn max_width(mut self, max_width: u32) -> Limits {
|
||||
self.max.width =
|
||||
self.max.width.min(max_width as f32).max(self.min.width);
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
pub fn max_height(mut self, max_height: u32) -> Limits {
|
||||
self.max.height =
|
||||
self.max.height.min(max_height as f32).max(self.min.height);
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
pub fn resolve(&self, intrinsic_size: Size) -> Size {
|
||||
Size::new(
|
||||
intrinsic_size
|
||||
.width
|
||||
.min(self.max.width)
|
||||
.max(self.fill.width),
|
||||
intrinsic_size
|
||||
.height
|
||||
.min(self.max.height)
|
||||
.max(self.fill.height),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn min(&self) -> Size {
|
||||
self.min
|
||||
}
|
||||
|
||||
pub fn max(&self) -> Size {
|
||||
self.max
|
||||
}
|
||||
|
||||
pub fn pad(&self, padding: f32) -> Limits {
|
||||
self.shrink(Size::new(padding * 2.0, padding * 2.0))
|
||||
}
|
||||
|
||||
pub fn shrink(&self, size: Size) -> Limits {
|
||||
let min = Size::new(
|
||||
(self.min().width - size.width).max(0.0),
|
||||
(self.min().height - size.height).max(0.0),
|
||||
);
|
||||
|
||||
let max = Size::new(
|
||||
(self.max().width - size.width).max(0.0),
|
||||
(self.max().height - size.height).max(0.0),
|
||||
);
|
||||
|
||||
let fill = Size::new(
|
||||
(self.fill.width - size.width).max(0.0),
|
||||
(self.fill.height - size.height).max(0.0),
|
||||
);
|
||||
|
||||
Limits { min, max, fill }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
37
native/src/layout/node.rs
Normal file
37
native/src/layout/node.rs
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
use crate::{Rectangle, Size};
|
||||
|
||||
#[derive(Debug, Clone, Default)]
|
||||
pub struct Node {
|
||||
pub bounds: Rectangle,
|
||||
children: Vec<Node>,
|
||||
}
|
||||
|
||||
impl Node {
|
||||
pub fn new(size: Size) -> Self {
|
||||
Self::with_children(size, Vec::new())
|
||||
}
|
||||
|
||||
pub fn with_children(size: Size, children: Vec<Node>) -> Self {
|
||||
Node {
|
||||
bounds: Rectangle {
|
||||
x: 0.0,
|
||||
y: 0.0,
|
||||
width: size.width,
|
||||
height: size.height,
|
||||
},
|
||||
children,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn size(&self) -> Size {
|
||||
Size::new(self.bounds.width, self.bounds.height)
|
||||
}
|
||||
|
||||
pub fn bounds(&self) -> Rectangle {
|
||||
self.bounds
|
||||
}
|
||||
|
||||
pub fn children(&self) -> &[Node] {
|
||||
&self.children
|
||||
}
|
||||
}
|
||||
|
|
@ -207,6 +207,7 @@ mod element;
|
|||
mod event;
|
||||
mod hasher;
|
||||
mod mouse_cursor;
|
||||
mod size;
|
||||
mod user_interface;
|
||||
|
||||
pub use iced_core::{
|
||||
|
|
@ -219,5 +220,6 @@ pub use hasher::Hasher;
|
|||
pub use layout::Layout;
|
||||
pub use mouse_cursor::MouseCursor;
|
||||
pub use renderer::Renderer;
|
||||
pub use size::Size;
|
||||
pub use user_interface::{Cache, UserInterface};
|
||||
pub use widget::*;
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ pub trait Debugger: super::Renderer {
|
|||
fn explain<Message>(
|
||||
&mut self,
|
||||
widget: &dyn Widget<Message, Self>,
|
||||
layout: &Layout,
|
||||
layout: Layout<'_>,
|
||||
cursor_position: Point,
|
||||
color: Color,
|
||||
) -> Self::Output;
|
||||
|
|
|
|||
25
native/src/size.rs
Normal file
25
native/src/size.rs
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
use std::f32;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub struct Size {
|
||||
/// The width.
|
||||
pub width: f32,
|
||||
/// The height.
|
||||
pub height: f32,
|
||||
}
|
||||
|
||||
impl Size {
|
||||
pub const ZERO: Size = Size::new(0., 0.);
|
||||
pub const INFINITY: Size = Size::new(f32::INFINITY, f32::INFINITY);
|
||||
|
||||
pub const fn new(width: f32, height: f32) -> Self {
|
||||
Size { width, height }
|
||||
}
|
||||
|
||||
pub fn pad(&self, padding: f32) -> Self {
|
||||
Size {
|
||||
width: self.width + padding * 2.0,
|
||||
height: self.height + padding * 2.0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
use crate::{input::mouse, layout, Element, Event, Layout, Point, Rectangle};
|
||||
use crate::{input::mouse, layout, Element, Event, Layout, Point, Size};
|
||||
|
||||
use std::hash::Hasher;
|
||||
|
||||
|
|
@ -14,7 +14,7 @@ use std::hash::Hasher;
|
|||
pub struct UserInterface<'a, Message, Renderer> {
|
||||
hash: u64,
|
||||
root: Element<'a, Message, Renderer>,
|
||||
layout: Layout,
|
||||
layout: layout::Node,
|
||||
cursor_position: Point,
|
||||
}
|
||||
|
||||
|
|
@ -109,7 +109,11 @@ where
|
|||
let layout = if hash == cache.hash {
|
||||
cache.layout
|
||||
} else {
|
||||
root.layout(renderer, &layout::Limits::NONE)
|
||||
let layout_start = std::time::Instant::now();
|
||||
let layout = root.layout(renderer, &layout::Limits::NONE);
|
||||
dbg!(std::time::Instant::now() - layout_start);
|
||||
|
||||
layout
|
||||
};
|
||||
|
||||
UserInterface {
|
||||
|
|
@ -209,7 +213,7 @@ where
|
|||
|
||||
self.root.widget.on_event(
|
||||
event,
|
||||
&self.layout,
|
||||
Layout::new(&self.layout),
|
||||
self.cursor_position,
|
||||
&mut messages,
|
||||
renderer,
|
||||
|
|
@ -298,9 +302,11 @@ where
|
|||
/// }
|
||||
/// ```
|
||||
pub fn draw(&self, renderer: &mut Renderer) -> Renderer::Output {
|
||||
self.root
|
||||
.widget
|
||||
.draw(renderer, &self.layout, self.cursor_position)
|
||||
self.root.widget.draw(
|
||||
renderer,
|
||||
Layout::new(&self.layout),
|
||||
self.cursor_position,
|
||||
)
|
||||
}
|
||||
|
||||
/// Extract the [`Cache`] of the [`UserInterface`], consuming it in the
|
||||
|
|
@ -323,7 +329,7 @@ where
|
|||
#[derive(Debug, Clone)]
|
||||
pub struct Cache {
|
||||
hash: u64,
|
||||
layout: Layout,
|
||||
layout: layout::Node,
|
||||
cursor_position: Point,
|
||||
}
|
||||
|
||||
|
|
@ -338,12 +344,7 @@ impl Cache {
|
|||
pub fn new() -> Cache {
|
||||
Cache {
|
||||
hash: 0,
|
||||
layout: Layout::new(Rectangle {
|
||||
x: 0.0,
|
||||
y: 0.0,
|
||||
width: 0.0,
|
||||
height: 0.0,
|
||||
}),
|
||||
layout: layout::Node::new(Size::new(0.0, 0.0)),
|
||||
cursor_position: Point::new(-1.0, -1.0),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ pub use text::Text;
|
|||
#[doc(no_inline)]
|
||||
pub use text_input::TextInput;
|
||||
|
||||
use crate::{layout, Event, Hasher, Layout, Point};
|
||||
use crate::{layout, Event, Hasher, Layout, Length, Point};
|
||||
|
||||
/// A component that displays information and allows interaction.
|
||||
///
|
||||
|
|
@ -73,7 +73,19 @@ where
|
|||
/// [`Node`]: ../struct.Node.html
|
||||
/// [`Widget`]: trait.Widget.html
|
||||
/// [`Layout`]: ../struct.Layout.html
|
||||
fn layout(&self, renderer: &Renderer, limits: &layout::Limits) -> Layout;
|
||||
fn layout(
|
||||
&self,
|
||||
renderer: &Renderer,
|
||||
limits: &layout::Limits,
|
||||
) -> layout::Node;
|
||||
|
||||
fn width(&self) -> Length {
|
||||
Length::Shrink
|
||||
}
|
||||
|
||||
fn height(&self) -> Length {
|
||||
Length::Shrink
|
||||
}
|
||||
|
||||
/// Draws the [`Widget`] using the associated `Renderer`.
|
||||
///
|
||||
|
|
@ -81,7 +93,7 @@ where
|
|||
fn draw(
|
||||
&self,
|
||||
renderer: &mut Renderer,
|
||||
layout: &Layout,
|
||||
layout: Layout<'_>,
|
||||
cursor_position: Point,
|
||||
) -> Renderer::Output;
|
||||
|
||||
|
|
@ -117,7 +129,7 @@ where
|
|||
fn on_event(
|
||||
&mut self,
|
||||
_event: Event,
|
||||
_layout: &Layout,
|
||||
_layout: Layout<'_>,
|
||||
_cursor_position: Point,
|
||||
_messages: &mut Vec<Message>,
|
||||
_renderer: &Renderer,
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
//! [`Class`]: enum.Class.html
|
||||
|
||||
use crate::input::{mouse, ButtonState};
|
||||
use crate::{layout, Element, Event, Hasher, Layout, Point, Widget};
|
||||
use crate::{layout, Element, Event, Hasher, Layout, Length, Point, Widget};
|
||||
use std::hash::Hash;
|
||||
|
||||
pub use iced_core::button::State;
|
||||
|
|
@ -21,14 +21,18 @@ where
|
|||
Renderer: self::Renderer,
|
||||
Message: Clone + std::fmt::Debug,
|
||||
{
|
||||
fn layout(&self, renderer: &Renderer, limits: &layout::Limits) -> Layout {
|
||||
fn layout(
|
||||
&self,
|
||||
renderer: &Renderer,
|
||||
limits: &layout::Limits,
|
||||
) -> layout::Node {
|
||||
renderer.layout(&self, limits)
|
||||
}
|
||||
|
||||
fn on_event(
|
||||
&mut self,
|
||||
event: Event,
|
||||
layout: &Layout,
|
||||
layout: Layout<'_>,
|
||||
cursor_position: Point,
|
||||
messages: &mut Vec<Message>,
|
||||
_renderer: &Renderer,
|
||||
|
|
@ -66,7 +70,7 @@ where
|
|||
fn draw(
|
||||
&self,
|
||||
renderer: &mut Renderer,
|
||||
layout: &Layout,
|
||||
layout: Layout<'_>,
|
||||
cursor_position: Point,
|
||||
) -> Renderer::Output {
|
||||
renderer.draw(&self, layout, cursor_position)
|
||||
|
|
@ -95,7 +99,7 @@ pub trait Renderer: crate::Renderer + Sized {
|
|||
&self,
|
||||
button: &Button<'_, Message, Self>,
|
||||
limits: &layout::Limits,
|
||||
) -> Layout;
|
||||
) -> layout::Node;
|
||||
|
||||
/// Draws a [`Button`].
|
||||
///
|
||||
|
|
@ -103,7 +107,7 @@ pub trait Renderer: crate::Renderer + Sized {
|
|||
fn draw<Message>(
|
||||
&mut self,
|
||||
button: &Button<'_, Message, Self>,
|
||||
layout: &Layout,
|
||||
layout: Layout<'_>,
|
||||
cursor_position: Point,
|
||||
) -> Self::Output;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,14 +10,18 @@ impl<Message, Renderer> Widget<Message, Renderer> for Checkbox<Message>
|
|||
where
|
||||
Renderer: self::Renderer,
|
||||
{
|
||||
fn layout(&self, renderer: &Renderer, limits: &layout::Limits) -> Layout {
|
||||
fn layout(
|
||||
&self,
|
||||
renderer: &Renderer,
|
||||
limits: &layout::Limits,
|
||||
) -> layout::Node {
|
||||
renderer.layout(&self, limits)
|
||||
}
|
||||
|
||||
fn on_event(
|
||||
&mut self,
|
||||
event: Event,
|
||||
layout: &Layout,
|
||||
layout: Layout<'_>,
|
||||
cursor_position: Point,
|
||||
messages: &mut Vec<Message>,
|
||||
_renderer: &Renderer,
|
||||
|
|
@ -40,7 +44,7 @@ where
|
|||
fn draw(
|
||||
&self,
|
||||
renderer: &mut Renderer,
|
||||
layout: &Layout,
|
||||
layout: Layout<'_>,
|
||||
cursor_position: Point,
|
||||
) -> Renderer::Output {
|
||||
renderer.draw(&self, layout, cursor_position)
|
||||
|
|
@ -67,7 +71,7 @@ pub trait Renderer: crate::Renderer {
|
|||
&self,
|
||||
checkbox: &Checkbox<Message>,
|
||||
limits: &layout::Limits,
|
||||
) -> Layout;
|
||||
) -> layout::Node;
|
||||
|
||||
/// Draws a [`Checkbox`].
|
||||
///
|
||||
|
|
@ -81,7 +85,7 @@ pub trait Renderer: crate::Renderer {
|
|||
fn draw<Message>(
|
||||
&mut self,
|
||||
checkbox: &Checkbox<Message>,
|
||||
layout: &Layout,
|
||||
layout: Layout<'_>,
|
||||
cursor_position: Point,
|
||||
) -> Self::Output;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
use std::hash::Hash;
|
||||
|
||||
use crate::{layout, Element, Event, Hasher, Layout, Point, Rectangle, Widget};
|
||||
use crate::{
|
||||
layout, Element, Event, Hasher, Layout, Length, Point, Size, Widget,
|
||||
};
|
||||
|
||||
/// A container that distributes its contents vertically.
|
||||
pub type Column<'a, Message, Renderer> =
|
||||
|
|
@ -11,20 +13,35 @@ impl<'a, Message, Renderer> Widget<Message, Renderer>
|
|||
where
|
||||
Renderer: self::Renderer,
|
||||
{
|
||||
fn layout(&self, renderer: &Renderer, limits: &layout::Limits) -> Layout {
|
||||
// TODO
|
||||
Layout::new(Rectangle {
|
||||
x: 0.0,
|
||||
y: 0.0,
|
||||
width: 0.0,
|
||||
height: 0.0,
|
||||
})
|
||||
fn width(&self) -> Length {
|
||||
self.width
|
||||
}
|
||||
|
||||
fn layout(
|
||||
&self,
|
||||
renderer: &Renderer,
|
||||
limits: &layout::Limits,
|
||||
) -> layout::Node {
|
||||
let limits = limits
|
||||
.max_width(self.max_width)
|
||||
.max_height(self.max_height)
|
||||
.width(self.width)
|
||||
.height(self.height);
|
||||
|
||||
layout::flex::resolve(
|
||||
layout::flex::Axis::Vertical,
|
||||
renderer,
|
||||
&limits,
|
||||
self.padding as f32,
|
||||
self.spacing as f32,
|
||||
&self.children,
|
||||
)
|
||||
}
|
||||
|
||||
fn on_event(
|
||||
&mut self,
|
||||
event: Event,
|
||||
layout: &Layout,
|
||||
layout: Layout<'_>,
|
||||
cursor_position: Point,
|
||||
messages: &mut Vec<Message>,
|
||||
renderer: &Renderer,
|
||||
|
|
@ -45,7 +62,7 @@ where
|
|||
fn draw(
|
||||
&self,
|
||||
renderer: &mut Renderer,
|
||||
layout: &Layout,
|
||||
layout: Layout<'_>,
|
||||
cursor_position: Point,
|
||||
) -> Renderer::Output {
|
||||
renderer.draw(&self, layout, cursor_position)
|
||||
|
|
@ -72,7 +89,7 @@ pub trait Renderer: crate::Renderer + Sized {
|
|||
fn draw<Message>(
|
||||
&mut self,
|
||||
row: &Column<'_, Message, Self>,
|
||||
layout: &Layout,
|
||||
layout: Layout<'_>,
|
||||
cursor_position: Point,
|
||||
) -> Self::Output;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,14 +10,18 @@ impl<Message, Renderer> Widget<Message, Renderer> for Image
|
|||
where
|
||||
Renderer: self::Renderer,
|
||||
{
|
||||
fn layout(&self, renderer: &Renderer, limits: &layout::Limits) -> Layout {
|
||||
fn layout(
|
||||
&self,
|
||||
renderer: &Renderer,
|
||||
limits: &layout::Limits,
|
||||
) -> layout::Node {
|
||||
renderer.layout(&self, limits)
|
||||
}
|
||||
|
||||
fn draw(
|
||||
&self,
|
||||
renderer: &mut Renderer,
|
||||
layout: &Layout,
|
||||
layout: Layout<'_>,
|
||||
_cursor_position: Point,
|
||||
) -> Renderer::Output {
|
||||
renderer.draw(&self, layout)
|
||||
|
|
@ -44,12 +48,12 @@ pub trait Renderer: crate::Renderer {
|
|||
///
|
||||
/// [`Node`]: ../../struct.Node.html
|
||||
/// [`Image`]: struct.Image.html
|
||||
fn layout(&self, image: &Image, limits: &layout::Limits) -> Layout;
|
||||
fn layout(&self, image: &Image, limits: &layout::Limits) -> layout::Node;
|
||||
|
||||
/// Draws an [`Image`].
|
||||
///
|
||||
/// [`Image`]: struct.Image.html
|
||||
fn draw(&mut self, image: &Image, layout: &Layout) -> Self::Output;
|
||||
fn draw(&mut self, image: &Image, layout: Layout<'_>) -> Self::Output;
|
||||
}
|
||||
|
||||
impl<'a, Message, Renderer> From<Image> for Element<'a, Message, Renderer>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
//! Create choices using radio buttons.
|
||||
use crate::input::{mouse, ButtonState};
|
||||
use crate::{layout, Element, Event, Hasher, Layout, Point, Widget};
|
||||
use crate::{layout, Element, Event, Hasher, Layout, Length, Point, Widget};
|
||||
|
||||
use std::hash::Hash;
|
||||
|
||||
|
|
@ -11,14 +11,22 @@ where
|
|||
Renderer: self::Renderer,
|
||||
Message: Clone + std::fmt::Debug,
|
||||
{
|
||||
fn layout(&self, renderer: &Renderer, limits: &layout::Limits) -> Layout {
|
||||
fn width(&self) -> Length {
|
||||
Length::Fill
|
||||
}
|
||||
|
||||
fn layout(
|
||||
&self,
|
||||
renderer: &Renderer,
|
||||
limits: &layout::Limits,
|
||||
) -> layout::Node {
|
||||
renderer.layout(&self, limits)
|
||||
}
|
||||
|
||||
fn on_event(
|
||||
&mut self,
|
||||
event: Event,
|
||||
layout: &Layout,
|
||||
layout: Layout<'_>,
|
||||
cursor_position: Point,
|
||||
messages: &mut Vec<Message>,
|
||||
_renderer: &Renderer,
|
||||
|
|
@ -39,7 +47,7 @@ where
|
|||
fn draw(
|
||||
&self,
|
||||
renderer: &mut Renderer,
|
||||
layout: &Layout,
|
||||
layout: Layout<'_>,
|
||||
cursor_position: Point,
|
||||
) -> Renderer::Output {
|
||||
renderer.draw(&self, layout, cursor_position)
|
||||
|
|
@ -66,7 +74,7 @@ pub trait Renderer: crate::Renderer {
|
|||
&self,
|
||||
radio: &Radio<Message>,
|
||||
limits: &layout::Limits,
|
||||
) -> Layout;
|
||||
) -> layout::Node;
|
||||
|
||||
/// Draws a [`Radio`] button.
|
||||
///
|
||||
|
|
@ -80,7 +88,7 @@ pub trait Renderer: crate::Renderer {
|
|||
fn draw<Message>(
|
||||
&mut self,
|
||||
radio: &Radio<Message>,
|
||||
layout: &Layout,
|
||||
layout: Layout<'_>,
|
||||
cursor_position: Point,
|
||||
) -> Self::Output;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use std::hash::Hash;
|
||||
|
||||
use crate::{layout, Element, Event, Hasher, Layout, Point, Rectangle, Widget};
|
||||
use crate::{layout, Element, Event, Hasher, Layout, Length, Point, Widget};
|
||||
|
||||
/// A container that distributes its contents horizontally.
|
||||
pub type Row<'a, Message, Renderer> =
|
||||
|
|
@ -11,20 +11,35 @@ impl<'a, Message, Renderer> Widget<Message, Renderer>
|
|||
where
|
||||
Renderer: self::Renderer,
|
||||
{
|
||||
fn layout(&self, renderer: &Renderer, limits: &layout::Limits) -> Layout {
|
||||
// TODO
|
||||
Layout::new(Rectangle {
|
||||
x: 0.0,
|
||||
y: 0.0,
|
||||
width: 0.0,
|
||||
height: 0.0,
|
||||
})
|
||||
fn width(&self) -> Length {
|
||||
self.width
|
||||
}
|
||||
|
||||
fn layout(
|
||||
&self,
|
||||
renderer: &Renderer,
|
||||
limits: &layout::Limits,
|
||||
) -> layout::Node {
|
||||
let limits = limits
|
||||
.max_width(self.max_width)
|
||||
.max_height(self.max_height)
|
||||
.width(self.width)
|
||||
.height(self.height);
|
||||
|
||||
layout::flex::resolve(
|
||||
layout::flex::Axis::Horizontal,
|
||||
renderer,
|
||||
&limits,
|
||||
self.padding as f32,
|
||||
self.spacing as f32,
|
||||
&self.children,
|
||||
)
|
||||
}
|
||||
|
||||
fn on_event(
|
||||
&mut self,
|
||||
event: Event,
|
||||
layout: &Layout,
|
||||
layout: Layout<'_>,
|
||||
cursor_position: Point,
|
||||
messages: &mut Vec<Message>,
|
||||
renderer: &Renderer,
|
||||
|
|
@ -45,7 +60,7 @@ where
|
|||
fn draw(
|
||||
&self,
|
||||
renderer: &mut Renderer,
|
||||
layout: &Layout,
|
||||
layout: Layout<'_>,
|
||||
cursor_position: Point,
|
||||
) -> Renderer::Output {
|
||||
renderer.draw(&self, layout, cursor_position)
|
||||
|
|
@ -73,7 +88,7 @@ pub trait Renderer: crate::Renderer + Sized {
|
|||
fn draw<Message>(
|
||||
&mut self,
|
||||
row: &Row<'_, Message, Self>,
|
||||
layout: &Layout,
|
||||
layout: Layout<'_>,
|
||||
cursor_position: Point,
|
||||
) -> Self::Output;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,13 @@
|
|||
use crate::{
|
||||
column,
|
||||
input::{mouse, ButtonState},
|
||||
layout, Element, Event, Hasher, Layout, Point, Rectangle, Widget,
|
||||
layout, Element, Event, Hasher, Layout, Length, Point, Rectangle, Size,
|
||||
Widget,
|
||||
};
|
||||
|
||||
pub use iced_core::scrollable::State;
|
||||
|
||||
use std::f32;
|
||||
use std::hash::Hash;
|
||||
|
||||
/// A scrollable [`Column`].
|
||||
|
|
@ -19,15 +21,31 @@ impl<'a, Message, Renderer> Widget<Message, Renderer>
|
|||
where
|
||||
Renderer: self::Renderer + column::Renderer,
|
||||
{
|
||||
fn layout(&self, renderer: &Renderer, limits: &layout::Limits) -> Layout {
|
||||
// TODO
|
||||
self.content.layout(renderer, limits)
|
||||
fn layout(
|
||||
&self,
|
||||
renderer: &Renderer,
|
||||
limits: &layout::Limits,
|
||||
) -> layout::Node {
|
||||
let limits = limits
|
||||
.max_height(self.max_height)
|
||||
.width(Length::Fill)
|
||||
.height(self.height);
|
||||
|
||||
let child_limits = layout::Limits::new(
|
||||
Size::new(limits.min().width, 0.0),
|
||||
Size::new(limits.max().width, f32::INFINITY),
|
||||
);
|
||||
|
||||
let content = self.content.layout(renderer, &child_limits);
|
||||
let size = limits.resolve(content.size());
|
||||
|
||||
layout::Node::with_children(size, vec![content])
|
||||
}
|
||||
|
||||
fn on_event(
|
||||
&mut self,
|
||||
event: Event,
|
||||
layout: &Layout,
|
||||
layout: Layout<'_>,
|
||||
cursor_position: Point,
|
||||
messages: &mut Vec<Message>,
|
||||
renderer: &Renderer,
|
||||
|
|
@ -130,7 +148,7 @@ where
|
|||
fn draw(
|
||||
&self,
|
||||
renderer: &mut Renderer,
|
||||
layout: &Layout,
|
||||
layout: Layout<'_>,
|
||||
cursor_position: Point,
|
||||
) -> Renderer::Output {
|
||||
let bounds = layout.bounds();
|
||||
|
|
@ -168,7 +186,7 @@ pub trait Renderer: crate::Renderer + Sized {
|
|||
&mut self,
|
||||
scrollable: &Scrollable<'_, Message, Self>,
|
||||
bounds: Rectangle,
|
||||
content_layout: &Layout,
|
||||
content_layout: Layout<'_>,
|
||||
cursor_position: Point,
|
||||
) -> Self::Output;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
use std::hash::Hash;
|
||||
|
||||
use crate::input::{mouse, ButtonState};
|
||||
use crate::{layout, Element, Event, Hasher, Layout, Point, Widget};
|
||||
use crate::{layout, Element, Event, Hasher, Layout, Length, Point, Widget};
|
||||
|
||||
pub use iced_core::slider::*;
|
||||
|
||||
|
|
@ -15,14 +15,22 @@ impl<'a, Message, Renderer> Widget<Message, Renderer> for Slider<'a, Message>
|
|||
where
|
||||
Renderer: self::Renderer,
|
||||
{
|
||||
fn layout(&self, renderer: &Renderer, limits: &layout::Limits) -> Layout {
|
||||
fn width(&self) -> Length {
|
||||
self.width
|
||||
}
|
||||
|
||||
fn layout(
|
||||
&self,
|
||||
renderer: &Renderer,
|
||||
limits: &layout::Limits,
|
||||
) -> layout::Node {
|
||||
renderer.layout(&self, limits)
|
||||
}
|
||||
|
||||
fn on_event(
|
||||
&mut self,
|
||||
event: Event,
|
||||
layout: &Layout,
|
||||
layout: Layout<'_>,
|
||||
cursor_position: Point,
|
||||
messages: &mut Vec<Message>,
|
||||
_renderer: &Renderer,
|
||||
|
|
@ -70,7 +78,7 @@ where
|
|||
fn draw(
|
||||
&self,
|
||||
renderer: &mut Renderer,
|
||||
layout: &Layout,
|
||||
layout: Layout<'_>,
|
||||
cursor_position: Point,
|
||||
) -> Renderer::Output {
|
||||
renderer.draw(&self, layout, cursor_position)
|
||||
|
|
@ -97,7 +105,7 @@ pub trait Renderer: crate::Renderer {
|
|||
&self,
|
||||
slider: &Slider<'_, Message>,
|
||||
limits: &layout::Limits,
|
||||
) -> Layout;
|
||||
) -> layout::Node;
|
||||
|
||||
/// Draws a [`Slider`].
|
||||
///
|
||||
|
|
@ -114,7 +122,7 @@ pub trait Renderer: crate::Renderer {
|
|||
fn draw<Message>(
|
||||
&mut self,
|
||||
slider: &Slider<'_, Message>,
|
||||
layout: &Layout,
|
||||
layout: Layout<'_>,
|
||||
cursor_position: Point,
|
||||
) -> Self::Output;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
//! Write some text for your users to read.
|
||||
use crate::{layout, Element, Hasher, Layout, Point, Widget};
|
||||
use crate::{layout, Element, Hasher, Layout, Length, Point, Widget};
|
||||
|
||||
use std::hash::Hash;
|
||||
|
||||
|
|
@ -9,14 +9,22 @@ impl<Message, Renderer> Widget<Message, Renderer> for Text
|
|||
where
|
||||
Renderer: self::Renderer,
|
||||
{
|
||||
fn layout(&self, renderer: &Renderer, limits: &layout::Limits) -> Layout {
|
||||
fn width(&self) -> Length {
|
||||
self.width
|
||||
}
|
||||
|
||||
fn layout(
|
||||
&self,
|
||||
renderer: &Renderer,
|
||||
limits: &layout::Limits,
|
||||
) -> layout::Node {
|
||||
renderer.layout(&self, limits)
|
||||
}
|
||||
|
||||
fn draw(
|
||||
&self,
|
||||
renderer: &mut Renderer,
|
||||
layout: &Layout,
|
||||
layout: Layout<'_>,
|
||||
_cursor_position: Point,
|
||||
) -> Renderer::Output {
|
||||
renderer.draw(&self, layout)
|
||||
|
|
@ -49,7 +57,7 @@ pub trait Renderer: crate::Renderer {
|
|||
/// [`Style`]: ../../struct.Style.html
|
||||
/// [`Text`]: struct.Text.html
|
||||
/// [`Node::with_measure`]: ../../struct.Node.html#method.with_measure
|
||||
fn layout(&self, text: &Text, limits: &layout::Limits) -> Layout;
|
||||
fn layout(&self, text: &Text, limits: &layout::Limits) -> layout::Node;
|
||||
|
||||
/// Draws a [`Text`] fragment.
|
||||
///
|
||||
|
|
@ -64,7 +72,7 @@ pub trait Renderer: crate::Renderer {
|
|||
/// [`Text`]: struct.Text.html
|
||||
/// [`HorizontalAlignment`]: enum.HorizontalAlignment.html
|
||||
/// [`VerticalAlignment`]: enum.VerticalAlignment.html
|
||||
fn draw(&mut self, text: &Text, layout: &Layout) -> Self::Output;
|
||||
fn draw(&mut self, text: &Text, layout: Layout<'_>) -> Self::Output;
|
||||
}
|
||||
|
||||
impl<'a, Message, Renderer> From<Text> for Element<'a, Message, Renderer>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
use crate::{
|
||||
input::{keyboard, mouse, ButtonState},
|
||||
layout, Element, Event, Hasher, Layout, Point, Rectangle, Widget,
|
||||
layout, Element, Event, Hasher, Layout, Length, Point, Rectangle, Size,
|
||||
Widget,
|
||||
};
|
||||
|
||||
pub use iced_core::{text_input::State, TextInput};
|
||||
|
|
@ -10,20 +11,30 @@ where
|
|||
Renderer: self::Renderer,
|
||||
Message: Clone + std::fmt::Debug,
|
||||
{
|
||||
fn layout(&self, renderer: &Renderer, limits: &layout::Limits) -> Layout {
|
||||
// TODO
|
||||
Layout::new(Rectangle {
|
||||
x: 0.0,
|
||||
y: 0.0,
|
||||
width: 0.0,
|
||||
height: 0.0,
|
||||
})
|
||||
fn layout(
|
||||
&self,
|
||||
renderer: &Renderer,
|
||||
limits: &layout::Limits,
|
||||
) -> layout::Node {
|
||||
let padding = self.padding as f32;
|
||||
let text_size = self.size.unwrap_or(renderer.default_size());
|
||||
|
||||
let limits = limits
|
||||
.pad(padding)
|
||||
.width(self.width)
|
||||
.height(Length::Units(text_size));
|
||||
|
||||
let mut text = layout::Node::new(limits.resolve(Size::ZERO));
|
||||
text.bounds.x = padding;
|
||||
text.bounds.y = padding;
|
||||
|
||||
layout::Node::with_children(text.size().pad(padding), vec![text])
|
||||
}
|
||||
|
||||
fn on_event(
|
||||
&mut self,
|
||||
event: Event,
|
||||
layout: &Layout,
|
||||
layout: Layout<'_>,
|
||||
cursor_position: Point,
|
||||
messages: &mut Vec<Message>,
|
||||
_renderer: &Renderer,
|
||||
|
|
@ -95,7 +106,7 @@ where
|
|||
fn draw(
|
||||
&self,
|
||||
renderer: &mut Renderer,
|
||||
layout: &Layout,
|
||||
layout: Layout<'_>,
|
||||
cursor_position: Point,
|
||||
) -> Renderer::Output {
|
||||
let bounds = layout.bounds();
|
||||
|
|
|
|||
|
|
@ -9,9 +9,8 @@ use wgpu::{
|
|||
Extensions, Limits, PowerPreference, Queue, RequestAdapterOptions,
|
||||
TextureFormat,
|
||||
};
|
||||
use wgpu_glyph::{GlyphBrush, GlyphBrushBuilder, Section};
|
||||
|
||||
use std::{cell::RefCell, rc::Rc};
|
||||
use std::cell::RefCell;
|
||||
|
||||
mod target;
|
||||
mod widget;
|
||||
|
|
@ -24,7 +23,7 @@ pub struct Renderer {
|
|||
quad_pipeline: quad::Pipeline,
|
||||
image_pipeline: crate::image::Pipeline,
|
||||
|
||||
glyph_brush: Rc<RefCell<GlyphBrush<'static, ()>>>,
|
||||
glyph_brush: RefCell<wgpu_glyph::GlyphBrush<'static, ()>>,
|
||||
}
|
||||
|
||||
pub struct Layer<'a> {
|
||||
|
|
@ -72,8 +71,10 @@ impl Renderer {
|
|||
.load(&[font::Family::Monospace])
|
||||
.expect("Find monospace font");
|
||||
|
||||
let fonts = vec![default_font, mono_font];
|
||||
|
||||
let glyph_brush =
|
||||
GlyphBrushBuilder::using_fonts_bytes(vec![default_font, mono_font])
|
||||
wgpu_glyph::GlyphBrushBuilder::using_fonts_bytes(fonts)
|
||||
.initial_cache_size((2048, 2048))
|
||||
.build(&mut device, TextureFormat::Bgra8UnormSrgb);
|
||||
|
||||
|
|
@ -86,7 +87,7 @@ impl Renderer {
|
|||
quad_pipeline,
|
||||
image_pipeline,
|
||||
|
||||
glyph_brush: Rc::new(RefCell::new(glyph_brush)),
|
||||
glyph_brush: RefCell::new(glyph_brush),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -190,7 +191,7 @@ impl Renderer {
|
|||
}
|
||||
};
|
||||
|
||||
layer.text.push(Section {
|
||||
layer.text.push(wgpu_glyph::Section {
|
||||
text: &content,
|
||||
screen_position: (
|
||||
x - layer.offset.x as f32,
|
||||
|
|
@ -297,22 +298,22 @@ impl Renderer {
|
|||
let scale = wgpu_glyph::Scale { x: 20.0, y: 20.0 };
|
||||
|
||||
for (i, line) in lines.iter().enumerate() {
|
||||
overlay.text.push(Section {
|
||||
overlay.text.push(wgpu_glyph::Section {
|
||||
text: line.as_ref(),
|
||||
screen_position: (11.0, 11.0 + 25.0 * i as f32),
|
||||
color: [0.9, 0.9, 0.9, 1.0],
|
||||
scale,
|
||||
font_id,
|
||||
..Section::default()
|
||||
..wgpu_glyph::Section::default()
|
||||
});
|
||||
|
||||
overlay.text.push(Section {
|
||||
overlay.text.push(wgpu_glyph::Section {
|
||||
text: line.as_ref(),
|
||||
screen_position: (10.0, 10.0 + 25.0 * i as f32),
|
||||
color: [0.0, 0.0, 0.0, 1.0],
|
||||
scale,
|
||||
font_id,
|
||||
..Section::default()
|
||||
..wgpu_glyph::Section::default()
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -364,7 +365,7 @@ impl Renderer {
|
|||
|
||||
for text in layer.text.iter() {
|
||||
// Target physical coordinates directly to avoid blurry text
|
||||
let text = Section {
|
||||
let text = wgpu_glyph::Section {
|
||||
screen_position: (
|
||||
(text.screen_position.0 * dpi).round(),
|
||||
(text.screen_position.1 * dpi).round(),
|
||||
|
|
@ -423,7 +424,7 @@ impl Debugger for Renderer {
|
|||
fn explain<Message>(
|
||||
&mut self,
|
||||
widget: &dyn Widget<Message, Self>,
|
||||
layout: &Layout,
|
||||
layout: Layout<'_>,
|
||||
cursor_position: Point,
|
||||
color: Color,
|
||||
) -> Self::Output {
|
||||
|
|
@ -438,7 +439,7 @@ impl Debugger for Renderer {
|
|||
}
|
||||
|
||||
fn explain_layout(
|
||||
layout: &Layout,
|
||||
layout: Layout<'_>,
|
||||
color: Color,
|
||||
primitives: &mut Vec<Primitive>,
|
||||
) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
use crate::{Primitive, Renderer};
|
||||
use iced_native::{
|
||||
button, layout, Background, Button, Layout, MouseCursor, Point, Rectangle,
|
||||
button, layout, Background, Button, Layout, Length, MouseCursor, Point,
|
||||
Rectangle,
|
||||
};
|
||||
|
||||
impl button::Renderer for Renderer {
|
||||
|
|
@ -8,20 +9,28 @@ impl button::Renderer for Renderer {
|
|||
&self,
|
||||
button: &Button<Message, Self>,
|
||||
limits: &layout::Limits,
|
||||
) -> Layout {
|
||||
// TODO
|
||||
Layout::new(Rectangle {
|
||||
x: 0.0,
|
||||
y: 0.0,
|
||||
width: 0.0,
|
||||
height: 0.0,
|
||||
})
|
||||
) -> layout::Node {
|
||||
let padding = f32::from(button.padding);
|
||||
let limits = limits
|
||||
.min_width(100)
|
||||
.width(button.width)
|
||||
.height(Length::Shrink)
|
||||
.pad(padding);
|
||||
|
||||
let mut content = button.content.layout(self, &limits);
|
||||
|
||||
content.bounds.x = padding;
|
||||
content.bounds.y = padding;
|
||||
|
||||
let size = limits.resolve(content.size()).pad(padding);
|
||||
|
||||
layout::Node::with_children(size, vec![content])
|
||||
}
|
||||
|
||||
fn draw<Message>(
|
||||
&mut self,
|
||||
button: &Button<Message, Self>,
|
||||
layout: &Layout,
|
||||
layout: Layout<'_>,
|
||||
cursor_position: Point,
|
||||
) -> Self::Output {
|
||||
let bounds = layout.bounds();
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
use crate::{Primitive, Renderer};
|
||||
use iced_native::{
|
||||
checkbox, layout, text, text::HorizontalAlignment, text::VerticalAlignment,
|
||||
Background, Checkbox, Layout, MouseCursor, Point, Rectangle, Text,
|
||||
Align, Background, Checkbox, Column, Layout, Length, MouseCursor, Point,
|
||||
Rectangle, Row, Text, Widget,
|
||||
};
|
||||
|
||||
const SIZE: f32 = 28.0;
|
||||
|
|
@ -11,20 +12,23 @@ impl checkbox::Renderer for Renderer {
|
|||
&self,
|
||||
checkbox: &Checkbox<Message>,
|
||||
limits: &layout::Limits,
|
||||
) -> Layout {
|
||||
// TODO
|
||||
Layout::new(Rectangle {
|
||||
x: 0.0,
|
||||
y: 0.0,
|
||||
width: 0.0,
|
||||
height: 0.0,
|
||||
})
|
||||
) -> layout::Node {
|
||||
Row::<(), Self>::new()
|
||||
.spacing(15)
|
||||
.align_items(Align::Center)
|
||||
.push(
|
||||
Column::new()
|
||||
.width(Length::Units(SIZE as u16))
|
||||
.height(Length::Units(SIZE as u16)),
|
||||
)
|
||||
.push(Text::new(&checkbox.label))
|
||||
.layout(self, limits)
|
||||
}
|
||||
|
||||
fn draw<Message>(
|
||||
&mut self,
|
||||
checkbox: &Checkbox<Message>,
|
||||
layout: &Layout,
|
||||
layout: Layout<'_>,
|
||||
cursor_position: Point,
|
||||
) -> Self::Output {
|
||||
let bounds = layout.bounds();
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ impl column::Renderer for Renderer {
|
|||
fn draw<Message>(
|
||||
&mut self,
|
||||
column: &Column<'_, Message, Self>,
|
||||
layout: &Layout,
|
||||
layout: Layout<'_>,
|
||||
cursor_position: Point,
|
||||
) -> Self::Output {
|
||||
let mut mouse_cursor = MouseCursor::OutOfBounds;
|
||||
|
|
|
|||
|
|
@ -1,18 +1,31 @@
|
|||
use crate::{Primitive, Renderer};
|
||||
use iced_native::{image, layout, Image, Layout, MouseCursor, Rectangle};
|
||||
use iced_native::{image, layout, Image, Layout, Length, MouseCursor, Size};
|
||||
|
||||
impl image::Renderer for Renderer {
|
||||
fn layout(&self, image: &Image, limits: &layout::Limits) -> Layout {
|
||||
// TODO
|
||||
Layout::new(Rectangle {
|
||||
x: 0.0,
|
||||
y: 0.0,
|
||||
width: 0.0,
|
||||
height: 0.0,
|
||||
})
|
||||
fn layout(&self, image: &Image, limits: &layout::Limits) -> layout::Node {
|
||||
let (width, height) = self.image_pipeline.dimensions(&image.path);
|
||||
|
||||
let aspect_ratio = width as f32 / height as f32;
|
||||
|
||||
// TODO: Deal with additional cases
|
||||
let (width, height) = match (image.width, image.height) {
|
||||
(Length::Units(width), _) => (
|
||||
image.width,
|
||||
Length::Units((width as f32 / aspect_ratio).round() as u16),
|
||||
),
|
||||
(_, _) => {
|
||||
(Length::Units(width as u16), Length::Units(height as u16))
|
||||
}
|
||||
};
|
||||
|
||||
let mut size = limits.width(width).height(height).resolve(Size::ZERO);
|
||||
|
||||
size.height = size.width / aspect_ratio;
|
||||
|
||||
layout::Node::new(size)
|
||||
}
|
||||
|
||||
fn draw(&mut self, image: &Image, layout: &Layout) -> Self::Output {
|
||||
fn draw(&mut self, image: &Image, layout: Layout<'_>) -> Self::Output {
|
||||
(
|
||||
Primitive::Image {
|
||||
path: image.path.clone(),
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use crate::{Primitive, Renderer};
|
||||
use iced_native::{
|
||||
layout, radio, text, Background, Layout, MouseCursor, Point, Radio,
|
||||
Rectangle, Text,
|
||||
layout, radio, text, Align, Background, Column, Layout, Length,
|
||||
MouseCursor, Point, Radio, Rectangle, Row, Text, Widget,
|
||||
};
|
||||
|
||||
const SIZE: f32 = 28.0;
|
||||
|
|
@ -12,20 +12,23 @@ impl radio::Renderer for Renderer {
|
|||
&self,
|
||||
radio: &Radio<Message>,
|
||||
limits: &layout::Limits,
|
||||
) -> Layout {
|
||||
// TODO
|
||||
Layout::new(Rectangle {
|
||||
x: 0.0,
|
||||
y: 0.0,
|
||||
width: 0.0,
|
||||
height: 0.0,
|
||||
})
|
||||
) -> layout::Node {
|
||||
Row::<(), Self>::new()
|
||||
.spacing(15)
|
||||
.align_items(Align::Center)
|
||||
.push(
|
||||
Column::new()
|
||||
.width(Length::Units(SIZE as u16))
|
||||
.height(Length::Units(SIZE as u16)),
|
||||
)
|
||||
.push(Text::new(&radio.label))
|
||||
.layout(self, limits)
|
||||
}
|
||||
|
||||
fn draw<Message>(
|
||||
&mut self,
|
||||
radio: &Radio<Message>,
|
||||
layout: &Layout,
|
||||
layout: Layout<'_>,
|
||||
cursor_position: Point,
|
||||
) -> Self::Output {
|
||||
let bounds = layout.bounds();
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ impl row::Renderer for Renderer {
|
|||
fn draw<Message>(
|
||||
&mut self,
|
||||
row: &Row<'_, Message, Self>,
|
||||
layout: &Layout,
|
||||
layout: Layout<'_>,
|
||||
cursor_position: Point,
|
||||
) -> Self::Output {
|
||||
let mut mouse_cursor = MouseCursor::OutOfBounds;
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ impl scrollable::Renderer for Renderer {
|
|||
&mut self,
|
||||
scrollable: &Scrollable<'_, Message, Self>,
|
||||
bounds: Rectangle,
|
||||
content: &Layout,
|
||||
content: Layout<'_>,
|
||||
cursor_position: Point,
|
||||
) -> Self::Output {
|
||||
let is_mouse_over = bounds.contains(cursor_position);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use crate::{Primitive, Renderer};
|
||||
use iced_native::{
|
||||
layout, slider, Background, Color, Layout, MouseCursor, Point, Rectangle,
|
||||
Slider,
|
||||
layout, slider, Background, Color, Layout, Length, MouseCursor, Point,
|
||||
Rectangle, Size, Slider,
|
||||
};
|
||||
|
||||
const HANDLE_WIDTH: f32 = 8.0;
|
||||
|
|
@ -12,20 +12,17 @@ impl slider::Renderer for Renderer {
|
|||
&self,
|
||||
slider: &Slider<Message>,
|
||||
limits: &layout::Limits,
|
||||
) -> Layout {
|
||||
// TODO
|
||||
Layout::new(Rectangle {
|
||||
x: 0.0,
|
||||
y: 0.0,
|
||||
width: 0.0,
|
||||
height: 0.0,
|
||||
})
|
||||
) -> layout::Node {
|
||||
let limits = limits.width(slider.width).height(Length::Units(30));
|
||||
let size = limits.resolve(Size::ZERO);
|
||||
|
||||
layout::Node::new(size)
|
||||
}
|
||||
|
||||
fn draw<Message>(
|
||||
&mut self,
|
||||
slider: &Slider<Message>,
|
||||
layout: &Layout,
|
||||
layout: Layout<'_>,
|
||||
cursor_position: Point,
|
||||
) -> Self::Output {
|
||||
let bounds = layout.bounds();
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use crate::{Primitive, Renderer};
|
||||
use iced_native::{layout, text, Color, Layout, MouseCursor, Rectangle, Text};
|
||||
use iced_native::{layout, text, Color, Layout, MouseCursor, Size, Text};
|
||||
|
||||
//use wgpu_glyph::{GlyphCruncher, Section};
|
||||
use wgpu_glyph::{GlyphCruncher, Section};
|
||||
|
||||
use std::f32;
|
||||
|
||||
|
|
@ -9,17 +9,32 @@ use std::f32;
|
|||
const DEFAULT_TEXT_SIZE: f32 = 20.0;
|
||||
|
||||
impl text::Renderer for Renderer {
|
||||
fn layout(&self, text: &Text, limits: &layout::Limits) -> Layout {
|
||||
// TODO
|
||||
Layout::new(Rectangle {
|
||||
x: 0.0,
|
||||
y: 0.0,
|
||||
width: 0.0,
|
||||
height: 0.0,
|
||||
})
|
||||
fn layout(&self, text: &Text, limits: &layout::Limits) -> layout::Node {
|
||||
let limits = limits.width(text.width).height(text.height);
|
||||
let size = text.size.map(f32::from).unwrap_or(DEFAULT_TEXT_SIZE);
|
||||
let bounds = limits.max();
|
||||
|
||||
let section = Section {
|
||||
text: &text.content,
|
||||
scale: wgpu_glyph::Scale { x: size, y: size },
|
||||
bounds: (bounds.width, bounds.height),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let (width, height) = if let Some(bounds) =
|
||||
self.glyph_brush.borrow_mut().glyph_bounds(§ion)
|
||||
{
|
||||
(bounds.width().ceil(), bounds.height().ceil())
|
||||
} else {
|
||||
(0.0, 0.0)
|
||||
};
|
||||
|
||||
let size = limits.resolve(Size::new(width, height));
|
||||
|
||||
layout::Node::new(size)
|
||||
}
|
||||
|
||||
fn draw(&mut self, text: &Text, layout: &Layout) -> Self::Output {
|
||||
fn draw(&mut self, text: &Text, layout: Layout<'_>) -> Self::Output {
|
||||
(
|
||||
Primitive::Text {
|
||||
content: text.content.clone(),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue