""" ui.py """
import tkinter as tk
from tkinter import ttk
[docs]
class UserInterface:
""" UserInterface """
_cam_slider_rpy_text = {
'roll': 'Roll (X) side-to-side',
'pitch': 'Pitch (Y) nose-up-down',
'yaw': 'Yaw((Z) left-right'
}
def __init__(self, title=None):
""" UserInterface """
self._root = tk.Tk()
# configure UI gloablly first
self._root.option_add('*Font', (self.font['family'], self.font['size'] - 2))
self._style = ttk.Style()
self._style.configure('Horizontal.TScale', sliderthickness=0, borderwidth=0, sliderlength=0) # does not work - hence zeros
self._style.configure('TLabel', justify='left', font=(self.font['family'], self.font['size']-2, ''))
self._style.configure('TOptionMenu', font=(self.font['family'], self.font['size']-2, ''))
self._style.configure('TCheckbutton', font=(self.font['family'], self.font['size']-2, ''))
self._style.configure('TMenubutton', font=(self.font['family'], self.font['size']-2, ''))
self._style.configure('TRadiobutton', justify='left', font=(self.font['family'], self.font['size']-2, ''))
self._core = None
self._title_label = None
self._camera_info_box = None
self._star_found_text_box = None
self._misc_text_box = None
self._accelerate_button = None
self._focal_length_buttons = {}
self._star_mag_buttons = {}
self._satellite_attitude_buttons ={}
self._rpy_label = None
self._sat_label = None
self._photo_label = None
self._rpy_sliders = {}
# rpy_values_deg - values of Roll, Pitch, and Yaw sliders.
self.rpy_values_deg = {
'roll': 0.0, # X
'pitch': 0.0, # Y
'yaw': 0.0 # Z
}
if title:
self.root.title('Satellite Camera Viewer')
@property
def root(self):
""" root """
return self._root
@property
def font(self):
""" font """
return tk.font.nametofont("TkDefaultFont").actual()
@property
def core(self):
""" core """
return self._core
@core.setter
def core(self, value=None):
""" core """
self._core = value
[docs]
def frame(self, parent, borderwidth=1, row=0, col=0, colspan=1, padx=2, pady=2, sticky='nsew', anchor=None):
""" frame """
if borderwidth == 0:
relief = ''
else:
relief='solid'
f = ttk.Frame(parent, borderwidth=borderwidth, relief=relief)
if anchor is not None:
f.pack(padx=padx, pady=pady, anchor=anchor)
else:
f.grid(row=row, column=col, columnspan=colspan, padx=padx, pady=pady, sticky=sticky)
return f
[docs]
def labelframe(self, parent, text='', borderwidth=1, row=0, col=0, colspan=1, padx=2, pady=2, sticky='nsew'):
""" labelframe """
if borderwidth == 0:
relief = ''
else:
relief='solid'
f = ttk.LabelFrame(parent, text=text, borderwidth=borderwidth, relief=relief)
f.grid(row=row, column=col, columnspan=colspan, padx=padx, pady=pady, sticky=sticky)
return f
# TITLE
#def title_label(self, parent, text):
# """ title_label """
# l = ttk.Label(parent, text=text, justify='left', font=('', 24, 'bold'))
# l.pack(padx=2, pady=2)
# self._title_label = l
# INFO TEXT BOXES
[docs]
def camera_info_box(self, parent, row, col):
""" camera_info_box """
t = tk.Text(parent, width=80, height=3, state='disabled', wrap=tk.WORD)
t.grid(row=row, column=col, padx=2, pady=2, sticky='ew')
self._camera_info_box = t
[docs]
def misc_text_box(self, parent, row, col):
""" misc_text_box """
t = tk.Text(parent, width=80, height=3, state='disabled', wrap=tk.WORD)
t.grid(row=row, column=col, padx=2, pady=2, sticky='ew')
self._misc_text_box = t
[docs]
def star_found_text_box(self, parent, row, col):
""" star_found_text_box """
t = tk.Text(parent, width=80, height=3, state='disabled', wrap=tk.WORD)
t.grid(row=row, column=col, padx=2, pady=2, sticky='ew')
self._star_found_text_box = t
[docs]
def camera_info(self, text):
""" camera_info """
self._camera_info_box.config(state='normal')
self._camera_info_box.delete('1.0', tk.END)
self._camera_info_box.insert(tk.END, '%s' % (text))
self._camera_info_box.config(state='disabled')
[docs]
def star_found_text(self, text):
""" star_found_text """
self._star_found_text_box.config(state='normal')
self._star_found_text_box.delete('1.0', tk.END)
self._star_found_text_box.insert(tk.END, '%s' % (text))
self._star_found_text_box.config(state='disabled')
[docs]
def misc_text(self, text):
""" misc_text """
self._misc_text_box.config(state='normal')
self._misc_text_box.delete('1.0', tk.END)
self._misc_text_box.insert(tk.END, '%s' % (text))
self._misc_text_box.config(state='disabled')
# BUTTONS
[docs]
def do_accelerate(self, value):
""" do_accelerate """
self.core.do_accelerate(bool(value.get()))
[docs]
def do_stars(self, value):
""" do_stars """
self.core.do_stars(bool(value.get()))
[docs]
def do_match_stars(self, value):
""" do_match_stars """
self.core.do_match_stars(bool(value.get()))
[docs]
def do_earth_vector(self, value):
""" do_earth_vector """
self.core.do_earth_vector(bool(value.get()))
# STAR MAGNITUDE
[docs]
def do_mag(self, value):
""" do_mag """
self.core.do_mag(float(value))
# FOCAL LENGTH
[docs]
def do_focal_length(self, value):
""" do_focal_length """
self.core.do_focal_length(float(value))
# SATELLITE SELECTION
[docs]
def do_satellite_selection(self, value):
""" do_satellite_selection """
self.core.do_satellite_selection(str(value))
[docs]
def satellite_selection(self, parent, row, col, satellite_names):
""" satellite_selection """
s_default = satellite_names[0]
self._satellite_selected = tk.StringVar(value=s_default)
drop = ttk.OptionMenu(parent, self._satellite_selected, *satellite_names, command=lambda val: self.do_satellite_selection(val))
drop.grid(row=row, column=col, columnspan=7, padx=2, pady=2, sticky='ew')
self._satellite_selection_drop = drop
# SATELLITE BUTTONS
[docs]
def do_satellite_attitude(self, value):
""" do_satellite_attitude """
self.core.do_satellite_attitude(str(value))
# ROLL PITCH YAW
[docs]
def rpy_label(self, parent, text, row, col):
""" rpy_label """
rpy_label = 'Roll(X) / Pitch(Y) / Yaw(Z) controls for satellite body (and hence camera)'
l = ttk.Label(parent, text=rpy_label, wraplength=160)
l.grid(row=row, column=col, padx=2, pady=2, sticky='w')
self._rpy_label = l
[docs]
def do_rpy(self, val, k):
""" do_rpy """
self.core.do_rpy(float(val), k)
[docs]
def rpy_sliders(self, parent, row, col):
""" rpy_sliders """
lf = self.labelframe(parent, 'Attitude')
lf.grid(row=row, column=col, sticky='ew')
self.v_sliders = {}
max_width = max([len(k) for v,k in self._cam_slider_rpy_text.items()])
for k,v in self.rpy_values_deg.items():
l = ttk.Label(lf, text=self._cam_slider_rpy_text[k], width=max_width+5)
l.grid(row=row, column=col, padx=2, pady=2, sticky='ew')
row += 1
self.v_sliders[k] = tk.IntVar(value=int(v))
s = ttk.Scale(lf,
# label=self._cam_slider_rpy_text[k],
variable=self.v_sliders[k],
from_=-90, to=90,
# resolution=10.0,
# showvalue=True,
orient='horizontal',
command=lambda val,k=k: self.do_rpy(val, k))
s.grid(row=row, column=col, padx=2, pady=2, sticky='ew')
self._rpy_sliders[k] = s
row += 1
# 3D cubesat image
[docs]
def sat_label(self, parent, row, col, width=300, height=300):
""" sat_label """
l = tk.Label(parent, bg='whitesmoke', borderwidth=0, width=width, height=height)
l.grid(row=row, column=col, padx=2, pady=2, sticky='w')
self._sat_label = l
return self._sat_label
# photo image
[docs]
def photo_label(self, parent, row, col, width=300, height=300):
""" photo_label """
l = tk.Label(parent, bg='cyan', borderwidth=0, width=width, height=height)
l.grid(row=row, column=col, padx=2, pady=2, sticky='w')
self._photo_label = l
# self._image150x150(width, height)
return self._photo_label
# RESET BUTTON
[docs]
def do_reset(self):
""" do_reset """
self.core.do_reset()
[docs]
def mainloop(self):
""" mainloop """
self.root.mainloop()