1 # -*- coding: utf-8 -*-
10 from . import __progname__
as progname
11 from . import __version__
as version
13 class MainFrame(wx
.Frame
):
19 def __init__(self
, *args
, **kw
):
20 """add to the init process for the wx.Frame"""
21 super(MainFrame
, self
).__init
__(*args
, **kw
)
24 self
.SetTitle(progname
)
25 self
.SetSize(600, 400)
27 self
.props
= self
.init_props()
28 self
.pnl
= wx
.Panel(self
)
30 # setup the GUI itself
31 self
.create_wx_items()
32 self
.establish_wx_bindings()
38 """centralized place to initialize props var"""
41 props
['elevation'] = 0
42 props
['fitness'] = 'average'
43 props
['units'] = 'imperial'
44 props
['travel_mode'] = 'uphill'
47 def create_wx_items(self
):
48 """create wxPython items"""
49 # title bar / program name
50 self
.program_name
= wx
.StaticText(self
.pnl
, label
=progname
)
51 font
= self
.program_name
.GetFont()
55 self
.program_name
.SetFont(font
)
58 self
.st_distance
= wx
.StaticText(self
.pnl
, label
="Distance: ", style
=wx
.ALIGN_RIGHT
)
59 self
.te_distance
= wx
.TextCtrl(self
.pnl
, value
="0", size
=(140, -1))
61 self
.st_elevation
= wx
.StaticText(self
.pnl
, label
="Elevation: ", style
=wx
.ALIGN_RIGHT
)
62 self
.te_elevation
= wx
.TextCtrl(self
.pnl
, value
="0", size
=(140, -1))
64 self
.st_fitness
= wx
.StaticText(self
.pnl
, label
="Fitness: ", style
=wx
.ALIGN_RIGHT
)
65 rb_fitness_choices
= ['slow', 'average', 'fast']
66 rb_fitness_default
= 'average'
67 self
.rb_fitness
= wx
.ComboBox(self
.pnl
, choices
=rb_fitness_choices
,
68 value
=rb_fitness_default
,
71 self
.st_travel_mode
= wx
.StaticText(self
.pnl
,
72 label
="Travel Mode: ",
74 rb_travel_mode_choices
= ['uphill', 'flat', 'downhill', 'bushwhacking']
75 rb_travel_mode_default
= 'uphill'
76 self
.rb_travel_mode
= wx
.ComboBox(self
.pnl
,
77 choices
=rb_travel_mode_choices
,
78 value
=rb_travel_mode_default
,
81 self
.st_units
= wx
.StaticText(self
.pnl
, label
="Units: ", style
=wx
.ALIGN_RIGHT
)
82 rb_units_choices
= ['imperial', 'metric']
83 rb_units_default
= 'imperial'
86 for choice
in rb_units_choices
:
88 style
= wx
.RB_GROUP
if choice
== rb_units_default
else 0
89 self
.rb_units
.append(wx
.RadioButton(self
.pnl
, label
=label
, style
=style
))
92 self
.st_mtc
= wx
.StaticText(self
.pnl
, label
="",
93 style
=wx
.ALIGN_CENTRE_HORIZONTAL
)
95 st_mtc_font
= self
.program_name
.GetFont()
96 st_mtc_font
.PointSize
+= 10
97 self
.st_mtc
.SetFont(st_mtc_font
)
100 self
.b_reset
= wx
.Button(self
.pnl
, wx
.NewId(), '&Reset', (-1, -1),
103 def establish_wx_bindings(self
):
104 """establish wxPython bindings"""
105 self
.pnl
.Bind(wx
.EVT_TEXT
, self
.update_distance
, self
.te_distance
)
106 self
.pnl
.Bind(wx
.EVT_TEXT
, self
.update_elevation
, self
.te_elevation
)
107 self
.rb_fitness
.Bind(wx
.EVT_COMBOBOX
, self
.update_fitness
)
108 self
.rb_travel_mode
.Bind(wx
.EVT_COMBOBOX
, self
.update_travel_mode
)
109 self
.b_reset
.Bind(wx
.EVT_BUTTON
, self
.reset
)
111 for rb_unit
in self
.rb_units
:
112 rb_unit
.Bind(wx
.EVT_RADIOBUTTON
, self
.update_units
)
114 def do_wx_layout(self
):
115 """layout the wxPython items"""
119 sizer
= wx
.BoxSizer(wx
.HORIZONTAL
)
120 sizer
.Add(self
.program_name
, wx
.SizerFlags().Border(wx
.TOP|wx
.LEFT
, 0))
122 static_line
= wx
.StaticLine(self
.pnl
, wx
.NewId(), style
=wx
.LI_HORIZONTAL
)
124 hsizer_distance
= wx
.BoxSizer(wx
.HORIZONTAL
)
125 hsizer_distance
.Add(self
.st_distance
, 0, wx
.RIGHT
, border
)
126 hsizer_distance
.Add(self
.te_distance
, 1, wx
.GROW
, border
)
127 hsizer_distance
.SetItemMinSize(self
.st_distance
, (width
, -1))
129 hsizer_elevation
= wx
.BoxSizer(wx
.HORIZONTAL
)
130 hsizer_elevation
.Add(self
.st_elevation
, 0, wx
.RIGHT
, border
)
131 hsizer_elevation
.Add(self
.te_elevation
, 1, wx
.GROW
, border
)
132 hsizer_elevation
.SetItemMinSize(self
.st_elevation
, (width
, -1))
134 hsizer_fitness
= wx
.BoxSizer(wx
.HORIZONTAL
)
135 hsizer_fitness
.Add(self
.st_fitness
, 0, wx
.RIGHT
, border
)
136 hsizer_fitness
.Add(self
.rb_fitness
, 1, wx
.GROW
, border
)
137 hsizer_fitness
.SetItemMinSize(self
.st_fitness
, (width
, -1))
139 hsizer_travel_mode
= wx
.BoxSizer(wx
.HORIZONTAL
)
140 hsizer_travel_mode
.Add(self
.st_travel_mode
, 0, wx
.RIGHT
, border
)
141 hsizer_travel_mode
.Add(self
.rb_travel_mode
, 1, wx
.GROW
, border
)
142 hsizer_travel_mode
.SetItemMinSize(self
.st_travel_mode
, (width
, -1))
144 hsizer_units
= wx
.BoxSizer(wx
.HORIZONTAL
)
145 hsizer_units
.Add(self
.st_units
, 0, wx
.RIGHT
, border
)
146 for rb_unit
in range(len(self
.rb_units
)):
147 hsizer_units
.Add(self
.rb_units
[rb_unit
], rb_unit
+ 1, wx
.GROW
, border
)
148 hsizer_units
.SetItemMinSize(self
.st_units
, (width
, -1))
150 hsizer_mtc
= wx
.BoxSizer(wx
.HORIZONTAL
)
151 hsizer_mtc
.Add(self
.st_mtc
, 1, wx
.GROW
, border
)
152 hsizer_mtc
.SetItemMinSize(self
.st_mtc
, (width
, -1))
154 hsizer5
= wx
.BoxSizer(wx
.HORIZONTAL
)
155 hsizer5
.Add(self
.b_reset
, 0)
157 vsizer1
= wx
.BoxSizer(wx
.VERTICAL
)
158 vsizer1
.Add(sizer
, 0, wx
.EXPAND | wx
.ALL
, border
*border
)
159 vsizer1
.Add(hsizer_distance
, 0, wx
.EXPAND | wx
.ALL
, border
)
160 vsizer1
.Add(hsizer_elevation
, 0, wx
.EXPAND | wx
.ALL
, border
)
161 vsizer1
.Add(hsizer_fitness
, 0, wx
.EXPAND | wx
.ALL
, border
)
162 vsizer1
.Add(hsizer_travel_mode
, 0, wx
.EXPAND | wx
.ALL
, border
)
163 vsizer1
.Add(hsizer_units
, 0, wx
.EXPAND | wx
.ALL
, border
)
164 vsizer1
.Add(hsizer_mtc
, 0, wx
.EXPAND | wx
.ALL
, border
)
165 vsizer1
.Add(static_line
, 0, wx
.GROW | wx
.ALL
, border
)
166 vsizer1
.Add(hsizer5
, 0, wx
.ALIGN_RIGHT | wx
.ALL
, border
)
168 self
.pnl
.SetSizerAndFit(vsizer1
)
169 self
.pnl
.SetClientSize(vsizer1
.GetSize())
172 def update_distance(self
, event
):
173 """updates distance prop"""
174 value
= event
.GetEventObject().GetValue()
177 new_val
= float(value
)
178 self
.props
['distance'] = new_val
180 # reset GUI to last-accepted val
181 self
.te_distance
.SetValue(str(self
.props
['distance']))
184 def update_elevation(self
, event
):
185 """updates elevation prop"""
186 value
= event
.GetEventObject().GetValue()
190 self
.props
['elevation'] = new_val
192 # reset GUI to last-accepted val
193 self
.te_elevation
.SetValue(str(self
.props
['elevation']))
196 def update_fitness(self
, event
):
197 """updates fitness prop"""
198 value
= event
.GetEventObject().GetValue()
200 self
.props
['fitness'] = value
203 def update_travel_mode(self
, event
):
204 """updates travel_mode prop"""
205 value
= event
.GetEventObject().GetValue()
207 self
.props
['travel_mode'] = value
210 def update_units(self
, event
):
211 """updates units prop"""
212 value
= event
.GetEventObject().GetLabel()
214 self
.props
['units'] = value
217 def reset(self
, event
):
218 """resets all values"""
220 self
.props
= self
.init_props()
221 self
.te_distance
.SetValue(str(self
.props
['distance']))
222 self
.te_elevation
.SetValue(str(self
.props
['elevation']))
223 self
.rb_fitness
.SetValue(str(self
.props
['fitness']))
224 self
.rb_travel_mode
.SetValue(str(self
.props
['travel_mode']))
225 # leave units as the user selected
229 def update_mtc(self
):
230 """updates mtc, the final result the user wants"""
231 if (self
.props
['distance'] is None) or (self
.props
['elevation'] is None):
234 est
= munter
.time_calc(self
.props
['distance'],
235 self
.props
['elevation'],
236 self
.props
['fitness'],
237 self
.props
['travel_mode'],
240 hours
= int(est
['time'])
241 minutes
= int((est
['time'] - hours
) * 60)
242 self
.st_mtc
.SetLabel("{human_time}".format(
243 human_time
="{hours} hours {minutes} minutes".format(
250 """kick off the GUI"""
252 frm
= MainFrame(None)