More buttons, FillText custom widget that adjusts text size based on available space, created button component thing (a reusable composition of widgets), fixed log to tracing rebase error

This commit is contained in:
Imbris 2020-05-27 03:42:55 -04:00
parent 04fe308b9c
commit 75adcb20e8
10 changed files with 255 additions and 79 deletions

8
Cargo.lock generated
View File

@ -2066,12 +2066,12 @@ dependencies = [
[[package]]
name = "iced_core"
version = "0.2.1"
source = "git+https://github.com/hecrj/iced#f46431600cb61d4e83e0ded1ca79525478436be3"
source = "git+https://github.com/Imberflur/iced?branch=text-clone#0a775191abad5787af3aaa302d5599ef12060264"
[[package]]
name = "iced_futures"
version = "0.1.2"
source = "git+https://github.com/hecrj/iced#f46431600cb61d4e83e0ded1ca79525478436be3"
source = "git+https://github.com/Imberflur/iced?branch=text-clone#0a775191abad5787af3aaa302d5599ef12060264"
dependencies = [
"futures 0.3.5",
"log",
@ -2081,11 +2081,11 @@ dependencies = [
[[package]]
name = "iced_native"
version = "0.2.2"
source = "git+https://github.com/hecrj/iced#f46431600cb61d4e83e0ded1ca79525478436be3"
source = "git+https://github.com/Imberflur/iced?branch=text-clone#0a775191abad5787af3aaa302d5599ef12060264"
dependencies = [
"iced_core",
"iced_futures",
"num-traits 0.2.12",
"raw-window-handle",
"twox-hash",
"unicode-segmentation",
]

View File

@ -35,7 +35,7 @@ winit = {version = "0.22.2", features = ["serde"]}
conrod_core = {git = "https://gitlab.com/veloren/conrod.git", branch="copypasta_0.7"}
conrod_winit = {git = "https://gitlab.com/veloren/conrod.git", branch="copypasta_0.7"}
euc = {git = "https://github.com/zesterer/euc.git"}
iced = {package = "iced_native", git = "https://github.com/hecrj/iced"}
iced = {package = "iced_native", git = "https://github.com/Imberflur/iced", branch = "text-clone"}
window_clipboard = "0.1.1"
glyph_brush = "0.6.3"

View File

@ -184,38 +184,55 @@ pub struct PopupData {
popup_type: PopupType,
}
// No state currently
use ui::ice::component::neat_button;
struct IcedState {
imgs: IcedImgs,
quit_button: iced::button::State,
quit_button: neat_button::State,
settings_button: neat_button::State,
servers_button: neat_button::State,
multiplayer_button: neat_button::State,
#[cfg(feature = "singleplayer")]
singleplayer_button: neat_button::State,
show_servers: bool,
}
#[derive(Clone)] // TODO: why does iced require Clone?
enum Message {
Quit,
ShowServers,
#[cfg(feature = "singleplayer")]
Singleplayer,
Multiplayer,
}
impl IcedState {
pub fn new(imgs: IcedImgs) -> Self {
Self {
imgs,
quit_button: iced::button::State::new(),
servers_button: Default::default(),
settings_button: Default::default(),
quit_button: Default::default(),
multiplayer_button: Default::default(),
#[cfg(feature = "singleplayer")]
singleplayer_button: Default::default(),
show_servers: false,
}
}
pub fn view(&mut self, i18n: &Localization) -> Element<Message> {
// TODO: scale with window size
let button_font_size = 30;
//let button_font_size = 30;
const TEXT_COLOR: iced::Color = iced::Color::from_rgb(1.0, 1.0, 1.0);
const DISABLED_TEXT_COLOR: iced::Color = iced::Color::from_rgba(1.0, 1.0, 1.0, 0.2);
const FILL_FRAC_ONE: f32 = 0.77;
const FILL_FRAC_TWO: f32 = 0.53;
use iced::{
Align, Button, Column, Container, HorizontalAlignment, Length, Row, Space, Text,
VerticalAlignment,
};
use iced::{Align, Column, Container, Length, Row, Space};
use ui::ice::{
compound_graphic::{CompoundGraphic, Graphic},
AspectRatioContainer, BackgroundContainer, ButtonStyle, Image, Padding,
widget::{
compound_graphic::{CompoundGraphic, Graphic},
BackgroundContainer, Image, Padding,
},
ButtonStyle,
};
use vek::*;
@ -224,50 +241,31 @@ impl IcedState {
.press_image(self.imgs.button_press)
.text_color(TEXT_COLOR)
.disabled_text_color(DISABLED_TEXT_COLOR);
let buttons = Column::with_children(vec![
Image::new(self.imgs.button).fix_aspect_ratio().into(),
Image::new(self.imgs.button).fix_aspect_ratio().into(),
AspectRatioContainer::new(
Button::new(
&mut self.quit_button,
Text::new(i18n.get("common.quit"))
.size(button_font_size)
.height(Length::Fill)
.width(Length::Fill)
.horizontal_alignment(HorizontalAlignment::Center)
.vertical_alignment(VerticalAlignment::Center),
)
.height(Length::Fill)
.width(Length::Fill)
.style(button_style)
.on_press(Message::Quit),
)
.ratio_of_image(self.imgs.button)
.into(),
self.servers_button.view(
i18n.get("common.servers"),
FILL_FRAC_ONE,
button_style,
Some(Message::ShowServers),
),
self.settings_button.view(
i18n.get("common.settings"),
FILL_FRAC_ONE,
button_style,
None,
),
self.quit_button.view(
i18n.get("common.quit"),
FILL_FRAC_ONE,
button_style,
Some(Message::Quit),
),
])
.width(Length::Fill)
.max_width(200)
.spacing(5)
.padding(10);
// Quit
/*if Button::image(self.imgs.button)
.w_h(190.0, 40.0)
.bottom_left_with_margins_on(ui_widgets.window, 60.0, 30.0)
.hover_image(self.imgs.button_hover)
.press_image(self.imgs.button_press)
.label(i18n.get("common.quit"))
.label_font_id(self.fonts.cyri.conrod_id)
.label_color(TEXT_COLOR)
.label_font_size(self.fonts.cyri.scale(20))
.label_y(Relative::Scalar(3.0))
.set(self.ids.quit_button, ui_widgets)
.was_clicked()
{
events.push(Event::Quit);
}*/
let buttons = Container::new(buttons)
.width(Length::Fill)
.height(Length::Fill)
@ -303,20 +301,22 @@ impl IcedState {
.height(Length::FillPortion(50))
.into(),
Column::with_children(vec![
BackgroundContainer::new(
CompoundGraphic::padded_image(self.imgs.button, [106, 26], [10, 0, 10, 2])
.fix_aspect_ratio(),
Space::new(Length::Fill, Length::Fill),
)
.into(),
BackgroundContainer::new(
CompoundGraphic::padded_image(self.imgs.button, [106, 26], [10, 2, 10, 0])
.fix_aspect_ratio(),
Space::new(Length::Fill, Length::Fill),
)
.into(),
self.multiplayer_button.view(
i18n.get("common.multiplayer"),
FILL_FRAC_TWO,
button_style,
Some(Message::Multiplayer),
),
#[cfg(feature = "singleplayer")]
self.singleplayer_button.view(
i18n.get("common.singleplayer"),
FILL_FRAC_TWO,
button_style,
Some(Message::Singleplayer),
),
])
.max_width(240)
.spacing(8) // TODO scale with available window size, awkward because both width and height can become limiting factors, might need custom column, could also just use fill portion
.height(Length::FillPortion(25))
.into(),
])
@ -358,6 +358,10 @@ impl IcedState {
pub fn update(&mut self, message: Message, events: &mut Vec<Event>) {
match message {
Message::Quit => events.push(Event::Quit),
Message::ShowServers => self.show_servers = true,
#[cfg(feature = "singleplayer")]
Message::Singleplayer => events.push(Event::StartSingleplayer),
Message::Multiplayer => (), //TODO
}
}
}

View File

@ -0,0 +1 @@
pub mod neat_button;

View File

@ -0,0 +1,44 @@
use crate::ui::ice as ui;
use iced::{Button, Element, Length};
use ui::{
widget::{AspectRatioContainer, FillText},
ButtonStyle,
};
#[derive(Default)]
pub struct State {
state: iced::button::State,
}
impl State {
pub fn new() -> Self { Self::default() }
pub fn view<M: Clone + 'static>(
&mut self,
label: impl Into<String>,
fill_fraction: f32,
button_style: ButtonStyle,
message: Option<M>,
) -> Element<M, ui::IcedRenderer> {
let button = Button::new(
&mut self.state,
FillText::new(label).fill_fraction(fill_fraction),
)
.height(Length::Fill)
.width(Length::Fill)
.style(button_style);
let button = match message {
Some(message) => button.on_press(message),
None => button,
};
let container = AspectRatioContainer::new(button);
let container = match button_style.active().0 {
Some(img) => container.ratio_of_image(img),
None => container,
};
container.into()
}
}

View File

@ -1,20 +1,15 @@
// tooltip_manager: TooltipManager,
mod cache;
mod clipboard;
pub mod component;
mod renderer;
mod widget;
pub mod widget;
mod winit_conversion;
pub use cache::Font;
pub use graphic::{Id, Rotation};
pub use iced::Event;
pub use renderer::{ButtonStyle, IcedRenderer};
pub use widget::{
aspect_ratio_container::AspectRatioContainer,
background_container::{BackgroundContainer, Padding},
compound_graphic,
image::Image,
};
pub use winit_conversion::window_event;
use super::{

View File

@ -227,7 +227,7 @@ impl IcedRenderer {
.collect::<Vec<[u8; 4]>>();
if let Err(err) = renderer.update_texture(cache_tex, offset, size, &new_data) {
log::warn!("Failed to update glyph cache texture: {:?}", err);
tracing::warn!("Failed to update glyph cache texture: {:?}", err);
}
},
// Urgh more allocation we don't need
@ -278,7 +278,7 @@ impl IcedRenderer {
});
},
Err(glyph_brush::BrushError::TextureTooSmall { suggested: (x, y) }) => {
log::error!(
tracing::error!(
"Texture to small for all glyphs, would need one of the size: ({}, {})",
x,
y

View File

@ -1,5 +0,0 @@
pub mod aspect_ratio_container;
pub mod background_container;
pub mod compound_graphic;
pub mod image;
pub mod stack;

View File

@ -0,0 +1,124 @@
use iced::{layout, Element, Hasher, Layout, Length, Point, Size, Widget};
use std::hash::Hash;
const DEFAULT_FILL_FRACTION: f32 = 1.0;
const DEFAULT_VERTICAL_ADJUSTMENT: f32 = 0.05;
/// Wraps the existing Text widget giving it more advanced layouting
/// capabilities
/// Centers child text widget and adjust the font size depending on the height
/// of the limits Assumes single line text is being used
pub struct FillText<R>
where
R: iced::text::Renderer,
{
//max_font_size: u16, uncomment if there is a use case for this
/// Portion of the height of the limits which the font size should be
fill_fraction: f32,
/// Adjustment factor to center the text vertically
/// Multiplied by font size and used to move the text up if positive
// TODO: use the produced glyph geometry directly to do this and/or add support to
// layouting library
vertical_adjustment: f32,
text: iced::Text<R>,
}
impl<R> FillText<R>
where
R: iced::text::Renderer,
{
pub fn new(label: impl Into<String>) -> Self {
Self {
//max_font_size: u16::MAX,
fill_fraction: DEFAULT_FILL_FRACTION,
vertical_adjustment: DEFAULT_VERTICAL_ADJUSTMENT,
text: iced::Text::new(label),
}
}
pub fn fill_fraction(mut self, fraction: f32) -> Self {
self.fill_fraction = fraction;
self
}
pub fn vertical_adjustment(mut self, adjustment: f32) -> Self {
self.vertical_adjustment = adjustment;
self
}
pub fn color(mut self, color: impl Into<iced::Color>) -> Self {
self.text = self.text.color(color);
self
}
pub fn font(mut self, font: impl Into<R::Font>) -> Self {
self.text = self.text.font(font);
self
}
}
impl<M, R> Widget<M, R> for FillText<R>
where
R: iced::text::Renderer,
{
fn width(&self) -> Length { Length::Fill }
fn height(&self) -> Length { Length::Fill }
fn layout(&self, renderer: &R, limits: &layout::Limits) -> layout::Node {
let limits = limits.width(Length::Fill).height(Length::Fill);
let size = limits.max();
let font_size = (size.height * self.fill_fraction) as u16;
let mut text =
Widget::<M, _>::layout(&self.text.clone().size(font_size), renderer, &limits);
// Size adjusted for centering
text.align(
iced::Align::Center,
iced::Align::Center,
Size::new(
size.width,
size.height - 2.0 * font_size as f32 * self.vertical_adjustment,
),
);
layout::Node::with_children(size, vec![text])
}
fn draw(
&self,
renderer: &mut R,
defaults: &R::Defaults,
layout: Layout<'_>,
cursor_position: Point,
) -> R::Output {
// Note: this breaks if the parent widget adjusts the bounds height
let font_size = (layout.bounds().height * self.fill_fraction) as u16;
Widget::<M, _>::draw(
&self.text.clone().size(font_size),
renderer,
defaults,
layout.children().next().unwrap(),
cursor_position,
)
}
fn hash_layout(&self, state: &mut Hasher) {
struct Marker;
std::any::TypeId::of::<Marker>().hash(state);
self.fill_fraction.to_bits().hash(state);
self.vertical_adjustment.to_bits().hash(state);
Widget::<M, R>::hash_layout(&self.text, state);
}
}
impl<'a, M, R> From<FillText<R>> for Element<'a, M, R>
where
R: 'a + iced::text::Renderer,
{
fn from(fill_text: FillText<R>) -> Element<'a, M, R> { Element::new(fill_text) }
}

View File

@ -0,0 +1,13 @@
pub mod aspect_ratio_container;
pub mod background_container;
pub mod compound_graphic;
pub mod fill_text;
pub mod image;
pub mod stack;
pub use self::{
aspect_ratio_container::AspectRatioContainer,
background_container::{BackgroundContainer, Padding},
fill_text::FillText,
image::Image,
};