From 180a4fe80ffbdd2c3725fdc35069b02dfe88c59f Mon Sep 17 00:00:00 2001 From: Jake Funke Date: Wed, 8 Mar 2017 02:35:04 +0000 Subject: [PATCH] added visual menu and live updates --- botany.py | 27 +++++++---- menu_screen.py | 122 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 140 insertions(+), 9 deletions(-) create mode 100644 menu_screen.py diff --git a/botany.py b/botany.py index 745165b..6bdd944 100644 --- a/botany.py +++ b/botany.py @@ -8,8 +8,8 @@ import os.path import random import getpass import threading - - +import errno +from menu_screen import * # ideas go here # lifecycle of a plant # seed -> seedling -> sprout -> young plant -> mature plant -> flower -> @@ -69,6 +69,7 @@ import threading # # curses.endwin() + class Plant(object): # This is your plant! stage_dict = { @@ -214,7 +215,8 @@ class Plant(object): output += self.stage_dict[self.stage] + " " if self.stage >= 2: output += self.species_dict[self.species] + " " - print output + # print output + return output def start_life(self): # runs life on a thread @@ -231,13 +233,13 @@ class Plant(object): while (self.stage < 5) or (self.dead == False): time.sleep(1) self.ticks += 1 - print self.ticks + # print self.ticks if self.stage < len(self.stage_dict)-1: if self.ticks == life_stages[self.stage]: self.growth() - self.parse_plant() + print self.parse_plant() if self.mutate_check(): - self.parse_plant() + print self.parse_plant() # what kills the plant? @@ -258,8 +260,13 @@ class DataManager(object): def __init__(self): self.this_user = getpass.getuser() - if not os.path.exists(self.botany_dir): + # check for .botany dir in home + try: os.makedirs(self.botany_dir) + except OSError as exception: + if exception.errno != errno.EEXIST: + raise + self.savefile_name = self.this_user + '_plant.dat' def check_plant(self): @@ -293,7 +300,7 @@ if __name__ == '__main__': if my_data.check_plant(): print "Welcome back, " + getpass.getuser() my_plant = my_data.load_plant() - my_plant.parse_plant() + print my_plant.parse_plant() # otherwise create new plant else: print "Welcome, " + getpass.getuser() @@ -301,7 +308,9 @@ if __name__ == '__main__': my_plant = Plant(my_data.savefile_path) my_plant.start_life() print "Your plant is living :)" - raw_input('Press return to save and exit...\n') + botany_menu = CursedMenu(my_plant) + botany_menu.show([1,2,3], title=' botany ', subtitle='Options') + #raw_input('Press return to save and exit...\n') my_data.save_plant(my_plant) my_data.data_write_json(my_plant) print "end" diff --git a/menu_screen.py b/menu_screen.py new file mode 100644 index 0000000..e6a5771 --- /dev/null +++ b/menu_screen.py @@ -0,0 +1,122 @@ +import curses, os, traceback, threading, time + +class CursedMenu(object): + '''A class which abstracts the horrors of building a curses-based menu system''' + def __init__(self, this_plant): + '''Initialization''' + self.screen = curses.initscr() + curses.noecho() + curses.cbreak() + curses.start_color() + curses.curs_set(0) + self.screen.keypad(1) + self.plant = this_plant + self.exit = False + + # Highlighted and Normal line definitions + curses.init_pair(1, curses.COLOR_BLACK, curses.COLOR_WHITE) + self.highlighted = curses.color_pair(1) + self.normal = curses.A_NORMAL + thread = threading.Thread(target=self.update_plant_live, args=()) + thread.daemon = True + thread.start() + + + def show(self, options, title="Title", subtitle="Subtitle"): + '''Draws a menu with the given parameters''' + self.set_options(options) + self.title = title + self.subtitle = subtitle + self.selected = 0 + self.draw_menu() + + + def set_options(self, options): + '''Validates that the last option is "Exit"''' + if options[-1] is not 'Exit': + options.append('Exit') + self.options = options + + + def draw_menu(self): + '''Actually draws the menu and handles branching''' + request = "" + try: + while request is not "Exit": + self.draw() + request = self.get_user_input() + self.handle_request(request) + self.__exit__() + + # Also calls __exit__, but adds traceback after + except Exception as exception: + self.__exit__() + traceback.print_exc() + + + def draw(self): + '''Draw the menu and lines''' + self.screen.border(0) + self.screen.addstr(2,2, self.title, curses.A_STANDOUT) # Title for this menu + self.screen.addstr(4,2, self.subtitle, curses.A_BOLD) #Subtitle for this menu + # Display all the menu items, showing the 'pos' item highlighted + for index in range(len(self.options)): + textstyle = self.normal + if index == self.selected: + textstyle = self.highlighted + self.screen.addstr(5+index,4, "%d - %s" % (index+1, self.options[index]), textstyle) + + self.screen.refresh() + + def update_plant_live(self): + while self.exit is not True: + plant_string = self.plant.parse_plant() + plant_ticks = str(self.plant.ticks) + self.screen.addstr(10,2, plant_string, curses.A_NORMAL) + self.screen.addstr(11,2, plant_ticks, curses.A_NORMAL) + self.screen.refresh() + time.sleep(1) + #curses.endwin() + #os.system('clear') + + def get_user_input(self): + '''Gets the user's input and acts appropriately''' + user_in = self.screen.getch() # Gets user input + + '''Enter and Exit Keys are special cases''' + if user_in == 10: + return self.options[self.selected] + if user_in == 27: + return self.options[-1] + + # This is a number; check to see if we can set it + if user_in >= ord('1') and user_in <= ord(str(min(9,len(self.options)+1))): + self.selected = user_in - ord('0') - 1 # convert keypress back to a number, then subtract 1 to get index + return + + # Increment or Decrement + if user_in == curses.KEY_DOWN: # down arrow + self.selected += 1 + if user_in == curses.KEY_UP: # up arrow + self.selected -=1 + self.selected = self.selected % len(self.options) + return + + + def handle_request(self, request): + '''This is where you do things with the request''' + if request is None: return + if request == 1: + self.screen.addstr(8,15,str(self.plant.ticks), curses.A_STANDOUT) # Title for this menu + self.screen.refresh() + + def __exit__(self): + self.exit = True + curses.curs_set(2) + curses.endwin() + os.system('clear') + + +'''demo''' +# cm = CursedMenu() +# cm.show([1,2,3], title=' botany ', subtitle='Options')