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