diff options
author | rhin123 <ryanrhin@gmail.com> | 2020-03-10 16:41:48 -0500 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2020-03-18 08:17:01 +0100 |
commit | 39c21f368a14f1df81b858b3a1ca8907d68a0616 (patch) | |
tree | 57e311a261b171b5a0e11ec1cb0d066956832cbb | |
parent | 08a30a49617956c63d62e8196c3c574a2317f7c8 (diff) | |
download | serenity-39c21f368a14f1df81b858b3a1ca8907d68a0616.zip |
Calendar: Implement basic GUI calendar application
-rw-r--r-- | Applications/Calendar/AddEventDialog.cpp | 56 | ||||
-rw-r--r-- | Applications/Calendar/AddEventDialog.h | 22 | ||||
-rw-r--r-- | Applications/Calendar/Calendar.cpp | 34 | ||||
-rw-r--r-- | Applications/Calendar/Calendar.h | 23 | ||||
-rw-r--r-- | Applications/Calendar/CalendarWidget.cpp | 177 | ||||
-rw-r--r-- | Applications/Calendar/CalendarWidget.h | 46 | ||||
-rw-r--r-- | Applications/Calendar/Makefile | 12 | ||||
-rw-r--r-- | Applications/Calendar/main.cpp | 54 | ||||
-rwxr-xr-x | Kernel/build-root-filesystem.sh | 2 |
9 files changed, 426 insertions, 0 deletions
diff --git a/Applications/Calendar/AddEventDialog.cpp b/Applications/Calendar/AddEventDialog.cpp new file mode 100644 index 0000000000..6d1d8b9800 --- /dev/null +++ b/Applications/Calendar/AddEventDialog.cpp @@ -0,0 +1,56 @@ +#include "AddEventDialog.h" +#include <LibCore/DateTime.h> +#include <LibGUI/BoxLayout.h> +#include <LibGUI/Button.h> +#include <LibGUI/Label.h> +#include <LibGUI/Layout.h> +#include <LibGUI/Painter.h> +#include <LibGUI/Widget.h> +#include <LibGUI/Window.h> +#include <LibGfx/Color.h> +#include <LibGfx/Font.h> + +AddEventDialog::AddEventDialog(Calendar* calendar, Window* parent_window) + : Dialog(parent_window) + , m_calendar(calendar) +{ + resize(230, 120); + set_title("Add Event"); + set_resizable(false); + + auto& widget = set_main_widget<GUI::Widget>(); + widget.set_fill_with_background_color(true); + widget.set_layout<GUI::HorizontalBoxLayout>(); + + auto& main_container = widget.add<GUI::Widget>(); + main_container.set_layout<GUI::VerticalBoxLayout>(); + main_container.layout()->set_margins({ 4, 4, 4, 4 }); + + auto make_label = [&](const StringView& text, bool bold = false) { + auto& label = main_container.add<GUI::Label>(text); + label.set_text_alignment(Gfx::TextAlignment::CenterLeft); + label.set_size_policy(GUI::SizePolicy::Fill, GUI::SizePolicy::Fixed); + label.set_preferred_size(0, 14); + if (bold) + label.set_font(Gfx::Font::default_bold_font()); + }; + make_label("TODO: Implement add event dialog", true); + + main_container.layout()->add_spacer(); + + auto& button_container = main_container.add<GUI::Widget>(); + button_container.set_size_policy(GUI::SizePolicy::Fill, GUI::SizePolicy::Fixed); + button_container.set_preferred_size(0, 20); + button_container.set_layout<GUI::HorizontalBoxLayout>(); + button_container.layout()->add_spacer(); + auto& ok_button = button_container.add<GUI::Button>("OK"); + ok_button.set_size_policy(GUI::SizePolicy::Fixed, GUI::SizePolicy::Fixed); + ok_button.set_preferred_size(80, 20); + ok_button.on_click = [this] { + done(Dialog::ExecOK); + }; +} + +AddEventDialog::~AddEventDialog() +{ +} diff --git a/Applications/Calendar/AddEventDialog.h b/Applications/Calendar/AddEventDialog.h new file mode 100644 index 0000000000..5e0883b46d --- /dev/null +++ b/Applications/Calendar/AddEventDialog.h @@ -0,0 +1,22 @@ +#pragma once + +#include "Calendar.h" +#include <LibGUI/Dialog.h> +#include <LibGUI/Window.h> + +class AddEventDialog final : public GUI::Dialog { + C_OBJECT(AddEventDialog) +public: + virtual ~AddEventDialog() override; + + static void show(Calendar* calendar, Window* parent_window = nullptr) + { + auto dialog = AddEventDialog::construct(calendar, parent_window); + dialog->exec(); + } + +private: + AddEventDialog(Calendar* calendar, Window* parent_window = nullptr); + + Calendar* m_calendar; +}; diff --git a/Applications/Calendar/Calendar.cpp b/Applications/Calendar/Calendar.cpp new file mode 100644 index 0000000000..7f731c7443 --- /dev/null +++ b/Applications/Calendar/Calendar.cpp @@ -0,0 +1,34 @@ +#include "Calendar.h" + +const String name_of_month(int month) +{ + const String month_names[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; + return month_names[month - 1]; +} + +Calendar::Calendar(Core::DateTime date_time) + : m_date_time(date_time) + , m_selected_year(date_time.year()) + , m_selected_month(date_time.month()) +{ +} + +Calendar::~Calendar() +{ +} + +const String Calendar::selected_date_text() +{ + return String::format("%s %d", name_of_month(m_selected_month).characters(), m_selected_year); +} + +void Calendar::set_selected_date(int year, int month) +{ + m_selected_year = year; + m_selected_month = month; +} + +bool Calendar::is_today(Core::DateTime date_time) const +{ + return date_time.day() == m_date_time.day() && date_time.month() == m_date_time.month() && date_time.year() == m_date_time.year(); +} diff --git a/Applications/Calendar/Calendar.h b/Applications/Calendar/Calendar.h new file mode 100644 index 0000000000..6ec5d84a1d --- /dev/null +++ b/Applications/Calendar/Calendar.h @@ -0,0 +1,23 @@ +#pragma once + +#include <AK/String.h> +#include <LibCore/DateTime.h> + +const String name_of_month(int month); + +class Calendar final { +public: + Calendar(Core::DateTime date_time); + ~Calendar(); + + const String selected_date_text(); + void set_selected_date(int year, int month); + int selected_year() const { return m_selected_year; } + int selected_month() const { return m_selected_month; } + bool is_today(Core::DateTime date_time) const; + +private: + Core::DateTime m_date_time; + int m_selected_year { 0 }; + int m_selected_month { 0 }; +}; diff --git a/Applications/Calendar/CalendarWidget.cpp b/Applications/Calendar/CalendarWidget.cpp new file mode 100644 index 0000000000..821c0551dd --- /dev/null +++ b/Applications/Calendar/CalendarWidget.cpp @@ -0,0 +1,177 @@ +#include "CalendarWidget.h" +#include "AddEventDialog.h" +#include "Calendar.h" +#include <LibCore/DateTime.h> +#include <LibGUI/BoxLayout.h> +#include <LibGUI/Button.h> +#include <LibGUI/Painter.h> +#include <LibGUI/Window.h> +#include <LibGfx/Font.h> + +CalendarWidget::CalendarWidget() +{ + set_fill_with_background_color(true); + m_calendar = make<Calendar>(Core::DateTime::now()); + + m_selected_date_label = add<GUI::Label>(); + m_selected_date_label->set_relative_rect(20, 13, 100, 25); + m_selected_date_label->set_text_alignment(Gfx::TextAlignment::CenterLeft); + m_selected_date_label->set_font(Gfx::Font::default_bold_font()); + m_selected_date_label->set_text(m_calendar->selected_date_text()); + + m_prev_month_button = add<GUI::Button>(); + m_prev_month_button->set_text("<"); + m_prev_month_button->set_font(Gfx::Font::default_bold_font()); + m_prev_month_button->set_relative_rect(90, 5, 40, 40); + m_prev_month_button->on_click = [this] { + int m_target_month = m_calendar->selected_month() - 1; + int m_target_year = m_calendar->selected_year(); + + if (m_calendar->selected_month() <= 1) { + m_target_month = 12; + m_target_year--; + } + update_calendar_tiles(m_target_year, m_target_month); + }; + + m_next_month_button = add<GUI::Button>(); + m_next_month_button->set_text(">"); + m_next_month_button->set_font(Gfx::Font::default_bold_font()); + m_next_month_button->set_relative_rect(131, 5, 40, 40); + m_next_month_button->on_click = [this] { + int m_target_month = m_calendar->selected_month() + 1; + int m_target_year = m_calendar->selected_year(); + + if (m_calendar->selected_month() >= 12) { + m_target_month = 1; + m_target_year++; + } + update_calendar_tiles(m_target_year, m_target_month); + }; + + m_prev_month_button = add<GUI::Button>(); + m_prev_month_button->set_text("Add Event"); + m_prev_month_button->set_relative_rect(475, 13, 100, 25); + m_prev_month_button->on_click = [this] { + AddEventDialog::show(m_calendar, window()); + }; + + update_calendar_tiles(m_calendar->selected_year(), m_calendar->selected_month()); +} + +CalendarWidget::~CalendarWidget() +{ +} + +void CalendarWidget::update_calendar_tiles(int target_year, int target_month) +{ + unsigned int i = 0; + //TODO: Modify m_tile_height if the end of the month doesn't fit onto the current tile array + for (int y = 0; y < 5; y++) + for (int x = 0; x < 7; x++) { + auto date_time = Core::DateTime::create(target_year, target_month, 1); + int x_offset = x * m_tile_width; + int y_offset = (y * m_tile_height) + 50; + + unsigned int start_of_month = date_time.weekday(); + unsigned int year; + unsigned int month; + unsigned int day; + + if (start_of_month > i) { + month = (target_month - 1 == 0) ? 12 : target_month - 1; + year = (month == 12) ? target_year - 1 : target_year; + date_time.set_time(year, month, 1); + day = (date_time.days_in_month() - (start_of_month) + i) + 1; + date_time.set_time(year, month, day); + + } else if ((i - start_of_month) + 1 > date_time.days_in_month()) { + month = (target_month + 1) > 12 ? 1 : target_month + 1; + year = (month == 1) ? target_year + 1 : target_year; + day = ((i - start_of_month) + 1) - date_time.days_in_month(); + date_time.set_time(year, month, day); + } else { + month = target_month; + year = target_year; + day = (i - start_of_month) + 1; + date_time.set_time(year, month, day); + } + + if (!m_calendar_tiles[i]) { + m_calendar_tiles[i] = add<CalendarTile>(*m_calendar, i, date_time); + m_calendar_tiles[i]->set_frame_thickness(0); + m_calendar_tiles[i]->set_relative_rect(x_offset, y_offset, 85, 85); + } else { + m_calendar_tiles[i]->update_values(*m_calendar, i, date_time); + m_calendar_tiles[i]->update(); + } + i++; + } + + m_calendar->set_selected_date(target_year, target_month); + m_selected_date_label->set_text(m_calendar->selected_date_text()); +} + +CalendarWidget::CalendarTile::CalendarTile(Calendar& calendar, int index, Core::DateTime date_time) + : m_index(index) + , m_date_time(date_time) + , m_calendar(calendar) +{ + update_values(calendar, index, date_time); +} + +void CalendarWidget::CalendarTile::update_values(Calendar& calendar, int index, Core::DateTime date_time) +{ + m_calendar = calendar; + m_index = index; + m_date_time = date_time; + m_display_weekday_name = index < 7; + + if (m_display_weekday_name) { + const String m_day_names[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; + m_weekday_name = m_day_names[index]; + } + + m_display_date = (m_date_time.day() == 1) ? String::format("%s %d", name_of_month(m_date_time.month()).characters(), m_date_time.day()) : String::number(m_date_time.day()); +} + +CalendarWidget::CalendarTile::~CalendarTile() +{ +} + +void CalendarWidget::CalendarTile::paint_event(GUI::PaintEvent& event) +{ + GUI::Frame::paint_event(event); + + GUI::Painter painter(*this); + painter.fill_rect(frame_inner_rect(), Color::NamedColor::White); + + painter.draw_line(frame_inner_rect().top_right(), frame_inner_rect().bottom_right(), Color::NamedColor::Black); + if (m_index == 0 || m_index % 7 == 0) + painter.draw_line(frame_inner_rect().top_left(), frame_inner_rect().bottom_left(), Color::NamedColor::Black); + + if (m_index < 7) + painter.draw_line(frame_inner_rect().top_left(), frame_inner_rect().top_right(), Color::NamedColor::Black); + painter.draw_line(frame_inner_rect().bottom_left(), frame_inner_rect().bottom_right(), Color::NamedColor::Black); + + Gfx::Rect day_rect; + + if (m_display_weekday_name) { + auto weekday_rect = frame_inner_rect().shrunken(0, frame_inner_rect().height() / 1.2); + weekday_rect.set_top(frame_inner_rect().y() + 2); + painter.draw_text(weekday_rect, m_weekday_name, Gfx::Font::default_bold_font(), Gfx::TextAlignment::Center, Color::Black); + + day_rect = frame_inner_rect().shrunken(0, frame_inner_rect().height() / 1.2); + day_rect.set_top(frame_inner_rect().y() + 15); + } else { + day_rect = frame_inner_rect().shrunken(0, frame_inner_rect().height() / 1.2); + day_rect.set_top(frame_inner_rect().y() + 4); + } + + if (m_calendar.is_today(m_date_time)) { + auto highlight_rect = day_rect.shrunken(day_rect.width() - (font().glyph_width('x') * (m_display_date.length() + 1)) - 4, 0); + painter.draw_rect(highlight_rect, Color::NamedColor::Blue); + painter.draw_text(day_rect, m_display_date, Gfx::Font::default_bold_font(), Gfx::TextAlignment::Center, Color::Black); + } else + painter.draw_text(day_rect, m_display_date, Gfx::TextAlignment::Center, Color::Black); +} diff --git a/Applications/Calendar/CalendarWidget.h b/Applications/Calendar/CalendarWidget.h new file mode 100644 index 0000000000..5dd60a0f53 --- /dev/null +++ b/Applications/Calendar/CalendarWidget.h @@ -0,0 +1,46 @@ +#pragma once + +#include "Calendar.h" +#include <LibGUI/Frame.h> +#include <LibGUI/Label.h> +#include <LibGUI/Widget.h> + +class CalendarWidget final : public GUI::Widget { + C_OBJECT(CalendarWidget) + +public: + CalendarWidget(); + virtual ~CalendarWidget() override; + +private: + void update_calendar_tiles(int target_year, int target_month); + void show_add_event_window(Calendar* calendar); + + OwnPtr<Calendar> m_calendar; + RefPtr<GUI::Label> m_selected_date_label; + RefPtr<GUI::Button> m_prev_month_button; + RefPtr<GUI::Button> m_next_month_button; + + class CalendarTile final : public GUI::Frame { + C_OBJECT(CalendarTile) + public: + CalendarTile(Calendar& calendar, int index, Core::DateTime m_date_time); + void update_values(Calendar& calendar, int index, Core::DateTime date_time); + virtual ~CalendarTile() override; + + private: + virtual void paint_event(GUI::PaintEvent&) override; + + int m_index { 0 }; + bool m_display_weekday_name { false }; + + String m_weekday_name; + String m_display_date; + Core::DateTime m_date_time; + Calendar& m_calendar; + }; + + RefPtr<CalendarTile> m_calendar_tiles[35]; + int m_tile_width { 85 }; + int m_tile_height { 85 }; +}; diff --git a/Applications/Calendar/Makefile b/Applications/Calendar/Makefile new file mode 100644 index 0000000000..9e8444cb37 --- /dev/null +++ b/Applications/Calendar/Makefile @@ -0,0 +1,12 @@ +OBJS = \ + Calendar.o \ + CalendarWidget.o \ + AddEventDialog.o \ + main.o + +PROGRAM = Calendar + +LIB_DEPS = GUI Gfx IPC Core + +include ../../Makefile.common + diff --git a/Applications/Calendar/main.cpp b/Applications/Calendar/main.cpp new file mode 100644 index 0000000000..c7fbc43187 --- /dev/null +++ b/Applications/Calendar/main.cpp @@ -0,0 +1,54 @@ +#include "CalendarWidget.h" +#include <LibGUI/AboutDialog.h> +#include <LibGUI/Action.h> +#include <LibGUI/Application.h> +#include <LibGUI/Menu.h> +#include <LibGUI/MenuBar.h> +#include <LibGUI/Window.h> +#include <LibGfx/Bitmap.h> +#include <stdio.h> + +int main(int argc, char** argv) +{ + + if (pledge("stdio shared_buffer rpath accept unix cpath fattr", nullptr) < 0) { + perror("pledge"); + return 1; + } + + GUI::Application app(argc, argv); + + if (pledge("stdio shared_buffer rpath accept", nullptr) < 0) { + perror("pledge"); + return 1; + } + + if (unveil("/res", "r") < 0) { + perror("unveil"); + return 1; + } + + unveil(nullptr, nullptr); + + auto window = GUI::Window::construct(); + window->set_title("Calendar"); + window->set_rect(20, 200, 596, 476); + //TODO: Allow proper resize + window->set_resizable(false); + + window->set_main_widget<CalendarWidget>(); + + window->show(); + + auto menubar = make<GUI::MenuBar>(); + + auto app_menu = GUI::Menu::construct("Calendar"); + app_menu->add_action(GUI::CommonActions::make_quit_action([](auto&) { + GUI::Application::the().quit(0); + return; + })); + menubar->add_menu(move(app_menu)); + app.set_menubar(move(menubar)); + + app.exec(); +} diff --git a/Kernel/build-root-filesystem.sh b/Kernel/build-root-filesystem.sh index 695b44d4c0..21c0f52ebb 100755 --- a/Kernel/build-root-filesystem.sh +++ b/Kernel/build-root-filesystem.sh @@ -135,6 +135,7 @@ cp ../Applications/Piano/Piano mnt/bin/Piano cp ../Applications/SystemMenu/SystemMenu mnt/bin/SystemMenu cp ../Applications/ChanViewer/ChanViewer mnt/bin/ChanViewer cp ../Applications/Calculator/Calculator mnt/bin/Calculator +cp ../Applications/Calendar/Calendar mnt/bin/Calendar cp ../Applications/SoundPlayer/SoundPlayer mnt/bin/SoundPlayer cp ../Applications/DisplayProperties/DisplayProperties mnt/bin/DisplayProperties cp ../Applications/Welcome/Welcome mnt/bin/Welcome @@ -189,6 +190,7 @@ ln -s Piano mnt/bin/pi ln -s SystemDialog mnt/bin/sd ln -s ChanViewer mnt/bin/cv ln -s Calculator mnt/bin/calc +ln -s Calendar mnt/bin/calendar ln -s Inspector mnt/bin/ins ln -s SoundPlayer mnt/bin/sp ln -s Help mnt/bin/help |