+# -*- coding: utf-8 -*-
+
+
+"""
+GUI implementation
+"""
+
+import wx
+from . import munter
+
+class MainFrame(wx.Frame):
+ """
+ The main wx.Frame
+ """
+
+ def __init__(self, *args, **kw):
+ super(MainFrame, self).__init__(*args, **kw)
+
+ self.SetTitle('Munter.py')
+ self.SetSize(600, 400)
+
+ self.props = dict()
+ self.props['distance'] = 0
+ self.props['elevation'] = 0
+ self.props['fitness'] = 'average'
+ self.props['units'] = 'imperial'
+ self.props['travel_mode'] = 'uphill'
+
+ self.pnl = wx.Panel(self)
+
+ st = wx.StaticText(self.pnl, label="Munter.py")
+ font = st.GetFont()
+ font.PointSize += 10
+ font = font.Bold()
+
+ st.SetFont(font)
+
+ #sizer = wx.BoxSizer(wx.VERTICAL)
+ sizer = wx.BoxSizer(wx.HORIZONTAL)
+ sizer.Add(st, wx.SizerFlags().Border(wx.TOP|wx.LEFT, 0))
+ #self.pnl.SetSizer(sizer)
+
+ # text entry fields
+ self.st_distance = wx.StaticText(self.pnl, label="Distance: ")
+ self.te_distance = wx.TextCtrl(self.pnl, value="0", size=(140, -1))
+
+ self.st_elevation = wx.StaticText(self.pnl, label="Elevation: ")
+ self.te_elevation = wx.TextCtrl(self.pnl, value="0", size=(140, -1))
+
+ self.st_fitness = wx.StaticText(self.pnl, label="Fitness: ")
+ cb_fitness_choices = ['slow', 'average', 'fast']
+ cb_fitness_default = 'average'
+ self.cb_fitness = wx.ComboBox(self.pnl, choices=cb_fitness_choices,
+ value=cb_fitness_default, style=wx.CB_READONLY)
+
+ self.st_travel_mode = wx.StaticText(self.pnl, label="Travel Mode: ")
+ cb_travel_mode_choices = ['uphill', 'flat', 'downhill', 'bushwhacking']
+ cb_travel_mode_default = 'uphill'
+ self.cb_travel_mode = wx.ComboBox(self.pnl, choices=cb_travel_mode_choices,
+ value=cb_travel_mode_default, style=wx.CB_READONLY)
+
+ self.st_units = wx.StaticText(self.pnl, label="Units: ")
+ cb_units_choices = ['imperial', 'metric']
+ cb_units_default = 'imperial'
+ self.cb_units = wx.ComboBox(self.pnl, choices=cb_units_choices,
+ value=cb_units_default, style=wx.CB_READONLY)
+
+ # static text
+ self.st_mtc = wx.StaticText(self.pnl, label="0h",
+ style=wx.ALIGN_CENTRE_HORIZONTAL)
+
+ st_mtc_font = st.GetFont()
+ st_mtc_font.PointSize += 10
+ self.st_mtc.SetFont(st_mtc_font)
+
+ # bindings
+ self.pnl.Bind(wx.EVT_TEXT, self.update_distance, self.te_distance)
+ self.pnl.Bind(wx.EVT_TEXT, self.update_elevation, self.te_elevation)
+ self.cb_fitness.Bind(wx.EVT_COMBOBOX, self.update_fitness)
+ self.cb_travel_mode.Bind(wx.EVT_COMBOBOX, self.update_travel_mode)
+ self.cb_units.Bind(wx.EVT_COMBOBOX, self.update_units)
+
+ # buttons
+ b_clear = wx.Button(self.pnl, wx.NewId(), '&Clear', (-1, -1),
+ wx.DefaultSize)
+
+ # layout
+ b = 5
+ w = 100
+
+ static_line = wx.StaticLine(self.pnl, wx.NewId(), style=wx.LI_HORIZONTAL)
+
+ hsizer_distance = wx.BoxSizer(wx.HORIZONTAL)
+ hsizer_distance.Add(self.st_distance, 0, wx.RIGHT, b)
+ hsizer_distance.Add(self.te_distance, 1, wx.GROW, b)
+ hsizer_distance.SetItemMinSize(self.st_distance, (w, -1))
+
+ hsizer_elevation = wx.BoxSizer(wx.HORIZONTAL)
+ hsizer_elevation.Add(self.st_elevation, 0, wx.RIGHT, b)
+ hsizer_elevation.Add(self.te_elevation, 1, wx.GROW, b)
+ hsizer_elevation.SetItemMinSize(self.st_elevation, (w, -1))
+
+ hsizer_fitness = wx.BoxSizer(wx.HORIZONTAL)
+ hsizer_fitness.Add(self.st_fitness, 0, wx.RIGHT, b)
+ hsizer_fitness.Add(self.cb_fitness, 1, wx.GROW, b)
+ hsizer_fitness.SetItemMinSize(self.st_fitness, (w, -1))
+
+ hsizer_travel_mode = wx.BoxSizer(wx.HORIZONTAL)
+ hsizer_travel_mode.Add(self.st_travel_mode, 0, wx.RIGHT, b)
+ hsizer_travel_mode.Add(self.cb_travel_mode, 1, wx.GROW, b)
+ hsizer_travel_mode.SetItemMinSize(self.st_travel_mode, (w, -1))
+
+ hsizer_units = wx.BoxSizer(wx.HORIZONTAL)
+ hsizer_units.Add(self.st_units, 0, wx.RIGHT, b)
+ hsizer_units.Add(self.cb_units, 1, wx.GROW, b)
+ hsizer_units.SetItemMinSize(self.st_units, (w, -1))
+
+ hsizer_mtc = wx.BoxSizer(wx.HORIZONTAL)
+ hsizer_mtc.Add(self.st_mtc, 1, wx.GROW, b)
+ hsizer_mtc.SetItemMinSize(self.st_mtc, (w, -1))
+
+ hsizer5 = wx.BoxSizer(wx.HORIZONTAL)
+ hsizer5.Add(b_clear, 0)
+
+ b = 5
+ vsizer1 = wx.BoxSizer(wx.VERTICAL)
+ vsizer1.Add(sizer, 0, wx.EXPAND | wx.ALL, b*b)
+ vsizer1.Add(hsizer_distance, 0, wx.EXPAND | wx.ALL, b)
+ vsizer1.Add(hsizer_elevation, 0, wx.EXPAND | wx.ALL, b)
+ vsizer1.Add(hsizer_fitness, 0, wx.EXPAND | wx.ALL, b)
+ vsizer1.Add(hsizer_travel_mode, 0, wx.EXPAND | wx.ALL, b)
+ vsizer1.Add(hsizer_units, 0, wx.EXPAND | wx.ALL, b)
+ vsizer1.Add(hsizer_mtc, 0, wx.EXPAND | wx.ALL, b)
+ vsizer1.Add(static_line, 0, wx.GROW | wx.ALL, b)
+ vsizer1.Add(hsizer5, 0, wx.ALIGN_RIGHT | wx.ALL, b)
+
+ self.pnl.SetSizerAndFit(vsizer1)
+ self.pnl.SetClientSize(vsizer1.GetSize())
+
+ def update_distance(self, event):
+ value = self.te_distance.GetValue()
+ if value:
+ self.props['distance'] = float(value)
+ self.update_mtc()
+
+ def update_elevation(self, event):
+ value = self.te_elevation.GetValue()
+ if value:
+ self.props['elevation'] = int(value)
+ self.update_mtc()
+
+ def update_fitness(self, event):
+ value = self.cb_fitness.GetValue()
+ if value:
+ self.props['fitness'] = value
+ self.update_mtc()
+
+ def update_travel_mode(self, event):
+ value = self.cb_travel_mode.GetValue()
+ if value:
+ self.props['travel_mode'] = value
+ self.update_mtc()
+
+ def update_units(self, event):
+ value = self.cb_units.GetValue()
+ if value:
+ self.props['units'] = value
+ self.update_mtc()
+
+ def update_mtc(self):
+ if (self.props['distance'] is None) or (self.props['elevation'] is None):
+ return
+
+ est = munter.time_calc(self.props['distance'],
+ self.props['elevation'],
+ self.props['fitness'],
+ self.props['travel_mode'],
+ self.props['units'])
+
+ hours = int(est['time'])
+ minutes = int((est['time'] - hours) * 60)
+ self.st_mtc.SetLabel("{human_time}".format(
+ human_time="{hours} hours {minutes} minutes".format(
+ hours=hours,
+ minutes=minutes)))
+
+ self.pnl.Layout()
+
+def startup():
+ app = wx.App()
+ frm = MainFrame(None)
+ frm.Show()
+
+ app.MainLoop()