veloren_voxygen/hud/
prompt_dialog.rs1use super::{TEXT_COLOR, UI_HIGHLIGHT_0, img_ids::Imgs};
2use crate::{
3 game_input::GameInput,
4 hud::{Event, PromptDialogSettings},
5 settings::Settings,
6 ui::fonts::Fonts,
7};
8use conrod_core::{
9 Colorable, Labelable, Positionable, Sizeable, Widget, WidgetCommon,
10 widget::{self, Button, Image, Text},
11 widget_ids,
12};
13use i18n::LocalizationHandle;
14use keyboard_keynames::key_layout::KeyLayout;
15
16widget_ids! {
17 struct Ids {
18 top,
19 mid,
20 bot,
21 text,
22 accept_txt, accept_key, decline_txt,
25 decline_key,
26 prompt_txt,
27 }
28}
29#[derive(WidgetCommon)]
30pub struct PromptDialog<'a> {
31 imgs: &'a Imgs,
32 fonts: &'a Fonts,
33 #[conrod(common_builder)]
34 common: widget::CommonBuilder,
35 localized_strings: &'a LocalizationHandle,
36 settings: &'a Settings,
37 prompt_dialog_settings: &'a PromptDialogSettings,
38 key_layout: &'a Option<KeyLayout>,
39}
40
41impl<'a> PromptDialog<'a> {
42 pub fn new(
43 imgs: &'a Imgs,
44 fonts: &'a Fonts,
45 localized_strings: &'a LocalizationHandle,
46 settings: &'a Settings,
47 prompt_dialog_settings: &'a PromptDialogSettings,
48 key_layout: &'a Option<KeyLayout>,
49 ) -> Self {
50 Self {
51 imgs,
52 fonts,
53 localized_strings,
54 common: widget::CommonBuilder::default(),
55 settings,
56 prompt_dialog_settings,
57 key_layout,
58 }
59 }
60}
61
62pub struct State {
63 ids: Ids,
64}
65
66pub enum DialogOutcomeEvent {
67 Affirmative(Event),
68 Negative(Option<Event>),
69}
70
71impl Widget for PromptDialog<'_> {
72 type Event = Option<DialogOutcomeEvent>;
73 type State = State;
74 type Style = ();
75
76 fn init_state(&self, id_gen: widget::id::Generator) -> Self::State {
77 State {
78 ids: Ids::new(id_gen),
79 }
80 }
81
82 fn style(&self) -> Self::Style {}
83
84 fn update(self, args: widget::UpdateArgs<Self>) -> Self::Event {
85 common_base::prof_span!("PromptDialog::update");
86 let widget::UpdateArgs { state, ui, .. } = args;
87 let _localized_strings = &self.localized_strings;
88 let mut event: Option<DialogOutcomeEvent> = None;
89
90 let accept_key = self
91 .settings
92 .controls
93 .get_binding(GameInput::AcceptGroupInvite)
94 .map_or_else(|| "".into(), |key| key.display_string(self.key_layout));
95 let decline_key = self
96 .settings
97 .controls
98 .get_binding(GameInput::DeclineGroupInvite)
99 .map_or_else(|| "".into(), |key| key.display_string(self.key_layout));
100
101 Image::new(self.imgs.prompt_top)
103 .w_h(276.0, 24.0)
104 .mid_top_with_margin_on(ui.window, 100.0)
105 .color(Some(UI_HIGHLIGHT_0))
106 .set(state.ids.top, ui);
107 if !self.prompt_dialog_settings.message.is_empty() {
108 Image::new(self.imgs.prompt_mid)
109 .w(276.0)
110 .h_of(state.ids.prompt_txt) .down_from(state.ids.top, 0.0)
112 .color(Some(UI_HIGHLIGHT_0))
113 .scroll_kids_vertically()
114 .set(state.ids.mid, ui);
115 }
116 Image::new(self.imgs.prompt_bot)
117 .w_h(276.0, 35.0)
118 .down_from(state.ids.mid, 0.0)
119 .color(Some(UI_HIGHLIGHT_0))
120 .set(state.ids.bot, ui);
121
122 if Button::image(self.imgs.key_button)
124 .w_h(20.0, 20.0)
125 .hover_image(self.imgs.close_btn_hover)
126 .press_image(self.imgs.close_btn_press)
127 .label(&accept_key)
128 .image_color(UI_HIGHLIGHT_0)
129 .label_color(TEXT_COLOR)
130 .label_font_size(self.fonts.cyri.scale(16))
131 .label_font_id(self.fonts.cyri.conrod_id)
132 .label_y(conrod_core::position::Relative::Scalar(2.5))
133 .label_x(conrod_core::position::Relative::Scalar(0.5))
134 .bottom_left_with_margins_on(state.ids.bot, 4.0, 6.0)
135 .set(state.ids.accept_key, ui)
136 .was_clicked()
137 || self
138 .prompt_dialog_settings
139 .outcome_via_keypress
140 .is_some_and(|outcome| outcome)
141 {
142 event = Some(DialogOutcomeEvent::Affirmative(
144 self.prompt_dialog_settings.affirmative_event.clone(),
145 ));
146 }
147 let accept_txt = if self.prompt_dialog_settings.negative_option {
148 "Accept"
149 } else {
150 "Ok"
151 };
152 Text::new(accept_txt)
153 .bottom_left_with_margins_on(state.ids.accept_key, 4.0, 28.0)
154 .font_id(self.fonts.cyri.conrod_id)
155 .font_size(self.fonts.cyri.scale(18))
156 .color(TEXT_COLOR)
157 .set(state.ids.accept_txt, ui);
158
159 if self.prompt_dialog_settings.negative_option {
160 if Button::image(self.imgs.key_button)
161 .w_h(20.0, 20.0)
162 .hover_image(self.imgs.close_btn_hover)
163 .press_image(self.imgs.close_btn_press)
164 .label(&decline_key)
165 .image_color(UI_HIGHLIGHT_0)
166 .label_color(TEXT_COLOR)
167 .label_font_size(self.fonts.cyri.scale(16))
168 .label_font_id(self.fonts.cyri.conrod_id)
169 .label_y(conrod_core::position::Relative::Scalar(2.5))
170 .label_x(conrod_core::position::Relative::Scalar(0.5))
171 .bottom_right_with_margins_on(state.ids.bot, 4.0, 6.0)
172 .set(state.ids.decline_key, ui)
173 .was_clicked()
174 || self
175 .prompt_dialog_settings
176 .outcome_via_keypress
177 .is_some_and(|outcome| !outcome)
178 {
179 event = Some(DialogOutcomeEvent::Negative(
180 self.prompt_dialog_settings.negative_event.as_ref().cloned(),
181 ));
182 }
183 Text::new("Decline")
184 .bottom_left_with_margins_on(state.ids.decline_key, 4.0, -65.0)
185 .font_id(self.fonts.cyri.conrod_id)
186 .font_size(self.fonts.cyri.scale(18))
187 .color(TEXT_COLOR)
188 .set(state.ids.decline_txt, ui);
189 }
190
191 Text::new(&self.prompt_dialog_settings.message)
193 .mid_top_with_margin_on(state.ids.mid,0.0)
194 .font_id(self.fonts.cyri.conrod_id)
195 .font_size(self.fonts.cyri.scale(18))
196 .color(TEXT_COLOR)
197 .w(260.0) .set(state.ids.prompt_txt, ui);
199
200 event
201 }
202}