]> Pileus Git - lackey/blobdiff - src/view.c
Add popup views
[lackey] / src / view.c
index fcba91598bc9a03c8273d8d02aa8b2df1a5ecaad..dfc087120f8b55d40d5b6d84488c6c02ee1cd1f0 100644 (file)
@@ -1,16 +1,16 @@
 /*
  * Copyright (C) 2012 Andy Spencer <andy753421@gmail.com>
- * 
+ *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation, either version 3 of the License, or
  * (at your option) any later version.
- * 
+ *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU General Public License
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
@@ -21,6 +21,7 @@
 #include <ncurses.h>
 
 #include "util.h"
+#include "conf.h"
 #include "date.h"
 #include "cal.h"
 #include "view.h"
@@ -36,21 +37,48 @@ typedef struct {
        WINDOW *win;
 } view_t;
 
-/* Data */
+/* Macros */
+#define VIEW(name)                     \
+       void name##_init(WINDOW *win); \
+       void name##_size(int,int);     \
+       void name##_draw(void);        \
+       int  name##_run(int,mmask_t,int,int)
+
+/* Prototypes */
+VIEW(day);
+VIEW(week);
+VIEW(month);
+VIEW(year);
+VIEW(events);
+VIEW(todo);
+VIEW(settings);
+VIEW(help);
+
+/* View data */
+static const char *names[] = {
+       "day", "week", "month", "year",
+       "|", "events", "todo",
+       "|", "settings", "help",
+};
+
 view_t views[] = {
-       { "Day",      day_init,      day_size,      day_draw,      day_run,      {KEY_F(1), '1',    } },
-       { "Week",     week_init,     week_size,     week_draw,     week_run,     {KEY_F(2), '2',    } },
-       { "Month",    month_init,    month_size,    month_draw,    month_run,    {KEY_F(3), '3',    } },
-       { "Year",     year_init,     year_size,     year_draw,     year_run,     {KEY_F(4), '4',    } },
-       { "|",        NULL,          NULL,          NULL,          NULL,         {                  } },
-       { "Events",   events_init,   events_size,   events_draw,   events_run,   {KEY_F(5), '5',    } },
-       { "Todo",     todo_init,     todo_size,     todo_draw,     todo_run,     {KEY_F(6), '6',    } },
-       { "|",        NULL,          NULL,          NULL,          NULL,         {                  } },
-       { "Settings", settings_init, settings_size, settings_draw, settings_run, {KEY_F(7), '7',    } },
-       { "Help",     help_init,     help_size,     help_draw,     help_run,     {KEY_F(8), '8', '?'} },
+       { "Day",      day_init,      day_size,      day_draw,      day_run,      {KEY_F(1), '1'} },
+       { "Week",     week_init,     week_size,     week_draw,     week_run,     {KEY_F(2), '2'} },
+       { "Month",    month_init,    month_size,    month_draw,    month_run,    {KEY_F(3), '3'} },
+       { "Year",     year_init,     year_size,     year_draw,     year_run,     {KEY_F(4), '4'} },
+       { "|",        NULL,          NULL,          NULL,          NULL,         {             } },
+       { "Events",   events_init,   events_size,   events_draw,   events_run,   {KEY_F(5), '5'} },
+       { "Todo",     todo_init,     todo_size,     todo_draw,     todo_run,     {KEY_F(6), '6'} },
+       { "|",        NULL,          NULL,          NULL,          NULL,         {             } },
+       { "Settings", settings_init, settings_size, settings_draw, settings_run, {KEY_F(7), '7'} },
+       { "Help",     help_init,     help_size,     help_draw,     help_run,     {KEY_F(8), '8'} },
+       { NULL,       NULL,          NULL,          NULL,          NULL,         {             } },
 };
 
-int active = 0;
+/* Config data */
+int COMPACT = 0;
+int ACTIVE  = 0;
+int POPUP   = -1;
 
 /* Local functions */
 static void draw_header(void)
@@ -58,23 +86,71 @@ static void draw_header(void)
        move(0, 0);
        attron(COLOR_PAIR(COLOR_TITLE));
        for (int i = 0; i < N_ELEMENTS(views); i++) {
-               if (i == active)
+               if (!views[i].name)
+                       break;
+               if (i == ACTIVE)
                        attron(A_BOLD);
                printw("%s ", views[i].name);
-               if (i == active)
+               if (i == ACTIVE)
                        attroff(A_BOLD);
        }
+       clrtoeol();
+       if (POPUP >= 0) {
+               attron(A_BOLD);
+               move(0, COLS-strlen(views[POPUP].name)-2);
+               printw("[%s]", views[POPUP].name);
+               attroff(A_BOLD);
+       }
        attroff(COLOR_PAIR(COLOR_TITLE));
-       mvhline(1, 0, ACS_HLINE, COLS);
+       if (!COMPACT)
+               mvhline(1, 0, ACS_HLINE, COLS);
        refresh();
 }
 
 static int get_color(const char *cat)
 {
        return cat == NULL           ? 0           :
-              !strcmp(cat, "class") ? COLOR_CLASS :
-              !strcmp(cat, "ec")    ? COLOR_EC    :
-              !strcmp(cat, "work")  ? COLOR_WORK  : COLOR_OTHER ;
+              match(cat, "class") ? COLOR_CLASS :
+              match(cat, "ec")    ? COLOR_EC    :
+              match(cat, "work")  ? COLOR_WORK  : COLOR_OTHER ;
+}
+
+static int view_set(int active, int popup)
+{
+       if (ACTIVE != active) {
+               ACTIVE = active;
+               set_enum("view", 0, "active", ACTIVE,
+                               names, N_ELEMENTS(names));
+               view_draw();
+       }
+       if (POPUP != popup) {
+               POPUP = popup;
+               view_draw();
+       }
+       return 1;
+}
+
+/* Curses functions */
+void wmvresize(WINDOW *win, int top, int left, int rows, int cols)
+{
+       int y = getpary(win);
+       if (top < y)
+               mvderwin(win, top, left);
+       wresize(win, rows, cols);
+       if (top > y)
+               mvderwin(win, top, left);
+}
+
+void wshrink(WINDOW *win, int top)
+{
+       int x    = getparx(win);
+       int y    = getpary(win);
+       int r    = getmaxy(win);
+       int c    = getmaxx(win);
+       int rows = r + (y - top);
+       if (top  <  y) mvderwin(win, top, x);
+       if (rows != r) wresize(win, rows, c);
+       if (top  >  y) mvderwin(win, top, x);
 }
 
 /* Helper functions */
@@ -174,69 +250,86 @@ void todo_line(WINDOW *win, todo_t *todo, int y, int x, int w, int full)
 /* View init */
 void view_init(void)
 {
+       int hdr = COMPACT ? 1 : 2;
        for (int i = 0; i < N_ELEMENTS(views); i++) {
                if (views[i].init) {
-                       views[i].win = newwin(LINES-2, COLS, 2, 0);
+                       views[i].win = newwin(LINES-hdr, COLS, hdr, 0);
                        views[i].init(views[i].win);
                }
+               if (views[i].size)
+                       views[i].size(LINES-hdr, COLS);
+       }
+}
+
+/* Config parser */
+void view_config(const char *group, const char *name, const char *key, const char *value)
+{
+       if (match(group, "view")) {
+               if (match(key, "compact"))
+                       COMPACT = get_bool(value);
+               else if (match(key, "active"))
+                       ACTIVE = get_enum(value, names, N_ELEMENTS(names));
        }
 }
 
 /* View draw */
 void view_resize(void)
 {
+       int hdr = COMPACT ? 1 : 2;
        for (int i = 0; i < N_ELEMENTS(views); i++) {
-               if (views[i].win)
-                       wresize(views[i].win, LINES-2, COLS);
+               if (views[i].win) {
+                       wresize(views[i].win, LINES-hdr, COLS);
+                       mvwin(views[i].win, hdr, 0);
+               }
                if (views[i].size)
-                       views[i].size(LINES-2, COLS);
+                       views[i].size(LINES-hdr, COLS);
        }
 }
 
 /* View draw */
 void view_draw(void)
 {
+       int view = POPUP >= 0 ? POPUP : ACTIVE;
        draw_header();
-       werase(views[active].win);
-       views[active].draw();
-       wrefresh(views[active].win);
+       werase(views[view].win);
+       views[view].draw();
+       wrefresh(views[view].win);
 }
 
-/* View set */
-int view_set(int num)
+/* View run */
+int view_run(int key, mmask_t btn, int row, int col)
 {
-       if (active != num) {
-               active = num;
+       /* Check for compact mode toggle */
+       if (key == 'c') {
+               COMPACT ^= 1;
+               set_bool("view", 0, "compact", COMPACT);
+               view_resize();
                view_draw();
+               return 1;
        }
-       return 1;
-}
 
-/* View run */
-int view_run(int key, mmask_t btn, int row, int col)
-{
        /* Check for mouse events */
        if (key == KEY_MOUSE && row == 0) {
                int start = 1;
                for (int i = 0; i < N_ELEMENTS(views); i++) {
                        int end = start + strlen(views[i].name) - 1;
                        if (start <= col && col <= end && views[i].draw)
-                               return view_set(i);
+                               return view_set(i, -1);
                        start = end + 2;
                }
        }
 
        /* Check for view change */
        for (int i = 0; i < N_ELEMENTS(views); i++) {
-               if (i == active)
+               if (i == ACTIVE)
                        continue;
                for (int j = 0; j < N_ELEMENTS(views[i].keys); j++)
                        if (views[i].keys[j] == key)
-                               return view_set(i);
+                               return view_set(i, -1);
        }
 
        /* Shift windows */
-       int num   = active;
+       int num   = ACTIVE;
        int shift = key == KEY_RIGHT ? +1 :
                    key == KEY_LEFT  ? -1 : 0;
        while (shift) {
@@ -244,9 +337,18 @@ int view_run(int key, mmask_t btn, int row, int col)
                num += N_ELEMENTS(views);
                num %= N_ELEMENTS(views);
                if (views[num].run)
-                       return view_set(num);
+                       return view_set(num, -1);
+       }
+
+       /* Handle popup views */
+       switch (key) {
+               case '\033': // escape
+                       return view_set(ACTIVE, -1);
+               case '?':    // help
+                       return view_set(ACTIVE, 9);
        }
 
        /* Pass key to active view */
-       return views[active].run(key, btn, row, col);
+       int view = POPUP >= 0 ? POPUP : ACTIVE;
+       return views[view].run(key, btn, row, col);
 }