cacao/examples/calculator/content_view.rs
2022-08-26 10:40:31 -04:00

165 lines
6.1 KiB
Rust

use cacao::appkit::FocusRingType;
use cacao::button::{BezelStyle, Button};
use cacao::color::Color;
use cacao::layout::{Layout, LayoutConstraint};
use cacao::text::{Font, Label, TextAlign};
use cacao::view::{View, ViewDelegate};
use crate::button_row::ButtonRow;
use crate::calculator::{dispatch, Msg};
pub const BUTTON_WIDTH: f64 = 57.;
pub const BUTTON_HEIGHT: f64 = 47.;
pub fn button(text: &str, msg: Msg) -> Button {
let mut button = Button::new(text);
button.set_bordered(false);
button.set_bezel_style(BezelStyle::SmallSquare);
button.set_focus_ring_type(FocusRingType::None);
button.set_action(move || dispatch(msg.clone()));
button.set_key_equivalent(&*text.to_lowercase());
let font = Font::system(22.);
button.set_font(&font);
button.set_text_color(Color::SystemWhite);
button
}
pub struct CalculatorView {
pub results_wrapper: View,
pub label: Label,
pub row0: ButtonRow,
pub row1: ButtonRow,
pub row2: ButtonRow,
pub row3: ButtonRow,
pub dot: Button,
pub zero: Button,
pub equals: Button
}
impl CalculatorView {
pub fn new() -> Self {
let results_wrapper = View::new();
let label = Label::new();
let font = Font::system(40.);
label.set_font(&font);
label.set_text("0");
label.set_text_color(Color::rgb(255, 255, 255));
label.set_text_alignment(TextAlign::Right);
Self {
results_wrapper,
label,
row0: ButtonRow::new(
[Msg::Clear, Msg::Invert, Msg::Mod, Msg::Divide],
Color::rgb(69, 69, 69),
Color::rgb(255, 148, 10)
),
row1: ButtonRow::new(
[Msg::Push(7), Msg::Push(8), Msg::Push(9), Msg::Multiply],
Color::rgb(100, 100, 100),
Color::rgb(255, 148, 10)
),
row2: ButtonRow::new(
[Msg::Push(4), Msg::Push(5), Msg::Push(6), Msg::Subtract],
Color::rgb(100, 100, 100),
Color::rgb(255, 148, 10)
),
row3: ButtonRow::new(
[Msg::Push(1), Msg::Push(2), Msg::Push(3), Msg::Add],
Color::rgb(100, 100, 100),
Color::rgb(255, 148, 10)
),
zero: button("0", Msg::Push(0)),
dot: button(".", Msg::Decimal),
equals: button("=", Msg::Equals)
}
}
pub fn render_update(&self, message: String) {
self.label.set_text(&message);
}
}
impl ViewDelegate for CalculatorView {
const NAME: &'static str = "CalculatorView";
fn did_load(&mut self, view: View) {
view.set_background_color(Color::rgb(49, 49, 49));
self.zero.set_background_color(Color::rgb(100, 100, 100));
self.dot.set_background_color(Color::rgb(100, 100, 100));
self.equals.set_background_color(Color::rgb(255, 148, 10));
self.zero.set_key_equivalent("0");
view.add_subview(&self.row0.view);
view.add_subview(&self.row1.view);
view.add_subview(&self.row2.view);
view.add_subview(&self.row3.view);
for button in &[&self.zero, &self.dot, &self.equals] {
view.add_subview(button);
}
self.results_wrapper.add_subview(&self.label);
view.add_subview(&self.results_wrapper);
LayoutConstraint::activate(&[
self.results_wrapper.top.constraint_equal_to(&view.top),
self.results_wrapper.leading.constraint_equal_to(&view.leading),
self.results_wrapper.trailing.constraint_equal_to(&view.trailing),
self.results_wrapper.height.constraint_equal_to_constant(80.),
self.label
.leading
.constraint_equal_to(&self.results_wrapper.leading)
.offset(22.),
self.label
.trailing
.constraint_equal_to(&self.results_wrapper.trailing)
.offset(-16.),
self.label
.bottom
.constraint_equal_to(&self.results_wrapper.bottom)
.offset(-4.),
// Buttons laid out from top-left
self.row0
.view
.top
.constraint_equal_to(&self.results_wrapper.bottom)
.offset(1.),
self.row0.view.leading.constraint_equal_to(&view.leading),
self.row0.view.trailing.constraint_equal_to(&view.trailing),
self.row1.view.top.constraint_equal_to(&self.row0.view.bottom).offset(1.),
self.row1.view.leading.constraint_equal_to(&view.leading),
self.row1.view.trailing.constraint_equal_to(&view.trailing),
self.row2.view.top.constraint_equal_to(&self.row1.view.bottom).offset(1.),
self.row2.view.leading.constraint_equal_to(&view.leading),
self.row2.view.trailing.constraint_equal_to(&view.trailing),
self.row3.view.top.constraint_equal_to(&self.row2.view.bottom).offset(1.),
self.row3.view.leading.constraint_equal_to(&view.leading),
self.row3.view.trailing.constraint_equal_to(&view.trailing),
self.zero.top.constraint_equal_to(&self.row3.view.bottom).offset(1.),
self.zero.leading.constraint_equal_to(&view.leading),
self.zero.bottom.constraint_equal_to(&view.bottom),
self.dot.top.constraint_equal_to(&self.row3.view.bottom).offset(1.),
self.dot.leading.constraint_equal_to(&self.zero.trailing).offset(1.),
self.dot.bottom.constraint_equal_to(&view.bottom),
self.dot.width.constraint_equal_to_constant(BUTTON_WIDTH),
self.dot.height.constraint_equal_to_constant(BUTTON_HEIGHT),
self.equals.top.constraint_equal_to(&self.row3.view.bottom).offset(1.),
self.equals.leading.constraint_equal_to(&self.dot.trailing).offset(1.),
self.equals.trailing.constraint_equal_to(&view.trailing),
self.equals.bottom.constraint_equal_to(&view.bottom),
self.equals.width.constraint_equal_to_constant(BUTTON_WIDTH),
self.equals.height.constraint_equal_to_constant(BUTTON_HEIGHT)
])
}
}