1use super::{RESET_BUTTONS_HEIGHT, RESET_BUTTONS_WIDTH};
2
3use crate::{
4 GlobalState,
5 hud::{ChatTab, Show, TEXT_COLOR, TEXT_GRAY_COLOR, UI_HIGHLIGHT_0, UI_MAIN, img_ids::Imgs},
6 session::settings_change::{Chat as ChatChange, Chat::*},
7 settings::chat::MAX_CHAT_TABS,
8 ui::{ImageSlider, ToggleButton, fonts::Fonts},
9};
10use conrod_core::{
11 Colorable, Labelable, Positionable, Sizeable, Widget, WidgetCommon, color,
12 position::Relative,
13 widget::{self, Button, DropDownList, Image, Rectangle, Text, TextEdit},
14 widget_ids,
15};
16use i18n::Localization;
17use std::cmp::Ordering;
18
19widget_ids! {
20 struct Ids {
21 window,
22 window_r,
23 general_txt,
24 transp_text,
25 transp_slider,
26 transp_value,
27 char_name_text,
28 char_name_button,
29 reset_chat_button,
30
31 tabs_frame,
33 tabs_bg,
34 tabs_text,
35 tab_align,
36 tab_add,
37 tabs[],
38
39 tab_content_align,
41 tab_content_align_r,
42 tab_label_text,
43 tab_label_input,
44 tab_label_bg,
45 btn_tab_delete,
46
47 text_messages,
48 btn_messages_all,
49 text_messages_all,
50 btn_messages_world,
51 text_messages_world,
52 icon_messages_world,
53 btn_messages_region,
54 text_messages_region,
55 icon_messages_region,
56 btn_messages_faction,
57 text_messages_faction,
58 icon_messages_faction,
59 btn_messages_group,
60 text_messages_group,
61 icon_messages_group,
62 btn_messages_say,
63 text_messages_say,
64 icon_messages_say,
65
66 text_activity,
67 list_activity,
68
69 text_death,
70 list_death,
71 }
72}
73
74#[derive(WidgetCommon)]
75pub struct Chat<'a> {
76 global_state: &'a GlobalState,
77 show: &'a Show,
78 imgs: &'a Imgs,
79 fonts: &'a Fonts,
80 localized_strings: &'a Localization,
81 #[conrod(common_builder)]
82 common: widget::CommonBuilder,
83}
84impl<'a> Chat<'a> {
85 pub fn new(
86 global_state: &'a GlobalState,
87 show: &'a Show,
88 imgs: &'a Imgs,
89 fonts: &'a Fonts,
90 localized_strings: &'a Localization,
91 ) -> Self {
92 Self {
93 global_state,
94 show,
95 imgs,
96 fonts,
97 localized_strings,
98 common: widget::CommonBuilder::default(),
99 }
100 }
101}
102
103pub struct State {
104 ids: Ids,
105}
106pub enum Event {
107 ChangeChatSettingsTab(Option<usize>),
108 ChatChange(ChatChange),
109}
110
111impl Widget for Chat<'_> {
112 type Event = Vec<Event>;
113 type State = State;
114 type Style = ();
115
116 fn init_state(&self, id_gen: widget::id::Generator) -> Self::State {
117 State {
118 ids: Ids::new(id_gen),
119 }
120 }
121
122 fn style(&self) -> Self::Style {}
123
124 fn update(self, args: widget::UpdateArgs<Self>) -> Self::Event {
125 common_base::prof_span!("Chat::update");
126 let widget::UpdateArgs { state, ui, .. } = args;
127
128 let mut events = Vec::new();
129 let chat_settings = &self.global_state.settings.chat;
130 Rectangle::fill_with(args.rect.dim(), color::TRANSPARENT)
133 .xy(args.rect.xy())
134 .graphics_for(args.id)
135 .scroll_kids()
136 .scroll_kids_vertically()
137 .set(state.ids.window, ui);
138 Rectangle::fill_with([args.rect.w() / 2.0, args.rect.h()], color::TRANSPARENT)
140 .top_right_of(state.ids.window)
141 .set(state.ids.window_r, ui);
142
143 Text::new(&self.localized_strings.get_msg("hud-settings-general"))
145 .top_left_with_margins_on(state.ids.window, 5.0, 5.0)
146 .font_size(self.fonts.cyri.scale(18))
147 .font_id(self.fonts.cyri.conrod_id)
148 .color(TEXT_COLOR)
149 .set(state.ids.general_txt, ui);
150
151 Text::new(
153 &self
154 .localized_strings
155 .get_msg("hud-settings-background_opacity"),
156 )
157 .down_from(state.ids.general_txt, 20.0)
158 .font_size(self.fonts.cyri.scale(14))
159 .font_id(self.fonts.cyri.conrod_id)
160 .color(TEXT_COLOR)
161 .set(state.ids.transp_text, ui);
162 if let Some(new_val) = ImageSlider::continuous(
163 chat_settings.chat_opacity,
164 0.0,
165 1.0,
166 self.imgs.slider_indicator,
167 self.imgs.slider,
168 )
169 .w_h(104.0, 22.0)
170 .down_from(state.ids.transp_text, 10.0)
171 .track_breadth(12.0)
172 .slider_length(10.0)
173 .pad_track((5.0, 5.0))
174 .set(state.ids.transp_slider, ui)
175 {
176 events.push(Event::ChatChange(Transp(new_val)));
177 }
178
179 Text::new(&format!("{:.2}", chat_settings.chat_opacity,))
180 .right_from(state.ids.transp_slider, 8.0)
181 .font_size(self.fonts.cyri.scale(14))
182 .graphics_for(state.ids.transp_slider)
183 .font_id(self.fonts.cyri.conrod_id)
184 .color(TEXT_COLOR)
185 .set(state.ids.transp_value, ui);
186
187 Text::new(
189 &self
190 .localized_strings
191 .get_msg("hud-settings-chat_character_name"),
192 )
193 .down_from(state.ids.transp_slider, 10.0)
194 .font_size(self.fonts.cyri.scale(14))
195 .font_id(self.fonts.cyri.conrod_id)
196 .color(TEXT_COLOR)
197 .set(state.ids.char_name_text, ui);
198
199 if chat_settings.chat_character_name
200 != ToggleButton::new(
201 chat_settings.chat_character_name,
202 self.imgs.checkbox,
203 self.imgs.checkbox_checked,
204 )
205 .w_h(18.0, 18.0)
206 .right_from(state.ids.char_name_text, 10.0)
207 .hover_images(self.imgs.checkbox_mo, self.imgs.checkbox_checked_mo)
208 .press_images(self.imgs.checkbox_press, self.imgs.checkbox_checked)
209 .set(state.ids.char_name_button, ui)
210 {
211 events.push(Event::ChatChange(CharName(
212 !chat_settings.chat_character_name,
213 )));
214 }
215
216 if Button::image(self.imgs.button)
218 .w_h(RESET_BUTTONS_WIDTH, RESET_BUTTONS_HEIGHT)
219 .hover_image(self.imgs.button_hover)
220 .press_image(self.imgs.button_press)
221 .down_from(state.ids.char_name_text, 20.0)
222 .label(&self.localized_strings.get_msg("hud-settings-reset_chat"))
223 .label_font_size(self.fonts.cyri.scale(14))
224 .label_color(TEXT_COLOR)
225 .label_font_id(self.fonts.cyri.conrod_id)
226 .label_y(Relative::Scalar(2.0))
227 .set(state.ids.reset_chat_button, ui)
228 .was_clicked()
229 {
230 events.push(Event::ChatChange(ResetChatSettings));
231 }
232
233 Text::new(&self.localized_strings.get_msg("hud-settings-chat_tabs"))
235 .top_left_with_margins_on(state.ids.window_r, 5.0, 5.0)
236 .font_size(self.fonts.cyri.scale(18))
237 .font_id(self.fonts.cyri.conrod_id)
238 .color(TEXT_COLOR)
239 .set(state.ids.tabs_text, ui);
240
241 Image::new(self.imgs.chat_tab_settings_bg)
243 .w_h(390.0, 270.0)
244 .color(Some(UI_MAIN))
245 .down_from(state.ids.tabs_text, 20.0)
246 .set(state.ids.tabs_bg, ui);
247
248 Image::new(self.imgs.chat_tab_settings_frame)
249 .w_h(390.0, 270.0)
250 .color(Some(UI_HIGHLIGHT_0))
251 .down_from(state.ids.tabs_text, 20.0)
252 .set(state.ids.tabs_frame, ui);
253
254 Rectangle::fill_with([390.0, 20.0], color::TRANSPARENT)
256 .down_from(state.ids.tabs_text, 20.0)
257 .set(state.ids.tab_align, ui);
258
259 Rectangle::fill_with([390.0, 250.0], color::TRANSPARENT)
261 .down_from(state.ids.tab_align, 0.0)
262 .set(state.ids.tab_content_align, ui);
263 Rectangle::fill_with([195.0, 250.0], color::TRANSPARENT)
264 .top_right_of(state.ids.tab_content_align)
265 .set(state.ids.tab_content_align_r, ui);
266
267 let chat_tabs = &chat_settings.chat_tabs;
268 if state.ids.tabs.len() < chat_tabs.len() {
269 state.update(|s| {
270 s.ids
271 .tabs
272 .resize(chat_tabs.len(), &mut ui.widget_id_generator())
273 });
274 }
275 for (i, chat_tab) in chat_tabs.iter().enumerate() {
276 let is_selected = self
277 .show
278 .chat_tab_settings_index
279 .map(|index| index == i)
280 .unwrap_or(false);
281
282 let button = Button::image(if is_selected {
283 self.imgs.selection
284 } else {
285 self.imgs.nothing
286 })
287 .w_h(390.0 / (MAX_CHAT_TABS as f64), 19.0)
288 .hover_image(self.imgs.selection_hover)
289 .press_image(self.imgs.selection_press)
290 .image_color(color::rgba(1.0, 0.82, 0.27, 1.0))
291 .label(chat_tab.label.as_str())
292 .label_font_size(self.fonts.cyri.scale(12))
293 .label_font_id(self.fonts.cyri.conrod_id)
294 .label_color(TEXT_COLOR)
295 .label_y(Relative::Scalar(1.0));
296
297 let button = if i == 0 {
298 button.top_left_with_margins_on(state.ids.tab_align, 1.0, 1.0)
299 } else {
300 button.right_from(state.ids.tabs[i - 1], 0.0)
301 };
302 if button.set(state.ids.tabs[i], ui).was_clicked() {
303 events.push(Event::ChangeChatSettingsTab(if is_selected {
304 None
305 } else {
306 Some(i)
307 }));
308 }
309 }
310 if chat_tabs.len() < MAX_CHAT_TABS {
312 let add_tab_button = Button::image(self.imgs.settings_plus)
313 .hover_image(self.imgs.settings_plus_hover)
314 .press_image(self.imgs.settings_plus_press)
315 .w_h(19.0, 19.0);
316
317 let add_tab_button = if chat_tabs.is_empty() {
318 add_tab_button.top_left_with_margins_on(state.ids.tab_align, 1.0, 1.0)
319 } else {
320 add_tab_button.right_from(state.ids.tabs[chat_tabs.len() - 1], 0.0)
321 };
322
323 if add_tab_button.set(state.ids.tab_add, ui).was_clicked() {
324 let index = chat_tabs.len();
325 events.push(Event::ChatChange(ChatTabInsert(index, ChatTab::default())));
326 events.push(Event::ChangeChatSettingsTab(Some(index)));
327 }
328 }
329
330 if let Some((index, chat_tab)) = self
332 .show
333 .chat_tab_settings_index
334 .and_then(|i| chat_tabs.get(i).map(|ct| (i, ct)))
335 {
336 let mut updated_chat_tab = chat_tab.clone();
337
338 Text::new(&self.localized_strings.get_msg("hud-settings-label"))
339 .top_left_with_margins_on(state.ids.tab_content_align, 5.0, 25.0)
340 .font_size(self.fonts.cyri.scale(16))
341 .font_id(self.fonts.cyri.conrod_id)
342 .color(TEXT_COLOR)
343 .set(state.ids.tab_label_text, ui);
344
345 Rectangle::fill([90.0, 20.0])
346 .right_from(state.ids.tab_label_text, 5.0)
347 .color(color::rgba(0.0, 0.0, 0.0, 0.7))
348 .set(state.ids.tab_label_bg, ui);
349
350 if let Some(label) = TextEdit::new(chat_tab.label.as_str())
351 .right_from(state.ids.tab_label_text, 10.0)
352 .y_relative_to(state.ids.tab_label_text, -3.0)
353 .w_h(75.0, 20.0)
354 .font_id(self.fonts.cyri.conrod_id)
355 .font_size(self.fonts.cyri.scale(14))
356 .color(TEXT_COLOR)
357 .set(state.ids.tab_label_input, ui)
358 {
359 updated_chat_tab.label = label;
360 }
361
362 if Button::image(self.imgs.button)
363 .hover_image(self.imgs.button_hover)
364 .press_image(self.imgs.button_press)
365 .w_h(100.0, 30.0)
366 .label(&self.localized_strings.get_msg("hud-settings-delete"))
367 .label_font_size(self.fonts.cyri.scale(14))
368 .label_font_id(self.fonts.cyri.conrod_id)
369 .label_color(TEXT_COLOR)
370 .label_y(Relative::Scalar(1.0))
371 .bottom_right_with_margins_on(state.ids.tab_content_align, 10.0, 10.0)
372 .set(state.ids.btn_tab_delete, ui)
373 .was_clicked()
374 {
375 events.push(Event::ChatChange(ChatTabRemove(index)));
376 events.push(Event::ChangeChatSettingsTab(None));
377
378 if let Some(chat_tab_index) = chat_settings.chat_tab_index {
379 match chat_tab_index.cmp(&index) {
380 Ordering::Equal => {
381 events.push(Event::ChatChange(ChangeChatTab(None)));
382 },
383 Ordering::Greater => {
384 events.push(Event::ChatChange(ChangeChatTab(Some(index - 1))));
385 },
386 _ => {},
387 }
388 }
389 }
390
391 let create_toggle = |selected, enabled| {
394 ToggleButton::new(selected, self.imgs.checkbox, self.imgs.checkbox_checked)
395 .and(|button| {
396 if enabled {
397 button
398 .hover_images(self.imgs.checkbox_mo, self.imgs.checkbox_checked_mo)
399 .press_images(self.imgs.checkbox_press, self.imgs.checkbox_checked)
400 } else {
401 button.image_colors(TEXT_GRAY_COLOR, TEXT_GRAY_COLOR)
402 }
403 })
404 .w_h(16.0, 16.0)
405 };
406
407 let create_toggle_text = |text, enabled| {
408 Text::new(text)
409 .font_id(self.fonts.cyri.conrod_id)
410 .font_size(self.fonts.cyri.scale(14))
411 .color(if enabled { TEXT_COLOR } else { TEXT_GRAY_COLOR })
412 };
413
414 let create_toggle_icon = |img, enabled: bool| {
415 Image::new(img)
416 .and_if(!enabled, |image| image.color(Some(TEXT_GRAY_COLOR)))
417 .w_h(18.0, 18.0)
418 };
419
420 Text::new(&self.localized_strings.get_msg("hud-settings-messages"))
422 .font_id(self.fonts.cyri.conrod_id)
423 .font_size(self.fonts.cyri.scale(16))
424 .color(TEXT_COLOR)
425 .top_left_with_margins_on(state.ids.tab_content_align, 35.0, 15.0)
426 .set(state.ids.text_messages, ui);
427
428 if chat_tab.filter.message_all
430 != ToggleButton::new(
431 chat_tab.filter.message_all,
432 self.imgs.checkbox,
433 self.imgs.checkbox_checked,
434 )
435 .hover_images(self.imgs.checkbox_mo, self.imgs.checkbox_checked_mo)
436 .press_images(self.imgs.checkbox_press, self.imgs.checkbox_checked)
437 .w_h(18.0, 18.0)
438 .down_from(state.ids.text_messages, 10.0)
439 .set(state.ids.btn_messages_all, ui)
440 {
441 updated_chat_tab.filter.message_all = !chat_tab.filter.message_all;
442 };
443
444 Text::new(&self.localized_strings.get_msg("hud-settings-show_all"))
445 .font_id(self.fonts.cyri.conrod_id)
446 .font_size(self.fonts.cyri.scale(16))
447 .color(TEXT_COLOR)
448 .right_from(state.ids.btn_messages_all, 5.0)
449 .set(state.ids.text_messages_all, ui);
450
451 if chat_tab.filter.message_group
453 != create_toggle(chat_tab.filter.message_group, !chat_tab.filter.message_all)
454 .down_from(state.ids.btn_messages_all, 10.0)
455 .set(state.ids.btn_messages_group, ui)
456 && !chat_tab.filter.message_all
457 {
458 updated_chat_tab.filter.message_group = !chat_tab.filter.message_group;
459 }
460
461 let group_text = self.localized_strings.get_msg("hud-settings-group");
462 create_toggle_text(&group_text, !chat_tab.filter.message_all)
463 .right_from(state.ids.btn_messages_group, 5.0)
464 .set(state.ids.text_messages_group, ui);
465
466 create_toggle_icon(self.imgs.chat_group_small, !chat_tab.filter.message_all)
467 .right_from(state.ids.text_messages_group, 5.0)
468 .set(state.ids.icon_messages_group, ui);
469
470 if chat_tab.filter.message_faction
472 != create_toggle(
473 chat_tab.filter.message_faction,
474 !chat_tab.filter.message_all,
475 )
476 .down_from(state.ids.btn_messages_group, 10.0)
477 .set(state.ids.btn_messages_faction, ui)
478 && !chat_tab.filter.message_all
479 {
480 updated_chat_tab.filter.message_faction = !chat_tab.filter.message_faction;
481 }
482
483 let faction_text = self.localized_strings.get_msg("hud-settings-faction");
484 create_toggle_text(&faction_text, !chat_tab.filter.message_all)
485 .right_from(state.ids.btn_messages_faction, 5.0)
486 .set(state.ids.text_messages_faction, ui);
487
488 create_toggle_icon(self.imgs.chat_faction_small, !chat_tab.filter.message_all)
489 .right_from(state.ids.text_messages_faction, 5.0)
490 .set(state.ids.icon_messages_faction, ui);
491
492 if chat_tab.filter.message_world
494 != create_toggle(chat_tab.filter.message_world, !chat_tab.filter.message_all)
495 .down_from(state.ids.btn_messages_faction, 10.0)
496 .set(state.ids.btn_messages_world, ui)
497 && !chat_tab.filter.message_all
498 {
499 updated_chat_tab.filter.message_world = !chat_tab.filter.message_world;
500 }
501
502 let world_text = self.localized_strings.get_msg("hud-settings-world");
503 create_toggle_text(&world_text, !chat_tab.filter.message_all)
504 .right_from(state.ids.btn_messages_world, 5.0)
505 .set(state.ids.text_messages_world, ui);
506
507 create_toggle_icon(self.imgs.chat_world_small, !chat_tab.filter.message_all)
508 .right_from(state.ids.text_messages_world, 5.0)
509 .set(state.ids.icon_messages_world, ui);
510
511 if chat_tab.filter.message_region
513 != create_toggle(chat_tab.filter.message_region, !chat_tab.filter.message_all)
514 .down_from(state.ids.btn_messages_world, 10.0)
515 .set(state.ids.btn_messages_region, ui)
516 && !chat_tab.filter.message_all
517 {
518 updated_chat_tab.filter.message_region = !chat_tab.filter.message_region;
519 }
520
521 let region_text = self.localized_strings.get_msg("hud-settings-region");
522 create_toggle_text(®ion_text, !chat_tab.filter.message_all)
523 .right_from(state.ids.btn_messages_region, 5.0)
524 .set(state.ids.text_messages_region, ui);
525
526 create_toggle_icon(self.imgs.chat_region_small, !chat_tab.filter.message_all)
527 .right_from(state.ids.text_messages_region, 5.0)
528 .set(state.ids.icon_messages_region, ui);
529
530 if chat_tab.filter.message_say
532 != create_toggle(chat_tab.filter.message_say, !chat_tab.filter.message_all)
533 .down_from(state.ids.btn_messages_region, 10.0)
534 .set(state.ids.btn_messages_say, ui)
535 && !chat_tab.filter.message_all
536 {
537 updated_chat_tab.filter.message_say = !chat_tab.filter.message_say;
538 }
539
540 let say_text = self.localized_strings.get_msg("hud-settings-say");
541 create_toggle_text(&say_text, !chat_tab.filter.message_all)
542 .right_from(state.ids.btn_messages_say, 5.0)
543 .set(state.ids.text_messages_say, ui);
544
545 create_toggle_icon(self.imgs.chat_say_small, !chat_tab.filter.message_all)
546 .right_from(state.ids.text_messages_say, 5.0)
547 .set(state.ids.icon_messages_say, ui);
548
549 Text::new(&self.localized_strings.get_msg("hud-settings-activity"))
551 .top_left_with_margins_on(state.ids.tab_content_align_r, 0.0, 5.0)
552 .align_middle_y_of(state.ids.text_messages)
553 .font_size(self.fonts.cyri.scale(16))
554 .font_id(self.fonts.cyri.conrod_id)
555 .color(TEXT_COLOR)
556 .set(state.ids.text_activity, ui);
557
558 if let Some(clicked) = DropDownList::new(
559 &[
560 &self.localized_strings.get_msg("hud-settings-none"),
561 &self.localized_strings.get_msg("hud-settings-all"),
562 &self.localized_strings.get_msg("hud-settings-group_only"),
563 ],
564 Some(if chat_tab.filter.activity_all {
565 1
567 } else if chat_tab.filter.activity_group {
568 2
570 } else {
571 0
573 }),
574 )
575 .w_h(100.0, 20.0)
576 .color(color::hsl(0.0, 0.0, 0.1))
577 .label_color(TEXT_COLOR)
578 .label_font_id(self.fonts.cyri.conrod_id)
579 .label_font_size(self.fonts.cyri.scale(14))
580 .label_y(Relative::Scalar(1.0))
581 .down_from(state.ids.text_activity, 10.0)
582 .set(state.ids.list_activity, ui)
583 {
584 match clicked {
585 0 => {
586 updated_chat_tab.filter.activity_all = false;
587 updated_chat_tab.filter.activity_group = false;
588 },
589 1 => {
590 updated_chat_tab.filter.activity_all = true;
591 },
592 2 => {
593 updated_chat_tab.filter.activity_all = false;
594 updated_chat_tab.filter.activity_group = true;
595 },
596 _ => unreachable!(),
597 }
598 }
599
600 Text::new(&self.localized_strings.get_msg("hud-settings-death"))
602 .down_from(state.ids.list_activity, 20.0)
603 .font_size(self.fonts.cyri.scale(16))
604 .font_id(self.fonts.cyri.conrod_id)
605 .color(TEXT_COLOR)
606 .set(state.ids.text_death, ui);
607
608 if let Some(clicked) = DropDownList::new(
609 &[
610 &self.localized_strings.get_msg("hud-settings-none"),
611 &self.localized_strings.get_msg("hud-settings-all"),
612 &self.localized_strings.get_msg("hud-settings-group_only"),
613 ],
614 Some(if chat_tab.filter.death_all {
615 1
617 } else if chat_tab.filter.death_group {
618 2
620 } else {
621 0
623 }),
624 )
625 .w_h(100.0, 20.0)
626 .color(color::hsl(0.0, 0.0, 0.1))
627 .label_color(TEXT_COLOR)
628 .label_font_id(self.fonts.cyri.conrod_id)
629 .label_font_size(self.fonts.cyri.scale(14))
630 .label_y(Relative::Scalar(1.0))
631 .down_from(state.ids.text_death, 10.0)
632 .set(state.ids.list_death, ui)
633 {
634 match clicked {
635 0 => {
636 updated_chat_tab.filter.death_all = false;
637 updated_chat_tab.filter.death_group = false;
638 },
639 1 => {
640 updated_chat_tab.filter.death_all = true;
641 },
642 2 => {
643 updated_chat_tab.filter.death_all = false;
644 updated_chat_tab.filter.death_group = true;
645 },
646 _ => unreachable!(),
647 }
648 }
649
650 if chat_tab != &updated_chat_tab {
651 events.insert(0, Event::ChatChange(ChatTabUpdate(index, updated_chat_tab)));
653 }
654 }
655
656 events
657 }
658}