Luny
Back

Console Moodle

A terminal-based UI app to recreate a course-management system with cross-platform support with ncurses and CMake.

Published on
Updated on

2.885

cmake
cpp
ncurses

Description

A terminal-based UI application as a final project for the course of Programming Techniques to recreate Moodle, a course-management system, utilizing cross-platform libraries like ncurses and universal build tools like CMake.

My Role

This was partly my fault, but no one in the group was willing to learn the ins and outs of ncurses, and wanted to rely on std::cout and std::cin to provide a terminal-based experience, which wouldn’t be as impressive as I wanted it to be.

My main role is to provide a Terminal UI from ncurses function calls, and use others’ implemented features (usually pure functions, data structures with no side effects).

Technical Feats

Abstraction over ncurses layer with a more centralized method to render strings on the screen better.

  void draw_date_dialog(Date &date, WINDOW *window, DateTimeScreenData *data)
  {
      box(window, 0, 0);
      renderer::draw_row(window, 2, true);

      wattron(window, A_BOLD);
      renderer::print_aligned(data->title).aligned(align::top | align::center).offset(1, 0).color(4).on(window).apply();
      renderer::print_aligned("Day").aligned(align::top | align::left).offset(3, 1).on(window).apply();
      renderer::print_aligned("Month").aligned(align::top | align::left).offset(5, 1).on(window).apply();
      renderer::print_aligned("Year").aligned(align::top | align::left).offset(7, 1).on(window).apply();
      renderer::print_aligned("Save").aligned(align::bottom | align::center).offset(-2, 0).on(window).apply();
      renderer::print_aligned("Cancel").aligned(align::bottom | align::center).offset(-1, 0).on(window).apply();
      wattroff(window, A_BOLD);

      renderer::print_aligned(data->tl_day()).aligned(align::top | align::center).offset(4, 0).on(window).clear().apply();
      renderer::print_aligned(data->tl_month()).aligned(align::top | align::center).offset(6, 0).on(window).clear().apply();
      renderer::print_extensible(data->year).on(window).start(8, 1).end(getmaxx(window) - 2).apply();

      curs_set(0);

      ~snip~
  }

A simple abstraction of a List View that is reused across the application:

namespace graphics
{
    namespace views
    {
        template <typename T>
        struct ListViewBuilder
        {
            ScrollControl *controls = nullptr;
            T *data;
            int length;

            std::function<void(WINDOW *, int)> header_painter;
            std::function<void(int, int, T)> line_painter;
            std::string empty_message = "There is nothing to display";
        }
    }
}

I wrote over 8000 lines in a 9000-LoC project. I was a machine here.

Key Features

It is better explained to view the video embedded below!

For those who are vision-impaired: