diff --git a/console-gui.py b/console-gui.py index a77e25f..195e354 100644 --- a/console-gui.py +++ b/console-gui.py @@ -19,12 +19,14 @@ WHITE_CYAN = 11 menu_width = 27 controls_lines = 5 +editing = False + STATUS_DONE = WHITE_GREEN STATUS_WORKING = WHITE_CYAN STATUS_IDLE = WHITE_MAGENTA -statuses = [STATUS_WORKING,STATUS_IDLE,STATUS_DONE,0] +statuses = [STATUS_WORKING, STATUS_IDLE, STATUS_DONE, 0] # TODO add description viewing @@ -46,22 +48,25 @@ statuses = [STATUS_WORKING,STATUS_IDLE,STATUS_DONE,0] COLOR_WHITE """ + class Project: def __init__(self, title: str): self.title = title self.tasks = [] - + def addTask(self, task): self.tasks.append(task) - + def removeTask(self, task): self.tasks.remove(task) + class Task: - def __init__(self,title: str,desc=""): + def __init__(self, title: str, desc=""): self.title = title self.status = Status.NONE + class Status(Enum): WORKING = 0 IDLE = 1 @@ -75,7 +80,7 @@ class Status(Enum): v = 3 print("previous is {}".format(Status(v))) return Status(v) - + def next(self): print("next of {}".format(self)) v = self.value + 1 @@ -84,55 +89,67 @@ class Status(Enum): print("next is {}".format(Status(v))) return Status(v) - # TODO maybe get rid of this enum and just use a number class SelectedWindow(Enum): PROJECTS = 1 TASKS = 2 + def get_x_pos_center(text: str): return curses.COLS // 2 - len(text) // 2 + def draw_instructions(stdscr): controls = "CONTROLS" # draw line h, w = stdscr.getmaxyx() instructions_start = h - controls_lines-1 - stdscr.hline(instructions_start,0,curses.ACS_HLINE,menu_width//2 - len(controls)//2,curses.color_pair(MAGENTA_BLACK)) - stdscr.addstr(instructions_start,menu_width//2-len(controls)//2,controls,curses.color_pair(WHITE_MAGENTA)) - stdscr.hline(instructions_start,menu_width//2+len(controls)//2,curses.ACS_HLINE,menu_width//2-len(controls)//2+1,curses.color_pair(MAGENTA_BLACK)) + stdscr.hline(instructions_start, 0, curses.ACS_HLINE, menu_width // + 2 - len(controls)//2, curses.color_pair(MAGENTA_BLACK)) + stdscr.addstr(instructions_start, menu_width//2-len(controls) // + 2, controls, curses.color_pair(WHITE_MAGENTA)) + stdscr.hline(instructions_start, menu_width//2+len(controls)//2, curses.ACS_HLINE, + menu_width//2-len(controls)//2+1, curses.color_pair(MAGENTA_BLACK)) stdscr.addstr(instructions_start + 1, 0, "UP/DOWN - move selection") stdscr.addstr(instructions_start + 2, 0, "LEFT/RIGHT - switch section") stdscr.addstr(instructions_start + 3, 0, "SPACE - change task status") -def draw_menu(stdscr, projects: list, idx: int, selected_window): + +def draw_projects(stdscr, projects: list, idx: int, selected_window): # draw line - stdscr.vline(0, menu_width, curses.ACS_VLINE, stdscr.getmaxyx()[0] - 1, curses.color_pair(CYAN_BLACK)) + stdscr.vline(0, menu_width, curses.ACS_VLINE, stdscr.getmaxyx()[ + 0] - 1, curses.color_pair(CYAN_BLACK)) # draw project title title = "PROJECTS" title_start = menu_width // 2 - len(title) // 2 stdscr.attron(curses.color_pair(YELLOW_BLACK) | curses.A_REVERSE) - stdscr.addstr(0,0," " * (title_start-1)) + stdscr.addstr(0, 0, " " * (title_start-1)) stdscr.addstr(0, title_start-1, title) - stdscr.addstr(0, len(title) + title_start - 1, " " * (menu_width - (len(title) + title_start)+1)) + stdscr.addstr(0, len(title) + title_start - 1, " " * + (menu_width - (len(title) + title_start)+1)) stdscr.attroff(curses.color_pair(YELLOW_BLACK) | curses.A_REVERSE) # draw projects y = 1 for project_index, project in enumerate(projects): - if project_index == idx and SelectedWindow(selected_window) == SelectedWindow.PROJECTS: - stdscr.addstr(y, 0, project.title,curses.A_REVERSE) - else: + if project_index == idx: + if SelectedWindow(selected_window) == SelectedWindow.PROJECTS: + stdscr.addstr(y, 0, project.title, curses.A_REVERSE) + else: + stdscr.addstr(y, 0, "-- " + project.title) + else: stdscr.addstr(y, 0, project.title) y = y + 1 -def draw_tasks(stdscr, tasks, selected_window,idx): + +def draw_tasks(stdscr, tasks, selected_window, idx): h, w = stdscr.getmaxyx() # draw middle devidor line - stdscr.vline(0, w // 2, curses.ACS_VLINE, h - 1, curses.color_pair(CYAN_BLACK)) + stdscr.vline(0, w // 2, curses.ACS_VLINE, h - + 1, curses.color_pair(CYAN_BLACK)) # draw tasks title title = "TASKS" @@ -140,42 +157,87 @@ def draw_tasks(stdscr, tasks, selected_window,idx): title_start = menu_width + (width//2 - len(title)//2) stdscr.attron(curses.color_pair(YELLOW_BLACK) | curses.A_REVERSE) stdscr.addstr(0, menu_width + 1, " " * (title_start - menu_width)) - stdscr.addstr(0,title_start,title) - stdscr.addstr(0,title_start + len(title), " " * (w//2 - (title_start + len(title)))) + stdscr.addstr(0, title_start, title) + stdscr.addstr(0, title_start + len(title), " " * + (w//2 - (title_start + len(title)))) stdscr.attroff(curses.color_pair(YELLOW_BLACK) | curses.A_REVERSE) - + # draw task names y = 1 for i, task in enumerate(tasks): stdscr.attron(curses.color_pair(statuses[task.status.value])) - stdscr.addstr(y,menu_width+1," " * (width-1)) + stdscr.addstr(y, menu_width+1, " " * (width-1)) if i == idx and SelectedWindow(selected_window) == SelectedWindow.TASKS: stdscr.addstr(y, menu_width + 1, task.title, curses.A_REVERSE) else: stdscr.addstr(y, menu_width + 1, task.title) if task.status != Status.NONE: - stdscr.addstr(y, menu_width + width - len(task.status.name), task.status.name) + stdscr.addstr(y, menu_width + width - + len(task.status.name), task.status.name) stdscr.attroff(curses.color_pair(statuses[task.status.value])) y = y + 1 - + # draw color instructions legend = "LEGEND" instructions_start = h - controls_lines-1 - stdscr.hline(instructions_start,menu_width+1,curses.ACS_HLINE,width//2-len(legend)//2-1,curses.color_pair(MAGENTA_BLACK)) - stdscr.addstr(instructions_start, menu_width + width // 2 - len(legend)//2,legend,curses.color_pair(WHITE_MAGENTA)) - stdscr.hline(instructions_start,menu_width+width//2+len(legend)//2,curses.ACS_HLINE,width//2- len(legend)//2,curses.color_pair(MAGENTA_BLACK)) + stdscr.hline(instructions_start, menu_width+1, curses.ACS_HLINE, + width//2-len(legend)//2-1, curses.color_pair(MAGENTA_BLACK)) + stdscr.addstr(instructions_start, menu_width + width // 2 - + len(legend)//2, legend, curses.color_pair(WHITE_MAGENTA)) + stdscr.hline(instructions_start, menu_width+width//2+len(legend)//2, + curses.ACS_HLINE, width//2 - len(legend)//2, curses.color_pair(MAGENTA_BLACK)) - stdscr.addstr(instructions_start + 1, menu_width + 1, " " * 3, curses.color_pair(STATUS_DONE)) - stdscr.addstr(instructions_start + 1,menu_width + 4 + width - 2*len("DONE"),"DONE",curses.color_pair(STATUS_DONE)) - stdscr.addstr(instructions_start + 2, menu_width + 1, " " * 3, curses.color_pair(STATUS_IDLE)) - stdscr.addstr(instructions_start + 2,menu_width + 4 + width - 2*len("IDLE"),"IDLE",curses.color_pair(STATUS_IDLE)) - stdscr.addstr(instructions_start + 3, menu_width + 1, " " * 3, curses.color_pair(STATUS_WORKING)) - stdscr.addstr(instructions_start + 3,menu_width + 4 + width - int(1.5*len("WORKING")+1),"WORKING",curses.color_pair(STATUS_WORKING)) + stdscr.addstr(instructions_start + 1, menu_width + 1, + " " * 3, curses.color_pair(STATUS_DONE)) + stdscr.addstr(instructions_start + 1, menu_width + 4 + width - + 2*len("DONE"), "DONE", curses.color_pair(STATUS_DONE)) + stdscr.addstr(instructions_start + 2, menu_width + 1, + " " * 3, curses.color_pair(STATUS_IDLE)) + stdscr.addstr(instructions_start + 2, menu_width + 4 + width - + 2*len("IDLE"), "IDLE", curses.color_pair(STATUS_IDLE)) + stdscr.addstr(instructions_start + 3, menu_width + 1, + " " * 3, curses.color_pair(STATUS_WORKING)) + stdscr.addstr(instructions_start + 3, menu_width + 4 + width - + int(1.5*len("WORKING")+1), "WORKING", curses.color_pair(STATUS_WORKING)) +def draw_description(stdscr, task, selected_window): + global editing + h, w = stdscr.getmaxyx() + begin = w // 2 + width = w // 2 + + # put description if we haven't selected a task + if SelectedWindow(selected_window) == SelectedWindow.TASKS: + title = task.title.upper() + else: + title = "DESCRIPTION" + + # draw the title + title_start = begin + width // 2 - len(title) // 2 + stdscr.attron(curses.color_pair(YELLOW_BLACK) | curses.A_REVERSE) + stdscr.addstr(0, begin + 1, " " * (title_start - begin)) + stdscr.addstr(0, title_start, title) + stdscr.addstr(0, title_start + len(title), " " * (width - len(title) - (title_start - begin) )) + stdscr.attroff(curses.color_pair(YELLOW_BLACK) | curses.A_REVERSE) + + edit_win_lines = h - 4 - controls_lines + edit_win_cols = w // 2 - 4 + + scr2 = curses.newwin(edit_win_lines,edit_win_cols , 2, w // 2 + 2) + # rectangle(stdscr, 1, w//2+1, h - controls_lines, w // 2) + rectangle(stdscr, 1, w//2+1, h - controls_lines-2, w-2) + stdscr.refresh() + scr2.refresh() + textpad = Textbox(scr2) + + if editing: + textpad.edit() + editing = False def main(stdscr): + global editing curses.init_pair(1, curses.COLOR_CYAN, curses.COLOR_MAGENTA) curses.init_pair(2, curses.COLOR_RED, curses.COLOR_BLACK) @@ -189,12 +251,12 @@ def main(stdscr): curses.init_pair(10, curses.COLOR_WHITE, curses.COLOR_YELLOW) curses.init_pair(11, curses.COLOR_WHITE, curses.COLOR_CYAN) - k = 0 # input key project_index = 0 task_index = 0 selected_window = 1 projects = [] + test_project = Project("Test") test_project.addTask(Task("testtask", "testdesc")) test_project.addTask(Task("testtask2", "testdesc2")) @@ -206,31 +268,35 @@ def main(stdscr): test_project2.addTask(Task("yeet3")) projects.append(test_project2) - while (k != ord('q')): if k == ord('e'): - editing = not editing + if SelectedWindow(selected_window) == SelectedWindow.TASKS: + editing = not editing elif k == 450: # up key # only move the projects selection if we're on that pane - if SelectedWindow(selected_window) == SelectedWindow.PROJECTS: + if SelectedWindow(selected_window) == SelectedWindow.PROJECTS: project_index = project_index - 1 - if project_index < 0: project_index = len(projects) - 1 + if project_index < 0: + project_index = len(projects) - 1 # only move the task selection if we're on that pane elif SelectedWindow(selected_window) == SelectedWindow.TASKS: task_index = task_index - 1 - if task_index < 0: task_index = len(projects[project_index].tasks)-1 - + if task_index < 0: + task_index = len(projects[project_index].tasks)-1 + elif k == 456: # down key # only move the projects selection if we're on that pane if SelectedWindow(selected_window) == SelectedWindow.PROJECTS: project_index = project_index + 1 - if project_index > len(projects) - 1: project_index = 0 + if project_index > len(projects) - 1: + project_index = 0 # only move the task selection if we're on that pane elif SelectedWindow(selected_window) == SelectedWindow.TASKS: task_index = task_index + 1 - if task_index > len(projects[project_index].tasks) - 1: task_index = 0 - - elif k == 454: # right key + if task_index > len(projects[project_index].tasks) - 1: + task_index = 0 + + elif k == 454: # right key selected_window = selected_window + 1 if selected_window > len(SelectedWindow): selected_window = 1 @@ -238,36 +304,40 @@ def main(stdscr): # set the task selection to the first for when we select a task next # because the previous task we were on might have more tasks than this one, # so we don't want the index to be out of bounds - if SelectedWindow(selected_window) == SelectedWindow.PROJECTS: task_index = 0 - - elif k == 452: # left key + if SelectedWindow(selected_window) == SelectedWindow.PROJECTS: + task_index = 0 + + elif k == 452: # left key selected_window = selected_window - 1 if selected_window < 1: selected_window = len(SelectedWindow) - + # set the task selection to the first for when we select a task next # because the previous task we were on might have more tasks than this one, # so we don't want the index to be out of bounds - if SelectedWindow(selected_window) == SelectedWindow.PROJECTS: task_index = 0 + if SelectedWindow(selected_window) == SelectedWindow.PROJECTS: + task_index = 0 elif k == 32: # space key - projects[project_index].tasks[task_index].status = projects[project_index].tasks[task_index].status.next() + if SelectedWindow(selected_window) == SelectedWindow.TASKS: + projects[project_index].tasks[task_index].status = projects[project_index].tasks[task_index].status.next() - - - stdscr.clear() - draw_menu(stdscr, projects, project_index, selected_window) - draw_tasks(stdscr, projects[project_index].tasks, selected_window, task_index) - draw_instructions(stdscr) # draw botton text - stdscr.addstr(stdscr.getmaxyx()[0]-1,0,"TPM by Sem van der Hoeven",) + stdscr.addstr(stdscr.getmaxyx()[0] - 1, 0, "TPM by Sem van der Hoeven",) + + draw_projects(stdscr, projects, project_index, selected_window) + draw_tasks(stdscr, projects[project_index].tasks, + selected_window, task_index) + draw_instructions(stdscr) + draw_description(stdscr, projects[project_index].tasks[task_index],selected_window) k = stdscr.getch() stdscr.refresh() curses.endwin() + # wrapper already calls noecho() and cbreak() and stdcr.keypad(True) # it also resets the settings upon closing or upon error wrapper(main)