Popup + fakeout log out button
This commit is contained in:
parent
5ee2dc3fad
commit
b9e6aacd45
|
@ -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 })
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 };
|
||||
|
|
Loading…
Reference in New Issue