use crate::utils::*;
use sfml::graphics::{
CircleShape, ConvexShape, Font, RectangleShape, RenderStates, RenderTarget, RenderWindow,
Shape, Sprite, Text as Tx, Texture, Transformable,
};
use sfml::system::Vector2f;
use sfml::window::{mouse::Button as MButton, ContextSettings, Event, Key, Style, VideoMode};
use std::collections::HashMap;
#[derive(Clone)]
enum Object {
Circle(Circle),
Rectangle(Rectangle),
Line(Line),
Text(Text),
Button(Button),
Image(Image),
Polygon(Polygon),
}
pub enum Retrieve<'l> {
Circle(&'l mut Circle),
Rectangle(&'l mut Rectangle),
Line(&'l mut Line),
Text(&'l mut Text),
Button(&'l mut Button),
Image(&'l mut Image),
Polygon(&'l mut Polygon),
}
struct DefContext {
c: ContextSettings,
}
impl DefContext {
fn new() -> Self {
Self {
c: ContextSettings::default(),
}
}
}
pub struct Canvas {
_size: (u32, u32),
_name: String,
bg: Color,
window: RenderWindow,
objects: HashMap<u32, Object>,
counter: u32,
bound: Vec<(&'static str, fn(&mut Canvas))>,
bound_mouse: Vec<(&'static str, fn(&mut Canvas, (f32, f32)))>,
}
impl Canvas {
pub fn new(size: (u32, u32), name: String, bg: Color) -> Self {
let context = DefContext::new().c;
Self {
_size: size,
_name: name.clone(),
bg,
window: RenderWindow::new(
VideoMode::new(size.0, size.1, 16),
&name,
Style::default(),
&context,
),
objects: HashMap::new(),
counter: 1u32,
bound: vec![],
bound_mouse: vec![],
}
}
}
impl Canvas {
pub fn create_rectangle(
&mut self,
point_a: (f32, f32),
point_b: (f32, f32),
fill: Color,
outline: Option<Color>,
outline_thickness: Option<f32>,
) -> u32 {
let mut ret = Rectangle::new(
(point_b.0 - point_a.0, point_b.1 - point_a.1),
point_a,
fill,
);
ret.set_outline_color(outline.unwrap_or(fill));
ret.set_outline_thickness(outline_thickness.unwrap_or(0f32));
&self
.objects
.insert(self.counter, Object::Rectangle(ret.clone()));
self.increment();
self.counter - 1
}
pub fn create_line(
&mut self,
point_a: (f32, f32),
point_b: (f32, f32),
thickness: f32,
fill: Color,
outline: Option<Color>,
outline_thickness: Option<f32>,
) -> u32 {
let mut ln = Line::new(point_a, point_b, thickness, fill);
ln.set_outline_color(outline.unwrap_or(fill));
ln.set_outline_thickness(outline_thickness.unwrap_or(0f32));
&self.objects.insert(self.counter, Object::Line(ln.clone()));
self.increment();
self.counter - 1
}
pub fn create_circle(
&mut self,
point: (f32, f32),
radius: f32,
fill: Color,
outline: Option<Color>,
out_thickness: Option<f32>,
) -> u32 {
let mut ret = Circle::new(point, radius, fill);
ret.set_outline_color(outline.unwrap_or(fill));
ret.set_outline_thickness(out_thickness.unwrap_or(0f32));
ret.set_origin((radius, radius));
&self
.objects
.insert(self.counter, Object::Circle(ret.clone()));
self.increment();
self.counter - 1
}
pub fn create_polygon(
&mut self,
points: Vec<(f32, f32)>,
fill: Color,
outline: Option<Color>,
outline_thickness: Option<f32>,
) -> u32 {
let mut ret = Polygon::new(points);
ret.set_fill_color(fill);
ret.set_outline_color(outline.unwrap_or(fill));
ret.set_outline_thickness(outline_thickness.unwrap_or(0f32));
&self
.objects
.insert(self.counter, Object::Polygon(ret.clone()));
self.increment();
self.counter - 1
}
pub fn create_text(
&mut self,
position: (f32, f32),
content: &str,
size: u32,
font: &str,
fill: Color,
) -> u32 {
let mut text = Text::new(content, size, fill, position);
text.set_font(font.to_string())
.expect("Font failed to load");
&self.objects.insert(self.counter, Object::Text(text));
self.increment();
self.counter - 1
}
pub fn create_from_text(&mut self, text: &Text) -> u32 {
&self
.objects
.insert(self.counter, Object::Text(text.clone()));
self.increment();
self.counter - 1
}
pub fn create_from_button(&mut self, button: &Button) -> u32 {
self.objects
.insert(self.counter, Object::Button(button.clone()));
self.increment();
self.counter - 1
}
pub fn create_image(&mut self, path: &str, position: (f32, f32)) -> Result<u32, Error> {
let image = Image::from_file(path, position)?;
self.objects
.insert(self.counter, Object::Image(image.clone()));
self.increment();
Ok(self.counter - 1)
}
pub fn create_from_image(&mut self, image: &Image) -> u32 {
&self
.objects
.insert(self.counter, Object::Image(image.clone()));
self.increment();
self.counter - 1
}
pub fn create_from_line(&mut self, line: &Line) -> u32 {
&self
.objects
.insert(self.counter, Object::Line(line.clone()));
self.increment();
self.counter - 1
}
pub fn create_from_rectangle(&mut self, rectangle: &Rectangle) -> u32 {
&self
.objects
.insert(self.counter, Object::Rectangle(rectangle.clone()));
self.increment();
self.counter - 1
}
pub fn create_from_circle(&mut self, circle: &Circle) -> u32 {
&self
.objects
.insert(self.counter, Object::Circle(circle.clone()));
self.increment();
self.counter - 1
}
pub fn create_from_polygon(&mut self, polygon: &Polygon) -> u32 {
&self
.objects
.insert(self.counter, Object::Polygon(polygon.clone()));
self.increment();
self.counter - 1
}
pub fn retrieve(&mut self, key: u32) -> Option<Retrieve> {
for obj in self.objects.iter_mut() {
if key == *obj.0 {
match obj.1 {
Object::Circle(c) => return Some(Retrieve::Circle(c)),
Object::Line(c) => return Some(Retrieve::Line(c)),
Object::Rectangle(c) => return Some(Retrieve::Rectangle(c)),
Object::Polygon(c) => return Some(Retrieve::Polygon(c)),
Object::Text(c) => return Some(Retrieve::Text(c)),
Object::Button(c) => return Some(Retrieve::Button(c)),
Object::Image(c) => return Some(Retrieve::Image(c)),
}
}
}
return None;
}
pub fn clear(&mut self) {
self.objects.clear();
}
pub fn ids(&mut self) -> Vec<u32> {
let mut vec: Vec<u32> = Vec::new();
for (key, _) in self.objects.iter() {
vec.push(*key)
}
vec
}
pub fn bind(&mut self, action: &'static str, func: fn(&mut Canvas)) {
let pair = (action, func);
self.bound.push(pair);
}
pub fn bind_mouse(&mut self, action: &'static str, func: fn(&mut Canvas, (f32, f32))) {
let pair = (action, func);
self.bound_mouse.push(pair);
}
pub fn mainloop(&mut self) {
let canvas = self;
while canvas.window.is_open() {
canvas.window.clear(canvas.bg.c);
while let Some(event) = &mut canvas.window.poll_event() {
match event {
Event::Closed => canvas.window.close(),
Event::KeyPressed {
shift: _,
ctrl: _,
alt: _,
system: _,
code,
} => {
let code = canvas.check_keys(*code);
if code == -1 || code == -2 {
()
} else {
canvas.bound[code as usize].1(canvas);
}
}
Event::MouseButtonPressed { button, x, y } => {
let mut fn_pointer: Vec<fn(&mut Canvas, (f32, f32))> = Vec::new();
for val in canvas.objects.values() {
match val {
Object::Button(b) => {
let size = b.get_size();
let pos = b.get_position();
let area_x = (pos.0, pos.0 + size.0);
let area_y = (pos.1, pos.1 + size.1);
if *x as f32 >= area_x.0 && *x as f32 <= area_x.1 {
if *y as f32 >= area_y.0 && *y as f32 <= area_y.1 {
fn_pointer.push(b.func.unwrap());
};
};
}
_ => (),
};
}
let code = canvas.check_mouse(*button);
if code == -1 || code == -2 {
for f in fn_pointer {
f(canvas, (*x as f32, *y as f32));
}
} else {
canvas.bound_mouse[code as usize].1(canvas, (*x as f32, *y as f32));
}
}
_ => (),
}
}
for object in canvas.objects.clone() {
match object.1 {
Object::Circle(circle) => canvas
.window
.draw_circle_shape(&circle.shape, RenderStates::default()),
Object::Rectangle(rect) => canvas
.window
.draw_rectangle_shape(&rect.shape, RenderStates::default()),
Object::Line(line) => canvas
.window
.draw_rectangle_shape(&line.shape, RenderStates::default()),
Object::Polygon(polygon) => canvas
.window
.draw_convex_shape(&polygon.shape, RenderStates::default()),
Object::Text(text) => {
let mut font_path = String::new();
match text.get_font() {
Some(string) => font_path = string,
None => {
font_path = FontHandler::find_fonts("Arial".to_string())
.expect("Default font Arial not found!")
.get()
}
}
let font =
Font::from_file(font_path.as_str()).expect("Failed to load a font");
let mut tex =
Tx::new(text.get_contents().clone().as_str(), &font, text.get_size());
let pos = text.get_position();
tex.set_position(Vector2f::new(pos.0, pos.1));
tex.set_fill_color(text.get_fill_color().c);
canvas.window.draw_text(&tex, RenderStates::default())
}
Object::Button(button) => {
let text_size = button.text.get_size();
let shape_size = button.get_size();
let position = button.get_position();
let fill_color = button.get_fill_color().unwrap_or(Color::BLACK);
if button.style == ButtonStyle::Rectangle() {
let mut shape = Rectangle::new(shape_size, position, fill_color);
shape.set_outline_color(
button.get_outline_color().unwrap_or(fill_color),
);
shape.set_outline_thickness(button.get_outline_thickness());
canvas
.window
.draw_rectangle_shape(&shape.shape, RenderStates::default());
}
if button.style == ButtonStyle::Circle() {
let mut shape = Circle::new(
(position.0, position.1 - shape_size.1 / 3.),
shape_size.0 / 2.,
fill_color,
);
shape.set_outline_color(
button.get_outline_color().unwrap_or(fill_color),
);
shape.set_outline_thickness(button.get_outline_thickness());
canvas
.window
.draw_circle_shape(&shape.shape, RenderStates::default())
}
let text = button.text.clone();
let mut font_path: String;
match text.get_font() {
Some(string) => font_path = string,
None => {
font_path = FontHandler::find_fonts("Arial".to_string())
.expect("Default font Arial not found!")
.get()
}
}
let font =
Font::from_file(font_path.as_str()).expect("Failed to load a font");
let mut tex =
Tx::new(text.get_contents().clone().as_str(), &font, text.get_size());
let pos = text.get_position();
tex.set_position(Vector2f::new(pos.0, pos.1));
tex.set_fill_color(text.get_fill_color().c);
canvas.window.draw_text(&tex, RenderStates::default())
}
Object::Image(image) => {
let texture = match Texture::from_image(&image.image) {
Some(tex) => tex,
None => panic!("Failed to display image"),
};
let mut sprite = Sprite::with_texture(&texture);
let pos = image.get_position();
sprite.set_position(Vector2f::new(pos.0, pos.1));
canvas.window.draw_sprite(&sprite, RenderStates::default())
}
}
}
canvas.window.display();
}
}
fn check_keys(&self, key: Key) -> i32 {
let pairs = &self.bound;
let key_ = match key {
Key::A => "a",
Key::B => "b",
Key::C => "c",
Key::D => "d",
Key::E => "e",
Key::F => "f",
Key::G => "g",
Key::H => "h",
Key::J => "j",
Key::K => "k",
Key::L => "l",
Key::M => "m",
Key::N => "n",
Key::O => "o",
Key::P => "p",
Key::Q => "q",
Key::R => "r",
Key::S => "s",
Key::T => "t",
Key::U => "u",
Key::V => "v",
Key::W => "w",
Key::X => "x",
Key::Y => "y",
Key::Z => "z",
Key::Num0 => "0",
Key::Num1 => "1",
Key::Num2 => "2",
Key::Num3 => "3",
Key::Num4 => "4",
Key::Num5 => "5",
Key::Num6 => "6",
Key::Num7 => "7",
Key::Num8 => "8",
Key::Num9 => "9",
Key::Space => "<Space>",
Key::Return => "<Enter>",
Key::Escape => "<Esc>",
_ => return -1,
};
let mut counter = 0i32;
for pair in pairs.iter() {
if key_ == pair.0 {
return counter;
} else {
counter += 1
}
}
return -2;
}
fn check_mouse(&self, button: MButton) -> i32 {
let pairs = &self.bound_mouse;
let button_ = match button {
MButton::Left => "<Button1>",
MButton::Right => "<Button2>",
MButton::Middle => "<Button3>",
_ => return -1,
};
let mut counter = 0i32;
for pair in pairs.iter() {
if button_ == pair.0 {
return counter;
} else {
counter += 1
}
}
return -2;
}
fn increment(&mut self) {
self.counter += 1;
}
}
impl Canvas {
pub fn resize(&mut self, size: (u32, u32)) {
self.window.set_size(size);
}
pub fn get_size(&self) -> (u32, u32) {
let size = self.window.size();
return (size.x, size.y);
}
pub fn set_title(&mut self, name: String) {
self.window.set_title(&name);
self._name = name;
}
pub fn title(&self) -> String {
return self._name.clone();
}
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Color {
pub c: sfml::graphics::Color,
}
impl Color {
pub fn rgb(r: u8, g: u8, b: u8) -> Self {
Self {
c: sfml::graphics::Color::rgb(r, g, b),
}
}
pub fn rgba(r: u8, g: u8, b: u8, a: u8) -> Self {
Self {
c: sfml::graphics::Color::rgba(r, g, b, a),
}
}
pub(crate) fn from_sfml_color(c: sfml::graphics::Color) -> Self {
Self { c }
}
pub const BLACK: Self = Self {
c: sfml::graphics::Color::BLACK,
};
pub const WHITE: Self = Self {
c: sfml::graphics::Color::WHITE,
};
pub const RED: Self = Self {
c: sfml::graphics::Color::RED,
};
pub const GREEN: Self = Self {
c: sfml::graphics::Color::GREEN,
};
pub const BLUE: Self = Self {
c: sfml::graphics::Color::BLUE,
};
pub const YELLOW: Self = Self {
c: sfml::graphics::Color::YELLOW,
};
pub const MAGENTA: Self = Self {
c: sfml::graphics::Color::MAGENTA,
};
pub const CYAN: Self = Self {
c: sfml::graphics::Color::CYAN,
};
}
#[derive(Clone)]
pub struct Rectangle {
pub(crate) shape: RectangleShape<'static>,
}
impl Rectangle {
pub fn new(size: (f32, f32), position: (f32, f32), color: Color) -> Self {
let mut rect = RectangleShape::new();
let size = Vector2f::new(size.0, size.1);
let position = Vector2f::new(position.0, position.1);
rect.set_size(size);
rect.set_position(position);
rect.set_fill_color(color.c);
Self { shape: rect }
}
pub fn from_rect(rect: &Rectangle) -> Option<Self> {
Some(Self {
shape: rect.shape.clone(),
})
}
}
impl Rectangle {
pub fn set_fill_color(&mut self, color: Color) {
&self.shape.set_fill_color(color.c);
}
pub fn set_outline_color(&mut self, color: Color) {
&self.shape.set_outline_color(color.c);
}
pub fn set_outline_thickness(&mut self, size: f32) {
&self.shape.set_outline_thickness(size);
}
pub fn set_position(&mut self, position: (f32, f32)) {
&self
.shape
.set_position(Vector2f::new(position.0, position.1));
}
pub fn set_size(&mut self, size: (f32, f32)) {
&self.shape.set_size(Vector2f::new(size.0, size.1));
}
pub fn set_rotation(&mut self, angle: f32) {
&self.shape.set_rotation(360. - angle);
}
pub fn rotate(&mut self, angle: f32) {
&self.shape.rotate(angle);
}
pub fn set_origin(&mut self, position: (f32, f32)) {
&self.shape.set_origin(Vector2f::new(position.0, position.1));
}
pub fn get_fill_color(&self) -> Color {
let color = Color::from_sfml_color(self.shape.fill_color());
color
}
pub fn get_outline_color(&self) -> Color {
let color = Color::from_sfml_color(self.shape.outline_color());
color
}
pub fn get_outline_thickness(&self) -> f32 {
self.shape.outline_thickness()
}
pub fn get_size(&self) -> (f32, f32) {
let size = self.shape.size();
(size.x, size.y)
}
pub fn get_position(&self) -> (f32, f32) {
let position = self.shape.position();
(position.x, position.y)
}
pub fn get_rotation(&self) -> f32 {
let rotation = self.shape.rotation();
rotation
}
pub fn get_origin(&self) -> (f32, f32) {
let origin = self.shape.origin();
(origin.x, origin.y)
}
}
#[derive(Clone)]
pub struct Circle {
pub(crate) shape: CircleShape<'static>,
}
impl Circle {
pub fn new(position: (f32, f32), radius: f32, color: Color) -> Self {
let mut circle = CircleShape::new(radius, 100);
circle.set_position(Vector2f::new(position.0, position.1));
circle.set_fill_color(color.c);
Self { shape: circle }
}
pub fn from_circle(circle: &Circle) -> Self {
circle.clone()
}
}
impl Circle {
pub fn set_fill_color(&mut self, color: Color) {
&self.shape.set_fill_color(color.c);
}
pub fn set_outline_color(&mut self, color: Color) {
&self.shape.set_outline_color(color.c);
}
pub fn set_outline_thickness(&mut self, size: f32) {
&self.shape.set_outline_thickness(size);
}
pub fn set_radius(&mut self, radius: f32) {
&self.shape.set_radius(radius);
}
pub fn set_point_count(&mut self, pc: u32) {
&self.shape.set_point_count(pc);
}
pub fn set_origin(&mut self, origin: (f32, f32)) {
&self.shape.set_origin(Vector2f::new(origin.0, origin.1));
}
pub fn set_rotation(&mut self, angle: f32) {
&self.shape.set_rotation(angle);
}
pub fn rotate(&mut self, angle: f32) {
&self.shape.rotate(angle);
}
pub fn set_position(&mut self, position: (f32, f32)) {
&self
.shape
.set_position(Vector2f::new(position.0, position.1));
}
pub fn get_fill_color(&self) -> Color {
let color = Color::from_sfml_color(self.shape.fill_color());
color
}
pub fn get_outline_color(&self) -> Color {
let color = Color::from_sfml_color(self.shape.outline_color());
color
}
pub fn get_outline_thickness(&self) -> f32 {
self.shape.outline_thickness()
}
pub fn get_radius(&self) -> f32 {
let radius = self.shape.radius();
radius
}
pub fn get_position(&self) -> Option<(f32, f32)> {
let position = self.shape.position();
Some((position.x, position.y))
}
pub fn get_rotation(&self) -> f32 {
let rotation = self.shape.rotation();
rotation
}
pub fn get_origin(&self) -> (f32, f32) {
let origin = self.shape.origin();
(origin.x, origin.y)
}
pub fn get_point_count(&self) -> u32 {
let pc = self.shape.point_count();
pc
}
}
#[derive(Clone)]
pub struct Polygon {
pub(crate) shape: ConvexShape<'static>,
}
impl Polygon {
pub fn new(points: Vec<(f32, f32)>) -> Self {
let mut shape = ConvexShape::new(points.len() as u32);
let mut p_counter = 0u32;
for point in points.iter() {
let vec2f = Vector2f::new(point.0, point.1);
shape.set_point(p_counter, vec2f);
p_counter += 1;
}
Self { shape }
}
pub fn from_polygon(polygon: &Polygon) -> Self {
Self {
shape: polygon.shape.clone(),
}
}
}
impl Polygon {
pub fn set_fill_color(&mut self, color: Color) {
&self.shape.set_fill_color(color.c);
}
pub fn set_outline_color(&mut self, color: Color) {
&self.shape.set_outline_color(color.c);
}
pub fn set_outline_thickness(&mut self, size: f32) {
&self.shape.set_outline_thickness(size);
}
pub fn set_point_count(&mut self, pc: u32) {
&self.shape.set_point_count(pc);
}
pub fn set_origin(&mut self, origin: (f32, f32)) {
&self.shape.set_origin(Vector2f::new(origin.0, origin.1));
}
pub fn set_rotation(&mut self, angle: f32) {
&self.shape.set_rotation(angle);
}
pub fn rotate(&mut self, angle: f32) {
&self.shape.rotate(angle);
}
pub fn set_position(&mut self, position: (f32, f32)) {
&self
.shape
.set_position(Vector2f::new(position.0, position.1));
}
pub fn get_fill_color(&self) -> Color {
let color = Color::from_sfml_color(self.shape.fill_color());
color
}
pub fn get_outline_color(&self) -> Color {
let color = Color::from_sfml_color(self.shape.outline_color());
color
}
pub fn get_outline_thickness(&self) -> f32 {
self.shape.outline_thickness()
}
pub fn get_position(&self) -> (f32, f32) {
let position = self.shape.position();
(position.x, position.y)
}
pub fn get_rotation(&self) -> f32 {
let rotation = self.shape.rotation();
rotation
}
pub fn get_origin(&self) -> (f32, f32) {
let origin = self.shape.origin();
(origin.x, origin.y)
}
pub fn get_point_count(&self) -> u32 {
let pc = self.shape.point_count();
pc
}
}
#[derive(Clone)]
pub struct Line {
pub(crate) shape: RectangleShape<'static>,
}
impl Line {
pub fn new(point_a: (f32, f32), point_b: (f32, f32), thickness: f32, color: Color) -> Self {
let mut ret = RectangleShape::new();
let size = Vector2f::new(thickness, point_b.1 - point_a.1);
let position = Vector2f::new(point_a.0, point_a.1);
let angle = 360. - (size.x.powi(2) + size.y.powi(2)).sqrt();
ret.set_rotation(angle);
ret.set_position(position);
ret.set_size(size);
ret.set_fill_color(color.c);
Self { shape: ret }
}
pub fn from_line(line: &Line) -> Self {
Self {
shape: line.shape.clone(),
}
}
}
impl Line {
pub fn set_thickness(&mut self, thickness: f32) {
let size = self.shape.size();
self.shape.set_size(Vector2f::new(thickness, size.y));
}
pub fn set_fill_color(&mut self, color: Color) {
self.shape.set_fill_color(color.c);
}
pub fn set_outline_color(&mut self, color: Color) {
self.shape.set_outline_color(color.c);
}
pub fn set_outline_thickness(&mut self, thickness: f32) {
self.shape.set_outline_thickness(thickness);
}
pub fn get_fill_color(&self) -> Color {
let color = Color::from_sfml_color(self.shape.fill_color());
color
}
pub fn get_outline_color(&self) -> Color {
let color = Color::from_sfml_color(self.shape.outline_color());
color
}
pub fn get_outline_thickness(&self) -> f32 {
self.shape.outline_thickness()
}
pub fn get_thickness(&self) -> f32 {
let vec = self.shape.size();
vec.x
}
}
#[derive(Clone)]
pub struct Text {
content: String,
text_size: u32,
fill_color: Color,
outline_color: Option<Color>,
font_file: Option<FontHandler>,
position: (f32, f32),
}
impl Text {
pub fn new(content: &str, text_size: u32, fill_color: Color, position: (f32, f32)) -> Self {
let c = String::from(content);
Self {
content: c,
text_size,
fill_color,
outline_color: None,
font_file: None,
position,
}
}
}
impl Text {
pub fn get_contents(&self) -> String {
return self.content.clone();
}
pub fn get_size(&self) -> u32 {
let ret = &self.text_size;
*ret
}
pub fn get_fill_color(&self) -> Color {
self.fill_color
}
pub fn get_font(&self) -> Option<String> {
match &self.font_file {
Some(handler) => return Some(handler.get()),
None => None,
}
}
pub fn get_position(&self) -> (f32, f32) {
return self.position;
}
pub fn set_content(&mut self, content: String) {
self.content = content;
}
pub fn set_size(&mut self, size: u32) {
self.text_size = size;
}
pub fn set_fill_color(&mut self, color: Color) {
self.fill_color = color;
}
pub fn set_font(&mut self, font: String) -> Result<(), Error> {
if let Some(handler) = FontHandler::find_fonts(font) {
self.font_file = Some(handler);
Ok(())
} else {
return Err(Error::GeneralError("Font file not found!".to_string()));
}
}
pub fn set_position(&mut self, pos: (f32, f32)) {
self.position = pos;
}
}
#[derive(Clone, Copy, PartialEq)]
enum ButtonStyle {
Rectangle(),
Circle(),
}
#[derive(Clone)]
pub struct Button {
text: Text,
position: (f32, f32),
size: (f32, f32),
func: Option<fn(&mut Canvas, (f32, f32)) -> ()>,
style: ButtonStyle,
fill_color: Option<Color>,
outline_color: Option<Color>,
outline_thickness: Option<f32>,
}
impl Button {
pub fn from_text(mut text: Text, position: (f32, f32), size: (f32, f32)) -> Self {
text.set_size(size.1 as u32 - size.1 as u32 / 2. as u32);
text.set_position((position.0 + size.0 / 4., position.1 + size.1 / 5.));
Self {
text,
position,
size,
func: None,
style: ButtonStyle::Rectangle(),
fill_color: None,
outline_color: None,
outline_thickness: None,
}
}
pub fn new(content: &str, position: (f32, f32), size: (f32, f32)) -> Self {
Self {
text: Text::new(
content,
size.1 as u32 - size.1 as u32 / 2,
Color::WHITE,
(position.0 + size.0 / 4., position.1 + size.1 / 5.),
),
position,
size,
func: None,
style: ButtonStyle::Rectangle(),
fill_color: None,
outline_color: None,
outline_thickness: None,
}
}
}
impl Button {
pub fn bind(&mut self, f: fn(&mut Canvas, (f32, f32)) -> ()) {
self.func = Some(f);
}
pub fn set_style(&mut self, style: &str) -> Result<(), Error> {
match style {
"rectangle" => self.style = ButtonStyle::Rectangle(),
"circle" => self.style = ButtonStyle::Circle(),
_ => return Err(Error::GeneralError(format!("{} not a style!", style))),
}
Ok(())
}
pub fn is_bound(&self) -> bool {
if self.func.is_some() {
return true;
} else {
return false;
}
}
pub fn set_fill_color(&mut self, color: Color) {
self.fill_color = Some(color);
}
pub fn set_outline_color(&mut self, color: Color) {
self.outline_color = Some(color);
}
pub fn set_outline_thickness(&mut self, size: f32) {
self.outline_thickness = Some(size);
}
pub fn get_fill_color(&self) -> Option<Color> {
match self.fill_color {
Some(c) => return Some(c),
None => return None,
}
}
pub fn get_outline_color(&self) -> Option<Color> {
match self.outline_color {
Some(c) => return Some(c),
None => return None,
}
}
pub fn get_outline_thickness(&self) -> f32 {
self.outline_thickness.unwrap_or(0f32)
}
pub fn set_size(&mut self, size: (f32, f32)) {
self.size = size;
}
pub fn get_size(&self) -> (f32, f32) {
self.size
}
pub fn set_position(&mut self, pos: (f32, f32)) {
self.position = pos;
self.text.set_position((
pos.0 - self.text.get_size() as f32,
pos.1 - self.text.get_size() as f32,
));
}
pub fn get_position(&self) -> (f32, f32) {
self.position
}
pub fn get_text_color(&self) -> Color {
self.text.get_fill_color()
}
pub fn set_text_color(&mut self, c: Color) {
self.text.set_fill_color(c);
}
}
pub struct Arc {
pub(crate) point_count: u32,
pub(crate) shape: ConvexShape<'static>,
}