Skip to content

Commit

Permalink
feat: more validation and icons
Browse files Browse the repository at this point in the history
  • Loading branch information
GenericConfluent committed Mar 4, 2024
1 parent a8dd5c1 commit fb2bdc3
Show file tree
Hide file tree
Showing 5 changed files with 109 additions and 48 deletions.
Binary file added fonts/icons.ttf
Binary file not shown.
30 changes: 21 additions & 9 deletions src/course_database.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,25 @@ impl FromStr for CourseId {
.split_whitespace()
.filter(|string| !string.trim_start().is_empty());

let subject_id = pieces
.next()
.ok_or(anyhow!("Could not find a subject id"))?
.to_uppercase()
.to_string();
let class_id = pieces
.next()
.ok_or(anyhow!("Could not find the class id"))?
.parse()?;

if class_id < 100 || 1000 <= class_id {

Check failure on line 54 in src/course_database.rs

View workflow job for this annotation

GitHub Actions / lint

manual `!Range::contains` implementation
return Err(anyhow!(
"Class id must be a number, at least 100 and less than 1000"
));
}

Ok(CourseId {
subject_id: pieces
.next()
.ok_or(anyhow!("Could not find a subject id"))?
.to_string(),
class_id: pieces
.next()
.ok_or(anyhow!("Could not find the class id"))?
.parse()?,
subject_id,
class_id,
})
}
}
Expand All @@ -60,7 +70,7 @@ impl std::fmt::Display for CourseId {
}
}

#[derive(Deserialize, Clone)]
#[derive(Deserialize, Clone, Debug)]
pub struct Course {
pub id: CourseId,
pub name: String,
Expand All @@ -83,6 +93,7 @@ impl Course {
}
}

#[derive(Debug)]
pub enum DatabaseNode {
Course(Course),
Or,
Expand Down Expand Up @@ -115,6 +126,7 @@ impl fmt::Display for DatabaseNode {

/// Abstraction over some way to retrieve course info for simplicity.
/// There must only be one entry for each course.
#[derive(Debug)]
pub struct CourseDatabase {
pub courses: DiGraph<DatabaseNode, Relation>,
}
Expand Down
37 changes: 37 additions & 0 deletions src/icons.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
use iced::alignment;
use iced::font::Font;
use iced::widget::{text, Text};

/// See https://fonts.google.com/icons. Just find some online icon font editor
/// to modify the ttf file.
pub enum Icon {
AccountTree,
FullStackedBarChart,
SideNavigation,
DragIndicator,
Settings,
DeleteForever,
}

impl Icon {
pub fn bytes() -> &'static [u8] {
include_bytes!("../fonts/icons.ttf").as_slice()
}
}

impl Into<Text<'static>> for Icon {

Check failure on line 22 in src/icons.rs

View workflow job for this annotation

GitHub Actions / lint

an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true
fn into(self) -> Text<'static> {
let ch = match self {
Icon::AccountTree => "A",
Icon::FullStackedBarChart => "B",
Icon::SideNavigation => "C",
Icon::DragIndicator => "D",
Icon::Settings => "E",
Icon::DeleteForever => "F",
};
text(ch)
.font(Font::with_name("icons"))
.width(20)
.horizontal_alignment(alignment::Horizontal::Center)
}
}
81 changes: 50 additions & 31 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,22 @@
#![allow(dead_code, unused_variables)]

use std::rc::Rc;

Check failure on line 3 in src/lib.rs

View workflow job for this annotation

GitHub Actions / test

unused import: `std::rc::Rc`

Check failure on line 3 in src/lib.rs

View workflow job for this annotation

GitHub Actions / lint

unused import: `std::rc::Rc`
use std::sync::Arc;

use iced::alignment::Horizontal;
use iced::theme::Palette;

Check failure on line 7 in src/lib.rs

View workflow job for this annotation

GitHub Actions / test

unused import: `iced::theme::Palette`

Check failure on line 7 in src/lib.rs

View workflow job for this annotation

GitHub Actions / lint

unused import: `iced::theme::Palette`
use iced::widget::{button, column, container, horizontal_rule, row, text, text_input};
use iced::{executor, Application, Color, Command, Element, Length, Theme};
use iced::widget::{button, column, container, horizontal_rule, row, text, text_input, Text};
use iced::{executor, font, Application, Color, Command, Element, Length, Padding, Theme};

Check failure on line 9 in src/lib.rs

View workflow job for this annotation

GitHub Actions / test

unused import: `Padding`

Check failure on line 9 in src/lib.rs

View workflow job for this annotation

GitHub Actions / lint

unused import: `Padding`

use iced_aw::native::Split;
use iced_aw::{modal, split, Card};
use iced_aw::{modal, split, Card, BOOTSTRAP_FONT_BYTES};

Check failure on line 12 in src/lib.rs

View workflow job for this annotation

GitHub Actions / test

unused import: `BOOTSTRAP_FONT_BYTES`

Check failure on line 12 in src/lib.rs

View workflow job for this annotation

GitHub Actions / lint

