c8e4130df45d94482e76dfaedd4b4d536e380214
[munter.git] / munter / gui.py
1 # -*- coding: utf-8 -*-
2
3
4 """
5 GUI implementation
6 """
7
8 import wx
9 from . import munter
10
11 class MainFrame(wx.Frame):
12 """
13 The main wx.Frame
14 """
15
16 def __init__(self, *args, **kw):
17 super(MainFrame, self).__init__(*args, **kw)
18
19 self.SetTitle('Munter.py')
20 self.SetSize(600, 400)
21
22 self.props = dict()
23 self.props['distance'] = 0
24 self.props['elevation'] = 0
25 self.props['fitness'] = 'average'
26 self.props['units'] = 'imperial'
27 self.props['travel_mode'] = 'uphill'
28
29 self.pnl = wx.Panel(self)
30
31 st = wx.StaticText(self.pnl, label="Munter.py")
32 font = st.GetFont()
33 font.PointSize += 10
34 font = font.Bold()
35
36 st.SetFont(font)
37
38 #sizer = wx.BoxSizer(wx.VERTICAL)
39 sizer = wx.BoxSizer(wx.HORIZONTAL)
40 sizer.Add(st, wx.SizerFlags().Border(wx.TOP|wx.LEFT, 0))
41 #self.pnl.SetSizer(sizer)
42
43 # text entry fields
44 self.st_distance = wx.StaticText(self.pnl, label="Distance: ")
45 self.te_distance = wx.TextCtrl(self.pnl, value="0", size=(140, -1))
46
47 self.st_elevation = wx.StaticText(self.pnl, label="Elevation: ")
48 self.te_elevation = wx.TextCtrl(self.pnl, value="0", size=(140, -1))
49
50 self.st_fitness = wx.StaticText(self.pnl, label="Fitness: ")
51 cb_fitness_choices = ['slow', 'average', 'fast']
52 cb_fitness_default = 'average'
53 self.cb_fitness = wx.ComboBox(self.pnl, choices=cb_fitness_choices,
54 value=cb_fitness_default, style=wx.CB_READONLY)
55
56 self.st_travel_mode = wx.StaticText(self.pnl, label="Travel Mode: ")
57 cb_travel_mode_choices = ['uphill', 'flat', 'downhill', 'bushwhacking']
58 cb_travel_mode_default = 'uphill'
59 self.cb_travel_mode = wx.ComboBox(self.pnl, choices=cb_travel_mode_choices,
60 value=cb_travel_mode_default, style=wx.CB_READONLY)
61
62 self.st_units = wx.StaticText(self.pnl, label="Units: ")
63 cb_units_choices = ['imperial', 'metric']
64 cb_units_default = 'imperial'
65 self.cb_units = wx.ComboBox(self.pnl, choices=cb_units_choices,
66 value=cb_units_default, style=wx.CB_READONLY)
67
68 # static text
69 self.st_mtc = wx.StaticText(self.pnl, label="0h",
70 style=wx.ALIGN_CENTRE_HORIZONTAL)
71
72 st_mtc_font = st.GetFont()
73 st_mtc_font.PointSize += 10
74 self.st_mtc.SetFont(st_mtc_font)
75
76 # bindings
77 self.pnl.Bind(wx.EVT_TEXT, self.update_distance, self.te_distance)
78 self.pnl.Bind(wx.EVT_TEXT, self.update_elevation, self.te_elevation)
79 self.cb_fitness.Bind(wx.EVT_COMBOBOX, self.update_fitness)
80 self.cb_travel_mode.Bind(wx.EVT_COMBOBOX, self.update_travel_mode)
81 self.cb_units.Bind(wx.EVT_COMBOBOX, self.update_units)
82
83 # buttons
84 b_clear = wx.Button(self.pnl, wx.NewId(), '&Clear', (-1, -1),
85 wx.DefaultSize)
86
87 # layout
88 b = 5
89 w = 100
90
91 static_line = wx.StaticLine(self.pnl, wx.NewId(), style=wx.LI_HORIZONTAL)
92
93 hsizer_distance = wx.BoxSizer(wx.HORIZONTAL)
94 hsizer_distance.Add(self.st_distance, 0, wx.RIGHT, b)
95 hsizer_distance.Add(self.te_distance, 1, wx.GROW, b)
96 hsizer_distance.SetItemMinSize(self.st_distance, (w, -1))
97
98 hsizer_elevation = wx.BoxSizer(wx.HORIZONTAL)
99 hsizer_elevation.Add(self.st_elevation, 0, wx.RIGHT, b)
100 hsizer_elevation.Add(self.te_elevation, 1, wx.GROW, b)
101 hsizer_elevation.SetItemMinSize(self.st_elevation, (w, -1))
102
103 hsizer_fitness = wx.BoxSizer(wx.HORIZONTAL)
104 hsizer_fitness.Add(self.st_fitness, 0, wx.RIGHT, b)
105 hsizer_fitness.Add(self.cb_fitness, 1, wx.GROW, b)
106 hsizer_fitness.SetItemMinSize(self.st_fitness, (w, -1))
107
108 hsizer_travel_mode = wx.BoxSizer(wx.HORIZONTAL)
109 hsizer_travel_mode.Add(self.st_travel_mode, 0, wx.RIGHT, b)
110 hsizer_travel_mode.Add(self.cb_travel_mode, 1, wx.GROW, b)
111 hsizer_travel_mode.SetItemMinSize(self.st_travel_mode, (w, -1))
112
113 hsizer_units = wx.BoxSizer(wx.HORIZONTAL)
114 hsizer_units.Add(self.st_units, 0, wx.RIGHT, b)
115 hsizer_units.Add(self.cb_units, 1, wx.GROW, b)
116 hsizer_units.SetItemMinSize(self.st_units, (w, -1))
117
118 hsizer_mtc = wx.BoxSizer(wx.HORIZONTAL)
119 hsizer_mtc.Add(self.st_mtc, 1, wx.GROW, b)
120 hsizer_mtc.SetItemMinSize(self.st_mtc, (w, -1))
121
122 hsizer5 = wx.BoxSizer(wx.HORIZONTAL)
123 hsizer5.Add(b_clear, 0)
124
125 b = 5
126 vsizer1 = wx.BoxSizer(wx.VERTICAL)
127 vsizer1.Add(sizer, 0, wx.EXPAND | wx.ALL, b*b)
128 vsizer1.Add(hsizer_distance, 0, wx.EXPAND | wx.ALL, b)
129 vsizer1.Add(hsizer_elevation, 0, wx.EXPAND | wx.ALL, b)
130 vsizer1.Add(hsizer_fitness, 0, wx.EXPAND | wx.ALL, b)
131 vsizer1.Add(hsizer_travel_mode, 0, wx.EXPAND | wx.ALL, b)
132 vsizer1.Add(hsizer_units, 0, wx.EXPAND | wx.ALL, b)
133 vsizer1.Add(hsizer_mtc, 0, wx.EXPAND | wx.ALL, b)
134 vsizer1.Add(static_line, 0, wx.GROW | wx.ALL, b)
135 vsizer1.Add(hsizer5, 0, wx.ALIGN_RIGHT | wx.ALL, b)
136
137 self.pnl.SetSizerAndFit(vsizer1)
138 self.pnl.SetClientSize(vsizer1.GetSize())
139
140 def update_distance(self, event):
141 value = self.te_distance.GetValue()
142 if value:
143 self.props['distance'] = float(value)
144 self.update_mtc()
145
146 def update_elevation(self, event):
147 value = self.te_elevation.GetValue()
148 if value:
149 self.props['elevation'] = int(value)
150 self.update_mtc()
151
152 def update_fitness(self, event):
153 value = self.cb_fitness.GetValue()
154 if value:
155 self.props['fitness'] = value
156 self.update_mtc()
157
158 def update_travel_mode(self, event):
159 value = self.cb_travel_mode.GetValue()
160 if value:
161 self.props['travel_mode'] = value
162 self.update_mtc()
163
164 def update_units(self, event):
165 value = self.cb_units.GetValue()
166 if value:
167 self.props['units'] = value
168 self.update_mtc()
169
170 def update_mtc(self):
171 if (self.props['distance'] is None) or (self.props['elevation'] is None):
172 return
173
174 est = munter.time_calc(self.props['distance'],
175 self.props['elevation'],
176 self.props['fitness'],
177 self.props['travel_mode'],
178 self.props['units'])
179
180 hours = int(est['time'])
181 minutes = int((est['time'] - hours) * 60)
182 self.st_mtc.SetLabel("{human_time}".format(
183 human_time="{hours} hours {minutes} minutes".format(
184 hours=hours,
185 minutes=minutes)))
186
187 self.pnl.Layout()
188
189 def startup():
190 app = wx.App()
191 frm = MainFrame(None)
192 frm.Show()
193
194 app.MainLoop()