Add border styling to container

This commit is contained in:
Imbris 2020-06-10 01:08:08 -04:00
parent a94bc4b725
commit e29364eedf
6 changed files with 190 additions and 55 deletions

View File

@ -6,7 +6,7 @@ use crate::{
ice::{component::neat_button, style, Element},
},
};
use iced::{button, Align, Color, Column, Container, Length, Row, Space, Text, VerticalAlignment};
use iced::{button, Align, Color, Column, Container, Length, Row, Space, Text};
/// Connecting screen for the main menu
pub struct Screen {
@ -25,7 +25,6 @@ impl Screen {
pub(super) fn view(
&mut self,
fonts: &Fonts,
imgs: &Imgs,
connection_state: &ConnectionState,
time: f32,
i18n: &Localization,
@ -99,8 +98,11 @@ impl Screen {
.height(Length::Fill);
let prompt_window = Container::new(content)
// TODO: add borders
.style(style::container::Style::Color((10, 10, 0, 255).into()))
.style(style::container::Style::color_double_cornerless_border(
(22, 18, 16, 255).into(),
(11, 11, 11, 255).into(),
(54, 46, 38, 255).into(),
))
.padding(10);
let container = Container::new(prompt_window)

View File

@ -7,7 +7,6 @@ use crate::{
},
};
use iced::{button, scrollable, Column, Container, Length, Scrollable, Space};
use vek::Rgba;
/// Connecting screen for the main menu
pub struct Screen {
@ -26,7 +25,6 @@ impl Screen {
pub(super) fn view(
&mut self,
fonts: &Fonts,
imgs: &Imgs,
i18n: &Localization,
button_style: style::button::Style,
) -> Element<Message> {
@ -66,7 +64,11 @@ impl Screen {
.width(Length::Fill)
.height(Length::Fill),
)
.style(style::container::Style::Color(Rgba::new(22, 19, 17, 255))),
.style(style::container::Style::color_double_cornerless_border(
(22, 19, 17, 255).into(),
(11, 11, 11, 255).into(),
(54, 46, 38, 255).into(),
)),
)
.center_x()
.center_y()

View File

@ -164,7 +164,6 @@ struct IcedState {
// Voxygen version
version: String,
servers: Vec<String>,
selected_server_index: Option<usize>,
login_info: LoginInfo,
@ -219,13 +218,16 @@ impl IcedState {
};
//};
let servers = settings.networking.servers.clone();
let login_info = LoginInfo {
username: settings.networking.username.clone(),
password: String::new(),
server: settings.networking.default_server.clone(),
};
let selected_server_index = servers.iter().position(|f| f == &login_info.server);
let selected_server_index = settings
.networking
.servers
.iter()
.position(|f| f == &login_info.server);
Self {
fonts,
@ -234,7 +236,6 @@ impl IcedState {
i18n,
version,
servers,
selected_server_index,
login_info,
@ -244,7 +245,7 @@ impl IcedState {
}
}
fn view(&mut self, dt: f32) -> Element<Message> {
fn view(&mut self, settings: &Settings, dt: f32) -> Element<Message> {
self.time = self.time + dt;
// TODO: consider setting this as the default in the renderer
@ -268,9 +269,7 @@ impl IcedState {
// TODO: make any large text blocks scrollable so that if the area is to
// small they can still be read
let content = match &mut self.screen {
/*Screen::Disclaimer { screen } => {
screen.view(&self.fonts, &self.imgs, &self.i18n, button_style)
},*/
//Screen::Disclaimer { screen } => screen.view(&self.fonts, &self.i18n, button_style),
Screen::Login { screen, error } => screen.view(
&self.fonts,
&self.imgs,
@ -281,8 +280,7 @@ impl IcedState {
),
Screen::Servers { screen } => screen.view(
&self.fonts,
&self.imgs,
&self.servers,
&settings.networking.servers,
self.selected_server_index,
&self.i18n,
button_style,
@ -292,7 +290,6 @@ impl IcedState {
connection_state,
} => screen.view(
&self.fonts,
&self.imgs,
&connection_state,
self.time,
&self.i18n,
@ -311,7 +308,9 @@ impl IcedState {
.into()
}
fn update(&mut self, message: Message, events: &mut Vec<Event>) {
fn update(&mut self, message: Message, events: &mut Vec<Event>, settings: &Settings) {
let servers = &settings.networking.servers;
match message {
Message::Quit => events.push(Event::Quit),
Message::Back => {
@ -321,6 +320,8 @@ impl IcedState {
};
},
Message::ShowServers => {
self.selected_server_index =
servers.iter().position(|f| f == &self.login_info.server);
self.screen = Screen::Servers {
screen: servers::Screen::new(),
};
@ -353,12 +354,11 @@ impl IcedState {
Message::Username(new_value) => self.login_info.username = new_value,
Message::Password(new_value) => self.login_info.password = new_value,
Message::Server(new_value) => {
self.selected_server_index = self.servers.iter().position(|f| f == &new_value);
self.login_info.server = new_value;
},
Message::ServerChanged(new_value) => {
self.login_info.server = self.servers[new_value].clone();
self.selected_server_index = Some(new_value);
self.login_info.server = servers[new_value].clone();
},
Message::FocusPassword => {
if let Screen::Login { screen, .. } = &mut self.screen {
@ -1272,12 +1272,14 @@ impl<'a> MainMenuUi {
self.ui.maintain(global_state.window.renderer_mut(), None);
if self.show_iced {
let (messages, _) = self.ice_ui.maintain(
self.ice_state.view(dt.as_secs_f32()),
self.ice_state
.view(&global_state.settings, dt.as_secs_f32()),
global_state.window.renderer_mut(),
);
messages
.into_iter()
.for_each(|message| self.ice_state.update(message, &mut events));
messages.into_iter().for_each(|message| {
self.ice_state
.update(message, &mut events, &global_state.settings)
});
}
events

View File

@ -3,16 +3,7 @@ use crate::{
i18n::Localization,
ui::{
fonts::IcedFonts as Fonts,
ice::{
component::neat_button,
style,
widget::{
background_container::Padding,
compound_graphic::{CompoundGraphic, Graphic},
BackgroundContainer,
},
Element,
},
ice::{component::neat_button, style, Element},
},
};
use iced::{button, scrollable, Align, Button, Column, Container, Length, Scrollable, Text};
@ -35,8 +26,7 @@ impl Screen {
pub(super) fn view(
&mut self,
fonts: &Fonts,
imgs: &Imgs,
servers: &Vec<String>,
servers: &[impl AsRef<str>],
selected_server_index: Option<usize>,
i18n: &Localization,
button_style: style::button::Style,
@ -56,38 +46,46 @@ impl Screen {
let mut list = Scrollable::new(&mut self.servers_list)
.align_items(Align::Start)
.width(Length::Fill)
.height(Length::Fill)
.spacing(10);
.height(Length::Fill);
if self.server_buttons.len() != servers.len() {
self.server_buttons = vec![Default::default(); servers.len()];
}
for (i, state) in self.server_buttons.iter_mut().enumerate() {
let server = servers.get(i).unwrap();
for (i, (state, server)) in self.server_buttons.iter_mut().zip(servers).enumerate() {
let text = format!(
"{}{}",
if i == selected_server_index.unwrap_or(std::usize::MAX) {
if Some(i) == selected_server_index {
"-> "
} else {
" "
},
server
server.as_ref(),
);
let button = Button::new(state, Text::new(text).size(fonts.cyri.scale(25)))
.on_press(Message::ServerChanged(i));
let button = Button::new(
state,
Container::new(Text::new(text).size(fonts.cyri.scale(25)))
.padding(5)
.center_y(),
)
.width(Length::Fill)
.on_press(Message::ServerChanged(i));
list = list.push(button);
}
Container::new(
BackgroundContainer::new(
CompoundGraphic::padded_image(imgs.info_frame, [500, 300], [0; 4]),
Container::new(
Column::with_children(vec![list.into(), button.into()])
.width(Length::Fill)
.height(Length::Fill)
.spacing(10)
.padding(20),
)
.style(style::container::Style::color_double_cornerless_border(
(22, 18, 16, 255).into(),
(11, 11, 11, 255).into(),
(54, 46, 38, 255).into(),
))
.max_width(500),
)
.width(Length::Fill)

View File

@ -1,16 +1,34 @@
use super::super::super::widget::image;
use vek::Rgba;
/// Container Border
pub enum Border {
DoubleCornerless { inner: Rgba<u8>, outer: Rgba<u8> },
None,
}
/// Background of the container
pub enum Style {
Image(image::Handle, Rgba<u8>),
Color(Rgba<u8>),
Color(Rgba<u8>, Border),
None,
}
impl Style {
/// Shorthand for common case where the color of the image is not modified
pub fn image(image: image::Handle) -> Self { Self::Image(image, Rgba::broadcast(255)) }
/// Shorthand for a color background with no border
pub fn color(color: Rgba<u8>) -> Self { Self::Color(color, Border::None) }
/// Shorthand for a color background with a cornerless border
pub fn color_double_cornerless_border(
color: Rgba<u8>,
inner: Rgba<u8>,
outer: Rgba<u8>,
) -> Self {
Self::Color(color, Border::DoubleCornerless { inner, outer })
}
}
impl Default for Style {

View File

@ -1,6 +1,9 @@
use super::super::{super::Rotation, style, IcedRenderer, Primitive};
use common::util::srgba_to_linear;
use iced::{container, Element, Layout, Point, Rectangle};
use style::container::Border;
const BORDER_SIZE: u16 = 8;
impl container::Renderer for IcedRenderer {
type Style = style::container::Style;
@ -29,15 +32,125 @@ impl container::Renderer for IcedRenderer {
primitives: vec![background, content],
}
},
Self::Style::Color(color) => {
let background = Primitive::Rectangle {
bounds,
linear_color: srgba_to_linear(color.map(|e| e as f32 / 255.0)),
Self::Style::Color(color, border) => {
let linear_color = srgba_to_linear(color.map(|e| e as f32 / 255.0));
let primitives = match border {
Border::None => {
let background = Primitive::Rectangle {
bounds,
linear_color,
};
vec![background, content]
},
Border::DoubleCornerless { inner, outer } => {
let border_size = f32::from(BORDER_SIZE)
.min(bounds.width / 4.0)
.min(bounds.height / 4.0);
let center = Primitive::Rectangle {
bounds: Rectangle {
x: bounds.x + border_size * 2.0,
y: bounds.y + border_size * 2.0,
width: bounds.width - border_size * 4.0,
height: bounds.height - border_size * 4.0,
},
linear_color,
};
let linear_color = srgba_to_linear(outer.map(|e| e as f32 / 255.0));
let top = Primitive::Rectangle {
bounds: Rectangle {
x: bounds.x + border_size,
y: bounds.y,
width: bounds.width - border_size * 2.0,
height: border_size,
},
linear_color,
};
let bottom = Primitive::Rectangle {
bounds: Rectangle {
x: bounds.x + border_size,
y: bounds.y + bounds.height - border_size,
width: bounds.width - border_size * 2.0,
height: border_size,
},
linear_color,
};
let left = Primitive::Rectangle {
bounds: Rectangle {
x: bounds.x,
y: bounds.y + border_size,
width: border_size,
height: bounds.height - border_size * 2.0,
},
linear_color,
};
let right = Primitive::Rectangle {
bounds: Rectangle {
x: bounds.x + bounds.width - border_size,
y: bounds.y + border_size,
width: border_size,
height: bounds.height - border_size * 2.0,
},
linear_color,
};
let linear_color = srgba_to_linear(inner.map(|e| e as f32 / 255.0));
let top_inner = Primitive::Rectangle {
bounds: Rectangle {
x: bounds.x + border_size,
y: bounds.y + border_size,
width: bounds.width - border_size * 2.0,
height: border_size,
},
linear_color,
};
let bottom_inner = Primitive::Rectangle {
bounds: Rectangle {
x: bounds.x + border_size,
y: bounds.y + bounds.height - border_size * 2.0,
width: bounds.width - border_size * 2.0,
height: border_size,
},
linear_color,
};
let left_inner = Primitive::Rectangle {
bounds: Rectangle {
x: bounds.x + border_size,
y: bounds.y + border_size * 2.0,
width: border_size,
height: bounds.height - border_size * 4.0,
},
linear_color,
};
let right_inner = Primitive::Rectangle {
bounds: Rectangle {
x: bounds.x + bounds.width - border_size * 2.0,
y: bounds.y + border_size * 2.0,
width: border_size,
height: bounds.height - border_size * 4.0,
},
linear_color,
};
vec![
center,
top,
bottom,
left,
right,
top_inner,
bottom_inner,
left_inner,
right_inner,
content,
]
},
};
Primitive::Group {
primitives: vec![background, content],
}
Primitive::Group { primitives }
},
Self::Style::None => content,
};