Home | Trees | Indices | Help |
|
---|
|
1 # The base Converter class. Not to be used directly. 2 # For a commented example on how to write general converter modules, see the 3 # file BaseConverter.py. But first, please, read below if a RatioConverter isn't 4 # well suitable for your desired task. 57 """The base class for the converters. The converters look after maintaining 8 the list of currently shown values - initialising, accepting keyboard input, 9 etc..""" 10 11 # the name of the class 12 __name__ = 'Converter' 13 # a short description to be used for selecting the converter 14 __title__ = 'Base' 15 16 # the number of fields shown on the display between 2 and 4 17 num_fields = 0 18 # field captions up to 4 chars long 19 field_names = [] 20 # zero-based index of field having input focus 21 active_field = 0 22 # the list of currently shown 'values'. They should always be strings. 23 values = [] 24 # replace: True = replace all the input by next keypress 25 replace = True 26 27 # initialize the list of values and fill it with defaults (strings!). 28 # Override this if you don't want then be '0's.128 129 130 # A subclass of Converter representing numerical converters whose field are 131 # bound by a simple linear relation. It cares about float value input and output 132 # and conversion, so the developer who wants to use it doesn't need to provide 133 # any functions. Besides the __anything__, num_fields and field_names variables, 134 # he must only provide a list describing desired ratios (see below). 135 # Not to be used directly. See LengthConverter for a commented example. 13630 self.values = [] 31 for i in range(self.num_fields): 32 self.values.append('0') 33 self.active_field = 03436 """If accepted, appends the pressed key to the value in the currently 37 active field.""" 38 translate_dict = {'comma': '.', 'period': '.', 'Add': '+', 'plus': '+', 39 'Subtract': '-', 'minus': '-'} 40 if key[:3] == 'KP_': 41 key = key[3:] # keys from numerical keypad come as digits 42 if translate_dict.has_key(key): 43 key = translate_dict[key] 44 if key == 'BackSpace': # try to guess :-) 45 self.values[self.active_field] = self.values[self.active_field][:-1] 46 elif key == 'Escape': # clean the field 47 self.values[self.active_field] = '' 48 elif key == 'Down': # move field focus 49 if self.active_field < self.num_fields - 1: 50 self.active_field += 1 51 self.replace = True # after a change, don't append next pressed 52 return True # key but start over 53 return False 54 elif key == 'Up': 55 if self.active_field > 0: 56 self.active_field -= 1 57 self.replace = True 58 return True 59 return False 60 elif key == 'Tab': 61 self.active_field += 1 62 self.active_field %= self.num_fields 63 self.replace = True 64 return True 65 else: # leave other keys unchanged 66 if not self.filter_key(key): 67 return False 68 if self.replace: 69 self.values[self.active_field] = key 70 # limit input length to 10 characters 71 elif len(self.values[self.active_field]) < 10: 72 self.values[self.active_field] = \ 73 self.values[self.active_field] + key 74 self.replace = False 75 self.neaten_input() 76 self.convert() 77 return True78 79 # You can use this function instead of str or fixed-width % - it leaves 80 # 3 digits after the decimal point for floats, and no decimal part if the 81 # number is integer. 82 # Serves good if the same converter can be used for both ints ant floats, 83 # so that the user doesn't get '1.000' when not necessary, also for showing 84 # '0' instead of '0.000' in all cases. 90 91 # Overridable functions: 92 93 # neaten_input: see the docstring 94 # Return value: none 95 # If you don't want such function, override it in your converter with pass. 96 # If you override it by something more complicated, be careful not to modify 97 # the current value so that it breaks the input.99 """Replaces an empty value with '0' and again removes leading '0' in 100 a non-empty string.""" 101 # This version is aware of the possibility of negative input values, 102 # but you must allow + and - keys in filter_key and avoid an error when 103 # the input is '-'. See TemperatureConverter for an example. 104 if self.values[self.active_field] == '' or \ 105 self.values[self.active_field][-1] == '+': 106 self.values[self.active_field] = '0' 107 elif self.values[self.active_field][-1] == '-': 108 self.values[self.active_field] = '-' 109 if len(self.values[self.active_field]) > 1 and \ 110 self.values[self.active_field][0] == '0': 111 self.values[self.active_field] = self.values[self.active_field][1:]112 113 # filter_key: decides if pressed key can be appended to current value. 114 # "key" is the GDK name of the key pressed by user 115 # Return value: True - accept key, False - reject it. 116 # There is no way to modify the value of key. 117 # Be prepared for various "keys", e.g., 'apostrophe' must not match 'a'. 121 122 # convert: actualizes field values to reflect input 123 # Return value: none 124 # Active value can be modified, but not so that it breaks the input.138 """A base class of converters having linear dependances between their 139 fields.""" 140 141 __name__ = 'RatioConverter' 142 __title__ = 'Base / Ratio' 143 144 # The list of relative weights of the individual fields. The length of this 145 # list must be equal to num_fields. The ratio between two fields will be 146 # inverse to the ratio of corresponding entries in this list. For example, 147 # see LengthConverter. One may ask whether not to better use relative 148 # ratios, i.e., ratios between fields = ratio between entries, the answer is 149 # that this approach is more intuitive. You would set 1 for some unit and 150 # 1000 for the corresponding kilo-unit this way. 151 # The above implies that the values in this list are relative to whichever 152 # one you would choose, e.g., [10, 5, 1] (will be converted to float) is 153 # equivalent to [2.0, 1.0, 0.2]. Actually, integer (exact) values are 154 # preferred if they reflect the logic of the conversion. 155 weights = [] 156176 # Note: if you don't like the Converter.str() function used above which 177 # tries to always display integers as integers, you can provide your own, 178 # e.g., def str(self, val): return '%.3f' % val 179158 # Accept digits 159 if key.isdigit(): 160 return True 161 # Also accept a decimal point if there is no one yet 162 elif key == '.': 163 return not ('.' in self.values[self.active_field]) 164 else: 165 return False166168 # A multiply-then-divide approach is used to help avoiding little 169 # inaccuracies arising in operations like (3/10)*100. 170 val = float(self.values[self.active_field]) \ 171 * self.weights[self.active_field] 172 for i in range(self.num_fields): 173 if i == self.active_field: 174 continue 175 self.values[i] = self.str(val / float(self.weights[i]))
Home | Trees | Indices | Help |
|
---|
Generated by Epydoc 3.0.1 on Mon Jun 6 10:56:41 2011 | http://epydoc.sourceforge.net |