Popup + fakeout log out button

This commit is contained in:
marceline-cramer 2022-07-27 22:24:55 -06:00
parent 5ee2dc3fad
commit b9e6aacd45
5 changed files with 166 additions and 33 deletions

View File

@ -12,6 +12,10 @@ use widgets::Widget;
export_abi!(MainMenuPanel);
pub const ICON_FONT: &str = "Iosevka Nerd Font";
pub const DISPLAY_FONT: &str = "Homenaje";
pub const CONTENT_FONT: &str = "Liberation Sans";
pub struct MainMenuPanel {
panel: Panel,
menu: widgets::MainMenu,
@ -50,8 +54,13 @@ impl BindPanel for ConfirmationDialogPanel {
fn bind(panel: Panel) -> Box<dyn PanelImpl> {
use widgets::dialog::*;
let style = DialogStyle::default();
let responses = &[DialogResponse::Yes, DialogResponse::No];
let dialog = Dialog::new(style, responses);
let info = DialogInfo {
title: "ha jk",
content: "lmao u wish",
responses: &[DialogResponse::Yes, DialogResponse::No],
};
let dialog = Dialog::new(style, &info);
Box::new(Self { panel, dialog })
}
}

View File

@ -47,17 +47,21 @@ impl Default for DialogStyle {
pub struct DialogHeaderStyle {
pub color: Color,
pub height: f32,
pub text_font: Font,
pub text_color: Color,
pub text_size_scale: f32,
pub text_scale_factor: f32,
pub text_baseline: f32,
}
impl Default for DialogHeaderStyle {
fn default() -> Self {
Self {
color: Color::WHITE,
height: 0.2,
height: 0.3,
text_font: Font::new(crate::DISPLAY_FONT),
text_color: Color::BLACK,
text_size_scale: 0.7,
text_scale_factor: 0.65,
text_baseline: 0.25,
}
}
}
@ -66,8 +70,9 @@ impl Default for DialogHeaderStyle {
pub struct DialogBodyStyle {
pub color: Color,
pub height: f32,
pub text_font: Font,
pub text_color: Color,
pub text_size_scale: f32,
pub text_scale_factor: f32,
}
impl Default for DialogBodyStyle {
@ -75,8 +80,9 @@ impl Default for DialogBodyStyle {
Self {
color: Color::new(1., 1., 1., 0.8),
height: 0.6,
text_font: Font::new(crate::CONTENT_FONT),
text_color: Color::BLACK,
text_size_scale: 0.1,
text_scale_factor: 0.15,
}
}
}
@ -92,7 +98,7 @@ pub struct DialogFooterStyle {
impl Default for DialogFooterStyle {
fn default() -> Self {
Self {
icon_font: Font::new("Iosevka Nerd Font"),
icon_font: Font::new(crate::ICON_FONT),
button_radius: 0.1,
color: Color::WHITE,
height: 0.25,
@ -100,19 +106,59 @@ impl Default for DialogFooterStyle {
}
}
pub struct DialogInfo<'a> {
pub title: &'a str,
pub content: &'a str,
pub responses: &'a [DialogResponse],
}
pub struct Dialog {
style: DialogStyle,
title: Label,
content: Label,
buttons: Vec<DialogButton>,
}
impl Dialog {
pub fn new(style: DialogStyle, responses: &[DialogResponse]) -> Self {
pub fn new(style: DialogStyle, info: &DialogInfo<'_>) -> Self {
let width2 = style.width / 2.0;
let button_y = -(style.body.height + style.footer.height) / 2.0;
let button_spacing = style.width / responses.len() as f32;
let button_spacing = style.width / info.responses.len() as f32;
let button_spacing2 = button_spacing / 2.0;
let title_scale = style.header.height * style.header.text_scale_factor;
let title_baseline =
style.header.height * style.header.text_baseline + style.body.height / 2.0;
let title = Label::new(
LabelText {
font: style.header.text_font,
text: info.title.to_string(),
},
HorizontalAlignment::Center,
title_scale,
style.header.text_color,
-width2,
width2,
title_baseline,
);
let content_scale = style.body.height * style.body.text_scale_factor;
let content = Label::new(
LabelText {
font: style.body.text_font,
text: info.content.to_string(),
},
HorizontalAlignment::Center,
content_scale,
style.body.text_color,
-width2,
width2,
0.0,
);
let mut buttons = Vec::new();
for (index, response) in responses.iter().enumerate() {
for (index, response) in info.responses.iter().enumerate() {
let button_x = button_spacing * index as f32 + button_spacing2 - style.width / 2.0;
let radius = style.footer.button_radius;
@ -138,14 +184,22 @@ impl Dialog {
});
}
Self { style, buttons }
Self {
style,
title,
content,
buttons,
}
}
}
impl Widget for Dialog {
fn update(&mut self, dt: f32) {
impl Container for Dialog {
fn with_children(&mut self, mut f: impl FnMut(&mut dyn Widget)) {
f(&mut self.title);
f(&mut self.content);
for button in self.buttons.iter_mut() {
button.button.update(dt);
f(&mut button.button);
}
}
@ -174,16 +228,6 @@ impl Widget for Dialog {
ctx.draw_rect(body_rect, style.body.color);
ctx.draw_partially_rounded_rect(header_corners, header_rect, rounding, style.header.color);
ctx.draw_partially_rounded_rect(footer_corners, footer_rect, rounding, style.footer.color);
for button in self.buttons.iter_mut() {
button.button.draw(ctx);
}
}
fn on_cursor_event(&mut self, kind: CursorEventKind, at: Vec2) {
for button in self.buttons.iter_mut() {
button.button.on_cursor_event(kind, at);
}
}
}

View File

@ -13,9 +13,10 @@ pub mod shell;
pub mod text;
use button::{Button, RectButton, RectButtonStyle, RoundButton, RoundButtonStyle};
use dialog::{Dialog, DialogInfo, DialogResponse, DialogStyle};
use menu::{SlotMenu, SlotMenuEvent, TabMenu};
use scroll::{ScrollBar, ScrollView};
use shell::{Offset, OffsetAlignment, Reveal};
use shell::{Offset, OffsetAlignment, Popup, Reveal};
use text::{HorizontalAlignment, Label, LabelText};
#[allow(unused)]
@ -88,7 +89,7 @@ impl MainMenu {
impl Default for MainMenu {
fn default() -> Self {
let icon_font = Font::new("Iosevka Nerd Font");
let icon_font = Font::new(crate::ICON_FONT);
let icons = ["", "", "", "", "", ""];
let button_style = RoundButtonStyle {
@ -244,13 +245,14 @@ impl Widget for Inventory {
}
pub struct SettingsMenu {
pub menu: SlotMenu<RectButton>,
menu: SlotMenu<RectButton>,
log_out_dialog: Option<Popup<Dialog>>,
}
impl SettingsMenu {
pub fn new() -> Self {
let icon_font = Font::new("Iosevka Nerd Font");
let label_font = Font::new("Liberation Sans");
let icon_font = Font::new(crate::ICON_FONT);
let label_font = Font::new(crate::DISPLAY_FONT);
let button_texts = [
("Graphics", ""),
@ -258,6 +260,7 @@ impl SettingsMenu {
("Interface", ""),
("Network", ""),
("Account", ""),
("Log Out", ""),
];
let button_size = Vec2::new(0.4, 0.1);
@ -283,13 +286,17 @@ impl SettingsMenu {
let menu = SlotMenu::new(buttons, 0.12);
Self { menu }
Self {
menu,
log_out_dialog: None,
}
}
}
impl Container for SettingsMenu {
fn with_children(&mut self, mut f: impl FnMut(&mut dyn Widget)) {
f(&mut self.menu);
f(&mut self.log_out_dialog);
}
fn update(&mut self, _dt: f32) {
@ -298,6 +305,17 @@ impl Container for SettingsMenu {
}
match self.menu.get_event() {
SlotMenuEvent::SubmenuOpen(5) => {
let style = DialogStyle::default();
let info = DialogInfo {
title: "ha jk",
content: "lmao u wish",
responses: &[DialogResponse::Yes, DialogResponse::No],
};
let dialog = Dialog::new(style, &info);
let dialog = Popup::new(dialog, Vec2::ZERO);
let _ = self.log_out_dialog.insert(dialog);
}
_ => {}
};
}

View File

@ -1,7 +1,7 @@
use super::{RectBounds, Widget};
use crate::anim::Animation;
use crate::{CursorEventKind, Vec2};
use canary_script::draw::{DrawContext, Rect};
use canary_script::draw::DrawContext;
use keyframe::functions::*;
use std::ops::{Deref, DerefMut};
@ -155,3 +155,51 @@ impl<T: Widget> Widget for Offset<T> {
self.inner.on_cursor_event(kind, at);
}
}
pub struct Popup<T> {
inner: T,
offset: Vec2,
}
impl_shell_inner!(Popup);
impl<T> Popup<T> {
pub fn new(inner: T, offset: Vec2) -> Self {
Self { inner, offset }
}
pub fn set_offset(&mut self, offset: Vec2) {
self.offset = offset;
}
}
impl<T: RectBounds> Popup<T> {
pub fn new_aligned(
inner: T,
anchor: Vec2,
hori_align: OffsetAlignment,
vert_align: OffsetAlignment,
) -> Self {
let bounds = inner.get_bounds();
let x = hori_align.align(bounds.bl.x, bounds.tr.x);
let y = vert_align.align(bounds.tr.y, bounds.bl.y);
let offset = anchor - Vec2::new(x, y);
Self { inner, offset }
}
}
impl<T: Widget> Widget for Popup<T> {
fn update(&mut self, dt: f32) {
self.inner.update(dt);
}
fn draw(&mut self, ctx: &DrawContext) {
let ctx = ctx.child_at(self.offset);
self.inner.draw(&ctx);
}
fn on_cursor_event(&mut self, kind: CursorEventKind, at: Vec2) {
let at = at - self.offset;
self.inner.on_cursor_event(kind, at);
}
}

View File

@ -1,4 +1,4 @@
use super::{Color, TextLayout, Panel};
use super::{Color, Panel, TextLayout};
use bitflags::bitflags;
use glam::Vec2;
@ -167,6 +167,20 @@ impl DrawContext {
}
}
pub fn child_at(&self, at: Vec2) -> Self {
let at = self.offset.map(|old| old + at).unwrap_or(at);
self.child_at_absolute(at)
}
pub fn child_at_absolute(&self, at: Vec2) -> Self {
Self {
panel: self.panel,
offset: Some(at),
clip_rect: None,
opacity: None,
}
}
pub fn draw_triangle(&self, v1: Vec2, v2: Vec2, v3: Vec2, color: Color) {
if let Some(clip_rect) = self.clip_rect.as_ref() {
let tri = ColoredTriangle { v1, v2, v3, color };