mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
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:
parent
04fe308b9c
commit
75adcb20e8
8
Cargo.lock
generated
8
Cargo.lock
generated
@ -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",
|
||||
]
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
1
voxygen/src/ui/ice/component/mod.rs
Normal file
1
voxygen/src/ui/ice/component/mod.rs
Normal file
@ -0,0 +1 @@
|
||||
pub mod neat_button;
|
44
voxygen/src/ui/ice/component/neat_button.rs
Normal file
44
voxygen/src/ui/ice/component/neat_button.rs
Normal 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()
|
||||
}
|
||||
}
|
@ -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::{
|
||||
|
@ -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
|
||||
|
@ -1,5 +0,0 @@
|
||||
pub mod aspect_ratio_container;
|
||||
pub mod background_container;
|
||||
pub mod compound_graphic;
|
||||
pub mod image;
|
||||
pub mod stack;
|
124
voxygen/src/ui/ice/widget/fill_text.rs
Normal file
124
voxygen/src/ui/ice/widget/fill_text.rs
Normal 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) }
|
||||
}
|
13
voxygen/src/ui/ice/widget/mod.rs
Normal file
13
voxygen/src/ui/ice/widget/mod.rs
Normal 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,
|
||||
};
|
Loading…
Reference in New Issue
Block a user