1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185
|
# Copyright (c) 2007, Enthought, Inc.
# License: BSD Style.
"""
This program demonstrates defining and visualizing dynamic ranges.
A dynamic range is a range whose low or high limit can be modified dynamically
at run time.
You can define a dynamic range using the standard Range trait and specifying
the name of other traits as either the low or high limit value (or both). In
fact, it is even possible to specify the default value of the range trait as
another trait if desired. The traits used as low, high or default values need
not be defined on the same object, but can be defined on any object reachable
from the object (i.e. it allows use of extended trait names).
In this completely artificial example, we present an example of the first
hotel at the North Pole. The hotel guarantees that each room will be heated
to a certain minimum temperature. However, that minimum value is determined
both by the time of year and the current cost of heating fuel, so it can vary;
but each room is guaranteed the same minimum temperature.
Each guest of the hotel can choose among several different plans that allow
them to control the maximum room temperature. Higher maximum room temperatures
correspond to higher plan costs. Thus each guest must decide which plan (and
highest maximum room temperature) to pay for.
And finally, each guest is free to set the current room temperature anywhere
between the hotel minimum value and the guest's maximum plan value.
The demo is organized as a series of tabs corresponding to each guest of the
hotel, with access to the plan they have chosen and the current room
temperature setting. In addition, there is a master set of hotel information
displayed at the top of the view which allows you to change the season of the
year and the current fuel cost. There is also a button to allow more guests to
be added to the hotel.
Notes:
- The dynamic range trait is the 'temperature' trait in the Guest class. It
depends upon traits defined both in the Guest instance as well as in the
containing Hotel object.
- As with most traits code and examples, observe how much of the code is
'declarative' versus 'imperative'. Note also the use of properties and
'depends_on' metadata, as well as 'cached_property' and 'on_trait_change'
method decorators.
- Try dragging the guest tabs around so that you can see multiple guests
simultaneously, and then watch the behavior of the guest's 'temperature'
slider as you adjust the hotel 'season', 'fuel cost' and each guest's
'plan'.
"""
#-- Imports --------------------------------------------------------------------
import logging, sys
logging.basicConfig(stream=sys.stderr)
from random \
import choice
from traits.api \
import HasPrivateTraits, Str, Enum, Range, List, Button, Instance, \
Property, cached_property, on_trait_change
from traitsui.api \
import View, VGroup, HGroup, Item, ListEditor, spring
#-- The Hotel class ------------------------------------------------------------
class Hotel ( HasPrivateTraits ):
# The season of the year:
season = Enum( 'Winter', 'Spring', 'Summer', 'Fall' )
# The current cost of heating fuel (in dollars/gallon):
fuel_cost = Range( 2.00, 10.00, 4.00 )
# The current minimum temparature allowed by the hotel:
min_temperature = Property( depends_on = 'season, fuel_cost' )
# The guests currently staying at the hotel:
guests = List # ( Instance( 'Guest' ) )
# Add a new guest to the hotel:
add_guest = Button( 'Add Guest' )
# The view of the hotel:
view = View(
VGroup(
HGroup(
Item( 'season' ), '20',
Item( 'fuel_cost', width = 300 ),
spring,
Item( 'add_guest', show_label = False ),
show_border = True,
label = 'Hotel Information'
),
VGroup(
Item( 'guests',
style = 'custom',
editor = ListEditor( use_notebook = True,
deletable = True,
dock_style = 'tab',
page_name = '.name' )
),
show_labels = False,
show_border = True,
label = 'Guests'
)
),
title = 'The Belmont Hotel Dashboard',
width = 0.6,
height = 0.2,
resizable = True
)
# Property implementations:
@cached_property
def _get_min_temperature ( self ):
return ({ 'Winter': 32,
'Spring': 40,
'Summer': 45,
'Fall': 40 }[ self.season ] +
min( int( 60.00 / self.fuel_cost ), 15 ))
# Event handlers:
@on_trait_change( 'guests[]' )
def _guests_modified ( self, removed, added ):
for guest in added:
guest.hotel = self
def _add_guest_changed ( self ):
self.guests.append( Guest() )
#-- The Guest class ------------------------------------------------------------
class Guest ( HasPrivateTraits ):
# The name of the guest:
name = Str
# The hotel the guest is staying at:
hotel = Instance( Hotel )
# The room plan the guest has chosen:
plan = Enum( 'Flop house', 'Cheap', 'Cozy', 'Deluxe' )
# The maximum temperature allowed by the guest's plan:
max_temperature = Property( depends_on = 'plan' )
# The current room temperature as set by the guest:
temperature = Range( 'hotel.min_temperature', 'max_temperature' )
# The view of the guest:
view = View(
Item( 'plan' ),
Item( 'temperature' )
)
# Property implementations:
@cached_property
def _get_max_temperature ( self ):
return { 'Flop house': 62,
'Cheap': 66,
'Cozy': 75,
'Deluxe': 85 }[ self.plan ]
# Default values:
def _name_default ( self ):
return choice(
[ 'Leah', 'Vibha', 'Janet', 'Jody', 'Dave', 'Evan', 'Ilan', 'Gael',
'Peter', 'Robert', 'Judah', 'Eric', 'Travis', 'Mike', 'Bryce',
'Chris' ] )
#-- Create the demo ------------------------------------------------------------
# Create the demo object:
demo = Hotel( guests = [ Guest() for i in range( 5 ) ] )
# Run the demo (if invoked from the command line):
if __name__ == '__main__':
logging.info('Start!')
demo.configure_traits()
|