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