Welcome, guest | Sign In | My Account | Store | Cart
####################
# source/gui_logs.py
####################

from tkinter import messagebox, simpledialog, font
from tkinter import Frame, Label, Button, StringVar
from tkinter import NSEW, LEFT, W, DISABLED, NORMAL
import textwrap, functools

################################################################################

TITLE_SIZE
= 16
TEXT_WIDTH
= 40

################################################################################

class _Dialog(simpledialog.Dialog):

   
def ok(self, event=None):
       
self.withdraw()
       
self.update_idletasks()
       
try:
           
self.apply()
       
finally:
           
self.cancel(force=True)

   
def cancel(self, event=None, force=False):
        title
= 'Warning'
        message
= 'Are you sure you want\nto stop taking this test?'
       
if force or messagebox.askyesno(title, message, master=self):
           
if self.parent is not None:
               
self.parent.focus_set()
           
self.destroy()

################################################################################

class ShowStatus(_Dialog):

    WAIT
= 3

   
def __init__(self, parent, title, message, callback):
       
self.message = message
       
self.callback = callback
       
super().__init__(parent, title)

   
def body(self, master):
        style
= font.Font(self, size=TITLE_SIZE)
       
self.status = Label(master, text=self.message, font=style)
       
self.status.grid(sticky=NSEW, padx=TITLE_SIZE, pady=TITLE_SIZE)
       
return self.status

   
def buttonbox(self):
       
self.after(self.WAIT * 1000, self.ok)

   
def apply(self):
        root
.after_idle(self.callback)

################################################################################

class AskQuestion(_Dialog):

   
def __init__(self, parent, event, callback):
       
self.question = textwrap.wrap(event.question, TEXT_WIDTH)
       
self.choices = event.choices
       
self.answer = event.answer
       
self.callback = callback
       
super().__init__(parent, event.category)

   
def body(self, master):
       
self.labels = []
       
for line in self.question:
           
self.labels.append(Label(master, text=line, justify=LEFT))
           
self.labels[-1].grid(sticky=NSEW)

   
def buttonbox(self):
       
self.buttons = []
        box
= Frame(self)
       
for choice in self.choices:
            options
= {'text': textwrap.fill(choice, TEXT_WIDTH),
                       
'width': TEXT_WIDTH,
                       
'command': functools.partial(self.click, choice)}
           
self.buttons.append(Button(box, **options))
           
self.buttons[-1].grid(padx=5, pady=5)
        box
.pack()

   
def click(self, choice):
       
self.answer(choice)
       
self.ok()

   
def apply(self):
        root
.after_idle(self.callback)

################################################################################

class ReviewProblems(_Dialog):

   
def __init__(self, parent, event, flag):
       
self.problems = list(event.problems())
       
self.problem = 0
       
self.flag = flag
       
super().__init__(parent, 'Problems')

   
def body(self, master):
        title
= font.Font(self, size=TITLE_SIZE)
        legend
= font.Font(self, weight='bold')
       
# Create display variables.
       
self.category = StringVar(master)
       
self.question = StringVar(master)
       
self.answer = StringVar(master)
       
self.right = StringVar(master)
       
# Create form labels.
       
self.c_label = Label(master, textvariable=self.category, font=title)
       
self.q_label = Label(master, textvariable=self.question)
       
self.you_answered = Label(master, text='You answered:', font=legend)
       
self.a_label = Label(master, textvariable=self.answer)
       
self.right_answer = Label(master, text='Right answer:', font=legend)
       
self.r_label = Label(master, textvariable=self.right)
       
# Create control buttons.
        options
= {'text': '< < <',
                   
'width': TEXT_WIDTH // 2,
                   
'command': self.go_back}
       
self.back = Button(master, **options)
        options
= {'text': '> > >',
                   
'width': TEXT_WIDTH // 2,
                   
'command': self.go_next}
       
self.next = Button(master, **options)
       
# Display the body.
        options
= {'sticky': NSEW, 'padx': 5, 'pady': 5}
       
self.c_label.grid(row=0, column=0, columnspan=2, **options)
       
self.q_label.grid(row=1, column=0, columnspan=2, **options)
       
self.you_answered.grid(row=2, column=0, **options)
       
self.a_label.grid(row=2, column=1, **options)
       
self.right_answer.grid(row=3, column=0, **options)
       
self.r_label.grid(row=3, column=1, **options)
       
self.back.grid(row=4, column=0, **options)
       
self.next.grid(row=4, column=1, **options)
       
# Update the labels.
       
self.update()
       
   
def go_back(self):
       
self.problem -= 1
       
self.update()

   
def go_next(self):
       
self.problem += 1
       
self.update()

   
def update(self):
       
# Update the labels.
        problem
= self.problems[self.problem]
       
self.category.set(problem.category)
       
self.question.set(textwrap.fill(problem.question, TEXT_WIDTH))
       
self.answer.set(textwrap.fill(problem.answer, TEXT_WIDTH // 2))
       
self.right.set(textwrap.fill(problem.right, TEXT_WIDTH // 2))
       
# Update the buttons.
       
if self.problem == 0:
           
self.back['state'] = DISABLED
       
else:
           
self.back['state'] = NORMAL
       
if self.problem + 1 == len(self.problems):
           
self.next['state'] = DISABLED
       
else:
           
self.next['state'] = NORMAL

   
def apply(self):
       
self.flag[0] = True

################################################################################

class ShowReport(_Dialog):
   
    RULE
= '='

   
def __init__(self, parent, event, callback):
       
self.level = event.level
       
self.right = event.right
       
self.wrong = event.wrong
       
self.total = event.total
       
self.callback = callback
       
super().__init__(parent, 'Report')

   
def body(self, master):
        title
= font.Font(self, size=TITLE_SIZE)
        legend
= {'anchor': W,
                 
'justify': LEFT,
                 
'font': font.Font(self, weight='bold')}
       
# Create all labels.
        text
= 'Cumulative score for\nprevious {}:'.format(self.level)
       
self.explanation = Label(master, text=text, font=title)
       
self.ruler_one = Label(master, text=(self.RULE * TEXT_WIDTH))
       
self.answers_right = Label(master, text='Answers right:', **legend)
       
self.display_right = Label(master, text=str(self.right))
       
self.answers_wrong = Label(master, text='Answers wrong:', **legend)
       
self.display_wrong = Label(master, text=str(self.wrong))
       
self.percent = Label(master, text='Percentage correct:', **legend)
        percentage
= str(int(100 * self.right / self.total + 0.5)) + '%'
       
self.display = Label(master, text=percentage)
       
self.ruler_two = Label(master, text=(self.RULE * TEXT_WIDTH))
       
# Display the results.
        options
= {'sticky': NSEW, 'padx': 5, 'pady': 5}
       
self.explanation.grid(row=0, column=0, columnspan=2, **options)
       
self.ruler_one.grid(row=1, column=0, columnspan=2, **options)
       
self.answers_right.grid(row=2, column=0, **options)
       
self.display_right.grid(row=2, column=1, **options)
       
self.answers_wrong.grid(row=3, column=0, **options)
       
self.display_wrong.grid(row=3, column=1, **options)
       
self.percent.grid(row=4, column=0, **options)
       
self.display.grid(row=4, column=1, **options)
       
self.ruler_two.grid(row=5, column=0, columnspan=2, **options)

   
def apply(self):
        root
.after_idle(self.callback)

History