unused import: `BOOTSTRAP_FONT_BYTES`

mod course_database;
use course_database::{CourseDatabase, CourseId};
use icons::Icon;

mod graph_widget;
mod icons;

#[derive(Default)]
pub struct FinescaleApp {
Expand All @@ -26,22 +32,18 @@ struct UiStates {
course_input_val: String,
}

#[derive(Default, Debug, Clone)]
pub struct CourseGraph;

#[derive(Debug, Clone)]
pub enum Message {
LoadedCourses(CourseGraph),
LoadedCourses(Arc<anyhow::Result<CourseDatabase>>),
MainDividerResize(u16),
CourseInputEvent(String),
CourseInputSubmit,
IconsLoaded(Result<(), font::Error>),
ClearError,
}

async fn load_courses<P: AsRef<std::path::Path>>(path: P) -> CourseGraph {
//let reader = std::fs::File::open(path).unwrap();
//let _json: serde_json::Value = serde_json::from_reader(reader).unwrap();
CourseGraph
async fn load_courses<P: AsRef<std::path::Path>>(path: P) -> Arc<anyhow::Result<CourseDatabase>> {
CourseDatabase::new("[]").into()
}

impl Application for FinescaleApp {
Expand All @@ -53,7 +55,10 @@ impl Application for FinescaleApp {
fn new(_: Self::Flags) -> (Self, Command<Self::Message>) {
(
FinescaleApp::default(),
Command::perform(load_courses("data/courses.json"), Message::LoadedCourses),
Command::batch([
Command::perform(load_courses("data/courses.ron"), Message::LoadedCourses),
iced::font::load(icons::Icon::bytes()).map(Message::IconsLoaded),
]),
)
}

Expand All @@ -63,7 +68,6 @@ impl Application for FinescaleApp {

fn update(&mut self, _message: Self::Message) -> Command<Self::Message> {
match _message {
Message::LoadedCourses(_) => {}
Message::ClearError => self.ui_states.error_modal = None,
// TODO: Limit the divider movement
Message::MainDividerResize(amt) => self.ui_states.main_divider_pos = Some(amt),
Expand All @@ -79,23 +83,45 @@ impl Application for FinescaleApp {
}
}
}
_ => {}
}

Command::none()
}

fn view(&self) -> Element<Self::Message> {
let mut left = column![
text("Desired Classes"),
text("Desired Classes")
.width(Length::Fill)
.size(40)
.style(Color::from_rgb(0.5, 0.5, 0.5))
.horizontal_alignment(Horizontal::Center),
text_input("Start typing!", &self.ui_states.course_input_val)
.padding(15)
.on_input(Message::CourseInputEvent)
.on_submit(Message::CourseInputSubmit),
]
.spacing(10);

let mut right = column![
row![text("Required Classes")
.width(Length::Fill)
.size(40)
.style(Color::from_rgb(0.5, 0.5, 0.5))
.horizontal_alignment(iced::alignment::Horizontal::Left),],
horizontal_rule(2)
];
let mut right = column![row![text("Required Classes"),], horizontal_rule(2)];

for course in self.desired_courses.iter() {
left = left.push(
row![
text(course).width(Length::Fill),
button(Into::<Text>::into(Icon::DeleteForever)).padding(10)
]
.spacing(20)
.align_items(iced::Alignment::Center),
);
right = right.push(text(course));
left = left.push(text(course));
}

// Todo read and push courses.
Expand All @@ -108,26 +134,19 @@ impl Application for FinescaleApp {
);

let overlay = self.ui_states.error_modal.as_ref().map(|err_msg| {
Card::new(text("Error"), text(err_msg)).foot(
container(button("Ok").on_press(Message::ClearError))
.width(Length::Fill)
.align_x(iced::alignment::Horizontal::Right),
)
Card::new(text("Error"), text(err_msg))
.foot(
container(button("Ok").on_press(Message::ClearError))
.width(Length::Fill)
.align_x(iced::alignment::Horizontal::Right),
)
.max_width(250.0)
});

modal(main_content, overlay).into()
}

fn theme(&self) -> Self::Theme {
Theme::custom(
"apptheme".to_string(),
Palette {
background: Color::from_rgba8(14, 14, 14, 0.1),
text: Color::WHITE,
primary: Color::WHITE,
success: Color::WHITE,
danger: Color::WHITE,
},
)
iced::Theme::Light
}
}
9 changes: 1 addition & 8 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,11 @@ fn main() -> iced::Result {
id: Some("finescale".into()),
window: window::Settings {
size: iced::Size::new(800.0, 400.0),
position: window::Position::Centered,
visible: true,
decorations: false,
transparent: true,
decorations: true,
..Default::default()
},
antialiasing: true,
..Default::default()
})
// let reader = std::fs::File::open("data/courses.json").unwrap();
// let _json: serde_json::Value = serde_json::from_reader(reader).unwrap();
// let mut graph = Graph::<&str, &str>::new();

// Ok(())
}

0 comments on commit fb2bdc3

Please sign in to comment.