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
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
|
# -*- coding: utf-8 -*-
#!/usr/bin/python
import random
import copy
NO_TRACKER = -1 # Tracker id for untracked values
class TrackerInfo(object):
'''Tracker state machine(singleton)
The singleton instance of this class is used to manipulate tracker
selection and tracked values, as well as interrogate tracker colors.
_tracks - dictionary for tracked values. The tracker id is used as the
key. A tracker is a dictionary that stored tracked values keyed by
its coordinates(x, y). _tracks[tracker_id][(x, y)] == tracked value
current_tracker - The tracker id for the currently selected tracker
showing_tracker - The tracker id for the tracker that is currently being
viewed. The point to this member is to store off the tracker when
the player switches to "Untracked" so that the last tracker they were
working on stays in view after the switch.
'''
__single = None
_tracks = {}
_colors = {}
current_tracker = NO_TRACKER
showing_tracker = NO_TRACKER
def __new__(cls, *args, **kwargs):
'''Overridden to implement as a singleton
'''
# Check to see if a __single exists already for this class
# Compare class types instead of just looking for None so
# that subclasses will create their own __single objects
if cls != type(cls.__single):
cls.__single = object.__new__(cls, *args, **kwargs)
return cls.__single
def __init__(self):
# Only initialize the colors once
if self._colors:
return
# Use tango colors recommended here:
# http://tango.freedesktop.org/Tango_Icon_Theme_Guidelines
for tracker_id, cols in enumerate(
[(32, 74, 135), # Sky Blue 3
(78, 154, 6), # Chameleon 3
(206, 92, 0), # Orange 3
(143, 89, 2), # Chocolate 3
(92, 53, 102), # Plum 3
(85, 87, 83), # Aluminium 5
(196, 160, 0) # Butter 3
]):
self._colors[tracker_id] = tuple([x / 255.0 for x in cols])
def load(self, pickle):
self.current_tracker, self.showing_tracker, self._tracks = pickle
def save(self):
return (self.current_tracker, self.showing_tracker, self.get_trackers())
def create_tracker (self, tracker_id = 0):
'''Create storage for a new tracker
tracker_id can be passed in to attempt creation of a specific id, but
if the tracker_id already exists then the passed number will be
incremented until a suitable key can be allocated.
'''
if not tracker_id:
tracker_id = 0
while self._tracks.has_key(tracker_id):
tracker_id += 1
self._tracks[tracker_id] = {}
return tracker_id
def get_tracker(self, tracker_id):
if self._tracks.has_key(tracker_id):
return self._tracks[tracker_id]
def delete_tracker(self, tracker_id):
if self._tracks.has_key(tracker_id):
del self._tracks[tracker_id]
def reset (self):
''' Reset the tracker information
'''
self._tracks = {}
self.current_tracker = NO_TRACKER
self.showing_tracker = NO_TRACKER
def use_trackers (self, trackers):
self._tracks = trackers
def get_trackers(self):
return copy.deepcopy(self._tracks)
def set_tracker(self, tracker_id):
self.current_tracker = tracker_id
if tracker_id != NO_TRACKER:
self.showing_tracker = tracker_id
def hide_tracker(self):
self.showing_tracker = NO_TRACKER
def get_tracker_view(self):
return((self.current_tracker, self.showing_tracker))
def set_tracker_view(self, tview):
self.current_tracker, self.showing_tracker = tview
def get_color (self, tracker_id):
# Untracked items don't get specially colored
if tracker_id == NO_TRACKER:
return None
# Create a random color for new trackers that are beyond the defaults
if not self._colors.has_key(tracker_id):
random_color = self._colors[0]
while random_color in self._colors.values():
# If we have generated all possible colors, this will
# enter an infinite loop
random_color = (random.randint(0, 100)/100.0,
random.randint(0, 100)/100.0,
random.randint(0, 100)/100.0)
self._colors[tracker_id] = random_color
return self._colors[tracker_id]
def get_color_markup(self, tracker_id):
color_tuple = self.get_color (tracker_id)
if not color_tuple:
return None
color_markup = '#'
color_markup += str(hex(int(color_tuple[0]*255))[2:]).zfill(2)
color_markup += str(hex(int(color_tuple[1]*255))[2:]).zfill(2)
color_markup += str(hex(int(color_tuple[2]*255))[2:]).zfill(2)
return color_markup.upper()
def get_current_color(self):
return self.get_color(self.current_tracker)
def get_showing_color(self):
return self.get_color(self.showing_tracker)
def add_trace(self, x, y, value, tracker_id = None):
'''Add a tracked value
By default(tracker_id set to None) this method adds a value to the
current tracker. tracker_id can be passed in to add it to a specific
tracker.
'''
if tracker_id == None:
to_tracker = self.current_tracker
else:
to_tracker = tracker_id
# Need a tracker
if to_tracker == NO_TRACKER:
return
# Make sure the dictionary is available for the tracker.
if not self._tracks.has_key(to_tracker):
self._tracks[to_tracker] = {}
# Add it
self._tracks[to_tracker][(x, y)] = value
def remove_trace(self, x, y, from_tracker = None):
'''Remove a tracked value
By default(from_tracker set to None) this method removes all tracked
values for a particular cell(x, y coords). from_tracker can be passed
to remove tracked values from a particular tracker only.
'''
if from_tracker == None:
from_tracks = self._tracks.keys()
else:
from_tracks = [from_tracker]
# Delete them
for tracker in from_tracks:
if self._tracks.has_key(tracker) and self._tracks[tracker].has_key((x, y)):
del self._tracks[tracker][(x, y)]
def get_trackers_for_cell(self, x, y):
'''Return all trackers for a cell
This function is used for the undo mechanism. A list in the format
(tracker, value) is returned so that it may later be reinstated with
reset_trackers_for_cell().
'''
ret = []
for tracker, track in self._tracks.items():
if track.has_key((x, y)):
ret.append((tracker, track[(x, y)]))
return ret
def reset_trackers_for_cell(self, x, y, old_trackers):
'''Reset all trackers to a previous state for a cell
This function is used for the undo mechanism. It reinstates the
tracked values the list created by get_trackers_for_cell().
'''
# Remove all the current traces
for tracker, track in self._tracks.items():
if track.has_key((x, y)):
del self._tracks[tracker][(x, y)]
# Add the old ones back
for tracker, value in old_trackers:
self._tracks[tracker][(x, y)] = value
|