veloren_voxygen/menu/main/ui/
servers.rs1use super::{FILL_FRAC_ONE, Imgs, Message};
2use crate::ui::{
3 fonts::IcedFonts as Fonts,
4 ice::{Element, component::neat_button, style},
5};
6use i18n::Localization;
7use iced::{
8 Align, Button, Column, Container, Length, Row, Scrollable, Space, Text, button, scrollable,
9};
10
11pub struct Screen {
12 back_button: button::State,
13 delete_button: button::State,
14 server_buttons: Vec<button::State>,
15 servers_list: scrollable::State,
16}
17
18impl Screen {
19 pub fn new() -> Self {
20 Self {
21 back_button: Default::default(),
22 delete_button: Default::default(),
23 server_buttons: vec![],
24 servers_list: Default::default(),
25 }
26 }
27
28 pub(super) fn view(
29 &mut self,
30 fonts: &Fonts,
31 imgs: &Imgs,
32 servers: &[impl AsRef<str>],
33 selected_server_index: Option<usize>,
34 i18n: &Localization,
35 button_style: style::button::Style,
36 ) -> Element<Message> {
37 let title = Text::new(i18n.get_msg("main-servers-select_server"))
38 .size(fonts.cyri.scale(35))
39 .width(Length::Fill)
40 .horizontal_alignment(iced::HorizontalAlignment::Center);
41
42 let back_button = Container::new(
43 Container::new(neat_button(
44 &mut self.back_button,
45 i18n.get_msg("common-back"),
46 FILL_FRAC_ONE,
47 button_style,
48 Some(Message::Back),
49 ))
50 .max_width(200),
51 )
52 .width(Length::Fill)
53 .align_x(Align::Center);
54
55 let delete_button = Container::new(
56 Container::new(neat_button(
57 &mut self.delete_button,
58 i18n.get_msg("common-delete_server"),
59 FILL_FRAC_ONE,
60 button_style,
61 Some(Message::DeleteServer),
62 ))
63 .max_width(200),
64 )
65 .width(Length::Fill)
66 .align_x(Align::Center);
67
68 let mut list = Scrollable::new(&mut self.servers_list)
69 .spacing(8)
70 .align_items(Align::Start)
71 .width(Length::Fill)
72 .height(Length::Fill);
73
74 if self.server_buttons.len() != servers.len() {
76 self.server_buttons = vec![Default::default(); servers.len()];
77 }
78
79 let list_items =
80 self.server_buttons
81 .iter_mut()
82 .zip(servers)
83 .enumerate()
84 .map(|(i, (state, server))| {
85 let color = if Some(i) == selected_server_index {
86 (97, 255, 18)
87 } else {
88 (97, 97, 25)
89 };
90 let button = Button::new(
91 state,
92 Row::with_children(vec![
93 Space::new(Length::FillPortion(5), Length::Units(0)).into(),
94 Text::new(server.as_ref())
95 .size(fonts.cyri.scale(30))
96 .width(Length::FillPortion(95))
97 .vertical_alignment(iced::VerticalAlignment::Center)
98 .into(),
99 ]),
100 )
101 .style(
102 style::button::Style::new(imgs.selection)
103 .hover_image(imgs.selection_hover)
104 .press_image(imgs.selection_press)
105 .image_color(vek::Rgba::new(color.0, color.1, color.2, 255)),
106 )
107 .min_height(100)
108 .on_press(Message::ServerChanged(i));
109 Row::with_children(vec![
110 Space::new(Length::FillPortion(3), Length::Units(0)).into(),
111 button.width(Length::FillPortion(92)).into(),
112 Space::new(Length::FillPortion(5), Length::Units(0)).into(),
113 ])
114 });
115
116 for item in list_items {
117 list = list.push(item);
118 }
119
120 Container::new(
121 Container::new(
122 Column::with_children(vec![
123 title.into(),
124 list.into(),
125 Row::with_children(vec![delete_button.into(), back_button.into()])
126 .width(Length::Fill)
127 .into(),
128 ])
129 .width(Length::Fill)
130 .height(Length::Fill)
131 .spacing(10)
132 .padding(20),
133 )
134 .style(
135 style::container::Style::color_with_double_cornerless_border(
136 (22, 18, 16, 255).into(),
137 (11, 11, 11, 255).into(),
138 (54, 46, 38, 255).into(),
139 ),
140 )
141 .max_width(500),
142 )
143 .width(Length::Fill)
144 .align_x(Align::Center)
145 .padding(80)
146 .into()
147 }
148}