You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

205 lines
6.2 KiB
Python

import curses
import sys
from . import constantes_curses as constantes
#import constantes_curses as constantes
def create_newwin():
"""Initialise une fenêtre
"""
window = curses.newwin(0,0)
window.border(0)
return window
def init_curses():
"""Initialise la biliothèque curses
"""
stdscr = curses.initscr()
curses.noecho()
curses.cbreak()
stdscr.keypad(True)
return stdscr
def close_curses(stdscr):
"""Ferme la fenêtre
"""
stdscr.keypad(0)
curses.nocbreak()
curses.echo()
curses.endwin()
def init_colors():
"""Initialisation des couleurs de la fenêtre
"""
curses.start_color()
curses.init_pair(1,curses.COLOR_RED,curses.COLOR_BLACK)
curses.init_pair(2,curses.COLOR_BLACK,curses.COLOR_RED)
class Echo():
"""Décorateur permettant de garantir que ce qui est écrit au clavier sera vu à l'écran
"""
def __init__(self,f):
self.f = f
def __call__(self,*args,**kwargs):
curses.echo()
return self.f(*args,**kwargs)
curses.noecho()
def add_line(window,pos,nombre_lignes):
"""Permet de passer à la ligne suivante lors d'une saisie utilisateur : on ré-initialise la fenêtre si on est descendu trop bas.
"""
if pos == nombre_lignes-2:
pos = 1
window = curses.newwin(0,0)
window.border(0)
window.refresh()
return pos
else:
pos +=1
return pos
@Echo
def get_user_entry(window,encoding=constantes.encoding):
"""Récupère la saisie d'un message à l'écran
"""
userentry = window.getstr()
return userentry.decode(encoding)
def get_entry(window,message,pos,nombre_lignes,encoding=constantes.encoding):
"""
Récupère la saisie utilisateur, en affichant un message d'erreur et demandant la re-saisie si la fonction decode plante (effacement d'un seul caractère au lieu de deux lors d'une saisie erronée d'un caractère accentué).
"""
while True:
try:
window.addstr(pos,1,message,curses.color_pair(1))
return [get_user_entry(window,encoding),add_line(window,pos,nombre_lignes)]
except:
pos = add_line(window,pos,nombre_lignes)
window.addstr(pos,1,"Erreur de saisie, merci de recommencer",curses.color_pair(1))
pos = add_line(window,pos,nombre_lignes)
def display_menu(title,menu,window,active=1):
"""Affiche un menu, qui ne doit pas avoir plus de lignes que la taille de l'écran (non vérifié).
"""
window.addstr(1,1,title,curses.color_pair(1))
item_pos = 6 ## WTF ??
pos = 1
for item in menu:
if pos == active:
color = curses.color_pair(2)
else:
color = curses.A_NORMAL
if item == 'Quitter':
item_pos +=1
window.addstr(item_pos,1," %d. %s" %(pos,item),color)
pos +=1
else:
window.addstr(item_pos,1," %d. %s" %(pos,item),color)
item_pos +=1
pos +=1
window.refresh()
def getkey(final,title,menu,window,active_pos=1):
"""Permet de se balader dans un menu
"""
c = None
while c != constantes.touche_entree:
c = window.getch()
if c == ord(constantes.touche_bas):
if active_pos != final:
active_pos +=1
else:
active_pos = 1
elif c == ord(constantes.touche_haut):
if active_pos != 1:
active_pos -=1
else:
active_pos = final
display_menu(title,menu,window,active_pos)
return active_pos
class Stdscr():
"""Décorateur permettant d'initialiser une fenêtre curses
"""
def __init__(self,f):
self.f = f
def __call__(self,*args):
window = init_curses()
nombre_lignes = curses.LINES
init_colors()
window = create_newwin()
window.refresh()
try:
return self.f(*args,window,nombre_lignes)
finally:
close_curses(window)
@Stdscr
def saisie_message_std(message,window,nombre_lignes):
"""Retourne la saisie de l'utilisateur, et quitte le programme si cette saisie est constantes.quitter
"""
pos = 1
user_entry = get_entry(window,message,pos,nombre_lignes,encoding=constantes.encoding)[0]
if user_entry.lower() == constantes.quitter:
quit() # pourquoi pas sys.exit() ?
else:
return user_entry
@Stdscr
def afficher_message_std(message,window,nombre_lignes):
"""Permet d'afficher un unique message à l'écran
"""
pos = 1
fin_message = " (appuyer sur une touche pour continuer) "
c = None
window.addstr(pos,1,message+fin_message,curses.color_pair(1))
while c == None:
c = window.getch()
return None
def saisie_message(pos,message,window,nombre_lignes):
"""Retourne la saisie de l'utilisateur, et quitte le programme si cette saisie est constantes.quitter
"""
user_entry,pos = get_entry(window,message,pos,nombre_lignes,encoding=constantes.encoding)
if user_entry.lower() == constantes.quitter:
sys.exit()
else:
return [user_entry, pos]
def afficher_message(pos,message,window,nombre_lignes):
"""Permet d'afficher un message à l'écran dans une fenêtre déjà initialisée
"""
fin_message = " (appuyer sur une touche pour continuer) "
c = None
window.addstr(pos,1,message+fin_message,curses.color_pair(1))
while c == None:
c = window.getch()
return add_line(window,pos,nombre_lignes)
def is_forceable(info,type_info):
"""Détermine si l'info peut être considérée comme un 'type_info'
"""
try:
return type_info(info)
except:
return False
def get_clean_info(type_info,message,pos,window,nombre_lignes):
"""Permet de s'assurer que l'information récupérée est bien du type voulue.
"""
var = False
while not var:
var,pos = saisie_message(pos,message,window,nombre_lignes)
if var == constantes.terminer: #cas particulier de nécessité de sortie de boucle
return [var,pos]
var = is_forceable(var,type_info)
if (var is 0) and type_info == int: #cas particulier du zéro interprété comme False
return [var, pos]
return [var, pos]