diff options
author | Mac Mollison <mollison@cs.unc.edu> | 2010-03-20 17:40:00 -0400 |
---|---|---|
committer | Mac Mollison <mollison@cs.unc.edu> | 2010-03-20 17:40:00 -0400 |
commit | 90d1825ad3ad20430734c1c75b899d14c4e6b700 (patch) | |
tree | 834a898b506f37a35c73d3845061ec8f7284394e | |
parent | 7fdb4dbbbca577efbeec47cd1364eb319346a0cc (diff) |
Zapped a bunch of trailing whitespace
-rwxr-xr-x | install.py | 4 | ||||
-rw-r--r-- | unit_trace/naive_trace_reader.py | 12 | ||||
-rw-r--r-- | unit_trace/progress.py | 2 | ||||
-rw-r--r-- | unit_trace/sanitizer.py | 2 | ||||
-rw-r--r-- | unit_trace/stats.py | 2 | ||||
-rw-r--r-- | unit_trace/stdout_printer.py | 2 | ||||
-rw-r--r-- | unit_trace/trace_reader.py | 16 | ||||
-rw-r--r-- | unit_trace/viz/convert.py | 24 | ||||
-rw-r--r-- | unit_trace/viz/draw.py | 628 | ||||
-rw-r--r-- | unit_trace/viz/format.py | 30 | ||||
-rw-r--r-- | unit_trace/viz/renderer.py | 16 | ||||
-rw-r--r-- | unit_trace/viz/schedule.py | 252 | ||||
-rw-r--r-- | unit_trace/viz/viewer.py | 218 | ||||
-rwxr-xr-x | unit_trace/viz/visualizer.py | 6 |
14 files changed, 607 insertions, 607 deletions
@@ -4,8 +4,8 @@ | |||
4 | # Description | 4 | # Description |
5 | ################################################################################ | 5 | ################################################################################ |
6 | 6 | ||
7 | # This script installes (or re-installs) the unit_trace Python module, so that | 7 | # This script installes (or re-installs) the unit_trace Python module, so that |
8 | # the unit_trace library can be imported with `import unit_trace` by a Python | 8 | # the unit_trace library can be imported with `import unit_trace` by a Python |
9 | # script, from anywhere on the system. | 9 | # script, from anywhere on the system. |
10 | 10 | ||
11 | # The installation merely consists of copying the unit_trace directory to | 11 | # The installation merely consists of copying the unit_trace directory to |
diff --git a/unit_trace/naive_trace_reader.py b/unit_trace/naive_trace_reader.py index 0f117b8..0f45895 100644 --- a/unit_trace/naive_trace_reader.py +++ b/unit_trace/naive_trace_reader.py | |||
@@ -31,18 +31,18 @@ def trace_reader(files): | |||
31 | data = f.read(RECORD_HEAD_SIZE) | 31 | data = f.read(RECORD_HEAD_SIZE) |
32 | try: | 32 | try: |
33 | type_num = struct.unpack_from('b',data)[0] | 33 | type_num = struct.unpack_from('b',data)[0] |
34 | except struct.error: | 34 | except struct.error: |
35 | break #We read to the end of the file | 35 | break #We read to the end of the file |
36 | type = _get_type(type_num) | 36 | type = _get_type(type_num) |
37 | try: | 37 | try: |
38 | values = struct.unpack_from(StHeader.format + | 38 | values = struct.unpack_from(StHeader.format + |
39 | type.format,data) | 39 | type.format,data) |
40 | record_dict = dict(zip(type.keys,values)) | 40 | record_dict = dict(zip(type.keys,values)) |
41 | except struct.error: | 41 | except struct.error: |
42 | f.close() | 42 | f.close() |
43 | print "Invalid record detected, stopping." | 43 | print "Invalid record detected, stopping." |
44 | exit() | 44 | exit() |
45 | 45 | ||
46 | # Convert the record_dict into an object | 46 | # Convert the record_dict into an object |
47 | record = _dict2obj(record_dict) | 47 | record = _dict2obj(record_dict) |
48 | 48 | ||
@@ -69,7 +69,7 @@ def _dict2obj(d): | |||
69 | o = Obj() | 69 | o = Obj() |
70 | for key in d.keys(): | 70 | for key in d.keys(): |
71 | o.__dict__[key] = d[key] | 71 | o.__dict__[key] = d[key] |
72 | return o | 72 | return o |
73 | 73 | ||
74 | ############################################################################### | 74 | ############################################################################### |
75 | # Trace record data types and accessor functions | 75 | # Trace record data types and accessor functions |
@@ -95,7 +95,7 @@ class StNameData(object): | |||
95 | keys = StHeader.keys + ['name'] | 95 | keys = StHeader.keys + ['name'] |
96 | message = 'The name of the executable of this process.' | 96 | message = 'The name of the executable of this process.' |
97 | 97 | ||
98 | class StParamData(object): | 98 | class StParamData(object): |
99 | format = 'IIIc' | 99 | format = 'IIIc' |
100 | formatStr = struct.Struct(StHeader.format + format) | 100 | formatStr = struct.Struct(StHeader.format + format) |
101 | keys = StHeader.keys + ['wcet','period','phase','partition'] | 101 | keys = StHeader.keys + ['wcet','period','phase','partition'] |
@@ -107,7 +107,7 @@ class StReleaseData(object): | |||
107 | keys = StHeader.keys + ['when','deadline'] | 107 | keys = StHeader.keys + ['when','deadline'] |
108 | message = 'A job was/is going to be released.' | 108 | message = 'A job was/is going to be released.' |
109 | 109 | ||
110 | #Not yet used by Sched Trace | 110 | #Not yet used by Sched Trace |
111 | class StAssignedData(object): | 111 | class StAssignedData(object): |
112 | format = 'Qc' | 112 | format = 'Qc' |
113 | formatStr = struct.Struct(StHeader.format + format) | 113 | formatStr = struct.Struct(StHeader.format + format) |
diff --git a/unit_trace/progress.py b/unit_trace/progress.py index d987ecd..d0f0482 100644 --- a/unit_trace/progress.py +++ b/unit_trace/progress.py | |||
@@ -25,7 +25,7 @@ def progress(stream): | |||
25 | 25 | ||
26 | start_time = 0 | 26 | start_time = 0 |
27 | count = 0 | 27 | count = 0 |
28 | 28 | ||
29 | for record in stream: | 29 | for record in stream: |
30 | if record.record_type=="event": | 30 | if record.record_type=="event": |
31 | count += 1 | 31 | count += 1 |
diff --git a/unit_trace/sanitizer.py b/unit_trace/sanitizer.py index 79315cc..598379a 100644 --- a/unit_trace/sanitizer.py +++ b/unit_trace/sanitizer.py | |||
@@ -49,5 +49,5 @@ def sanitizer(stream): | |||
49 | if record.type_name == 'switch_away': | 49 | if record.type_name == 'switch_away': |
50 | if (record.pid,record.job) not in jobs_switched_to: | 50 | if (record.pid,record.job) not in jobs_switched_to: |
51 | record.job -= 1 | 51 | record.job -= 1 |
52 | 52 | ||
53 | yield record | 53 | yield record |
diff --git a/unit_trace/stats.py b/unit_trace/stats.py index 34a842f..17c5fc9 100644 --- a/unit_trace/stats.py +++ b/unit_trace/stats.py | |||
@@ -32,7 +32,7 @@ def stats(stream): | |||
32 | rec = Obj() | 32 | rec = Obj() |
33 | rec.record_type = "meta" | 33 | rec.record_type = "meta" |
34 | rec.type_name = "stats" | 34 | rec.type_name = "stats" |
35 | rec.num_inversions = num_inversions | 35 | rec.num_inversions = num_inversions |
36 | rec.min_inversion = min_inversion | 36 | rec.min_inversion = min_inversion |
37 | rec.max_inversion = max_inversion | 37 | rec.max_inversion = max_inversion |
38 | rec.avg_inversion = avg_inversion | 38 | rec.avg_inversion = avg_inversion |
diff --git a/unit_trace/stdout_printer.py b/unit_trace/stdout_printer.py index f8d9a84..8842b71 100644 --- a/unit_trace/stdout_printer.py +++ b/unit_trace/stdout_printer.py | |||
@@ -62,7 +62,7 @@ def _print_inversion_end(record): | |||
62 | print #newline | 62 | print #newline |
63 | 63 | ||
64 | def _print_stats(record): | 64 | def _print_stats(record): |
65 | print "Inversion statistics" | 65 | print "Inversion statistics" |
66 | print "Num inversions: %d" % (record.num_inversions) | 66 | print "Num inversions: %d" % (record.num_inversions) |
67 | print "Min inversion: %d" % (record.min_inversion) | 67 | print "Min inversion: %d" % (record.min_inversion) |
68 | print "Max inversion: %d" % (record.max_inversion) | 68 | print "Max inversion: %d" % (record.max_inversion) |
diff --git a/unit_trace/trace_reader.py b/unit_trace/trace_reader.py index 44a3c75..e1d2095 100644 --- a/unit_trace/trace_reader.py +++ b/unit_trace/trace_reader.py | |||
@@ -5,7 +5,7 @@ | |||
5 | # trace_reader(files) returns an iterator which produces records | 5 | # trace_reader(files) returns an iterator which produces records |
6 | # in order from the files given. (the param is a list of files.) | 6 | # in order from the files given. (the param is a list of files.) |
7 | # | 7 | # |
8 | # Each record is just a Python object. It is guaranteed to have the following | 8 | # Each record is just a Python object. It is guaranteed to have the following |
9 | # attributes: | 9 | # attributes: |
10 | # - 'pid': pid of the task | 10 | # - 'pid': pid of the task |
11 | # - 'job': job number for that task | 11 | # - 'job': job number for that task |
@@ -66,7 +66,7 @@ def trace_reader(files): | |||
66 | # overwhelmingly probably. | 66 | # overwhelmingly probably. |
67 | for x in range(0,len(file_iter_buff)): | 67 | for x in range(0,len(file_iter_buff)): |
68 | for y in range(0,100): | 68 | for y in range(0,100): |
69 | file_iter_buff[x].append(file_iters[x].next()) | 69 | file_iter_buff[x].append(file_iters[x].next()) |
70 | for x in range(0,len(file_iter_buff)): | 70 | for x in range(0,len(file_iter_buff)): |
71 | file_iter_buff[x] = sorted(file_iter_buff[x],key=lambda rec: rec.when) | 71 | file_iter_buff[x] = sorted(file_iter_buff[x],key=lambda rec: rec.when) |
72 | 72 | ||
@@ -110,7 +110,7 @@ def trace_reader(files): | |||
110 | last_time = earliest.when | 110 | last_time = earliest.when |
111 | 111 | ||
112 | # Yield the record | 112 | # Yield the record |
113 | yield earliest | 113 | yield earliest |
114 | 114 | ||
115 | ############################################################################### | 115 | ############################################################################### |
116 | # Private functions | 116 | # Private functions |
@@ -123,11 +123,11 @@ def _get_file_iter(file): | |||
123 | data = f.read(RECORD_HEAD_SIZE) | 123 | data = f.read(RECORD_HEAD_SIZE) |
124 | try: | 124 | try: |
125 | type_num = struct.unpack_from('b',data)[0] | 125 | type_num = struct.unpack_from('b',data)[0] |
126 | except struct.error: | 126 | except struct.error: |
127 | break #We read to the end of the file | 127 | break #We read to the end of the file |
128 | type = _get_type(type_num) | 128 | type = _get_type(type_num) |
129 | try: | 129 | try: |
130 | values = struct.unpack_from(StHeader.format + | 130 | values = struct.unpack_from(StHeader.format + |
131 | type.format,data) | 131 | type.format,data) |
132 | record_dict = dict(zip(type.keys,values)) | 132 | record_dict = dict(zip(type.keys,values)) |
133 | except struct.error: | 133 | except struct.error: |
@@ -157,7 +157,7 @@ def _dict2obj(d): | |||
157 | o = Obj() | 157 | o = Obj() |
158 | for key in d.keys(): | 158 | for key in d.keys(): |
159 | o.__dict__[key] = d[key] | 159 | o.__dict__[key] = d[key] |
160 | return o | 160 | return o |
161 | 161 | ||
162 | ############################################################################### | 162 | ############################################################################### |
163 | # Trace record data types and accessor functions | 163 | # Trace record data types and accessor functions |
@@ -183,7 +183,7 @@ class StNameData: | |||
183 | keys = StHeader.keys + ['name'] | 183 | keys = StHeader.keys + ['name'] |
184 | message = 'The name of the executable of this process.' | 184 | message = 'The name of the executable of this process.' |
185 | 185 | ||
186 | class StParamData: | 186 | class StParamData: |
187 | format = 'IIIc' | 187 | format = 'IIIc' |
188 | formatStr = struct.Struct(StHeader.format + format) | 188 | formatStr = struct.Struct(StHeader.format + format) |
189 | keys = StHeader.keys + ['wcet','period','phase','partition'] | 189 | keys = StHeader.keys + ['wcet','period','phase','partition'] |
@@ -195,7 +195,7 @@ class StReleaseData: | |||
195 | keys = StHeader.keys + ['when','deadline'] | 195 | keys = StHeader.keys + ['when','deadline'] |
196 | message = 'A job was/is going to be released.' | 196 | message = 'A job was/is going to be released.' |
197 | 197 | ||
198 | #Not yet used by Sched Trace | 198 | #Not yet used by Sched Trace |
199 | class StAssignedData: | 199 | class StAssignedData: |
200 | format = 'Qc' | 200 | format = 'Qc' |
201 | formatStr = struct.Struct(StHeader.format + format) | 201 | formatStr = struct.Struct(StHeader.format + format) |
diff --git a/unit_trace/viz/convert.py b/unit_trace/viz/convert.py index a7aff8b..d19bc73 100644 --- a/unit_trace/viz/convert.py +++ b/unit_trace/viz/convert.py | |||
@@ -24,13 +24,13 @@ def _get_job_from_record(sched, record): | |||
24 | sched.get_tasks()[tname].add_job(Job(job_no, [])) | 24 | sched.get_tasks()[tname].add_job(Job(job_no, [])) |
25 | job = sched.get_tasks()[tname].get_jobs()[job_no] | 25 | job = sched.get_tasks()[tname].get_jobs()[job_no] |
26 | return job | 26 | return job |
27 | 27 | ||
28 | def convert_trace_to_schedule(stream): | 28 | def convert_trace_to_schedule(stream): |
29 | """The main function of interest in this module. Coverts a stream of records | 29 | """The main function of interest in this module. Coverts a stream of records |
30 | to a Schedule object.""" | 30 | to a Schedule object.""" |
31 | def noop(): | 31 | def noop(): |
32 | pass | 32 | pass |
33 | 33 | ||
34 | num_cpus, stream = _find_num_cpus(stream) | 34 | num_cpus, stream = _find_num_cpus(stream) |
35 | sched = Schedule('sched', num_cpus) | 35 | sched = Schedule('sched', num_cpus) |
36 | for record in stream: | 36 | for record in stream: |
@@ -41,10 +41,10 @@ def convert_trace_to_schedule(stream): | |||
41 | if record.record_type == 'event': | 41 | if record.record_type == 'event': |
42 | job = _get_job_from_record(sched, record) | 42 | job = _get_job_from_record(sched, record) |
43 | cpu = record.cpu | 43 | cpu = record.cpu |
44 | 44 | ||
45 | if not hasattr(record, 'deadline'): | 45 | if not hasattr(record, 'deadline'): |
46 | record.deadline = None | 46 | record.deadline = None |
47 | 47 | ||
48 | actions = { | 48 | actions = { |
49 | 'name' : (noop), | 49 | 'name' : (noop), |
50 | 'params' : (noop), | 50 | 'params' : (noop), |
@@ -64,27 +64,27 @@ def convert_trace_to_schedule(stream): | |||
64 | job.add_event(ResumeEvent(record.when, cpu))), | 64 | job.add_event(ResumeEvent(record.when, cpu))), |
65 | 'sys_release' : (noop) | 65 | 'sys_release' : (noop) |
66 | } | 66 | } |
67 | 67 | ||
68 | actions[record.type_name]() | 68 | actions[record.type_name]() |
69 | 69 | ||
70 | elif record.record_type == 'error': | 70 | elif record.record_type == 'error': |
71 | job = _get_job_from_record(sched, record.job) | 71 | job = _get_job_from_record(sched, record.job) |
72 | 72 | ||
73 | actions = { | 73 | actions = { |
74 | 'inversion_start' : (lambda : | 74 | 'inversion_start' : (lambda : |
75 | job.add_event(InversionStartEvent(record.job.inversion_start))), | 75 | job.add_event(InversionStartEvent(record.job.inversion_start))), |
76 | 'inversion_end' : (lambda : | 76 | 'inversion_end' : (lambda : |
77 | job.add_event(InversionEndEvent(record.job.inversion_end))) | 77 | job.add_event(InversionEndEvent(record.job.inversion_end))) |
78 | } | 78 | } |
79 | 79 | ||
80 | actions[record.type_name]() | 80 | actions[record.type_name]() |
81 | 81 | ||
82 | return sched | 82 | return sched |
83 | 83 | ||
84 | def _pid_to_task_name(pid): | 84 | def _pid_to_task_name(pid): |
85 | """Converts a PID to an appropriate name for a task.""" | 85 | """Converts a PID to an appropriate name for a task.""" |
86 | return str(pid) | 86 | return str(pid) |
87 | 87 | ||
88 | def _find_num_cpus(stream): | 88 | def _find_num_cpus(stream): |
89 | """Determines the number of CPUs used by scanning the binary format.""" | 89 | """Determines the number of CPUs used by scanning the binary format.""" |
90 | max = 0 | 90 | max = 0 |
@@ -94,7 +94,7 @@ def _find_num_cpus(stream): | |||
94 | if record.record_type == 'event': | 94 | if record.record_type == 'event': |
95 | if record.cpu > max: | 95 | if record.cpu > max: |
96 | max = record.cpu | 96 | max = record.cpu |
97 | 97 | ||
98 | def recycle(l): | 98 | def recycle(l): |
99 | for record in l: | 99 | for record in l: |
100 | yield record | 100 | yield record |
diff --git a/unit_trace/viz/draw.py b/unit_trace/viz/draw.py index 8c48744..dced27d 100644 --- a/unit_trace/viz/draw.py +++ b/unit_trace/viz/draw.py | |||
@@ -27,19 +27,19 @@ class Surface(object): | |||
27 | self.height = 0 | 27 | self.height = 0 |
28 | self.fname = fname | 28 | self.fname = fname |
29 | self.ctx = ctx | 29 | self.ctx = ctx |
30 | 30 | ||
31 | def renew(self, width, height): | 31 | def renew(self, width, height): |
32 | raise NotImplementedError | 32 | raise NotImplementedError |
33 | 33 | ||
34 | def change_ctx(self, ctx): | 34 | def change_ctx(self, ctx): |
35 | self.ctx = ctx | 35 | self.ctx = ctx |
36 | 36 | ||
37 | def get_fname(self): | 37 | def get_fname(self): |
38 | return self.fname | 38 | return self.fname |
39 | 39 | ||
40 | def write_out(self, fname): | 40 | def write_out(self, fname): |
41 | raise NotImplementedError | 41 | raise NotImplementedError |
42 | 42 | ||
43 | def pan(self, x, y, width, height): | 43 | def pan(self, x, y, width, height): |
44 | """A surface might actually represent just a ``window'' into | 44 | """A surface might actually represent just a ``window'' into |
45 | what we are drawing on. For instance, if we are scrolling through | 45 | what we are drawing on. For instance, if we are scrolling through |
@@ -51,7 +51,7 @@ class Surface(object): | |||
51 | self.virt_y = y | 51 | self.virt_y = y |
52 | self.width = width | 52 | self.width = width |
53 | self.height = height | 53 | self.height = height |
54 | 54 | ||
55 | def get_real_coor(self, x, y): | 55 | def get_real_coor(self, x, y): |
56 | """Translates the coordinates (x, y) | 56 | """Translates the coordinates (x, y) |
57 | in the ``theoretical'' plane to the true (x, y) coordinates on this surface | 57 | in the ``theoretical'' plane to the true (x, y) coordinates on this surface |
@@ -59,48 +59,48 @@ class Surface(object): | |||
59 | bounds of the surface, | 59 | bounds of the surface, |
60 | if we want something outside the surface's ``window''.""" | 60 | if we want something outside the surface's ``window''.""" |
61 | return (x - self.virt_x, y - self.virt_y) | 61 | return (x - self.virt_x, y - self.virt_y) |
62 | 62 | ||
63 | class SVGSurface(Surface): | 63 | class SVGSurface(Surface): |
64 | def renew(self, width, height): | 64 | def renew(self, width, height): |
65 | iwidth = int(math.ceil(width)) | 65 | iwidth = int(math.ceil(width)) |
66 | iheight = int(math.ceil(height)) | 66 | iheight = int(math.ceil(height)) |
67 | self.surface = cairo.SVGSurface(self.fname, iwidth, iheight) | 67 | self.surface = cairo.SVGSurface(self.fname, iwidth, iheight) |
68 | self.ctx = cairo.Context(self.surface) | 68 | self.ctx = cairo.Context(self.surface) |
69 | 69 | ||
70 | def write_out(self, fname): | 70 | def write_out(self, fname): |
71 | os.execl('cp', self.fname, fname) | 71 | os.execl('cp', self.fname, fname) |
72 | 72 | ||
73 | class ImageSurface(Surface): | 73 | class ImageSurface(Surface): |
74 | def renew(self, width, height): | 74 | def renew(self, width, height): |
75 | iwidth = int(math.ceil(width)) | 75 | iwidth = int(math.ceil(width)) |
76 | iheight = int(math.ceil(height)) | 76 | iheight = int(math.ceil(height)) |
77 | self.surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, iwidth, iheight) | 77 | self.surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, iwidth, iheight) |
78 | self.ctx = cairo.Context(self.surface) | 78 | self.ctx = cairo.Context(self.surface) |
79 | 79 | ||
80 | def write_out(self, fname): | 80 | def write_out(self, fname): |
81 | if self.surface is None: | 81 | if self.surface is None: |
82 | raise ValueError('Don\'t own surface, can\'t write to to file') | 82 | raise ValueError('Don\'t own surface, can\'t write to to file') |
83 | 83 | ||
84 | self.surface.write_to_png(fname) | 84 | self.surface.write_to_png(fname) |
85 | 85 | ||
86 | class Pattern(object): | 86 | class Pattern(object): |
87 | DEF_STRIPE_SIZE = 10 | 87 | DEF_STRIPE_SIZE = 10 |
88 | MAX_FADE_WIDTH = 250 | 88 | MAX_FADE_WIDTH = 250 |
89 | 89 | ||
90 | def __init__(self, color_list, stripe_size=DEF_STRIPE_SIZE): | 90 | def __init__(self, color_list, stripe_size=DEF_STRIPE_SIZE): |
91 | self.color_list = color_list | 91 | self.color_list = color_list |
92 | self.stripe_size = stripe_size | 92 | self.stripe_size = stripe_size |
93 | 93 | ||
94 | def render_on_canvas(self, canvas, x, y, width, height, fade=False): | 94 | def render_on_canvas(self, canvas, x, y, width, height, fade=False): |
95 | fade_span = min(width, Pattern.MAX_FADE_WIDTH) | 95 | fade_span = min(width, Pattern.MAX_FADE_WIDTH) |
96 | 96 | ||
97 | if len(self.color_list) == 1: | 97 | if len(self.color_list) == 1: |
98 | if fade: | 98 | if fade: |
99 | canvas.fill_rect_fade(x, y, fade_span, height, (1.0, 1.0, 1.0), \ | 99 | canvas.fill_rect_fade(x, y, fade_span, height, (1.0, 1.0, 1.0), \ |
100 | self.color_list[0]) | 100 | self.color_list[0]) |
101 | else: | 101 | else: |
102 | canvas.fill_rect(x, y, width, height, self.color_list[0]) | 102 | canvas.fill_rect(x, y, width, height, self.color_list[0]) |
103 | 103 | ||
104 | if width > Pattern.MAX_FADE_WIDTH: | 104 | if width > Pattern.MAX_FADE_WIDTH: |
105 | canvas.fill_rect(x + Pattern.MAX_FADE_WIDTH, y, width - Pattern.MAX_FADE_WIDTH, | 105 | canvas.fill_rect(x + Pattern.MAX_FADE_WIDTH, y, width - Pattern.MAX_FADE_WIDTH, |
106 | height, self.color_list[0]) | 106 | height, self.color_list[0]) |
@@ -114,89 +114,89 @@ class Pattern(object): | |||
114 | min(self.stripe_size, bottom - y), (1.0, 1.0, 1.0), self.color_list[i]) | 114 | min(self.stripe_size, bottom - y), (1.0, 1.0, 1.0), self.color_list[i]) |
115 | else: | 115 | else: |
116 | canvas.fill_rect(x, y, width, min(self.stripe_size, bottom - y), self.color_list[i]) | 116 | canvas.fill_rect(x, y, width, min(self.stripe_size, bottom - y), self.color_list[i]) |
117 | 117 | ||
118 | if width > Pattern.MAX_FADE_WIDTH: | 118 | if width > Pattern.MAX_FADE_WIDTH: |
119 | canvas.fill_rect(x + Pattern.MAX_FADE_WIDTH, y, width - Pattern.MAX_FADE_WIDTH, | 119 | canvas.fill_rect(x + Pattern.MAX_FADE_WIDTH, y, width - Pattern.MAX_FADE_WIDTH, |
120 | min(self.stripe_size, bottom - y), self.color_list[i]) | 120 | min(self.stripe_size, bottom - y), self.color_list[i]) |
121 | 121 | ||
122 | y += self.stripe_size | 122 | y += self.stripe_size |
123 | n += 1 | 123 | n += 1 |
124 | 124 | ||
125 | class Canvas(object): | 125 | class Canvas(object): |
126 | """This is a basic class that stores and draws on a Cairo surface, | 126 | """This is a basic class that stores and draws on a Cairo surface, |
127 | using various primitives related to drawing a real-time graph (up-arrows, | 127 | using various primitives related to drawing a real-time graph (up-arrows, |
128 | down-arrows, bars, ...). | 128 | down-arrows, bars, ...). |
129 | 129 | ||
130 | This is the lowest-level representation (aside perhaps from the Cairo | 130 | This is the lowest-level representation (aside perhaps from the Cairo |
131 | surface itself) of a real-time graph. It allows the user to draw | 131 | surface itself) of a real-time graph. It allows the user to draw |
132 | primitives at certain locations, but for the most part does not know | 132 | primitives at certain locations, but for the most part does not know |
133 | anything about real-time scheduling, just how to draw the basic parts | 133 | anything about real-time scheduling, just how to draw the basic parts |
134 | that make up a schedule graph. For that, see Graph or its descendants.""" | 134 | that make up a schedule graph. For that, see Graph or its descendants.""" |
135 | 135 | ||
136 | BOTTOM_LAYER = 0 | 136 | BOTTOM_LAYER = 0 |
137 | MIDDLE_LAYER = 1 | 137 | MIDDLE_LAYER = 1 |
138 | TOP_LAYER = 2 | 138 | TOP_LAYER = 2 |
139 | 139 | ||
140 | LAYERS = (BOTTOM_LAYER, MIDDLE_LAYER, TOP_LAYER) | 140 | LAYERS = (BOTTOM_LAYER, MIDDLE_LAYER, TOP_LAYER) |
141 | 141 | ||
142 | NULL_PATTERN = -1 | 142 | NULL_PATTERN = -1 |
143 | 143 | ||
144 | SQRT3 = math.sqrt(3.0) | 144 | SQRT3 = math.sqrt(3.0) |
145 | 145 | ||
146 | def __init__(self, width, height, item_clist, bar_plist, surface): | 146 | def __init__(self, width, height, item_clist, bar_plist, surface): |
147 | """Creates a new Canvas of dimensions (width, height). The | 147 | """Creates a new Canvas of dimensions (width, height). The |
148 | parameters ``item_plist'' and ``bar_plist'' each specify a list | 148 | parameters ``item_plist'' and ``bar_plist'' each specify a list |
149 | of patterns to choose from when drawing the items on the y-axis | 149 | of patterns to choose from when drawing the items on the y-axis |
150 | or filling in bars, respectively.""" | 150 | or filling in bars, respectively.""" |
151 | 151 | ||
152 | self.surface = surface | 152 | self.surface = surface |
153 | 153 | ||
154 | self.width = int(math.ceil(width)) | 154 | self.width = int(math.ceil(width)) |
155 | self.height = int(math.ceil(height)) | 155 | self.height = int(math.ceil(height)) |
156 | self.item_clist = item_clist | 156 | self.item_clist = item_clist |
157 | self.bar_plist = bar_plist | 157 | self.bar_plist = bar_plist |
158 | 158 | ||
159 | self.selectable_regions = {} | 159 | self.selectable_regions = {} |
160 | 160 | ||
161 | self.scale = 1.0 | 161 | self.scale = 1.0 |
162 | 162 | ||
163 | # clears the canvas. | 163 | # clears the canvas. |
164 | def clear(self): | 164 | def clear(self): |
165 | raise NotImplementedError | 165 | raise NotImplementedError |
166 | 166 | ||
167 | def scaled(self, *coors): | 167 | def scaled(self, *coors): |
168 | return [coor * self.scale for coor in coors] | 168 | return [coor * self.scale for coor in coors] |
169 | 169 | ||
170 | def draw_rect(self, x, y, width, height, color, thickness, snap=True): | 170 | def draw_rect(self, x, y, width, height, color, thickness, snap=True): |
171 | """Draws a rectangle somewhere (border only).""" | 171 | """Draws a rectangle somewhere (border only).""" |
172 | raise NotImplementedError | 172 | raise NotImplementedError |
173 | 173 | ||
174 | def fill_rect(self, x, y, width, height, color, snap=True): | 174 | def fill_rect(self, x, y, width, height, color, snap=True): |
175 | """Draws a filled rectangle somewhere. ``color'' is a 3-tuple.""" | 175 | """Draws a filled rectangle somewhere. ``color'' is a 3-tuple.""" |
176 | raise NotImplementedError | 176 | raise NotImplementedError |
177 | 177 | ||
178 | def fill_rect_fade(self, x, y, width, height, lcolor, rcolor, snap=True): | 178 | def fill_rect_fade(self, x, y, width, height, lcolor, rcolor, snap=True): |
179 | """Draws a rectangle somewhere, filled in with the fade.""" | 179 | """Draws a rectangle somewhere, filled in with the fade.""" |
180 | raise NotImplementedError | 180 | raise NotImplementedError |
181 | 181 | ||
182 | def draw_line(self, p0, p1, color, thickness, snap=True): | 182 | def draw_line(self, p0, p1, color, thickness, snap=True): |
183 | """Draws a line from p0 to p1 with a certain color and thickness.""" | 183 | """Draws a line from p0 to p1 with a certain color and thickness.""" |
184 | raise NotImplementedError | 184 | raise NotImplementedError |
185 | 185 | ||
186 | def draw_polyline(self, coor_list, color, thickness, snap=True): | 186 | def draw_polyline(self, coor_list, color, thickness, snap=True): |
187 | """Draws a polyline, where coor_list = [(x_0, y_0), (x_1, y_1), ... (x_m, y_m)] | 187 | """Draws a polyline, where coor_list = [(x_0, y_0), (x_1, y_1), ... (x_m, y_m)] |
188 | specifies a polyline from (x_0, y_0) to (x_1, y_1), etc.""" | 188 | specifies a polyline from (x_0, y_0) to (x_1, y_1), etc.""" |
189 | raise NotImplementedError | 189 | raise NotImplementedError |
190 | 190 | ||
191 | def fill_polyline(self, coor_list, color, thickness, snap=True): | 191 | def fill_polyline(self, coor_list, color, thickness, snap=True): |
192 | """Draws a polyline (probably a polygon) and fills it.""" | 192 | """Draws a polyline (probably a polygon) and fills it.""" |
193 | raise NotImplementedError | 193 | raise NotImplementedError |
194 | 194 | ||
195 | def draw_label(self, text, x, y, fopts=GraphFormat.DEF_FOPTS_LABEL, | 195 | def draw_label(self, text, x, y, fopts=GraphFormat.DEF_FOPTS_LABEL, |
196 | halign=AlignMode.LEFT, valign=AlignMode.BOTTOM, snap=True): | 196 | halign=AlignMode.LEFT, valign=AlignMode.BOTTOM, snap=True): |
197 | """Draws text at a position with a certain alignment.""" | 197 | """Draws text at a position with a certain alignment.""" |
198 | raise NotImplementedError | 198 | raise NotImplementedError |
199 | 199 | ||
200 | def draw_label_with_sscripts(self, text, supscript, subscript, x, y, \ | 200 | def draw_label_with_sscripts(self, text, supscript, subscript, x, y, \ |
201 | textfopts=GraphFormat.DEF_FOPTS_LABEL, | 201 | textfopts=GraphFormat.DEF_FOPTS_LABEL, |
202 | sscriptfopts=GraphFormat.DEF_FOPTS_LABEL_SSCRIPT, \ | 202 | sscriptfopts=GraphFormat.DEF_FOPTS_LABEL_SSCRIPT, \ |
@@ -204,31 +204,31 @@ class Canvas(object): | |||
204 | """Draws text at a position with a certain alignment, along with optionally a superscript and | 204 | """Draws text at a position with a certain alignment, along with optionally a superscript and |
205 | subscript (which are None if either is not used.)""" | 205 | subscript (which are None if either is not used.)""" |
206 | raise NotImplementedError | 206 | raise NotImplementedError |
207 | 207 | ||
208 | def draw_y_axis(self, x, y, height): | 208 | def draw_y_axis(self, x, y, height): |
209 | """Draws the y-axis, starting from the bottom at the point x, y.""" | 209 | """Draws the y-axis, starting from the bottom at the point x, y.""" |
210 | self.surface.ctx.set_source_rgb(0.0, 0.0, 0.0) | 210 | self.surface.ctx.set_source_rgb(0.0, 0.0, 0.0) |
211 | 211 | ||
212 | self.draw_line((x, y), (x, y - height), (0.0, 0.0, 0.0), GraphFormat.AXIS_THICKNESS) | 212 | self.draw_line((x, y), (x, y - height), (0.0, 0.0, 0.0), GraphFormat.AXIS_THICKNESS) |
213 | 213 | ||
214 | def draw_y_axis_labels(self, x, y, height, item_list, item_size, fopts=None): | 214 | def draw_y_axis_labels(self, x, y, height, item_list, item_size, fopts=None): |
215 | """Draws the item labels on the y-axis. ``item_list'' is the list | 215 | """Draws the item labels on the y-axis. ``item_list'' is the list |
216 | of strings to print, while item_size gives the vertical amount of | 216 | of strings to print, while item_size gives the vertical amount of |
217 | space that each item shall take up, in pixels.""" | 217 | space that each item shall take up, in pixels.""" |
218 | if fopts is None: | 218 | if fopts is None: |
219 | fopts = GraphFormat.DEF_FOPTS_ITEM | 219 | fopts = GraphFormat.DEF_FOPTS_ITEM |
220 | 220 | ||
221 | x -= GraphFormat.Y_AXIS_ITEM_GAP | 221 | x -= GraphFormat.Y_AXIS_ITEM_GAP |
222 | y -= height - item_size / 2.0 | 222 | y -= height - item_size / 2.0 |
223 | 223 | ||
224 | orig_color = fopts.color | 224 | orig_color = fopts.color |
225 | for ctr, item in enumerate(item_list): | 225 | for ctr, item in enumerate(item_list): |
226 | fopts.color = self.get_item_color(ctr) | 226 | fopts.color = self.get_item_color(ctr) |
227 | self.draw_label(item, x, y, fopts, AlignMode.RIGHT, AlignMode.CENTER) | 227 | self.draw_label(item, x, y, fopts, AlignMode.RIGHT, AlignMode.CENTER) |
228 | y += item_size | 228 | y += item_size |
229 | 229 | ||
230 | fopts.color = orig_color | 230 | fopts.color = orig_color |
231 | 231 | ||
232 | def draw_x_axis(self, x, y, start_tick, end_tick, maj_sep, min_per_maj): | 232 | def draw_x_axis(self, x, y, start_tick, end_tick, maj_sep, min_per_maj): |
233 | """Draws the x-axis, including all the major and minor ticks (but not the labels). | 233 | """Draws the x-axis, including all the major and minor ticks (but not the labels). |
234 | ``num_maj'' gives the number of major ticks, ``maj_sep'' the number of pixels between | 234 | ``num_maj'' gives the number of major ticks, ``maj_sep'' the number of pixels between |
@@ -241,48 +241,48 @@ class Canvas(object): | |||
241 | for i in range(start_tick, end_tick + 1): | 241 | for i in range(start_tick, end_tick + 1): |
242 | self.draw_line((x, y), (x, y + GraphFormat.MAJ_TICK_SIZE), | 242 | self.draw_line((x, y), (x, y + GraphFormat.MAJ_TICK_SIZE), |
243 | (0.0, 0.0, 0.0), GraphFormat.AXIS_THICKNESS) | 243 | (0.0, 0.0, 0.0), GraphFormat.AXIS_THICKNESS) |
244 | 244 | ||
245 | if (i < end_tick): | 245 | if (i < end_tick): |
246 | for j in range(0, min_per_maj): | 246 | for j in range(0, min_per_maj): |
247 | self.draw_line((x, y), (x + maj_sep / min_per_maj, y), | 247 | self.draw_line((x, y), (x + maj_sep / min_per_maj, y), |
248 | (0.0, 0.0, 0.0), GraphFormat.AXIS_THICKNESS) | 248 | (0.0, 0.0, 0.0), GraphFormat.AXIS_THICKNESS) |
249 | 249 | ||
250 | x += 1.0 * maj_sep / min_per_maj | 250 | x += 1.0 * maj_sep / min_per_maj |
251 | if j < min_per_maj - 1: | 251 | if j < min_per_maj - 1: |
252 | self.draw_line((x, y), (x, y + GraphFormat.MIN_TICK_SIZE), | 252 | self.draw_line((x, y), (x, y + GraphFormat.MIN_TICK_SIZE), |
253 | (0.0, 0.0, 0.0), GraphFormat.AXIS_THICKNESS) | 253 | (0.0, 0.0, 0.0), GraphFormat.AXIS_THICKNESS) |
254 | 254 | ||
255 | def draw_x_axis_labels(self, x, y, start_tick, end_tick, maj_sep, min_per_maj, start=0, incr=1, show_min=False, \ | 255 | def draw_x_axis_labels(self, x, y, start_tick, end_tick, maj_sep, min_per_maj, start=0, incr=1, show_min=False, \ |
256 | majfopts=GraphFormat.DEF_FOPTS_MAJ, minfopts=GraphFormat.DEF_FOPTS_MIN): | 256 | majfopts=GraphFormat.DEF_FOPTS_MAJ, minfopts=GraphFormat.DEF_FOPTS_MIN): |
257 | """Draws the labels for the x-axis. (x, y) should give the origin. | 257 | """Draws the labels for the x-axis. (x, y) should give the origin. |
258 | how far down you want the text. ``incr'' gives the increment per major | 258 | how far down you want the text. ``incr'' gives the increment per major |
259 | tick. ``start'' gives the value of the first tick. ``show_min'' specifies | 259 | tick. ``start'' gives the value of the first tick. ``show_min'' specifies |
260 | whether to draw labels at minor ticks.""" | 260 | whether to draw labels at minor ticks.""" |
261 | 261 | ||
262 | x += GraphFormat.X_AXIS_MEASURE_OFS + start_tick * maj_sep | 262 | x += GraphFormat.X_AXIS_MEASURE_OFS + start_tick * maj_sep |
263 | y += GraphFormat.X_AXIS_LABEL_GAP + GraphFormat.MAJ_TICK_SIZE | 263 | y += GraphFormat.X_AXIS_LABEL_GAP + GraphFormat.MAJ_TICK_SIZE |
264 | 264 | ||
265 | minincr = incr / (min_per_maj * 1.0) | 265 | minincr = incr / (min_per_maj * 1.0) |
266 | 266 | ||
267 | cur = start * 1.0 | 267 | cur = start * 1.0 |
268 | 268 | ||
269 | for i in range(start_tick, end_tick + 1): | 269 | for i in range(start_tick, end_tick + 1): |
270 | text = util.format_float(cur, 2) | 270 | text = util.format_float(cur, 2) |
271 | self.draw_label(text, x, y, majfopts, AlignMode.CENTER, AlignMode.TOP) | 271 | self.draw_label(text, x, y, majfopts, AlignMode.CENTER, AlignMode.TOP) |
272 | 272 | ||
273 | if (i < end_tick): | 273 | if (i < end_tick): |
274 | if show_min: | 274 | if show_min: |
275 | for j in range(0, min_per_maj): | 275 | for j in range(0, min_per_maj): |
276 | x += 1.0 * maj_sep / min_per_maj | 276 | x += 1.0 * maj_sep / min_per_maj |
277 | cur += minincr | 277 | cur += minincr |
278 | text = util.format_float(cur, 2) | 278 | text = util.format_float(cur, 2) |
279 | 279 | ||
280 | if j < min_per_maj - 1: | 280 | if j < min_per_maj - 1: |
281 | self.draw_label(text, x, y, minfopts, AlignMode.CENTER, AlignMode.TOP) | 281 | self.draw_label(text, x, y, minfopts, AlignMode.CENTER, AlignMode.TOP) |
282 | else: | 282 | else: |
283 | x += maj_sep | 283 | x += maj_sep |
284 | cur += incr | 284 | cur += incr |
285 | 285 | ||
286 | def draw_grid(self, x, y, height, start_tick, end_tick, start_item, end_item, maj_sep, item_size, \ | 286 | def draw_grid(self, x, y, height, start_tick, end_tick, start_item, end_item, maj_sep, item_size, \ |
287 | min_per_maj=None, show_min=False): | 287 | min_per_maj=None, show_min=False): |
288 | """Draws a grid dividing along the item boundaries and the major ticks. | 288 | """Draws a grid dividing along the item boundaries and the major ticks. |
@@ -291,22 +291,22 @@ class Canvas(object): | |||
291 | ``start_item'' and ``end_item'' give the item boundaries to start and end drawing horizontal lines.""" | 291 | ``start_item'' and ``end_item'' give the item boundaries to start and end drawing horizontal lines.""" |
292 | if start_tick > end_tick or start_item > end_item: | 292 | if start_tick > end_tick or start_item > end_item: |
293 | return | 293 | return |
294 | 294 | ||
295 | line_width = (end_tick - start_tick) * maj_sep | 295 | line_width = (end_tick - start_tick) * maj_sep |
296 | line_height = (end_item - start_item) * item_size | 296 | line_height = (end_item - start_item) * item_size |
297 | 297 | ||
298 | origin = (x, y) | 298 | origin = (x, y) |
299 | 299 | ||
300 | # draw horizontal lines first | 300 | # draw horizontal lines first |
301 | x = origin[0] + GraphFormat.X_AXIS_MEASURE_OFS + start_tick * maj_sep | 301 | x = origin[0] + GraphFormat.X_AXIS_MEASURE_OFS + start_tick * maj_sep |
302 | y = origin[1] - height + start_item * item_size | 302 | y = origin[1] - height + start_item * item_size |
303 | for i in range(start_item, end_item + 1): | 303 | for i in range(start_item, end_item + 1): |
304 | self.draw_line((x, y), (x + line_width, y), GraphFormat.GRID_COLOR, GraphFormat.GRID_THICKNESS) | 304 | self.draw_line((x, y), (x + line_width, y), GraphFormat.GRID_COLOR, GraphFormat.GRID_THICKNESS) |
305 | y += item_size | 305 | y += item_size |
306 | 306 | ||
307 | x = origin[0] + GraphFormat.X_AXIS_MEASURE_OFS + start_tick * maj_sep | 307 | x = origin[0] + GraphFormat.X_AXIS_MEASURE_OFS + start_tick * maj_sep |
308 | y = origin[1] - height + start_item * item_size | 308 | y = origin[1] - height + start_item * item_size |
309 | 309 | ||
310 | if show_min: | 310 | if show_min: |
311 | for i in range(0, (end_tick - start_tick) * min_per_maj + 1): | 311 | for i in range(0, (end_tick - start_tick) * min_per_maj + 1): |
312 | self.draw_line((x, y), (x, y + line_height), GraphFormat.GRID_COLOR, GraphFormat.GRID_THICKNESS) | 312 | self.draw_line((x, y), (x, y + line_height), GraphFormat.GRID_COLOR, GraphFormat.GRID_THICKNESS) |
@@ -315,7 +315,7 @@ class Canvas(object): | |||
315 | for i in range(start_tick, end_tick + 1): | 315 | for i in range(start_tick, end_tick + 1): |
316 | self.draw_line((x, y), (x, y + line_height), GraphFormat.GRID_COLOR, GraphFormat.GRID_THICKNESS) | 316 | self.draw_line((x, y), (x, y + line_height), GraphFormat.GRID_COLOR, GraphFormat.GRID_THICKNESS) |
317 | x += maj_sep | 317 | x += maj_sep |
318 | 318 | ||
319 | def _draw_bar_border_common(self, x, y, width, height, color, thickness, clip_side): | 319 | def _draw_bar_border_common(self, x, y, width, height, color, thickness, clip_side): |
320 | if clip_side is None: | 320 | if clip_side is None: |
321 | self.draw_rect(x, y, width, height, color, thickness) | 321 | self.draw_rect(x, y, width, height, color, thickness) |
@@ -325,213 +325,213 @@ class Canvas(object): | |||
325 | elif clip_side == AlignMode.RIGHT: | 325 | elif clip_side == AlignMode.RIGHT: |
326 | self.draw_polyline([(x + width, y), (x, y), (x, y + height), (x + width, y + height)], | 326 | self.draw_polyline([(x + width, y), (x, y), (x, y + height), (x + width, y + height)], |
327 | color, thickness) | 327 | color, thickness) |
328 | 328 | ||
329 | def draw_bar(self, x, y, width, height, n, clip_side, selected): | 329 | def draw_bar(self, x, y, width, height, n, clip_side, selected): |
330 | """Draws a bar with a certain set of dimensions, using pattern ``n'' from the | 330 | """Draws a bar with a certain set of dimensions, using pattern ``n'' from the |
331 | bar pattern list.""" | 331 | bar pattern list.""" |
332 | 332 | ||
333 | color, thickness = {False : (GraphFormat.BORDER_COLOR, GraphFormat.BORDER_THICKNESS), | 333 | color, thickness = {False : (GraphFormat.BORDER_COLOR, GraphFormat.BORDER_THICKNESS), |
334 | True : (GraphFormat.HIGHLIGHT_COLOR, GraphFormat.BORDER_THICKNESS * 2.0)}[selected] | 334 | True : (GraphFormat.HIGHLIGHT_COLOR, GraphFormat.BORDER_THICKNESS * 2.0)}[selected] |
335 | 335 | ||
336 | # use a pattern to be pretty | 336 | # use a pattern to be pretty |
337 | self.get_bar_pattern(n).render_on_canvas(self, x, y, width, height, True) | 337 | self.get_bar_pattern(n).render_on_canvas(self, x, y, width, height, True) |
338 | 338 | ||
339 | self._draw_bar_border_common(x, y, width, height, color, thickness, clip_side) | 339 | self._draw_bar_border_common(x, y, width, height, color, thickness, clip_side) |
340 | 340 | ||
341 | def add_sel_bar(self, x, y, width, height, event): | 341 | def add_sel_bar(self, x, y, width, height, event): |
342 | self.add_sel_region(SelectableRegion(x, y, width, height, event)) | 342 | self.add_sel_region(SelectableRegion(x, y, width, height, event)) |
343 | 343 | ||
344 | def draw_mini_bar(self, x, y, width, height, n, clip_side, selected): | 344 | def draw_mini_bar(self, x, y, width, height, n, clip_side, selected): |
345 | """Like the above, except it draws a miniature version. This is usually used for | 345 | """Like the above, except it draws a miniature version. This is usually used for |
346 | secondary purposes (i.e. to show jobs that _should_ have been running at a certain time). | 346 | secondary purposes (i.e. to show jobs that _should_ have been running at a certain time). |
347 | 347 | ||
348 | Of course we don't enforce the fact that this is mini, since the user can pass in width | 348 | Of course we don't enforce the fact that this is mini, since the user can pass in width |
349 | and height (but the mini bars do look slightly different: namely the borders are a different | 349 | and height (but the mini bars do look slightly different: namely the borders are a different |
350 | color)""" | 350 | color)""" |
351 | 351 | ||
352 | color, thickness = {False : (GraphFormat.LITE_BORDER_COLOR, GraphFormat.BORDER_THICKNESS), | 352 | color, thickness = {False : (GraphFormat.LITE_BORDER_COLOR, GraphFormat.BORDER_THICKNESS), |
353 | True : (GraphFormat.HIGHLIGHT_COLOR, GraphFormat.BORDER_THICKNESS * 1.5)}[selected] | 353 | True : (GraphFormat.HIGHLIGHT_COLOR, GraphFormat.BORDER_THICKNESS * 1.5)}[selected] |
354 | 354 | ||
355 | self.get_bar_pattern(n).render_on_canvas(self, x, y, width, height, True) | 355 | self.get_bar_pattern(n).render_on_canvas(self, x, y, width, height, True) |
356 | 356 | ||
357 | self._draw_bar_border_common(x, y, width, height, color, thickness, clip_side) | 357 | self._draw_bar_border_common(x, y, width, height, color, thickness, clip_side) |
358 | 358 | ||
359 | def add_sel_mini_bar(self, x, y, width, height, event): | 359 | def add_sel_mini_bar(self, x, y, width, height, event): |
360 | self.add_sel_region(SelectableRegion(x, y, width, height, event)) | 360 | self.add_sel_region(SelectableRegion(x, y, width, height, event)) |
361 | 361 | ||
362 | def draw_completion_marker(self, x, y, height, selected): | 362 | def draw_completion_marker(self, x, y, height, selected): |
363 | """Draws the symbol that represents a job completion, using a certain height.""" | 363 | """Draws the symbol that represents a job completion, using a certain height.""" |
364 | 364 | ||
365 | color = {False : GraphFormat.BORDER_COLOR, True : GraphFormat.HIGHLIGHT_COLOR}[selected] | 365 | color = {False : GraphFormat.BORDER_COLOR, True : GraphFormat.HIGHLIGHT_COLOR}[selected] |
366 | self.draw_line((x - height * GraphFormat.TEE_FACTOR / 2.0, y), | 366 | self.draw_line((x - height * GraphFormat.TEE_FACTOR / 2.0, y), |
367 | (x + height * GraphFormat.TEE_FACTOR / 2.0, y), | 367 | (x + height * GraphFormat.TEE_FACTOR / 2.0, y), |
368 | color, GraphFormat.BORDER_THICKNESS) | 368 | color, GraphFormat.BORDER_THICKNESS) |
369 | self.draw_line((x, y), (x, y + height), color, GraphFormat.BORDER_THICKNESS) | 369 | self.draw_line((x, y), (x, y + height), color, GraphFormat.BORDER_THICKNESS) |
370 | 370 | ||
371 | def add_sel_completion_marker(self, x, y, height, event): | 371 | def add_sel_completion_marker(self, x, y, height, event): |
372 | self.add_sel_region(SelectableRegion(x - height * GraphFormat.TEE_FACTOR / 2.0, y, | 372 | self.add_sel_region(SelectableRegion(x - height * GraphFormat.TEE_FACTOR / 2.0, y, |
373 | height * GraphFormat.TEE_FACTOR, height, event)) | 373 | height * GraphFormat.TEE_FACTOR, height, event)) |
374 | 374 | ||
375 | def draw_release_arrow_big(self, x, y, height, selected): | 375 | def draw_release_arrow_big(self, x, y, height, selected): |
376 | """Draws a release arrow of a certain height: (x, y) should give the top | 376 | """Draws a release arrow of a certain height: (x, y) should give the top |
377 | (northernmost point) of the arrow. The height includes the arrowhead.""" | 377 | (northernmost point) of the arrow. The height includes the arrowhead.""" |
378 | big_arrowhead_height = GraphFormat.BIG_ARROWHEAD_FACTOR * height | 378 | big_arrowhead_height = GraphFormat.BIG_ARROWHEAD_FACTOR * height |
379 | 379 | ||
380 | color = {False : GraphFormat.BORDER_COLOR, True : GraphFormat.HIGHLIGHT_COLOR}[selected] | 380 | color = {False : GraphFormat.BORDER_COLOR, True : GraphFormat.HIGHLIGHT_COLOR}[selected] |
381 | colors = [(1.0, 1.0, 1.0), color] | 381 | colors = [(1.0, 1.0, 1.0), color] |
382 | draw_funcs = [self.__class__.fill_polyline, self.__class__.draw_polyline] | 382 | draw_funcs = [self.__class__.fill_polyline, self.__class__.draw_polyline] |
383 | for i in range(0, 2): | 383 | for i in range(0, 2): |
384 | color = colors[i] | 384 | color = colors[i] |
385 | draw_func = draw_funcs[i] | 385 | draw_func = draw_funcs[i] |
386 | 386 | ||
387 | draw_func(self, [(x, y), (x - big_arrowhead_height / Canvas.SQRT3, y + big_arrowhead_height), \ | 387 | draw_func(self, [(x, y), (x - big_arrowhead_height / Canvas.SQRT3, y + big_arrowhead_height), \ |
388 | (x + big_arrowhead_height / Canvas.SQRT3, y + big_arrowhead_height), (x, y)], \ | 388 | (x + big_arrowhead_height / Canvas.SQRT3, y + big_arrowhead_height), (x, y)], \ |
389 | color, GraphFormat.BORDER_THICKNESS) | 389 | color, GraphFormat.BORDER_THICKNESS) |
390 | 390 | ||
391 | self.draw_line((x, y + big_arrowhead_height), (x, y + height), color, GraphFormat.BORDER_THICKNESS) | 391 | self.draw_line((x, y + big_arrowhead_height), (x, y + height), color, GraphFormat.BORDER_THICKNESS) |
392 | 392 | ||
393 | def add_sel_release_arrow_big(self, x, y, height, event): | 393 | def add_sel_release_arrow_big(self, x, y, height, event): |
394 | self.add_sel_arrow_big(x, y, height, event) | 394 | self.add_sel_arrow_big(x, y, height, event) |
395 | 395 | ||
396 | def draw_deadline_arrow_big(self, x, y, height, selected): | 396 | def draw_deadline_arrow_big(self, x, y, height, selected): |
397 | """Draws a release arrow: x, y should give the top (northernmost | 397 | """Draws a release arrow: x, y should give the top (northernmost |
398 | point) of the arrow. The height includes the arrowhead.""" | 398 | point) of the arrow. The height includes the arrowhead.""" |
399 | big_arrowhead_height = GraphFormat.BIG_ARROWHEAD_FACTOR * height | 399 | big_arrowhead_height = GraphFormat.BIG_ARROWHEAD_FACTOR * height |
400 | 400 | ||
401 | color = {False : GraphFormat.BORDER_COLOR, True : GraphFormat.HIGHLIGHT_COLOR}[selected] | 401 | color = {False : GraphFormat.BORDER_COLOR, True : GraphFormat.HIGHLIGHT_COLOR}[selected] |
402 | colors = [(1.0, 1.0, 1.0), color] | 402 | colors = [(1.0, 1.0, 1.0), color] |
403 | draw_funcs = [self.__class__.fill_polyline, self.__class__.draw_polyline] | 403 | draw_funcs = [self.__class__.fill_polyline, self.__class__.draw_polyline] |
404 | for i in range(0, 2): | 404 | for i in range(0, 2): |
405 | color = colors[i] | 405 | color = colors[i] |
406 | draw_func = draw_funcs[i] | 406 | draw_func = draw_funcs[i] |
407 | 407 | ||
408 | draw_func(self, [(x, y + height), (x - big_arrowhead_height / Canvas.SQRT3, \ | 408 | draw_func(self, [(x, y + height), (x - big_arrowhead_height / Canvas.SQRT3, \ |
409 | y + height - big_arrowhead_height), \ | 409 | y + height - big_arrowhead_height), \ |
410 | (x + big_arrowhead_height / Canvas.SQRT3, \ | 410 | (x + big_arrowhead_height / Canvas.SQRT3, \ |
411 | y + height - big_arrowhead_height), \ | 411 | y + height - big_arrowhead_height), \ |
412 | (x, y + height)], color, GraphFormat.BORDER_THICKNESS) | 412 | (x, y + height)], color, GraphFormat.BORDER_THICKNESS) |
413 | 413 | ||
414 | self.draw_line((x, y), (x, y + height - big_arrowhead_height), | 414 | self.draw_line((x, y), (x, y + height - big_arrowhead_height), |
415 | color, GraphFormat.BORDER_THICKNESS) | 415 | color, GraphFormat.BORDER_THICKNESS) |
416 | 416 | ||
417 | def add_sel_deadline_arrow_big(self, x, y, height, event): | 417 | def add_sel_deadline_arrow_big(self, x, y, height, event): |
418 | self.add_sel_arrow_big(x, y, height, event) | 418 | self.add_sel_arrow_big(x, y, height, event) |
419 | 419 | ||
420 | def add_sel_arrow_big(self, x, y, height, event): | 420 | def add_sel_arrow_big(self, x, y, height, event): |
421 | big_arrowhead_height = GraphFormat.BIG_ARROWHEAD_FACTOR * height | 421 | big_arrowhead_height = GraphFormat.BIG_ARROWHEAD_FACTOR * height |
422 | 422 | ||
423 | self.add_sel_region(SelectableRegion(x - big_arrowhead_height / Canvas.SQRT3, | 423 | self.add_sel_region(SelectableRegion(x - big_arrowhead_height / Canvas.SQRT3, |
424 | y, 2.0 * big_arrowhead_height / Canvas.SQRT3, height, event)) | 424 | y, 2.0 * big_arrowhead_height / Canvas.SQRT3, height, event)) |
425 | 425 | ||
426 | def draw_release_arrow_small(self, x, y, height, selected): | 426 | def draw_release_arrow_small(self, x, y, height, selected): |
427 | """Draws a small release arrow (most likely coming off the x-axis, although | 427 | """Draws a small release arrow (most likely coming off the x-axis, although |
428 | this method doesn't enforce this): x, y should give the top of the arrow""" | 428 | this method doesn't enforce this): x, y should give the top of the arrow""" |
429 | small_arrowhead_height = GraphFormat.SMALL_ARROWHEAD_FACTOR * height | 429 | small_arrowhead_height = GraphFormat.SMALL_ARROWHEAD_FACTOR * height |
430 | 430 | ||
431 | color = {False : GraphFormat.BORDER_COLOR, True : GraphFormat.HIGHLIGHT_COLOR}[selected] | 431 | color = {False : GraphFormat.BORDER_COLOR, True : GraphFormat.HIGHLIGHT_COLOR}[selected] |
432 | 432 | ||
433 | self.draw_line((x, y), (x - small_arrowhead_height, y + small_arrowhead_height), \ | 433 | self.draw_line((x, y), (x - small_arrowhead_height, y + small_arrowhead_height), \ |
434 | color, GraphFormat.BORDER_THICKNESS) | 434 | color, GraphFormat.BORDER_THICKNESS) |
435 | self.draw_line((x, y), (x + small_arrowhead_height, y + small_arrowhead_height), \ | 435 | self.draw_line((x, y), (x + small_arrowhead_height, y + small_arrowhead_height), \ |
436 | color, GraphFormat.BORDER_THICKNESS) | 436 | color, GraphFormat.BORDER_THICKNESS) |
437 | self.draw_line((x, y), (x, y + height), color, GraphFormat.BORDER_THICKNESS) | 437 | self.draw_line((x, y), (x, y + height), color, GraphFormat.BORDER_THICKNESS) |
438 | 438 | ||
439 | def add_sel_release_arrow_small(self, x, y, height, event): | 439 | def add_sel_release_arrow_small(self, x, y, height, event): |
440 | self.add_sel_arrow_small(x, y, height, event) | 440 | self.add_sel_arrow_small(x, y, height, event) |
441 | 441 | ||
442 | def draw_deadline_arrow_small(self, x, y, height, selected): | 442 | def draw_deadline_arrow_small(self, x, y, height, selected): |
443 | """Draws a small deadline arrow (most likely coming off the x-axis, although | 443 | """Draws a small deadline arrow (most likely coming off the x-axis, although |
444 | this method doesn't enforce this): x, y should give the top of the arrow""" | 444 | this method doesn't enforce this): x, y should give the top of the arrow""" |
445 | small_arrowhead_height = GraphFormat.SMALL_ARROWHEAD_FACTOR * height | 445 | small_arrowhead_height = GraphFormat.SMALL_ARROWHEAD_FACTOR * height |
446 | 446 | ||
447 | color = {False : GraphFormat.BORDER_COLOR, True : GraphFormat.HIGHLIGHT_COLOR}[selected] | 447 | color = {False : GraphFormat.BORDER_COLOR, True : GraphFormat.HIGHLIGHT_COLOR}[selected] |
448 | 448 | ||
449 | self.draw_line((x, y), (x, y + height), color, GraphFormat.BORDER_THICKNESS) | 449 | self.draw_line((x, y), (x, y + height), color, GraphFormat.BORDER_THICKNESS) |
450 | self.draw_line((x - small_arrowhead_height, y + height - small_arrowhead_height), \ | 450 | self.draw_line((x - small_arrowhead_height, y + height - small_arrowhead_height), \ |
451 | (x, y + height), color, GraphFormat.BORDER_THICKNESS) | 451 | (x, y + height), color, GraphFormat.BORDER_THICKNESS) |
452 | self.draw_line((x + small_arrowhead_height, y + height - small_arrowhead_height), \ | 452 | self.draw_line((x + small_arrowhead_height, y + height - small_arrowhead_height), \ |
453 | (x, y + height), color, GraphFormat.BORDER_THICKNESS) | 453 | (x, y + height), color, GraphFormat.BORDER_THICKNESS) |
454 | 454 | ||
455 | def add_sel_deadline_arrow_small(self, x, y, height, event): | 455 | def add_sel_deadline_arrow_small(self, x, y, height, event): |
456 | self.add_sel_arrow_small(x, y, height, event) | 456 | self.add_sel_arrow_small(x, y, height, event) |
457 | 457 | ||
458 | def add_sel_arrow_small(self, x, y, height, event): | 458 | def add_sel_arrow_small(self, x, y, height, event): |
459 | small_arrowhead_height = GraphFormat.SMALL_ARROWHEAD_FACTOR * height | 459 | small_arrowhead_height = GraphFormat.SMALL_ARROWHEAD_FACTOR * height |
460 | 460 | ||
461 | self.add_sel_region(SelectableRegion(x - small_arrowhead_height, y, | 461 | self.add_sel_region(SelectableRegion(x - small_arrowhead_height, y, |
462 | small_arrowhead_height * 2.0, height, event)) | 462 | small_arrowhead_height * 2.0, height, event)) |
463 | 463 | ||
464 | def draw_suspend_triangle(self, x, y, height, selected): | 464 | def draw_suspend_triangle(self, x, y, height, selected): |
465 | """Draws the triangle that marks a suspension. (x, y) gives the topmost (northernmost) point | 465 | """Draws the triangle that marks a suspension. (x, y) gives the topmost (northernmost) point |
466 | of the symbol.""" | 466 | of the symbol.""" |
467 | 467 | ||
468 | color = {False : GraphFormat.BORDER_COLOR, True : GraphFormat.HIGHLIGHT_COLOR}[selected] | 468 | color = {False : GraphFormat.BORDER_COLOR, True : GraphFormat.HIGHLIGHT_COLOR}[selected] |
469 | colors = [(0.0, 0.0, 0.0), color] | 469 | colors = [(0.0, 0.0, 0.0), color] |
470 | 470 | ||
471 | draw_funcs = [self.__class__.fill_polyline, self.__class__.draw_polyline] | 471 | draw_funcs = [self.__class__.fill_polyline, self.__class__.draw_polyline] |
472 | for i in range(0, 2): | 472 | for i in range(0, 2): |
473 | color = colors[i] | 473 | color = colors[i] |
474 | draw_func = draw_funcs[i] | 474 | draw_func = draw_funcs[i] |
475 | draw_func(self, [(x, y), (x + height / 2.0, y + height / 2.0), (x, y + height), (x, y)], \ | 475 | draw_func(self, [(x, y), (x + height / 2.0, y + height / 2.0), (x, y + height), (x, y)], \ |
476 | color, GraphFormat.BORDER_THICKNESS) | 476 | color, GraphFormat.BORDER_THICKNESS) |
477 | 477 | ||
478 | def add_sel_suspend_triangle(self, x, y, height, event): | 478 | def add_sel_suspend_triangle(self, x, y, height, event): |
479 | self.add_sel_region(SelectableRegion(x, y, height / 2.0, height, event)) | 479 | self.add_sel_region(SelectableRegion(x, y, height / 2.0, height, event)) |
480 | 480 | ||
481 | def draw_resume_triangle(self, x, y, height, selected): | 481 | def draw_resume_triangle(self, x, y, height, selected): |
482 | """Draws the triangle that marks a resumption. (x, y) gives the topmost (northernmost) point | 482 | """Draws the triangle that marks a resumption. (x, y) gives the topmost (northernmost) point |
483 | of the symbol.""" | 483 | of the symbol.""" |
484 | 484 | ||
485 | color = {False : GraphFormat.BORDER_COLOR, True : GraphFormat.HIGHLIGHT_COLOR}[selected] | 485 | color = {False : GraphFormat.BORDER_COLOR, True : GraphFormat.HIGHLIGHT_COLOR}[selected] |
486 | colors = [(1.0, 1.0, 1.0), color] | 486 | colors = [(1.0, 1.0, 1.0), color] |
487 | 487 | ||
488 | draw_funcs = [self.__class__.fill_polyline, self.__class__.draw_polyline] | 488 | draw_funcs = [self.__class__.fill_polyline, self.__class__.draw_polyline] |
489 | for i in range(0, 2): | 489 | for i in range(0, 2): |
490 | color = colors[i] | 490 | color = colors[i] |
491 | draw_func = draw_funcs[i] | 491 | draw_func = draw_funcs[i] |
492 | draw_func(self, [(x, y), (x - height / 2.0, y + height / 2.0), (x, y + height), (x, y)], \ | 492 | draw_func(self, [(x, y), (x - height / 2.0, y + height / 2.0), (x, y + height), (x, y)], \ |
493 | color, GraphFormat.BORDER_THICKNESS) | 493 | color, GraphFormat.BORDER_THICKNESS) |
494 | 494 | ||
495 | def add_sel_resume_triangle(self, x, y, height, event): | 495 | def add_sel_resume_triangle(self, x, y, height, event): |
496 | self.add_sel_region(SelectableRegion(x - height / 2.0, y, height / 2.0, height, event)) | 496 | self.add_sel_region(SelectableRegion(x - height / 2.0, y, height / 2.0, height, event)) |
497 | 497 | ||
498 | def clear_selectable_regions(self, real_x, real_y, width, height): | 498 | def clear_selectable_regions(self, real_x, real_y, width, height): |
499 | x = real_x + self.surface.virt_x | 499 | x = real_x + self.surface.virt_x |
500 | y = real_y + self.surface.virt_y | 500 | y = real_y + self.surface.virt_y |
501 | for event in self.selectable_regions.keys(): | 501 | for event in self.selectable_regions.keys(): |
502 | if self.selectable_regions[event].intersects(x, y, width, height): | 502 | if self.selectable_regions[event].intersects(x, y, width, height): |
503 | del self.selectable_regions[event] | 503 | del self.selectable_regions[event] |
504 | 504 | ||
505 | def add_sel_region(self, region): | 505 | def add_sel_region(self, region): |
506 | self.selectable_regions[region.get_event()] = region | 506 | self.selectable_regions[region.get_event()] = region |
507 | 507 | ||
508 | def get_sel_region(self, event): | 508 | def get_sel_region(self, event): |
509 | return self.selectable_regions[event] | 509 | return self.selectable_regions[event] |
510 | 510 | ||
511 | def get_selected_regions(self, real_x, real_y, width, height): | 511 | def get_selected_regions(self, real_x, real_y, width, height): |
512 | x = real_x + self.surface.virt_x | 512 | x = real_x + self.surface.virt_x |
513 | y = real_y + self.surface.virt_y | 513 | y = real_y + self.surface.virt_y |
514 | 514 | ||
515 | selected = {} | 515 | selected = {} |
516 | for event in self.selectable_regions: | 516 | for event in self.selectable_regions: |
517 | region = self.selectable_regions[event] | 517 | region = self.selectable_regions[event] |
518 | if region.intersects(x, y, width, height): | 518 | if region.intersects(x, y, width, height): |
519 | selected[event] = region | 519 | selected[event] = region |
520 | 520 | ||
521 | return selected | 521 | return selected |
522 | 522 | ||
523 | def whiteout(self, real_x, real_y, width, height): | 523 | def whiteout(self, real_x, real_y, width, height): |
524 | """Overwrites the surface completely white, but technically doesn't delete anything""" | 524 | """Overwrites the surface completely white, but technically doesn't delete anything""" |
525 | self.fill_rect(self.surface.virt_x + real_x, self.surface.virt_y + real_y, width, | 525 | self.fill_rect(self.surface.virt_x + real_x, self.surface.virt_y + real_y, width, |
526 | height, (1.0, 1.0, 1.0), False) | 526 | height, (1.0, 1.0, 1.0), False) |
527 | 527 | ||
528 | def get_item_color(self, n): | 528 | def get_item_color(self, n): |
529 | """Gets the nth color in the item color list, which are the colors used to draw the items | 529 | """Gets the nth color in the item color list, which are the colors used to draw the items |
530 | on the y-axis. Note that there are conceptually infinitely | 530 | on the y-axis. Note that there are conceptually infinitely |
531 | many patterns because the patterns repeat -- that is, we just mod out by the size of the pattern | 531 | many patterns because the patterns repeat -- that is, we just mod out by the size of the pattern |
532 | list when indexing.""" | 532 | list when indexing.""" |
533 | return self.item_clist[n % len(self.item_clist)] | 533 | return self.item_clist[n % len(self.item_clist)] |
534 | 534 | ||
535 | def get_bar_pattern(self, n): | 535 | def get_bar_pattern(self, n): |
536 | """Gets the nth pattern in the bar pattern list, which is a list of surfaces that are used to | 536 | """Gets the nth pattern in the bar pattern list, which is a list of surfaces that are used to |
537 | fill in the bars. Note that there are conceptually infinitely | 537 | fill in the bars. Note that there are conceptually infinitely |
@@ -545,30 +545,30 @@ class CairoCanvas(Canvas): | |||
545 | """This is a basic class that stores and draws on a Cairo surface, | 545 | """This is a basic class that stores and draws on a Cairo surface, |
546 | using various primitives related to drawing a real-time graph (up-arrows, | 546 | using various primitives related to drawing a real-time graph (up-arrows, |
547 | down-arrows, bars, ...). | 547 | down-arrows, bars, ...). |
548 | 548 | ||
549 | This is the lowest-level non-abstract representation | 549 | This is the lowest-level non-abstract representation |
550 | (aside perhaps from the Cairo surface itself) of a real-time graph. | 550 | (aside perhaps from the Cairo surface itself) of a real-time graph. |
551 | It allows the user to draw primitives at certain locations, but for | 551 | It allows the user to draw primitives at certain locations, but for |
552 | the most part does not know anything about real-time scheduling, | 552 | the most part does not know anything about real-time scheduling, |
553 | just how to draw the basic parts that make up a schedule graph. | 553 | just how to draw the basic parts that make up a schedule graph. |
554 | For that, see Graph or its descendants.""" | 554 | For that, see Graph or its descendants.""" |
555 | 555 | ||
556 | #def __init__(self, fname, width, height, item_clist, bar_plist, surface): | 556 | #def __init__(self, fname, width, height, item_clist, bar_plist, surface): |
557 | # """Creates a new Canvas of dimensions (width, height). The | 557 | # """Creates a new Canvas of dimensions (width, height). The |
558 | # parameters ``item_plist'' and ``bar_plist'' each specify a list | 558 | # parameters ``item_plist'' and ``bar_plist'' each specify a list |
559 | # of patterns to choose from when drawing the items on the y-axis | 559 | # of patterns to choose from when drawing the items on the y-axis |
560 | # or filling in bars, respectively.""" | 560 | # or filling in bars, respectively.""" |
561 | 561 | ||
562 | # super(CairoCanvas, self).__init__(fname, width, height, item_clist, bar_plist, surface) | 562 | # super(CairoCanvas, self).__init__(fname, width, height, item_clist, bar_plist, surface) |
563 | 563 | ||
564 | #def clear(self): | 564 | #def clear(self): |
565 | # self.surface = self.SurfaceType(self.width, self.height, self.fname) | 565 | # self.surface = self.SurfaceType(self.width, self.height, self.fname) |
566 | # self.whiteout() | 566 | # self.whiteout() |
567 | 567 | ||
568 | def get_surface(self): | 568 | def get_surface(self): |
569 | """Gets the Surface that we are drawing on in its current state.""" | 569 | """Gets the Surface that we are drawing on in its current state.""" |
570 | return self.surface | 570 | return self.surface |
571 | 571 | ||
572 | def _rect_common(self, x, y, width, height, color, thickness, do_snap=True): | 572 | def _rect_common(self, x, y, width, height, color, thickness, do_snap=True): |
573 | x, y, width, height = self.scaled(x, y, width, height) | 573 | x, y, width, height = self.scaled(x, y, width, height) |
574 | x, y = self.surface.get_real_coor(x, y) | 574 | x, y = self.surface.get_real_coor(x, y) |
@@ -576,23 +576,23 @@ class CairoCanvas(Canvas): | |||
576 | self.surface.ctx.rectangle(snap(x), snap(y), width, height) | 576 | self.surface.ctx.rectangle(snap(x), snap(y), width, height) |
577 | else: | 577 | else: |
578 | self.surface.ctx.rectangle(x, y, width, height) | 578 | self.surface.ctx.rectangle(x, y, width, height) |
579 | 579 | ||
580 | self.surface.ctx.set_line_width(thickness * self.scale) | 580 | self.surface.ctx.set_line_width(thickness * self.scale) |
581 | self.surface.ctx.set_source_rgb(color[0], color[1], color[2]) | 581 | self.surface.ctx.set_source_rgb(color[0], color[1], color[2]) |
582 | 582 | ||
583 | def draw_rect(self, x, y, width, height, color, thickness, do_snap=True): | 583 | def draw_rect(self, x, y, width, height, color, thickness, do_snap=True): |
584 | self._rect_common(x, y, width, height, color, thickness, do_snap) | 584 | self._rect_common(x, y, width, height, color, thickness, do_snap) |
585 | self.surface.ctx.stroke() | 585 | self.surface.ctx.stroke() |
586 | 586 | ||
587 | def fill_rect(self, x, y, width, height, color, do_snap=True): | 587 | def fill_rect(self, x, y, width, height, color, do_snap=True): |
588 | self._rect_common(x, y, width, height, color, 1, do_snap) | 588 | self._rect_common(x, y, width, height, color, 1, do_snap) |
589 | self.surface.ctx.fill() | 589 | self.surface.ctx.fill() |
590 | 590 | ||
591 | def fill_rect_fade(self, x, y, width, height, lcolor, rcolor, do_snap=True): | 591 | def fill_rect_fade(self, x, y, width, height, lcolor, rcolor, do_snap=True): |
592 | """Draws a rectangle somewhere, filled in with the fade.""" | 592 | """Draws a rectangle somewhere, filled in with the fade.""" |
593 | x, y, width, height = self.scaled(x, y, width, height) | 593 | x, y, width, height = self.scaled(x, y, width, height) |
594 | x, y = self.surface.get_real_coor(x, y) | 594 | x, y = self.surface.get_real_coor(x, y) |
595 | 595 | ||
596 | if do_snap: | 596 | if do_snap: |
597 | linear = cairo.LinearGradient(snap(x), snap(y), \ | 597 | linear = cairo.LinearGradient(snap(x), snap(y), \ |
598 | snap(x + width), snap(y + height)) | 598 | snap(x + width), snap(y + height)) |
@@ -607,7 +607,7 @@ class CairoCanvas(Canvas): | |||
607 | else: | 607 | else: |
608 | self.surface.ctx.rectangle(snap(x), snap(y), width, height) | 608 | self.surface.ctx.rectangle(snap(x), snap(y), width, height) |
609 | self.surface.ctx.fill() | 609 | self.surface.ctx.fill() |
610 | 610 | ||
611 | def draw_line(self, p0, p1, color, thickness, do_snap=True): | 611 | def draw_line(self, p0, p1, color, thickness, do_snap=True): |
612 | """Draws a line from p0 to p1 with a certain color and thickness.""" | 612 | """Draws a line from p0 to p1 with a certain color and thickness.""" |
613 | p0 = self.scaled(p0[0], p0[1]) | 613 | p0 = self.scaled(p0[0], p0[1]) |
@@ -617,34 +617,34 @@ class CairoCanvas(Canvas): | |||
617 | if do_snap: | 617 | if do_snap: |
618 | p0 = (snap(p0[0]), snap(p0[1])) | 618 | p0 = (snap(p0[0]), snap(p0[1])) |
619 | p1 = (snap(p1[0]), snap(p1[1])) | 619 | p1 = (snap(p1[0]), snap(p1[1])) |
620 | 620 | ||
621 | self.surface.ctx.move_to(p0[0], p0[1]) | 621 | self.surface.ctx.move_to(p0[0], p0[1]) |
622 | self.surface.ctx.line_to(p1[0], p1[1]) | 622 | self.surface.ctx.line_to(p1[0], p1[1]) |
623 | self.surface.ctx.set_source_rgb(color[0], color[1], color[2]) | 623 | self.surface.ctx.set_source_rgb(color[0], color[1], color[2]) |
624 | self.surface.ctx.set_line_width(thickness * self.scale) | 624 | self.surface.ctx.set_line_width(thickness * self.scale) |
625 | self.surface.ctx.stroke() | 625 | self.surface.ctx.stroke() |
626 | 626 | ||
627 | def _polyline_common(self, coor_list, color, thickness, do_snap=True): | 627 | def _polyline_common(self, coor_list, color, thickness, do_snap=True): |
628 | real_coor_list = [self.surface.get_real_coor(coor[0], coor[1]) for coor in coor_list] | 628 | real_coor_list = [self.surface.get_real_coor(coor[0], coor[1]) for coor in coor_list] |
629 | self.surface.ctx.move_to(real_coor_list[0][0], real_coor_list[0][1]) | 629 | self.surface.ctx.move_to(real_coor_list[0][0], real_coor_list[0][1]) |
630 | if do_snap: | 630 | if do_snap: |
631 | for i in range(0, len(real_coor_list)): | 631 | for i in range(0, len(real_coor_list)): |
632 | real_coor_list[i] = (snap(real_coor_list[i][0]), snap(real_coor_list[i][1])) | 632 | real_coor_list[i] = (snap(real_coor_list[i][0]), snap(real_coor_list[i][1])) |
633 | 633 | ||
634 | for coor in real_coor_list[1:]: | 634 | for coor in real_coor_list[1:]: |
635 | self.surface.ctx.line_to(coor[0], coor[1]) | 635 | self.surface.ctx.line_to(coor[0], coor[1]) |
636 | 636 | ||
637 | self.surface.ctx.set_line_width(thickness) | 637 | self.surface.ctx.set_line_width(thickness) |
638 | self.surface.ctx.set_source_rgb(color[0], color[1], color[2]) | 638 | self.surface.ctx.set_source_rgb(color[0], color[1], color[2]) |
639 | 639 | ||
640 | def draw_polyline(self, coor_list, color, thickness, do_snap=True): | 640 | def draw_polyline(self, coor_list, color, thickness, do_snap=True): |
641 | self._polyline_common(coor_list, color, thickness, do_snap) | 641 | self._polyline_common(coor_list, color, thickness, do_snap) |
642 | self.surface.ctx.stroke() | 642 | self.surface.ctx.stroke() |
643 | 643 | ||
644 | def fill_polyline(self, coor_list, color, thickness, do_snap=True): | 644 | def fill_polyline(self, coor_list, color, thickness, do_snap=True): |
645 | self._polyline_common(coor_list, color, thickness, do_snap) | 645 | self._polyline_common(coor_list, color, thickness, do_snap) |
646 | self.surface.ctx.fill() | 646 | self.surface.ctx.fill() |
647 | 647 | ||
648 | def _draw_label_common(self, text, x, y, fopts, x_bearing_factor, \ | 648 | def _draw_label_common(self, text, x, y, fopts, x_bearing_factor, \ |
649 | f_descent_factor, width_factor, f_height_factor, do_snap=True): | 649 | f_descent_factor, width_factor, f_height_factor, do_snap=True): |
650 | """Helper function for drawing a label with some alignment. Instead of taking in an alignment, | 650 | """Helper function for drawing a label with some alignment. Instead of taking in an alignment, |
@@ -652,30 +652,30 @@ class CairoCanvas(Canvas): | |||
652 | the x and y parameters. Only should be used internally.""" | 652 | the x and y parameters. Only should be used internally.""" |
653 | x, y = self.scaled(x, y) | 653 | x, y = self.scaled(x, y) |
654 | x, y = self.surface.get_real_coor(x, y) | 654 | x, y = self.surface.get_real_coor(x, y) |
655 | 655 | ||
656 | self.surface.ctx.set_source_rgb(0.0, 0.0, 0.0) | 656 | self.surface.ctx.set_source_rgb(0.0, 0.0, 0.0) |
657 | 657 | ||
658 | self.surface.ctx.select_font_face(fopts.name, cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_BOLD) | 658 | self.surface.ctx.select_font_face(fopts.name, cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_BOLD) |
659 | self.surface.ctx.set_font_size(fopts.size) | 659 | self.surface.ctx.set_font_size(fopts.size) |
660 | 660 | ||
661 | fe = self.surface.ctx.font_extents() | 661 | fe = self.surface.ctx.font_extents() |
662 | f_ascent, f_descent, f_height = fe[:3] | 662 | f_ascent, f_descent, f_height = fe[:3] |
663 | 663 | ||
664 | te = self.surface.ctx.text_extents(text) | 664 | te = self.surface.ctx.text_extents(text) |
665 | x_bearing, y_bearing, width, height = te[:4] | 665 | x_bearing, y_bearing, width, height = te[:4] |
666 | 666 | ||
667 | actual_x = x - x_bearing * x_bearing_factor - width * width_factor | 667 | actual_x = x - x_bearing * x_bearing_factor - width * width_factor |
668 | actual_y = y - f_descent * f_descent_factor + f_height * f_height_factor | 668 | actual_y = y - f_descent * f_descent_factor + f_height * f_height_factor |
669 | 669 | ||
670 | self.surface.ctx.set_source_rgb(fopts.color[0], fopts.color[1], fopts.color[2]) | 670 | self.surface.ctx.set_source_rgb(fopts.color[0], fopts.color[1], fopts.color[2]) |
671 | 671 | ||
672 | if do_snap: | 672 | if do_snap: |
673 | self.surface.ctx.move_to(snap(actual_x), snap(actual_y)) | 673 | self.surface.ctx.move_to(snap(actual_x), snap(actual_y)) |
674 | else: | 674 | else: |
675 | self.surface.ctx.move_to(actual_x, actual_y) | 675 | self.surface.ctx.move_to(actual_x, actual_y) |
676 | 676 | ||
677 | self.surface.ctx.show_text(text) | 677 | self.surface.ctx.show_text(text) |
678 | 678 | ||
679 | def draw_label(self, text, x, y, fopts=GraphFormat.DEF_FOPTS_LABEL, halign=AlignMode.LEFT, valign=AlignMode.BOTTOM, do_snap=True): | 679 | def draw_label(self, text, x, y, fopts=GraphFormat.DEF_FOPTS_LABEL, halign=AlignMode.LEFT, valign=AlignMode.BOTTOM, do_snap=True): |
680 | """Draws a label with the given parameters, with the given horizontal and vertical justification. One can override | 680 | """Draws a label with the given parameters, with the given horizontal and vertical justification. One can override |
681 | the color from ``fopts'' by passing something in to ``pattern'', which overrides the color with an arbitrary | 681 | the color from ``fopts'' by passing something in to ``pattern'', which overrides the color with an arbitrary |
@@ -685,21 +685,21 @@ class CairoCanvas(Canvas): | |||
685 | if halign not in halign_factors: | 685 | if halign not in halign_factors: |
686 | raise ValueError('Invalid alignment value') | 686 | raise ValueError('Invalid alignment value') |
687 | x_bearing_factor, width_factor = halign_factors[halign] | 687 | x_bearing_factor, width_factor = halign_factors[halign] |
688 | 688 | ||
689 | valign_factors = {AlignMode.BOTTOM : (0.0, 0.0), AlignMode.CENTER : (1.0, 0.5), AlignMode.TOP : (1.0, 1.0)} | 689 | valign_factors = {AlignMode.BOTTOM : (0.0, 0.0), AlignMode.CENTER : (1.0, 0.5), AlignMode.TOP : (1.0, 1.0)} |
690 | if valign not in valign_factors: | 690 | if valign not in valign_factors: |
691 | raise ValueError('Invalid alignment value') | 691 | raise ValueError('Invalid alignment value') |
692 | f_descent_factor, f_height_factor = valign_factors[valign] | 692 | f_descent_factor, f_height_factor = valign_factors[valign] |
693 | 693 | ||
694 | self._draw_label_common(text, x, y, fopts, x_bearing_factor, \ | 694 | self._draw_label_common(text, x, y, fopts, x_bearing_factor, \ |
695 | f_descent_factor, width_factor, f_height_factor, do_snap) | 695 | f_descent_factor, width_factor, f_height_factor, do_snap) |
696 | 696 | ||
697 | def draw_label_with_sscripts(self, text, supscript, subscript, x, y, \ | 697 | def draw_label_with_sscripts(self, text, supscript, subscript, x, y, \ |
698 | textfopts=GraphFormat.DEF_FOPTS_LABEL, sscriptfopts=GraphFormat.DEF_FOPTS_LABEL_SSCRIPT, \ | 698 | textfopts=GraphFormat.DEF_FOPTS_LABEL, sscriptfopts=GraphFormat.DEF_FOPTS_LABEL_SSCRIPT, \ |
699 | halign=AlignMode.LEFT, valign=AlignMode.BOTTOM, do_snap=True): | 699 | halign=AlignMode.LEFT, valign=AlignMode.BOTTOM, do_snap=True): |
700 | """Draws a label, but also optionally allows a superscript and subscript to be rendered.""" | 700 | """Draws a label, but also optionally allows a superscript and subscript to be rendered.""" |
701 | self.draw_label(text, x, y, textfopts, halign, valign) | 701 | self.draw_label(text, x, y, textfopts, halign, valign) |
702 | 702 | ||
703 | self.surface.ctx.set_source_rgb(0.0, 0.0, 0.0) | 703 | self.surface.ctx.set_source_rgb(0.0, 0.0, 0.0) |
704 | self.surface.ctx.select_font_face(textfopts.name, cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_BOLD) | 704 | self.surface.ctx.select_font_face(textfopts.name, cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_BOLD) |
705 | self.surface.ctx.set_font_size(textfopts.size) | 705 | self.surface.ctx.set_font_size(textfopts.size) |
@@ -719,7 +719,7 @@ class CairoCanvas(Canvas): | |||
719 | ytmp = y | 719 | ytmp = y |
720 | ytmp = y + f_height / 4.0 | 720 | ytmp = y + f_height / 4.0 |
721 | self.draw_label(subscript, xtmp, ytmp, sscriptfopts, halign, valign, do_snap) | 721 | self.draw_label(subscript, xtmp, ytmp, sscriptfopts, halign, valign, do_snap) |
722 | 722 | ||
723 | # represents a selectable region of the graph | 723 | # represents a selectable region of the graph |
724 | class SelectableRegion(object): | 724 | class SelectableRegion(object): |
725 | def __init__(self, x, y, width, height, event): | 725 | def __init__(self, x, y, width, height, event): |
@@ -728,23 +728,23 @@ class SelectableRegion(object): | |||
728 | self.width = width | 728 | self.width = width |
729 | self.height = height | 729 | self.height = height |
730 | self.event = event | 730 | self.event = event |
731 | 731 | ||
732 | def get_dimensions(self): | 732 | def get_dimensions(self): |
733 | return (self.x, self.y, self.width, self.height) | 733 | return (self.x, self.y, self.width, self.height) |
734 | 734 | ||
735 | def get_event(self): | 735 | def get_event(self): |
736 | return self.event | 736 | return self.event |
737 | 737 | ||
738 | def intersects(self, x, y, width, height): | 738 | def intersects(self, x, y, width, height): |
739 | return x <= self.x + self.width and x + width >= self.x and y <= self.y + self.height and y + height >= self.y | 739 | return x <= self.x + self.width and x + width >= self.x and y <= self.y + self.height and y + height >= self.y |
740 | 740 | ||
741 | class Graph(object): | 741 | class Graph(object): |
742 | DEF_BAR_PLIST = [Pattern([(0.0, 0.9, 0.9)]), Pattern([(0.9, 0.3, 0.0)]), Pattern([(0.9, 0.7, 0.0)]), | 742 | DEF_BAR_PLIST = [Pattern([(0.0, 0.9, 0.9)]), Pattern([(0.9, 0.3, 0.0)]), Pattern([(0.9, 0.7, 0.0)]), |
743 | Pattern([(0.0, 0.0, 0.8)]), Pattern([(0.0, 0.2, 0.9)]), Pattern([(0.0, 0.6, 0.6)]), | 743 | Pattern([(0.0, 0.0, 0.8)]), Pattern([(0.0, 0.2, 0.9)]), Pattern([(0.0, 0.6, 0.6)]), |
744 | Pattern([(0.75, 0.75, 0.75)])] | 744 | Pattern([(0.75, 0.75, 0.75)])] |
745 | DEF_ITEM_CLIST = [(0.3, 0.0, 0.0), (0.0, 0.3, 0.0), (0.0, 0.0, 0.3), (0.3, 0.3, 0.0), (0.0, 0.3, 0.3), | 745 | DEF_ITEM_CLIST = [(0.3, 0.0, 0.0), (0.0, 0.3, 0.0), (0.0, 0.0, 0.3), (0.3, 0.3, 0.0), (0.0, 0.3, 0.3), |
746 | (0.3, 0.0, 0.3)] | 746 | (0.3, 0.0, 0.3)] |
747 | 747 | ||
748 | def __init__(self, CanvasType, surface, start_time, end_time, y_item_list, attrs=GraphFormat(), | 748 | def __init__(self, CanvasType, surface, start_time, end_time, y_item_list, attrs=GraphFormat(), |
749 | item_clist=DEF_ITEM_CLIST, bar_plist=DEF_BAR_PLIST): | 749 | item_clist=DEF_ITEM_CLIST, bar_plist=DEF_BAR_PLIST): |
750 | # deal with possibly blank schedules | 750 | # deal with possibly blank schedules |
@@ -752,16 +752,16 @@ class Graph(object): | |||
752 | start_time = 0 | 752 | start_time = 0 |
753 | if end_time is None: | 753 | if end_time is None: |
754 | end_time = 0 | 754 | end_time = 0 |
755 | 755 | ||
756 | if start_time > end_time: | 756 | if start_time > end_time: |
757 | raise ValueError("Litmus is not a time machine") | 757 | raise ValueError("Litmus is not a time machine") |
758 | 758 | ||
759 | self.attrs = attrs | 759 | self.attrs = attrs |
760 | self.start_time = start_time | 760 | self.start_time = start_time |
761 | self.end_time = end_time | 761 | self.end_time = end_time |
762 | self.y_item_list = y_item_list | 762 | self.y_item_list = y_item_list |
763 | self.num_maj = int(math.ceil((self.end_time - self.start_time) * 1.0 / self.attrs.time_per_maj)) + 1 | 763 | self.num_maj = int(math.ceil((self.end_time - self.start_time) * 1.0 / self.attrs.time_per_maj)) + 1 |
764 | 764 | ||
765 | width = self.num_maj * self.attrs.maj_sep + GraphFormat.X_AXIS_MEASURE_OFS + GraphFormat.WIDTH_PAD | 765 | width = self.num_maj * self.attrs.maj_sep + GraphFormat.X_AXIS_MEASURE_OFS + GraphFormat.WIDTH_PAD |
766 | height = (len(self.y_item_list) + 1) * self.attrs.y_item_size + GraphFormat.HEIGHT_PAD | 766 | height = (len(self.y_item_list) + 1) * self.attrs.y_item_size + GraphFormat.HEIGHT_PAD |
767 | 767 | ||
@@ -771,7 +771,7 @@ class Graph(object): | |||
771 | extra_width = 0.0 | 771 | extra_width = 0.0 |
772 | dummy_surface = surface.__class__() | 772 | dummy_surface = surface.__class__() |
773 | dummy_surface.renew(10, 10) | 773 | dummy_surface.renew(10, 10) |
774 | 774 | ||
775 | dummy_surface.ctx.select_font_face(self.attrs.item_fopts.name, cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_BOLD) | 775 | dummy_surface.ctx.select_font_face(self.attrs.item_fopts.name, cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_BOLD) |
776 | dummy_surface.ctx.set_font_size(self.attrs.item_fopts.size) | 776 | dummy_surface.ctx.set_font_size(self.attrs.item_fopts.size) |
777 | for item in self.y_item_list: | 777 | for item in self.y_item_list: |
@@ -780,45 +780,45 @@ class Graph(object): | |||
780 | cur_width = te[2] | 780 | cur_width = te[2] |
781 | if cur_width > extra_width: | 781 | if cur_width > extra_width: |
782 | extra_width = cur_width | 782 | extra_width = cur_width |
783 | 783 | ||
784 | width += extra_width | 784 | width += extra_width |
785 | 785 | ||
786 | self.origin = (extra_width + GraphFormat.WIDTH_PAD / 2.0, height - GraphFormat.HEIGHT_PAD / 2.0) | 786 | self.origin = (extra_width + GraphFormat.WIDTH_PAD / 2.0, height - GraphFormat.HEIGHT_PAD / 2.0) |
787 | 787 | ||
788 | self.width = width | 788 | self.width = width |
789 | self.height = height | 789 | self.height = height |
790 | 790 | ||
791 | #if surface.ctx is None: | 791 | #if surface.ctx is None: |
792 | # surface.renew(width, height) | 792 | # surface.renew(width, height) |
793 | 793 | ||
794 | self.canvas = CanvasType(width, height, item_clist, bar_plist, surface) | 794 | self.canvas = CanvasType(width, height, item_clist, bar_plist, surface) |
795 | 795 | ||
796 | def get_selected_regions(self, real_x, real_y, width, height): | 796 | def get_selected_regions(self, real_x, real_y, width, height): |
797 | return self.canvas.get_selected_regions(real_x, real_y, width, height) | 797 | return self.canvas.get_selected_regions(real_x, real_y, width, height) |
798 | 798 | ||
799 | def get_width(self): | 799 | def get_width(self): |
800 | return self.width | 800 | return self.width |
801 | 801 | ||
802 | def get_height(self): | 802 | def get_height(self): |
803 | return self.height | 803 | return self.height |
804 | 804 | ||
805 | def get_origin(self): | 805 | def get_origin(self): |
806 | return self.origin | 806 | return self.origin |
807 | 807 | ||
808 | def get_attrs(self): | 808 | def get_attrs(self): |
809 | return self.attrs | 809 | return self.attrs |
810 | 810 | ||
811 | def add_sel_region(self, region): | 811 | def add_sel_region(self, region): |
812 | self.canvas.add_sel_region(region) | 812 | self.canvas.add_sel_region(region) |
813 | 813 | ||
814 | def get_sel_region(self, event): | 814 | def get_sel_region(self, event): |
815 | return self.canvas.get_sel_region(event) | 815 | return self.canvas.get_sel_region(event) |
816 | 816 | ||
817 | def update_view(self, x, y, width, height, ctx): | 817 | def update_view(self, x, y, width, height, ctx): |
818 | """Proxy into the surface's pan.""" | 818 | """Proxy into the surface's pan.""" |
819 | self.canvas.surface.pan(x, y, width, height) | 819 | self.canvas.surface.pan(x, y, width, height) |
820 | self.canvas.surface.change_ctx(ctx) | 820 | self.canvas.surface.change_ctx(ctx) |
821 | 821 | ||
822 | def _recomp_min_max(self, start_time, end_time, start_item, end_item): | 822 | def _recomp_min_max(self, start_time, end_time, start_item, end_item): |
823 | if self.min_time is None or start_time < self.min_time: | 823 | if self.min_time is None or start_time < self.min_time: |
824 | self.min_time = start_time | 824 | self.min_time = start_time |
@@ -828,79 +828,79 @@ class Graph(object): | |||
828 | self.min_item = start_item | 828 | self.min_item = start_item |
829 | if self.max_item is None or end_item > self.max_item: | 829 | if self.max_item is None or end_item > self.max_item: |
830 | self.max_item = end_item | 830 | self.max_item = end_item |
831 | 831 | ||
832 | def _get_time_xpos(self, time): | 832 | def _get_time_xpos(self, time): |
833 | """get x so that x is at instant ``time'' on the graph""" | 833 | """get x so that x is at instant ``time'' on the graph""" |
834 | return self.origin[0] + GraphFormat.X_AXIS_MEASURE_OFS + 1.0 * (time - self.start_time) / self.attrs.time_per_maj * self.attrs.maj_sep | 834 | return self.origin[0] + GraphFormat.X_AXIS_MEASURE_OFS + 1.0 * (time - self.start_time) / self.attrs.time_per_maj * self.attrs.maj_sep |
835 | 835 | ||
836 | def _get_item_ypos(self, item_no): | 836 | def _get_item_ypos(self, item_no): |
837 | """get y so that y is where the top of a bar would be in item #n's area""" | 837 | """get y so that y is where the top of a bar would be in item #n's area""" |
838 | return self.origin[1] - self._get_y_axis_height() + self.attrs.y_item_size * (item_no + 0.5 - GraphFormat.BAR_SIZE_FACTOR / 2.0) | 838 | return self.origin[1] - self._get_y_axis_height() + self.attrs.y_item_size * (item_no + 0.5 - GraphFormat.BAR_SIZE_FACTOR / 2.0) |
839 | 839 | ||
840 | def _get_bar_width(self, start_time, end_time): | 840 | def _get_bar_width(self, start_time, end_time): |
841 | return 1.0 * (end_time - start_time) / self.attrs.time_per_maj * self.attrs.maj_sep | 841 | return 1.0 * (end_time - start_time) / self.attrs.time_per_maj * self.attrs.maj_sep |
842 | 842 | ||
843 | def _get_bar_height(self): | 843 | def _get_bar_height(self): |
844 | return self.attrs.y_item_size * GraphFormat.BAR_SIZE_FACTOR | 844 | return self.attrs.y_item_size * GraphFormat.BAR_SIZE_FACTOR |
845 | 845 | ||
846 | def _get_mini_bar_height(self): | 846 | def _get_mini_bar_height(self): |
847 | return self.attrs.y_item_size * GraphFormat.MINI_BAR_SIZE_FACTOR | 847 | return self.attrs.y_item_size * GraphFormat.MINI_BAR_SIZE_FACTOR |
848 | 848 | ||
849 | def _get_mini_bar_ofs(self): | 849 | def _get_mini_bar_ofs(self): |
850 | return self.attrs.y_item_size * (GraphFormat.MINI_BAR_SIZE_FACTOR + GraphFormat.BAR_MINI_BAR_GAP_FACTOR) | 850 | return self.attrs.y_item_size * (GraphFormat.MINI_BAR_SIZE_FACTOR + GraphFormat.BAR_MINI_BAR_GAP_FACTOR) |
851 | 851 | ||
852 | def _get_y_axis_height(self): | 852 | def _get_y_axis_height(self): |
853 | return (len(self.y_item_list) + 1) * self.attrs.y_item_size | 853 | return (len(self.y_item_list) + 1) * self.attrs.y_item_size |
854 | 854 | ||
855 | def _get_bottom_tick(self, time): | 855 | def _get_bottom_tick(self, time): |
856 | return int(math.floor((time - self.start_time) / self.attrs.time_per_maj)) | 856 | return int(math.floor((time - self.start_time) / self.attrs.time_per_maj)) |
857 | 857 | ||
858 | def _get_top_tick(self, time): | 858 | def _get_top_tick(self, time): |
859 | return int(math.ceil((time - self.start_time) / self.attrs.time_per_maj)) | 859 | return int(math.ceil((time - self.start_time) / self.attrs.time_per_maj)) |
860 | 860 | ||
861 | def get_surface(self): | 861 | def get_surface(self): |
862 | """Gets the underlying surface.""" | 862 | """Gets the underlying surface.""" |
863 | return self.canvas.get_surface() | 863 | return self.canvas.get_surface() |
864 | 864 | ||
865 | def xcoor_to_time(self, x): | 865 | def xcoor_to_time(self, x): |
866 | #x = self.origin[0] + GraphFormat.X_AXIS_MEASURE_OFS + (time - self.start) / self.attrs.time_per_maj * self.attrs.maj_sep | 866 | #x = self.origin[0] + GraphFormat.X_AXIS_MEASURE_OFS + (time - self.start) / self.attrs.time_per_maj * self.attrs.maj_sep |
867 | return (x - self.origin[0] - GraphFormat.X_AXIS_MEASURE_OFS) / self.attrs.maj_sep \ | 867 | return (x - self.origin[0] - GraphFormat.X_AXIS_MEASURE_OFS) / self.attrs.maj_sep \ |
868 | * self.attrs.time_per_maj + self.start_time | 868 | * self.attrs.time_per_maj + self.start_time |
869 | 869 | ||
870 | def ycoor_to_item_no(self, y): | 870 | def ycoor_to_item_no(self, y): |
871 | return int((y - self.origin[1] + self._get_y_axis_height()) // self.attrs.y_item_size) | 871 | return int((y - self.origin[1] + self._get_y_axis_height()) // self.attrs.y_item_size) |
872 | 872 | ||
873 | def get_offset_params(self, real_x, real_y, width, height): | 873 | def get_offset_params(self, real_x, real_y, width, height): |
874 | start_time = self.xcoor_to_time(self.canvas.surface.virt_x + real_x) | 874 | start_time = self.xcoor_to_time(self.canvas.surface.virt_x + real_x) |
875 | end_time = self.xcoor_to_time(self.canvas.surface.virt_x + real_x + width) | 875 | end_time = self.xcoor_to_time(self.canvas.surface.virt_x + real_x + width) |
876 | 876 | ||
877 | start_item = self.ycoor_to_item_no(self.canvas.surface.virt_y + real_y) | 877 | start_item = self.ycoor_to_item_no(self.canvas.surface.virt_y + real_y) |
878 | end_item = 2 + self.ycoor_to_item_no(self.canvas.surface.virt_y + real_y + height) | 878 | end_item = 2 + self.ycoor_to_item_no(self.canvas.surface.virt_y + real_y + height) |
879 | 879 | ||
880 | return (start_time, end_time, start_item, end_item) | 880 | return (start_time, end_time, start_item, end_item) |
881 | 881 | ||
882 | def draw_skeleton(self, start_time, end_time, start_item, end_item): | 882 | def draw_skeleton(self, start_time, end_time, start_item, end_item): |
883 | self.draw_grid_at_time(start_time, end_time, start_item, end_item) | 883 | self.draw_grid_at_time(start_time, end_time, start_item, end_item) |
884 | self.draw_x_axis_with_labels_at_time(start_time, end_time) | 884 | self.draw_x_axis_with_labels_at_time(start_time, end_time) |
885 | self.draw_y_axis_with_labels() | 885 | self.draw_y_axis_with_labels() |
886 | 886 | ||
887 | def render_surface(self, sched, regions, selectable=False): | 887 | def render_surface(self, sched, regions, selectable=False): |
888 | raise NotImplementedError | 888 | raise NotImplementedError |
889 | 889 | ||
890 | def render_all(self, schedule): | 890 | def render_all(self, schedule): |
891 | raise NotImplementedError | 891 | raise NotImplementedError |
892 | 892 | ||
893 | def render_events(self, event_list): | 893 | def render_events(self, event_list): |
894 | for layer in Canvas.LAYERS: | 894 | for layer in Canvas.LAYERS: |
895 | prev_events = {} | 895 | prev_events = {} |
896 | for event in event_list: | 896 | for event in event_list: |
897 | event.render(self, layer, prev_events) | 897 | event.render(self, layer, prev_events) |
898 | 898 | ||
899 | def draw_axes(self, x_axis_label, y_axis_label): | 899 | def draw_axes(self, x_axis_label, y_axis_label): |
900 | """Draws and labels the axes according to the parameters that we were initialized | 900 | """Draws and labels the axes according to the parameters that we were initialized |
901 | with.""" | 901 | with.""" |
902 | self.draw_grid_at_time(self.start_time, self.end_time, 0, len(self.attrs.y_item_list) - 1) | 902 | self.draw_grid_at_time(self.start_time, self.end_time, 0, len(self.attrs.y_item_list) - 1) |
903 | 903 | ||
904 | self.canvas.draw_x_axis(self.origin[0], self.origin[1], self.num_maj, self.attrs.maj_sep, self.attrs.min_per_maj) | 904 | self.canvas.draw_x_axis(self.origin[0], self.origin[1], self.num_maj, self.attrs.maj_sep, self.attrs.min_per_maj) |
905 | self.canvas.draw_y_axis(self.origin[0], self.origin[1], self._get_y_axis_height()) | 905 | self.canvas.draw_y_axis(self.origin[0], self.origin[1], self._get_y_axis_height()) |
906 | self.canvas.draw_x_axis_labels(self.origin[0], self.origin[1], 0, self.num_maj - 1,\ | 906 | self.canvas.draw_x_axis_labels(self.origin[0], self.origin[1], 0, self.num_maj - 1,\ |
@@ -908,274 +908,274 @@ class Graph(object): | |||
908 | self.attrs.time_per_maj, self.attrs.show_min, self.attrs.majfopts, self.attrs.minfopts) | 908 | self.attrs.time_per_maj, self.attrs.show_min, self.attrs.majfopts, self.attrs.minfopts) |
909 | self.canvas.draw_y_axis_labels(self.origin[0], self.origin[1], self._get_y_axis_height(), self.y_item_list, \ | 909 | self.canvas.draw_y_axis_labels(self.origin[0], self.origin[1], self._get_y_axis_height(), self.y_item_list, \ |
910 | self.attrs.y_item_size, self.attrs.item_fopts) | 910 | self.attrs.y_item_size, self.attrs.item_fopts) |
911 | 911 | ||
912 | def draw_grid_at_time(self, start_time, end_time, start_item, end_item): | 912 | def draw_grid_at_time(self, start_time, end_time, start_item, end_item): |
913 | """Draws the grid, but only in a certain time and item range.""" | 913 | """Draws the grid, but only in a certain time and item range.""" |
914 | start_tick = max(0, self._get_bottom_tick(start_time)) | 914 | start_tick = max(0, self._get_bottom_tick(start_time)) |
915 | end_tick = min(self.num_maj - 1, self._get_top_tick(end_time)) | 915 | end_tick = min(self.num_maj - 1, self._get_top_tick(end_time)) |
916 | 916 | ||
917 | start_item = max(0, start_item) | 917 | start_item = max(0, start_item) |
918 | end_item = min(len(self.y_item_list), end_item) | 918 | end_item = min(len(self.y_item_list), end_item) |
919 | 919 | ||
920 | self.canvas.draw_grid(self.origin[0], self.origin[1], self._get_y_axis_height(), | 920 | self.canvas.draw_grid(self.origin[0], self.origin[1], self._get_y_axis_height(), |
921 | start_tick, end_tick, start_item, end_item, self.attrs.maj_sep, self.attrs.y_item_size, \ | 921 | start_tick, end_tick, start_item, end_item, self.attrs.maj_sep, self.attrs.y_item_size, \ |
922 | self.attrs.min_per_maj, True) | 922 | self.attrs.min_per_maj, True) |
923 | 923 | ||
924 | def draw_x_axis_with_labels_at_time(self, start_time, end_time): | 924 | def draw_x_axis_with_labels_at_time(self, start_time, end_time): |
925 | start_tick = max(0, self._get_bottom_tick(start_time)) | 925 | start_tick = max(0, self._get_bottom_tick(start_time)) |
926 | end_tick = min(self.num_maj - 1, self._get_top_tick(end_time)) | 926 | end_tick = min(self.num_maj - 1, self._get_top_tick(end_time)) |
927 | 927 | ||
928 | self.canvas.draw_x_axis(self.origin[0], self.origin[1], start_tick, end_tick, \ | 928 | self.canvas.draw_x_axis(self.origin[0], self.origin[1], start_tick, end_tick, \ |
929 | self.attrs.maj_sep, self.attrs.min_per_maj) | 929 | self.attrs.maj_sep, self.attrs.min_per_maj) |
930 | self.canvas.draw_x_axis_labels(self.origin[0], self.origin[1], start_tick, \ | 930 | self.canvas.draw_x_axis_labels(self.origin[0], self.origin[1], start_tick, \ |
931 | end_tick, self.attrs.maj_sep, self.attrs.min_per_maj, | 931 | end_tick, self.attrs.maj_sep, self.attrs.min_per_maj, |
932 | self.start_time + start_tick * self.attrs.time_per_maj, | 932 | self.start_time + start_tick * self.attrs.time_per_maj, |
933 | self.attrs.time_per_maj, False) | 933 | self.attrs.time_per_maj, False) |
934 | 934 | ||
935 | def draw_y_axis_with_labels(self): | 935 | def draw_y_axis_with_labels(self): |
936 | self.canvas.draw_y_axis(self.origin[0], self.origin[1], self._get_y_axis_height()) | 936 | self.canvas.draw_y_axis(self.origin[0], self.origin[1], self._get_y_axis_height()) |
937 | self.canvas.draw_y_axis_labels(self.origin[0], self.origin[1], self._get_y_axis_height(), \ | 937 | self.canvas.draw_y_axis_labels(self.origin[0], self.origin[1], self._get_y_axis_height(), \ |
938 | self.y_item_list, self.attrs.y_item_size) | 938 | self.y_item_list, self.attrs.y_item_size) |
939 | 939 | ||
940 | def draw_suspend_triangle_at_time(self, time, task_no, cpu_no, selected=False): | 940 | def draw_suspend_triangle_at_time(self, time, task_no, cpu_no, selected=False): |
941 | """Draws a suspension symbol for a certain task at an instant in time.""" | 941 | """Draws a suspension symbol for a certain task at an instant in time.""" |
942 | raise NotImplementedError | 942 | raise NotImplementedError |
943 | 943 | ||
944 | def add_sel_suspend_triangle_at_time(self, time, task_no, cpu_no, event): | 944 | def add_sel_suspend_triangle_at_time(self, time, task_no, cpu_no, event): |
945 | """Same as above, except instead of drawing adds a selectable region at | 945 | """Same as above, except instead of drawing adds a selectable region at |
946 | a certain time.""" | 946 | a certain time.""" |
947 | raise NotImplementedError | 947 | raise NotImplementedError |
948 | 948 | ||
949 | def draw_resume_triangle_at_time(self, time, task_no, cpu_no, selected=False): | 949 | def draw_resume_triangle_at_time(self, time, task_no, cpu_no, selected=False): |
950 | """Draws a resumption symbol for a certain task at an instant in time.""" | 950 | """Draws a resumption symbol for a certain task at an instant in time.""" |
951 | raise NotImplementedError | 951 | raise NotImplementedError |
952 | 952 | ||
953 | def add_sel_resume_triangle_at_time(self, time, task_no, cpu_no, event): | 953 | def add_sel_resume_triangle_at_time(self, time, task_no, cpu_no, event): |
954 | """Same as above, except instead of drawing adds a selectable region at | 954 | """Same as above, except instead of drawing adds a selectable region at |
955 | a certain time.""" | 955 | a certain time.""" |
956 | raise NotImplementedError | 956 | raise NotImplementedError |
957 | 957 | ||
958 | def draw_completion_marker_at_time(self, time, task_no, cpu_no, selected=False): | 958 | def draw_completion_marker_at_time(self, time, task_no, cpu_no, selected=False): |
959 | """Draws a completion marker for a certain task at an instant in time.""" | 959 | """Draws a completion marker for a certain task at an instant in time.""" |
960 | raise NotImplementedError | 960 | raise NotImplementedError |
961 | 961 | ||
962 | def add_sel_completion_marker_at_time(self, time, task_no, cpu_no, event): | 962 | def add_sel_completion_marker_at_time(self, time, task_no, cpu_no, event): |
963 | """Same as above, except instead of drawing adds a selectable region at | 963 | """Same as above, except instead of drawing adds a selectable region at |
964 | a certain time.""" | 964 | a certain time.""" |
965 | raise NotImplementedError | 965 | raise NotImplementedError |
966 | 966 | ||
967 | def draw_release_arrow_at_time(self, time, task_no, job_no, selected=False): | 967 | def draw_release_arrow_at_time(self, time, task_no, job_no, selected=False): |
968 | """Draws a release arrow at a certain time for some task and job""" | 968 | """Draws a release arrow at a certain time for some task and job""" |
969 | raise NotImplementedError | 969 | raise NotImplementedError |
970 | 970 | ||
971 | def add_sel_release_arrow_at_time(self, time, task_no, event): | 971 | def add_sel_release_arrow_at_time(self, time, task_no, event): |
972 | """Same as above, except instead of drawing adds a selectable region at | 972 | """Same as above, except instead of drawing adds a selectable region at |
973 | a certain time.""" | 973 | a certain time.""" |
974 | raise NotImplementedError | 974 | raise NotImplementedError |
975 | 975 | ||
976 | def draw_deadline_arrow_at_time(self, time, task_no, job_no, selected=False): | 976 | def draw_deadline_arrow_at_time(self, time, task_no, job_no, selected=False): |
977 | """Draws a deadline arrow at a certain time for some task and job""" | 977 | """Draws a deadline arrow at a certain time for some task and job""" |
978 | raise NotImplementedError | 978 | raise NotImplementedError |
979 | 979 | ||
980 | def add_sel_deadline_arrow_at_time(self, time, task_no, event): | 980 | def add_sel_deadline_arrow_at_time(self, time, task_no, event): |
981 | """Same as above, except instead of drawing adds a selectable region at | 981 | """Same as above, except instead of drawing adds a selectable region at |
982 | a certain time.""" | 982 | a certain time.""" |
983 | raise NotImplementedError | 983 | raise NotImplementedError |
984 | 984 | ||
985 | def draw_bar_at_time(self, start_time, end_time, task_no, cpu_no, job_no=None, clip_side=None): | 985 | def draw_bar_at_time(self, start_time, end_time, task_no, cpu_no, job_no=None, clip_side=None): |
986 | """Draws a bar over a certain time period for some task, optionally labelling it.""" | 986 | """Draws a bar over a certain time period for some task, optionally labelling it.""" |
987 | raise NotImplementedError | 987 | raise NotImplementedError |
988 | 988 | ||
989 | def add_sel_bar_at_time(self, start_time, end_time, task_no, cpu_no, event): | 989 | def add_sel_bar_at_time(self, start_time, end_time, task_no, cpu_no, event): |
990 | """Same as above, except instead of drawing adds a selectable region at | 990 | """Same as above, except instead of drawing adds a selectable region at |
991 | a certain time.""" | 991 | a certain time.""" |
992 | raise NotImplementedError | 992 | raise NotImplementedError |
993 | 993 | ||
994 | def draw_mini_bar_at_time(self, start_time, end_time, task_no, cpu_no, clip_side=None, job_no=None): | 994 | def draw_mini_bar_at_time(self, start_time, end_time, task_no, cpu_no, clip_side=None, job_no=None): |
995 | """Draws a mini bar over a certain time period for some task, optionally labelling it.""" | 995 | """Draws a mini bar over a certain time period for some task, optionally labelling it.""" |
996 | raise NotImplementedError | 996 | raise NotImplementedError |
997 | 997 | ||
998 | def add_sel_mini_bar_at_time(self, start_time, end_time, task_no, cpu_no, event): | 998 | def add_sel_mini_bar_at_time(self, start_time, end_time, task_no, cpu_no, event): |
999 | """Same as above, except instead of drawing adds a selectable region at | 999 | """Same as above, except instead of drawing adds a selectable region at |
1000 | a certain time.""" | 1000 | a certain time.""" |
1001 | raise NotImplementedError | 1001 | raise NotImplementedError |
1002 | 1002 | ||
1003 | class TaskGraph(Graph): | 1003 | class TaskGraph(Graph): |
1004 | def render_surface(self, sched, regions, selectable=False): | 1004 | def render_surface(self, sched, regions, selectable=False): |
1005 | events_to_render = {} | 1005 | events_to_render = {} |
1006 | for layer in Canvas.LAYERS: | 1006 | for layer in Canvas.LAYERS: |
1007 | events_to_render[layer] = {} | 1007 | events_to_render[layer] = {} |
1008 | 1008 | ||
1009 | for region in regions: | 1009 | for region in regions: |
1010 | x, y, width, height = region | 1010 | x, y, width, height = region |
1011 | if not selectable: | 1011 | if not selectable: |
1012 | self.canvas.whiteout(x, y, width, height) | 1012 | self.canvas.whiteout(x, y, width, height) |
1013 | else: | 1013 | else: |
1014 | self.canvas.clear_selectable_regions(x, y, width, height) | 1014 | self.canvas.clear_selectable_regions(x, y, width, height) |
1015 | 1015 | ||
1016 | self.min_time, self.max_time, self.min_item, self.max_item = None, None, None, None | 1016 | self.min_time, self.max_time, self.min_item, self.max_item = None, None, None, None |
1017 | for region in regions: | 1017 | for region in regions: |
1018 | x, y, width, height = region | 1018 | x, y, width, height = region |
1019 | start_time, end_time, start_item, end_item = self.get_offset_params(x, y, width, height) | 1019 | start_time, end_time, start_item, end_item = self.get_offset_params(x, y, width, height) |
1020 | self._recomp_min_max(start_time, end_time, start_item, end_item) | 1020 | self._recomp_min_max(start_time, end_time, start_item, end_item) |
1021 | 1021 | ||
1022 | for event in sched.get_time_slot_array().iter_over_period( | 1022 | for event in sched.get_time_slot_array().iter_over_period( |
1023 | start_time, end_time, start_item, end_item, | 1023 | start_time, end_time, start_item, end_item, |
1024 | schedule.TimeSlotArray.TASK_LIST, schedule.EVENT_LIST): | 1024 | schedule.TimeSlotArray.TASK_LIST, schedule.EVENT_LIST): |
1025 | events_to_render[event.get_layer()][event] = None | 1025 | events_to_render[event.get_layer()][event] = None |
1026 | 1026 | ||
1027 | if not selectable: | 1027 | if not selectable: |
1028 | self.draw_skeleton(self.min_time, self.max_time, | 1028 | self.draw_skeleton(self.min_time, self.max_time, |
1029 | self.min_item, self.max_item) | 1029 | self.min_item, self.max_item) |
1030 | 1030 | ||
1031 | #if not selectable: | 1031 | #if not selectable: |
1032 | # for layer in events_to_render: | 1032 | # for layer in events_to_render: |
1033 | # print 'task render on layer', layer, ':', [str(e) for e in events_to_render[layer].keys()] | 1033 | # print 'task render on layer', layer, ':', [str(e) for e in events_to_render[layer].keys()] |
1034 | 1034 | ||
1035 | for layer in Canvas.LAYERS: | 1035 | for layer in Canvas.LAYERS: |
1036 | prev_events = {} | 1036 | prev_events = {} |
1037 | for event in events_to_render[layer]: | 1037 | for event in events_to_render[layer]: |
1038 | event.render(self, layer, prev_events, selectable) | 1038 | event.render(self, layer, prev_events, selectable) |
1039 | 1039 | ||
1040 | def draw_suspend_triangle_at_time(self, time, task_no, cpu_no, selected=False): | 1040 | def draw_suspend_triangle_at_time(self, time, task_no, cpu_no, selected=False): |
1041 | height = self._get_bar_height() * GraphFormat.BLOCK_TRIANGLE_FACTOR | 1041 | height = self._get_bar_height() * GraphFormat.BLOCK_TRIANGLE_FACTOR |
1042 | x = self._get_time_xpos(time) | 1042 | x = self._get_time_xpos(time) |
1043 | y = self._get_item_ypos(task_no) + self._get_bar_height() / 2.0 - height / 2.0 | 1043 | y = self._get_item_ypos(task_no) + self._get_bar_height() / 2.0 - height / 2.0 |
1044 | self.canvas.draw_suspend_triangle(x, y, height, selected) | 1044 | self.canvas.draw_suspend_triangle(x, y, height, selected) |
1045 | 1045 | ||
1046 | def add_sel_suspend_triangle_at_time(self, time, task_no, cpu_no, event): | 1046 | def add_sel_suspend_triangle_at_time(self, time, task_no, cpu_no, event): |
1047 | height = self._get_bar_height() * GraphFormat.BLOCK_TRIANGLE_FACTOR | 1047 | height = self._get_bar_height() * GraphFormat.BLOCK_TRIANGLE_FACTOR |
1048 | x = self._get_time_xpos(time) | 1048 | x = self._get_time_xpos(time) |
1049 | y = self._get_item_ypos(task_no) + self._get_bar_height() / 2.0 - height / 2.0 | 1049 | y = self._get_item_ypos(task_no) + self._get_bar_height() / 2.0 - height / 2.0 |
1050 | 1050 | ||
1051 | self.canvas.add_sel_suspend_triangle(x, y, height, event) | 1051 | self.canvas.add_sel_suspend_triangle(x, y, height, event) |
1052 | 1052 | ||
1053 | def draw_resume_triangle_at_time(self, time, task_no, cpu_no, selected=False): | 1053 | def draw_resume_triangle_at_time(self, time, task_no, cpu_no, selected=False): |
1054 | height = self._get_bar_height() * GraphFormat.BLOCK_TRIANGLE_FACTOR | 1054 | height = self._get_bar_height() * GraphFormat.BLOCK_TRIANGLE_FACTOR |
1055 | x = self._get_time_xpos(time) | 1055 | x = self._get_time_xpos(time) |
1056 | y = self._get_item_ypos(task_no) + self._get_bar_height() / 2.0 - height / 2.0 | 1056 | y = self._get_item_ypos(task_no) + self._get_bar_height() / 2.0 - height / 2.0 |
1057 | 1057 | ||
1058 | self.canvas.draw_resume_triangle(x, y, height, selected) | 1058 | self.canvas.draw_resume_triangle(x, y, height, selected) |
1059 | 1059 | ||
1060 | def add_sel_resume_triangle_at_time(self, time, task_no, cpu_no, event): | 1060 | def add_sel_resume_triangle_at_time(self, time, task_no, cpu_no, event): |
1061 | height = self._get_bar_height() * GraphFormat.BLOCK_TRIANGLE_FACTOR | 1061 | height = self._get_bar_height() * GraphFormat.BLOCK_TRIANGLE_FACTOR |
1062 | x = self._get_time_xpos(time) | 1062 | x = self._get_time_xpos(time) |
1063 | y = self._get_item_ypos(task_no) + self._get_bar_height() / 2.0 - height / 2.0 | 1063 | y = self._get_item_ypos(task_no) + self._get_bar_height() / 2.0 - height / 2.0 |
1064 | 1064 | ||
1065 | self.canvas.add_sel_resume_triangle(x, y, height, event) | 1065 | self.canvas.add_sel_resume_triangle(x, y, height, event) |
1066 | 1066 | ||
1067 | def draw_completion_marker_at_time(self, time, task_no, cpu_no, selected=False): | 1067 | def draw_completion_marker_at_time(self, time, task_no, cpu_no, selected=False): |
1068 | height = self._get_bar_height() * GraphFormat.COMPLETION_MARKER_FACTOR | 1068 | height = self._get_bar_height() * GraphFormat.COMPLETION_MARKER_FACTOR |
1069 | x = self._get_time_xpos(time) | 1069 | x = self._get_time_xpos(time) |
1070 | y = self._get_item_ypos(task_no) + self._get_bar_height() - height | 1070 | y = self._get_item_ypos(task_no) + self._get_bar_height() - height |
1071 | 1071 | ||
1072 | self.canvas.draw_completion_marker(x, y, height, selected) | 1072 | self.canvas.draw_completion_marker(x, y, height, selected) |
1073 | 1073 | ||
1074 | def add_sel_completion_marker_at_time(self, time, task_no, cpu_no, event): | 1074 | def add_sel_completion_marker_at_time(self, time, task_no, cpu_no, event): |
1075 | height = self._get_bar_height() * GraphFormat.COMPLETION_MARKER_FACTOR | 1075 | height = self._get_bar_height() * GraphFormat.COMPLETION_MARKER_FACTOR |
1076 | 1076 | ||
1077 | x = self._get_time_xpos(time) | 1077 | x = self._get_time_xpos(time) |
1078 | y = self._get_item_ypos(task_no) + self._get_bar_height() - height | 1078 | y = self._get_item_ypos(task_no) + self._get_bar_height() - height |
1079 | 1079 | ||
1080 | self.canvas.add_sel_completion_marker(x, y, height, event) | 1080 | self.canvas.add_sel_completion_marker(x, y, height, event) |
1081 | 1081 | ||
1082 | def draw_release_arrow_at_time(self, time, task_no, job_no=None, selected=False): | 1082 | def draw_release_arrow_at_time(self, time, task_no, job_no=None, selected=False): |
1083 | height = self._get_bar_height() * GraphFormat.BIG_ARROW_FACTOR | 1083 | height = self._get_bar_height() * GraphFormat.BIG_ARROW_FACTOR |
1084 | 1084 | ||
1085 | x = self._get_time_xpos(time) | 1085 | x = self._get_time_xpos(time) |
1086 | y = self._get_item_ypos(task_no) + self._get_bar_height() - height | 1086 | y = self._get_item_ypos(task_no) + self._get_bar_height() - height |
1087 | 1087 | ||
1088 | self.canvas.draw_release_arrow_big(x, y, height, selected) | 1088 | self.canvas.draw_release_arrow_big(x, y, height, selected) |
1089 | 1089 | ||
1090 | def add_sel_release_arrow_at_time(self, time, task_no, event): | 1090 | def add_sel_release_arrow_at_time(self, time, task_no, event): |
1091 | height = self._get_bar_height() * GraphFormat.BIG_ARROW_FACTOR | 1091 | height = self._get_bar_height() * GraphFormat.BIG_ARROW_FACTOR |
1092 | 1092 | ||
1093 | x = self._get_time_xpos(time) | 1093 | x = self._get_time_xpos(time) |
1094 | y = self._get_item_ypos(task_no) + self._get_bar_height() - height | 1094 | y = self._get_item_ypos(task_no) + self._get_bar_height() - height |
1095 | 1095 | ||
1096 | self.canvas.add_sel_release_arrow_big(x, y, height, event) | 1096 | self.canvas.add_sel_release_arrow_big(x, y, height, event) |
1097 | 1097 | ||
1098 | def draw_deadline_arrow_at_time(self, time, task_no, job_no=None, selected=False): | 1098 | def draw_deadline_arrow_at_time(self, time, task_no, job_no=None, selected=False): |
1099 | height = self._get_bar_height() * GraphFormat.BIG_ARROW_FACTOR | 1099 | height = self._get_bar_height() * GraphFormat.BIG_ARROW_FACTOR |
1100 | 1100 | ||
1101 | x = self._get_time_xpos(time) | 1101 | x = self._get_time_xpos(time) |
1102 | y = self._get_item_ypos(task_no) | 1102 | y = self._get_item_ypos(task_no) |
1103 | 1103 | ||
1104 | self.canvas.draw_deadline_arrow_big(x, y, height, selected) | 1104 | self.canvas.draw_deadline_arrow_big(x, y, height, selected) |
1105 | 1105 | ||
1106 | def add_sel_deadline_arrow_at_time(self, time, task_no, event): | 1106 | def add_sel_deadline_arrow_at_time(self, time, task_no, event): |
1107 | height = self._get_bar_height() * GraphFormat.BIG_ARROW_FACTOR | 1107 | height = self._get_bar_height() * GraphFormat.BIG_ARROW_FACTOR |
1108 | 1108 | ||
1109 | x = self._get_time_xpos(time) | 1109 | x = self._get_time_xpos(time) |
1110 | y = self._get_item_ypos(task_no) | 1110 | y = self._get_item_ypos(task_no) |
1111 | 1111 | ||
1112 | self.canvas.add_sel_deadline_arrow_big(x, y, height, event) | 1112 | self.canvas.add_sel_deadline_arrow_big(x, y, height, event) |
1113 | 1113 | ||
1114 | def draw_bar_at_time(self, start_time, end_time, task_no, cpu_no, job_no=None, clip_side=None, selected=False): | 1114 | def draw_bar_at_time(self, start_time, end_time, task_no, cpu_no, job_no=None, clip_side=None, selected=False): |
1115 | if start_time > end_time: | 1115 | if start_time > end_time: |
1116 | raise ValueError("Litmus is not a time machine") | 1116 | raise ValueError("Litmus is not a time machine") |
1117 | 1117 | ||
1118 | x = self._get_time_xpos(start_time) | 1118 | x = self._get_time_xpos(start_time) |
1119 | y = self._get_item_ypos(task_no) | 1119 | y = self._get_item_ypos(task_no) |
1120 | width = self._get_bar_width(start_time, end_time) | 1120 | width = self._get_bar_width(start_time, end_time) |
1121 | height = self._get_bar_height() | 1121 | height = self._get_bar_height() |
1122 | 1122 | ||
1123 | self.canvas.draw_bar(x, y, width, height, cpu_no, clip_side, selected) | 1123 | self.canvas.draw_bar(x, y, width, height, cpu_no, clip_side, selected) |
1124 | 1124 | ||
1125 | # if a job number is specified, we want to draw a superscript and subscript for the task and job number, respectively | 1125 | # if a job number is specified, we want to draw a superscript and subscript for the task and job number, respectively |
1126 | if job_no is not None: | 1126 | if job_no is not None: |
1127 | x += GraphFormat.BAR_LABEL_OFS | 1127 | x += GraphFormat.BAR_LABEL_OFS |
1128 | y += self.attrs.y_item_size * GraphFormat.BAR_SIZE_FACTOR / 2.0 | 1128 | y += self.attrs.y_item_size * GraphFormat.BAR_SIZE_FACTOR / 2.0 |
1129 | self.canvas.draw_label_with_sscripts('T', str(task_no), str(job_no), x, y, \ | 1129 | self.canvas.draw_label_with_sscripts('T', str(task_no), str(job_no), x, y, \ |
1130 | GraphFormat.DEF_FOPTS_BAR, GraphFormat.DEF_FOPTS_BAR_SSCRIPT, AlignMode.LEFT, AlignMode.CENTER) | 1130 | GraphFormat.DEF_FOPTS_BAR, GraphFormat.DEF_FOPTS_BAR_SSCRIPT, AlignMode.LEFT, AlignMode.CENTER) |
1131 | 1131 | ||
1132 | def add_sel_bar_at_time(self, start_time, end_time, task_no, cpu_no, event): | 1132 | def add_sel_bar_at_time(self, start_time, end_time, task_no, cpu_no, event): |
1133 | if start_time > end_time: | 1133 | if start_time > end_time: |
1134 | raise ValueError("Litmus is not a time machine") | 1134 | raise ValueError("Litmus is not a time machine") |
1135 | 1135 | ||
1136 | x = self._get_time_xpos(start_time) | 1136 | x = self._get_time_xpos(start_time) |
1137 | y = self._get_item_ypos(task_no) | 1137 | y = self._get_item_ypos(task_no) |
1138 | width = self._get_bar_width(start_time, end_time) | 1138 | width = self._get_bar_width(start_time, end_time) |
1139 | height = self._get_bar_height() | 1139 | height = self._get_bar_height() |
1140 | 1140 | ||
1141 | self.canvas.add_sel_bar(x, y, width, height, event) | 1141 | self.canvas.add_sel_bar(x, y, width, height, event) |
1142 | 1142 | ||
1143 | def draw_mini_bar_at_time(self, start_time, end_time, task_no, cpu_no, job_no=None, clip_side=None, selected=False): | 1143 | def draw_mini_bar_at_time(self, start_time, end_time, task_no, cpu_no, job_no=None, clip_side=None, selected=False): |
1144 | if start_time > end_time: | 1144 | if start_time > end_time: |
1145 | raise ValueError("Litmus is not a time machine") | 1145 | raise ValueError("Litmus is not a time machine") |
1146 | 1146 | ||
1147 | x = self._get_time_xpos(start_time) | 1147 | x = self._get_time_xpos(start_time) |
1148 | y = self._get_item_ypos(task_no) - self._get_mini_bar_ofs() | 1148 | y = self._get_item_ypos(task_no) - self._get_mini_bar_ofs() |
1149 | width = self._get_bar_width(start_time, end_time) | 1149 | width = self._get_bar_width(start_time, end_time) |
1150 | height = self._get_mini_bar_height() | 1150 | height = self._get_mini_bar_height() |
1151 | 1151 | ||
1152 | self.canvas.draw_mini_bar(x, y, width, height, Canvas.NULL_PATTERN, clip_side, selected) | 1152 | self.canvas.draw_mini_bar(x, y, width, height, Canvas.NULL_PATTERN, clip_side, selected) |
1153 | 1153 | ||
1154 | if job_no is not None: | 1154 | if job_no is not None: |
1155 | x += GraphFormat.MINI_BAR_LABEL_OFS | 1155 | x += GraphFormat.MINI_BAR_LABEL_OFS |
1156 | y += self.attrs.y_item_size * GraphFormat.MINI_BAR_SIZE_FACTOR / 2.0 | 1156 | y += self.attrs.y_item_size * GraphFormat.MINI_BAR_SIZE_FACTOR / 2.0 |
1157 | self.canvas.draw_label_with_sscripts('T', str(task_no), str(job_no), x, y, \ | 1157 | self.canvas.draw_label_with_sscripts('T', str(task_no), str(job_no), x, y, \ |
1158 | GraphFormat.DEF_FOPTS_MINI_BAR, GraphFormat.DEF_FOPTS_MINI_BAR_SSCRIPT, AlignMode.LEFT, AlignMode.CENTER) | 1158 | GraphFormat.DEF_FOPTS_MINI_BAR, GraphFormat.DEF_FOPTS_MINI_BAR_SSCRIPT, AlignMode.LEFT, AlignMode.CENTER) |
1159 | 1159 | ||
1160 | def add_sel_mini_bar_at_time(self, start_time, end_time, task_no, cpu_no, event): | 1160 | def add_sel_mini_bar_at_time(self, start_time, end_time, task_no, cpu_no, event): |
1161 | x = self._get_time_xpos(start_time) | 1161 | x = self._get_time_xpos(start_time) |
1162 | y = self._get_item_ypos(task_no) - self._get_mini_bar_ofs() | 1162 | y = self._get_item_ypos(task_no) - self._get_mini_bar_ofs() |
1163 | width = self._get_bar_width(start_time, end_time) | 1163 | width = self._get_bar_width(start_time, end_time) |
1164 | height = self._get_mini_bar_height() | 1164 | height = self._get_mini_bar_height() |
1165 | 1165 | ||
1166 | self.canvas.add_sel_mini_bar(x, y, width, height, event) | 1166 | self.canvas.add_sel_mini_bar(x, y, width, height, event) |
1167 | 1167 | ||
1168 | class CpuGraph(Graph): | 1168 | class CpuGraph(Graph): |
1169 | def render_surface(self, sched, regions, selectable=False): | 1169 | def render_surface(self, sched, regions, selectable=False): |
1170 | BOTTOM_EVENTS = [schedule.ReleaseEvent, schedule.DeadlineEvent, schedule.InversionStartEvent, | 1170 | BOTTOM_EVENTS = [schedule.ReleaseEvent, schedule.DeadlineEvent, schedule.InversionStartEvent, |
1171 | schedule.InversionEndEvent, schedule.InversionDummy] | 1171 | schedule.InversionEndEvent, schedule.InversionDummy] |
1172 | TOP_EVENTS = [schedule.SuspendEvent, schedule.ResumeEvent, schedule.CompleteEvent, | 1172 | TOP_EVENTS = [schedule.SuspendEvent, schedule.ResumeEvent, schedule.CompleteEvent, |
1173 | schedule.SwitchAwayEvent, schedule.SwitchToEvent, schedule.IsRunningDummy] | 1173 | schedule.SwitchAwayEvent, schedule.SwitchToEvent, schedule.IsRunningDummy] |
1174 | 1174 | ||
1175 | events_to_render = {} | 1175 | events_to_render = {} |
1176 | for layer in Canvas.LAYERS: | 1176 | for layer in Canvas.LAYERS: |
1177 | events_to_render[layer] = {} | 1177 | events_to_render[layer] = {} |
1178 | 1178 | ||
1179 | self.min_time, self.max_time, self.min_item, self.max_item = None, None, None, None | 1179 | self.min_time, self.max_time, self.min_item, self.max_item = None, None, None, None |
1180 | for region in regions: | 1180 | for region in regions: |
1181 | x, y, width, height = region | 1181 | x, y, width, height = region |
@@ -1184,18 +1184,18 @@ class CpuGraph(Graph): | |||
1184 | self.canvas.whiteout(0, 0, self.canvas.surface.width, self.canvas.surface.height) | 1184 | self.canvas.whiteout(0, 0, self.canvas.surface.width, self.canvas.surface.height) |
1185 | else: | 1185 | else: |
1186 | self.canvas.clear_selectable_regions(x, y, width, height) | 1186 | self.canvas.clear_selectable_regions(x, y, width, height) |
1187 | 1187 | ||
1188 | for region in regions: | 1188 | for region in regions: |
1189 | x, y, width, height = region | 1189 | x, y, width, height = region |
1190 | start_time, end_time, start_item, end_item = self.get_offset_params(x, y, width, height) | 1190 | start_time, end_time, start_item, end_item = self.get_offset_params(x, y, width, height) |
1191 | self._recomp_min_max(start_time, end_time, start_item, end_item) | 1191 | self._recomp_min_max(start_time, end_time, start_item, end_item) |
1192 | 1192 | ||
1193 | for event in sched.get_time_slot_array().iter_over_period( | 1193 | for event in sched.get_time_slot_array().iter_over_period( |
1194 | start_time, end_time, start_item, end_item, | 1194 | start_time, end_time, start_item, end_item, |
1195 | schedule.TimeSlotArray.CPU_LIST, | 1195 | schedule.TimeSlotArray.CPU_LIST, |
1196 | TOP_EVENTS): | 1196 | TOP_EVENTS): |
1197 | events_to_render[event.get_layer()][event] = None | 1197 | events_to_render[event.get_layer()][event] = None |
1198 | 1198 | ||
1199 | if end_item >= len(self.y_item_list): | 1199 | if end_item >= len(self.y_item_list): |
1200 | # we are far down enough that we should render the releases and deadlines and inversions, | 1200 | # we are far down enough that we should render the releases and deadlines and inversions, |
1201 | # which appear near the x-axis | 1201 | # which appear near the x-axis |
@@ -1205,136 +1205,136 @@ class CpuGraph(Graph): | |||
1205 | schedule.TimeSlotArray.CPU_LIST, | 1205 | schedule.TimeSlotArray.CPU_LIST, |
1206 | BOTTOM_EVENTS): | 1206 | BOTTOM_EVENTS): |
1207 | events_to_render[event.get_layer()][event] = None | 1207 | events_to_render[event.get_layer()][event] = None |
1208 | 1208 | ||
1209 | if not selectable: | 1209 | if not selectable: |
1210 | self.draw_skeleton(self.min_time, self.max_time, | 1210 | self.draw_skeleton(self.min_time, self.max_time, |
1211 | self.min_item, self.max_item) | 1211 | self.min_item, self.max_item) |
1212 | 1212 | ||
1213 | for layer in Canvas.LAYERS: | 1213 | for layer in Canvas.LAYERS: |
1214 | prev_events = {} | 1214 | prev_events = {} |
1215 | for event in events_to_render[layer]: | 1215 | for event in events_to_render[layer]: |
1216 | event.render(self, layer, prev_events, selectable) | 1216 | event.render(self, layer, prev_events, selectable) |
1217 | 1217 | ||
1218 | def render(self, schedule, start_time=None, end_time=None): | 1218 | def render(self, schedule, start_time=None, end_time=None): |
1219 | if end_time < start_time: | 1219 | if end_time < start_time: |
1220 | raise ValueError('start must be less than end') | 1220 | raise ValueError('start must be less than end') |
1221 | 1221 | ||
1222 | if start_time is None: | 1222 | if start_time is None: |
1223 | start_time = self.start | 1223 | start_time = self.start |
1224 | if end_time is None: | 1224 | if end_time is None: |
1225 | end_time = self.end | 1225 | end_time = self.end |
1226 | start_slot = self.get_time_slot(start_time) | 1226 | start_slot = self.get_time_slot(start_time) |
1227 | end_slot = min(len(self.time_slots), self.get_time_slot(end_time) + 1) | 1227 | end_slot = min(len(self.time_slots), self.get_time_slot(end_time) + 1) |
1228 | 1228 | ||
1229 | for layer in Canvas.LAYERS: | 1229 | for layer in Canvas.LAYERS: |
1230 | prev_events = {} | 1230 | prev_events = {} |
1231 | for i in range(start_slot, end_slot): | 1231 | for i in range(start_slot, end_slot): |
1232 | for event in self.time_slots[i]: | 1232 | for event in self.time_slots[i]: |
1233 | event.render(graph, layer, prev_events) | 1233 | event.render(graph, layer, prev_events) |
1234 | 1234 | ||
1235 | def draw_suspend_triangle_at_time(self, time, task_no, cpu_no, selected=False): | 1235 | def draw_suspend_triangle_at_time(self, time, task_no, cpu_no, selected=False): |
1236 | height = self._get_bar_height() * GraphFormat.BLOCK_TRIANGLE_FACTOR | 1236 | height = self._get_bar_height() * GraphFormat.BLOCK_TRIANGLE_FACTOR |
1237 | x = self._get_time_xpos(time) | 1237 | x = self._get_time_xpos(time) |
1238 | y = self._get_item_ypos(cpu_no) + self._get_bar_height() / 2.0 - height / 2.0 | 1238 | y = self._get_item_ypos(cpu_no) + self._get_bar_height() / 2.0 - height / 2.0 |
1239 | self.canvas.draw_suspend_triangle(x, y, height, selected) | 1239 | self.canvas.draw_suspend_triangle(x, y, height, selected) |
1240 | 1240 | ||
1241 | def add_sel_suspend_triangle_at_time(self, time, task_no, cpu_no, event): | 1241 | def add_sel_suspend_triangle_at_time(self, time, task_no, cpu_no, event): |
1242 | height = self._get_bar_height() * GraphFormat.BLOCK_TRIANGLE_FACTOR | 1242 | height = self._get_bar_height() * GraphFormat.BLOCK_TRIANGLE_FACTOR |
1243 | x = self._get_time_xpos(time) | 1243 | x = self._get_time_xpos(time) |
1244 | y = self._get_item_ypos(cpu_no) + self._get_bar_height() / 2.0 - height / 2.0 | 1244 | y = self._get_item_ypos(cpu_no) + self._get_bar_height() / 2.0 - height / 2.0 |
1245 | 1245 | ||
1246 | self.canvas.add_sel_suspend_triangle(x, y, height, event) | 1246 | self.canvas.add_sel_suspend_triangle(x, y, height, event) |
1247 | 1247 | ||
1248 | def draw_resume_triangle_at_time(self, time, task_no, cpu_no, selected=False): | 1248 | def draw_resume_triangle_at_time(self, time, task_no, cpu_no, selected=False): |
1249 | height = self._get_bar_height() * GraphFormat.BLOCK_TRIANGLE_FACTOR | 1249 | height = self._get_bar_height() * GraphFormat.BLOCK_TRIANGLE_FACTOR |
1250 | x = self._get_time_xpos(time) | 1250 | x = self._get_time_xpos(time) |
1251 | y = self._get_item_ypos(cpu_no) + self._get_bar_height() / 2.0 - height / 2.0 | 1251 | y = self._get_item_ypos(cpu_no) + self._get_bar_height() / 2.0 - height / 2.0 |
1252 | 1252 | ||
1253 | self.canvas.draw_resume_triangle(x, y, height, selected) | 1253 | self.canvas.draw_resume_triangle(x, y, height, selected) |
1254 | 1254 | ||
1255 | def add_sel_resume_triangle_at_time(self, time, task_no, cpu_no, event): | 1255 | def add_sel_resume_triangle_at_time(self, time, task_no, cpu_no, event): |
1256 | height = self._get_bar_height() * GraphFormat.BLOCK_TRIANGLE_FACTOR | 1256 | height = self._get_bar_height() * GraphFormat.BLOCK_TRIANGLE_FACTOR |
1257 | x = self._get_time_xpos(time) | 1257 | x = self._get_time_xpos(time) |
1258 | y = self._get_item_ypos(cpu_no) + self._get_bar_height() / 2.0 - height / 2.0 | 1258 | y = self._get_item_ypos(cpu_no) + self._get_bar_height() / 2.0 - height / 2.0 |
1259 | 1259 | ||
1260 | self.canvas.add_sel_resume_triangle(x, y, height, event) | 1260 | self.canvas.add_sel_resume_triangle(x, y, height, event) |
1261 | 1261 | ||
1262 | def draw_completion_marker_at_time(self, time, task_no, cpu_no, selected=False): | 1262 | def draw_completion_marker_at_time(self, time, task_no, cpu_no, selected=False): |
1263 | height = self._get_bar_height() * GraphFormat.COMPLETION_MARKER_FACTOR | 1263 | height = self._get_bar_height() * GraphFormat.COMPLETION_MARKER_FACTOR |
1264 | x = self._get_time_xpos(time) | 1264 | x = self._get_time_xpos(time) |
1265 | y = self._get_item_ypos(cpu_no) + self._get_bar_height() - height | 1265 | y = self._get_item_ypos(cpu_no) + self._get_bar_height() - height |
1266 | 1266 | ||
1267 | self.canvas.draw_completion_marker(x, y, height, selected) | 1267 | self.canvas.draw_completion_marker(x, y, height, selected) |
1268 | 1268 | ||
1269 | def add_sel_completion_marker_at_time(self, time, task_no, cpu_no, event): | 1269 | def add_sel_completion_marker_at_time(self, time, task_no, cpu_no, event): |
1270 | height = self._get_bar_height() * GraphFormat.COMPLETION_MARKER_FACTOR | 1270 | height = self._get_bar_height() * GraphFormat.COMPLETION_MARKER_FACTOR |
1271 | 1271 | ||
1272 | x = self._get_time_xpos(time) | 1272 | x = self._get_time_xpos(time) |
1273 | y = self._get_item_ypos(cpu_no) + self._get_bar_height() - height | 1273 | y = self._get_item_ypos(cpu_no) + self._get_bar_height() - height |
1274 | 1274 | ||
1275 | self.canvas.add_sel_completion_marker(x, y, height, event) | 1275 | self.canvas.add_sel_completion_marker(x, y, height, event) |
1276 | 1276 | ||
1277 | def draw_release_arrow_at_time(self, time, task_no, job_no=None, selected=False): | 1277 | def draw_release_arrow_at_time(self, time, task_no, job_no=None, selected=False): |
1278 | if job_no is None and task_no is not None: | 1278 | if job_no is None and task_no is not None: |
1279 | raise ValueError("Must specify a job number along with the task number") | 1279 | raise ValueError("Must specify a job number along with the task number") |
1280 | 1280 | ||
1281 | height = self._get_bar_height() * GraphFormat.SMALL_ARROW_FACTOR | 1281 | height = self._get_bar_height() * GraphFormat.SMALL_ARROW_FACTOR |
1282 | 1282 | ||
1283 | x = self._get_time_xpos(time) | 1283 | x = self._get_time_xpos(time) |
1284 | y = self.origin[1] - height | 1284 | y = self.origin[1] - height |
1285 | 1285 | ||
1286 | self.canvas.draw_release_arrow_small(x, y, height, selected) | 1286 | self.canvas.draw_release_arrow_small(x, y, height, selected) |
1287 | 1287 | ||
1288 | if task_no is not None: | 1288 | if task_no is not None: |
1289 | y -= GraphFormat.ARROW_LABEL_OFS | 1289 | y -= GraphFormat.ARROW_LABEL_OFS |
1290 | self.canvas.draw_label_with_sscripts('T', str(task_no), str(job_no), x, y, \ | 1290 | self.canvas.draw_label_with_sscripts('T', str(task_no), str(job_no), x, y, \ |
1291 | GraphFormat.DEF_FOPTS_ARROW, GraphFormat.DEF_FOPTS_ARROW_SSCRIPT, \ | 1291 | GraphFormat.DEF_FOPTS_ARROW, GraphFormat.DEF_FOPTS_ARROW_SSCRIPT, \ |
1292 | AlignMode.CENTER, AlignMode.BOTTOM) | 1292 | AlignMode.CENTER, AlignMode.BOTTOM) |
1293 | 1293 | ||
1294 | def add_sel_release_arrow_at_time(self, time, task_no, event): | 1294 | def add_sel_release_arrow_at_time(self, time, task_no, event): |
1295 | height = self._get_bar_height() * GraphFormat.SMALL_ARROW_FACTOR | 1295 | height = self._get_bar_height() * GraphFormat.SMALL_ARROW_FACTOR |
1296 | 1296 | ||
1297 | x = self._get_time_xpos(time) | 1297 | x = self._get_time_xpos(time) |
1298 | y = self.origin[1] - height | 1298 | y = self.origin[1] - height |
1299 | 1299 | ||
1300 | self.canvas.add_sel_release_arrow_small(x, y, height, event) | 1300 | self.canvas.add_sel_release_arrow_small(x, y, height, event) |
1301 | 1301 | ||
1302 | def draw_deadline_arrow_at_time(self, time, task_no, job_no=None, selected=False): | 1302 | def draw_deadline_arrow_at_time(self, time, task_no, job_no=None, selected=False): |
1303 | if job_no is None and task_no is not None: | 1303 | if job_no is None and task_no is not None: |
1304 | raise ValueError("Must specify a job number along with the task number") | 1304 | raise ValueError("Must specify a job number along with the task number") |
1305 | 1305 | ||
1306 | height = self._get_bar_height() * GraphFormat.SMALL_ARROW_FACTOR | 1306 | height = self._get_bar_height() * GraphFormat.SMALL_ARROW_FACTOR |
1307 | 1307 | ||
1308 | x = self._get_time_xpos(time) | 1308 | x = self._get_time_xpos(time) |
1309 | y = self.origin[1] - height | 1309 | y = self.origin[1] - height |
1310 | 1310 | ||
1311 | self.canvas.draw_deadline_arrow_small(x, y, height, selected) | 1311 | self.canvas.draw_deadline_arrow_small(x, y, height, selected) |
1312 | 1312 | ||
1313 | if task_no is not None: | 1313 | if task_no is not None: |
1314 | y -= GraphFormat.ARROW_LABEL_OFS | 1314 | y -= GraphFormat.ARROW_LABEL_OFS |
1315 | self.canvas.draw_label_with_sscripts('T', str(task_no), str(job_no), x, y, \ | 1315 | self.canvas.draw_label_with_sscripts('T', str(task_no), str(job_no), x, y, \ |
1316 | GraphFormat.DEF_FOPTS_ARROW, GraphFormat.DEF_FOPTS_ARROW_SSCRIPT, \ | 1316 | GraphFormat.DEF_FOPTS_ARROW, GraphFormat.DEF_FOPTS_ARROW_SSCRIPT, \ |
1317 | AlignMode.CENTER, AlignMode.BOTTOM) | 1317 | AlignMode.CENTER, AlignMode.BOTTOM) |
1318 | 1318 | ||
1319 | def add_sel_deadline_arrow_at_time(self, time, task_no, event): | 1319 | def add_sel_deadline_arrow_at_time(self, time, task_no, event): |
1320 | height = self._get_bar_height() * GraphFormat.SMALL_ARROW_FACTOR | 1320 | height = self._get_bar_height() * GraphFormat.SMALL_ARROW_FACTOR |
1321 | 1321 | ||
1322 | x = self._get_time_xpos(time) | 1322 | x = self._get_time_xpos(time) |
1323 | y = self.origin[1] - height | 1323 | y = self.origin[1] - height |
1324 | 1324 | ||
1325 | self.canvas.add_sel_deadline_arrow_small(x, y, height, event) | 1325 | self.canvas.add_sel_deadline_arrow_small(x, y, height, event) |
1326 | 1326 | ||
1327 | def draw_bar_at_time(self, start_time, end_time, task_no, cpu_no, job_no=None, clip_side=None, selected=False): | 1327 | def draw_bar_at_time(self, start_time, end_time, task_no, cpu_no, job_no=None, clip_side=None, selected=False): |
1328 | if start_time > end_time: | 1328 | if start_time > end_time: |
1329 | raise ValueError("Litmus is not a time machine") | 1329 | raise ValueError("Litmus is not a time machine") |
1330 | 1330 | ||
1331 | x = self._get_time_xpos(start_time) | 1331 | x = self._get_time_xpos(start_time) |
1332 | y = self._get_item_ypos(cpu_no) | 1332 | y = self._get_item_ypos(cpu_no) |
1333 | width = self._get_bar_width(start_time, end_time) | 1333 | width = self._get_bar_width(start_time, end_time) |
1334 | height = self._get_bar_height() | 1334 | height = self._get_bar_height() |
1335 | 1335 | ||
1336 | self.canvas.draw_bar(x, y, width, height, task_no, clip_side, selected) | 1336 | self.canvas.draw_bar(x, y, width, height, task_no, clip_side, selected) |
1337 | 1337 | ||
1338 | # if a job number is specified, we want to draw a superscript and subscript for the task and job number, respectively | 1338 | # if a job number is specified, we want to draw a superscript and subscript for the task and job number, respectively |
1339 | if job_no is not None: | 1339 | if job_no is not None: |
1340 | x += GraphFormat.BAR_LABEL_OFS | 1340 | x += GraphFormat.BAR_LABEL_OFS |
@@ -1342,36 +1342,36 @@ class CpuGraph(Graph): | |||
1342 | self.canvas.draw_label_with_sscripts('T', str(task_no), str(job_no), x, y, \ | 1342 | self.canvas.draw_label_with_sscripts('T', str(task_no), str(job_no), x, y, \ |
1343 | GraphFormat.DEF_FOPTS_BAR, GraphFormat.DEF_FOPTS_BAR_SSCRIPT, \ | 1343 | GraphFormat.DEF_FOPTS_BAR, GraphFormat.DEF_FOPTS_BAR_SSCRIPT, \ |
1344 | AlignMode.LEFT, AlignMode.CENTER) | 1344 | AlignMode.LEFT, AlignMode.CENTER) |
1345 | 1345 | ||
1346 | def add_sel_bar_at_time(self, start_time, end_time, task_no, cpu_no, event): | 1346 | def add_sel_bar_at_time(self, start_time, end_time, task_no, cpu_no, event): |
1347 | x = self._get_time_xpos(start_time) | 1347 | x = self._get_time_xpos(start_time) |
1348 | y = self._get_item_ypos(cpu_no) | 1348 | y = self._get_item_ypos(cpu_no) |
1349 | width = self._get_bar_width(start_time, end_time) | 1349 | width = self._get_bar_width(start_time, end_time) |
1350 | height = self._get_bar_height() | 1350 | height = self._get_bar_height() |
1351 | 1351 | ||
1352 | self.canvas.add_sel_bar(x, y, width, height, event) | 1352 | self.canvas.add_sel_bar(x, y, width, height, event) |
1353 | 1353 | ||
1354 | def draw_mini_bar_at_time(self, start_time, end_time, task_no, cpu_no, job_no=None, clip_side=None, selected=False): | 1354 | def draw_mini_bar_at_time(self, start_time, end_time, task_no, cpu_no, job_no=None, clip_side=None, selected=False): |
1355 | if start_time > end_time: | 1355 | if start_time > end_time: |
1356 | raise ValueError("Litmus is not a time machine") | 1356 | raise ValueError("Litmus is not a time machine") |
1357 | 1357 | ||
1358 | x = self._get_time_xpos(start_time) | 1358 | x = self._get_time_xpos(start_time) |
1359 | y = self._get_item_ypos(len(self.y_item_list)) | 1359 | y = self._get_item_ypos(len(self.y_item_list)) |
1360 | width = self._get_bar_width(start_time, end_time) | 1360 | width = self._get_bar_width(start_time, end_time) |
1361 | height = self._get_mini_bar_height() | 1361 | height = self._get_mini_bar_height() |
1362 | 1362 | ||
1363 | self.canvas.draw_mini_bar(x, y, width, height, task_no, clip_side, selected) | 1363 | self.canvas.draw_mini_bar(x, y, width, height, task_no, clip_side, selected) |
1364 | 1364 | ||
1365 | if job_no is not None: | 1365 | if job_no is not None: |
1366 | x += GraphFormat.MINI_BAR_LABEL_OFS | 1366 | x += GraphFormat.MINI_BAR_LABEL_OFS |
1367 | y += self.attrs.y_item_size * GraphFormat.MINI_BAR_SIZE_FACTOR / 2.0 | 1367 | y += self.attrs.y_item_size * GraphFormat.MINI_BAR_SIZE_FACTOR / 2.0 |
1368 | self.canvas.draw_label_with_sscripts('T', str(task_no), str(job_no), x, y, \ | 1368 | self.canvas.draw_label_with_sscripts('T', str(task_no), str(job_no), x, y, \ |
1369 | GraphFormat.DEF_FOPTS_MINI_BAR, GraphFormat.DEF_FOPTS_MINI_BAR_SSCRIPT, AlignMode.LEFT, AlignMode.CENTER) | 1369 | GraphFormat.DEF_FOPTS_MINI_BAR, GraphFormat.DEF_FOPTS_MINI_BAR_SSCRIPT, AlignMode.LEFT, AlignMode.CENTER) |
1370 | 1370 | ||
1371 | def add_sel_mini_bar_at_time(self, start_time, end_time, task_no, cpu_no, event): | 1371 | def add_sel_mini_bar_at_time(self, start_time, end_time, task_no, cpu_no, event): |
1372 | x = self._get_time_xpos(start_time) | 1372 | x = self._get_time_xpos(start_time) |
1373 | y = self._get_item_ypos(len(self.y_item_list)) | 1373 | y = self._get_item_ypos(len(self.y_item_list)) |
1374 | width = self._get_bar_width(start_time, end_time) | 1374 | width = self._get_bar_width(start_time, end_time) |
1375 | height = self._get_mini_bar_height() | 1375 | height = self._get_mini_bar_height() |
1376 | 1376 | ||
1377 | self.canvas.add_sel_mini_bar(x, y, width, height, event) | 1377 | self.canvas.add_sel_mini_bar(x, y, width, height, event) |
diff --git a/unit_trace/viz/format.py b/unit_trace/viz/format.py index 33e0b03..c544e26 100644 --- a/unit_trace/viz/format.py +++ b/unit_trace/viz/format.py | |||
@@ -13,41 +13,41 @@ class AlignMode(object): | |||
13 | LEFT = 0 | 13 | LEFT = 0 |
14 | CENTER = 1 | 14 | CENTER = 1 |
15 | RIGHT = 2 | 15 | RIGHT = 2 |
16 | 16 | ||
17 | BOTTOM = 3 | 17 | BOTTOM = 3 |
18 | TOP = 4 | 18 | TOP = 4 |
19 | 19 | ||
20 | class GraphFormat(object): | 20 | class GraphFormat(object): |
21 | """Container class for a bunch of optional and non-optional attributes to configure the appearance of the graph | 21 | """Container class for a bunch of optional and non-optional attributes to configure the appearance of the graph |
22 | (because it would be annoying to just have these all as raw arguments to the Graph constructor, and many people | 22 | (because it would be annoying to just have these all as raw arguments to the Graph constructor, and many people |
23 | probably don't care about most of them anyway).""" | 23 | probably don't care about most of them anyway).""" |
24 | 24 | ||
25 | GRID_COLOR = (0.7, 0.7, 0.7) | 25 | GRID_COLOR = (0.7, 0.7, 0.7) |
26 | HIGHLIGHT_COLOR = (0.85, 0.0, 0.0) | 26 | HIGHLIGHT_COLOR = (0.85, 0.0, 0.0) |
27 | BORDER_COLOR = (0.0, 0.0, 0.0) | 27 | BORDER_COLOR = (0.0, 0.0, 0.0) |
28 | LITE_BORDER_COLOR = (0.4, 0.4, 0.4) | 28 | LITE_BORDER_COLOR = (0.4, 0.4, 0.4) |
29 | 29 | ||
30 | BORDER_THICKNESS = 1 | 30 | BORDER_THICKNESS = 1 |
31 | GRID_THICKNESS = 1 | 31 | GRID_THICKNESS = 1 |
32 | AXIS_THICKNESS = 1 | 32 | AXIS_THICKNESS = 1 |
33 | 33 | ||
34 | BAND_THICKNESS = 1.5 | 34 | BAND_THICKNESS = 1.5 |
35 | BAND_COLOR = (0.85, 0.0, 0.0) | 35 | BAND_COLOR = (0.85, 0.0, 0.0) |
36 | 36 | ||
37 | X_AXIS_MEASURE_OFS = 30 | 37 | X_AXIS_MEASURE_OFS = 30 |
38 | X_AXIS_LABEL_GAP = 10 | 38 | X_AXIS_LABEL_GAP = 10 |
39 | Y_AXIS_ITEM_GAP = 10 | 39 | Y_AXIS_ITEM_GAP = 10 |
40 | MAJ_TICK_SIZE = 20 | 40 | MAJ_TICK_SIZE = 20 |
41 | MIN_TICK_SIZE = 12 | 41 | MIN_TICK_SIZE = 12 |
42 | 42 | ||
43 | BIG_ARROWHEAD_FACTOR = 0.2 | 43 | BIG_ARROWHEAD_FACTOR = 0.2 |
44 | SMALL_ARROWHEAD_FACTOR = 0.3 | 44 | SMALL_ARROWHEAD_FACTOR = 0.3 |
45 | TEE_FACTOR = 0.3 | 45 | TEE_FACTOR = 0.3 |
46 | 46 | ||
47 | DEF_FOPTS_LABEL = FontOptions("Times", 16, (0.0, 0.0, 0.0)) | 47 | DEF_FOPTS_LABEL = FontOptions("Times", 16, (0.0, 0.0, 0.0)) |
48 | DEF_FOPTS_LABEL_SSCRIPT = FontOptions("Times", 8, (0.0, 0.0, 0.0)) | 48 | DEF_FOPTS_LABEL_SSCRIPT = FontOptions("Times", 8, (0.0, 0.0, 0.0)) |
49 | DEF_FOPTS_MAJ = FontOptions("Times", 14, (0.1, 0.1, 0.1)) | 49 | DEF_FOPTS_MAJ = FontOptions("Times", 14, (0.1, 0.1, 0.1)) |
50 | DEF_FOPTS_MIN = FontOptions("Times", 9, (0.1, 0.1, 0.1)) | 50 | DEF_FOPTS_MIN = FontOptions("Times", 9, (0.1, 0.1, 0.1)) |
51 | DEF_FOPTS_ITEM = FontOptions("Times", 20, (0.0, 0.5, 0.1)) | 51 | DEF_FOPTS_ITEM = FontOptions("Times", 20, (0.0, 0.5, 0.1)) |
52 | DEF_FOPTS_BAR = FontOptions("Times", 14, (0.0, 0.0, 0.0)) | 52 | DEF_FOPTS_BAR = FontOptions("Times", 14, (0.0, 0.0, 0.0)) |
53 | DEF_FOPTS_BAR_SSCRIPT = FontOptions("Times", 7, (0.0, 0.0, 0.0)) | 53 | DEF_FOPTS_BAR_SSCRIPT = FontOptions("Times", 7, (0.0, 0.0, 0.0)) |
@@ -55,31 +55,31 @@ class GraphFormat(object): | |||
55 | DEF_FOPTS_MINI_BAR_SSCRIPT = FontOptions("Times", 7, (0.0, 0.0, 0.0)) | 55 | DEF_FOPTS_MINI_BAR_SSCRIPT = FontOptions("Times", 7, (0.0, 0.0, 0.0)) |
56 | DEF_FOPTS_ARROW = FontOptions("Times", 12, (0.0, 0.0, 0.0)) | 56 | DEF_FOPTS_ARROW = FontOptions("Times", 12, (0.0, 0.0, 0.0)) |
57 | DEF_FOPTS_ARROW_SSCRIPT = FontOptions("Times", 7, (0.0, 0.0, 0.0)) | 57 | DEF_FOPTS_ARROW_SSCRIPT = FontOptions("Times", 7, (0.0, 0.0, 0.0)) |
58 | 58 | ||
59 | LEFT_SIDE_PAD = 30 | 59 | LEFT_SIDE_PAD = 30 |
60 | WIDTH_PAD = 50 | 60 | WIDTH_PAD = 50 |
61 | HEIGHT_PAD = 150 | 61 | HEIGHT_PAD = 150 |
62 | Y_ITEM_PAD_FACTOR = 0.5 | 62 | Y_ITEM_PAD_FACTOR = 0.5 |
63 | 63 | ||
64 | DEF_TIME_PER_MAJ = 10 | 64 | DEF_TIME_PER_MAJ = 10 |
65 | DEF_MAJ_SEP = 200 | 65 | DEF_MAJ_SEP = 200 |
66 | DEF_MIN_PER_MAJ = 5 | 66 | DEF_MIN_PER_MAJ = 5 |
67 | DEF_Y_ITEM_SIZE = 50 | 67 | DEF_Y_ITEM_SIZE = 50 |
68 | 68 | ||
69 | AXIS_LABEL_VERT_OFS = 30 | 69 | AXIS_LABEL_VERT_OFS = 30 |
70 | BAR_SIZE_FACTOR = 0.4 | 70 | BAR_SIZE_FACTOR = 0.4 |
71 | MINI_BAR_SIZE_FACTOR = 0.2 | 71 | MINI_BAR_SIZE_FACTOR = 0.2 |
72 | BAR_MINI_BAR_GAP_FACTOR = 0.1 | 72 | BAR_MINI_BAR_GAP_FACTOR = 0.1 |
73 | 73 | ||
74 | BAR_LABEL_OFS = 2 | 74 | BAR_LABEL_OFS = 2 |
75 | MINI_BAR_LABEL_OFS = 1 | 75 | MINI_BAR_LABEL_OFS = 1 |
76 | ARROW_LABEL_OFS = 2 | 76 | ARROW_LABEL_OFS = 2 |
77 | 77 | ||
78 | BLOCK_TRIANGLE_FACTOR = 0.7 | 78 | BLOCK_TRIANGLE_FACTOR = 0.7 |
79 | BIG_ARROW_FACTOR = 1.6 | 79 | BIG_ARROW_FACTOR = 1.6 |
80 | SMALL_ARROW_FACTOR = 0.6 | 80 | SMALL_ARROW_FACTOR = 0.6 |
81 | COMPLETION_MARKER_FACTOR = 1.6 | 81 | COMPLETION_MARKER_FACTOR = 1.6 |
82 | 82 | ||
83 | def __init__(self, time_per_maj=DEF_TIME_PER_MAJ, maj_sep=DEF_MAJ_SEP, \ | 83 | def __init__(self, time_per_maj=DEF_TIME_PER_MAJ, maj_sep=DEF_MAJ_SEP, \ |
84 | min_per_maj=DEF_MIN_PER_MAJ, y_item_size=DEF_Y_ITEM_SIZE, bar_fopts=DEF_FOPTS_BAR, \ | 84 | min_per_maj=DEF_MIN_PER_MAJ, y_item_size=DEF_Y_ITEM_SIZE, bar_fopts=DEF_FOPTS_BAR, \ |
85 | item_fopts=DEF_FOPTS_ITEM, show_min=False, majfopts=DEF_FOPTS_MAJ, \ | 85 | item_fopts=DEF_FOPTS_ITEM, show_min=False, majfopts=DEF_FOPTS_MAJ, \ |
diff --git a/unit_trace/viz/renderer.py b/unit_trace/viz/renderer.py index d94129c..46c6628 100644 --- a/unit_trace/viz/renderer.py +++ b/unit_trace/viz/renderer.py | |||
@@ -4,17 +4,17 @@ from draw import * | |||
4 | 4 | ||
5 | """The renderer, a glue object which converts a schedule to its representation | 5 | """The renderer, a glue object which converts a schedule to its representation |
6 | on a graph.""" | 6 | on a graph.""" |
7 | 7 | ||
8 | class Renderer(object): | 8 | class Renderer(object): |
9 | def __init__(self, schedule): | 9 | def __init__(self, schedule): |
10 | self.schedule = schedule | 10 | self.schedule = schedule |
11 | 11 | ||
12 | def prepare_task_graph(self, SurfaceType=ImageSurface, attrs=GraphFormat()): | 12 | def prepare_task_graph(self, SurfaceType=ImageSurface, attrs=GraphFormat()): |
13 | """Outputs the fully-rendered graph (y-axis = tasks) to a Cairo ImageSurface""" | 13 | """Outputs the fully-rendered graph (y-axis = tasks) to a Cairo ImageSurface""" |
14 | item_list = self.get_task_item_list() | 14 | item_list = self.get_task_item_list() |
15 | start, end = self.schedule.get_time_bounds() | 15 | start, end = self.schedule.get_time_bounds() |
16 | self.graph = TaskGraph(CairoCanvas, SurfaceType(), start, end, item_list, attrs) | 16 | self.graph = TaskGraph(CairoCanvas, SurfaceType(), start, end, item_list, attrs) |
17 | 17 | ||
18 | def prepare_cpu_graph(self, SurfaceType=ImageSurface, attrs=GraphFormat()): | 18 | def prepare_cpu_graph(self, SurfaceType=ImageSurface, attrs=GraphFormat()): |
19 | item_list = ['CPU %d' % i for i in range(0, self.schedule.get_num_cpus())] | 19 | item_list = ['CPU %d' % i for i in range(0, self.schedule.get_num_cpus())] |
20 | start, end = self.schedule.get_time_bounds() | 20 | start, end = self.schedule.get_time_bounds() |
@@ -25,16 +25,16 @@ class Renderer(object): | |||
25 | and drawing it piece by piece""" | 25 | and drawing it piece by piece""" |
26 | #graph.draw_axes('Time', '') | 26 | #graph.draw_axes('Time', '') |
27 | self.schedule.render(self.graph) | 27 | self.schedule.render(self.graph) |
28 | 28 | ||
29 | def write_out(self, fname): | 29 | def write_out(self, fname): |
30 | self.graph.surface.write_out(fname) | 30 | self.graph.surface.write_out(fname) |
31 | 31 | ||
32 | def get_graph(self): | 32 | def get_graph(self): |
33 | return self.graph | 33 | return self.graph |
34 | 34 | ||
35 | def get_schedule(self): | 35 | def get_schedule(self): |
36 | return self.schedule | 36 | return self.schedule |
37 | 37 | ||
38 | def get_task_item_list(self): | 38 | def get_task_item_list(self): |
39 | return [task.get_name() for task in self.schedule.get_task_list()] | 39 | return [task.get_name() for task in self.schedule.get_task_list()] |
40 | 40 | ||
diff --git a/unit_trace/viz/schedule.py b/unit_trace/viz/schedule.py index f134562..71f42ec 100644 --- a/unit_trace/viz/schedule.py +++ b/unit_trace/viz/schedule.py | |||
@@ -18,19 +18,19 @@ class TimeSlotArray(object): | |||
18 | the (approximate) time at which they occur. Events that occur at approximately the same | 18 | the (approximate) time at which they occur. Events that occur at approximately the same |
19 | time are assigned the same ``slot'', and each slot organizes its events by task number | 19 | time are assigned the same ``slot'', and each slot organizes its events by task number |
20 | as well as by CPU.""" | 20 | as well as by CPU.""" |
21 | 21 | ||
22 | TASK_LIST = 0 | 22 | TASK_LIST = 0 |
23 | CPU_LIST = 1 | 23 | CPU_LIST = 1 |
24 | 24 | ||
25 | def __init__(self, time_per_maj=None, num_tasks=0, num_cpus=0): | 25 | def __init__(self, time_per_maj=None, num_tasks=0, num_cpus=0): |
26 | if time_per_maj is None: | 26 | if time_per_maj is None: |
27 | self.array = None | 27 | self.array = None |
28 | return | 28 | return |
29 | 29 | ||
30 | self.time_per_maj = time_per_maj | 30 | self.time_per_maj = time_per_maj |
31 | self.list_sizes = { TimeSlotArray.TASK_LIST : num_tasks, TimeSlotArray.CPU_LIST : num_cpus } | 31 | self.list_sizes = { TimeSlotArray.TASK_LIST : num_tasks, TimeSlotArray.CPU_LIST : num_cpus } |
32 | self.array = {} | 32 | self.array = {} |
33 | 33 | ||
34 | for type in self.list_sizes: | 34 | for type in self.list_sizes: |
35 | num = self.list_sizes[type] | 35 | num = self.list_sizes[type] |
36 | self.array[type] = [] | 36 | self.array[type] = [] |
@@ -40,26 +40,26 @@ class TimeSlotArray(object): | |||
40 | # by task). | 40 | # by task). |
41 | self.array[type].append(dict(zip(EVENT_LIST, \ | 41 | self.array[type].append(dict(zip(EVENT_LIST, \ |
42 | [{} for j in range(0, len(EVENT_LIST))]))) | 42 | [{} for j in range(0, len(EVENT_LIST))]))) |
43 | 43 | ||
44 | def get_time_slot(self, time): | 44 | def get_time_slot(self, time): |
45 | return int(time // self.time_per_maj) | 45 | return int(time // self.time_per_maj) |
46 | 46 | ||
47 | def _put_event_in_slot(self, list_type, no, klass, slot, event): | 47 | def _put_event_in_slot(self, list_type, no, klass, slot, event): |
48 | if slot not in self.array[list_type][no][klass]: | 48 | if slot not in self.array[list_type][no][klass]: |
49 | self.array[list_type][no][klass][slot] = [] | 49 | self.array[list_type][no][klass][slot] = [] |
50 | self.array[list_type][no][klass][slot].append(event) | 50 | self.array[list_type][no][klass][slot].append(event) |
51 | 51 | ||
52 | def add_event_to_time_slot(self, event): | 52 | def add_event_to_time_slot(self, event): |
53 | task_no = event.get_job().get_task().get_task_no() | 53 | task_no = event.get_job().get_task().get_task_no() |
54 | cpu = event.get_cpu() | 54 | cpu = event.get_cpu() |
55 | time_slot = self.get_time_slot(event.get_time()) | 55 | time_slot = self.get_time_slot(event.get_time()) |
56 | 56 | ||
57 | self._put_event_in_slot(TimeSlotArray.TASK_LIST, task_no, event.__class__, time_slot, event) | 57 | self._put_event_in_slot(TimeSlotArray.TASK_LIST, task_no, event.__class__, time_slot, event) |
58 | self._put_event_in_slot(TimeSlotArray.CPU_LIST, cpu, event.__class__, time_slot, event) | 58 | self._put_event_in_slot(TimeSlotArray.CPU_LIST, cpu, event.__class__, time_slot, event) |
59 | 59 | ||
60 | if event.__class__ in SPAN_END_EVENTS: | 60 | if event.__class__ in SPAN_END_EVENTS: |
61 | self.fill_span_event_from_end(event) | 61 | self.fill_span_event_from_end(event) |
62 | 62 | ||
63 | def fill_span_event_from_end(self, event): | 63 | def fill_span_event_from_end(self, event): |
64 | start_slot = None | 64 | start_slot = None |
65 | if event.corresp_start_event is None: | 65 | if event.corresp_start_event is None: |
@@ -67,18 +67,18 @@ class TimeSlotArray(object): | |||
67 | else: | 67 | else: |
68 | start_slot = self.get_time_slot(event.corresp_start_event.get_time()) | 68 | start_slot = self.get_time_slot(event.corresp_start_event.get_time()) |
69 | end_slot = self.get_time_slot(event.get_time()) | 69 | end_slot = self.get_time_slot(event.get_time()) |
70 | 70 | ||
71 | for slot in range(start_slot + 1, end_slot): | 71 | for slot in range(start_slot + 1, end_slot): |
72 | task_no = event.get_job().get_task().get_task_no() | 72 | task_no = event.get_job().get_task().get_task_no() |
73 | cpu = event.get_cpu() | 73 | cpu = event.get_cpu() |
74 | 74 | ||
75 | dummy = SPAN_END_EVENTS[event.__class__](task_no, cpu) | 75 | dummy = SPAN_END_EVENTS[event.__class__](task_no, cpu) |
76 | dummy.corresp_start_event = event.corresp_start_event | 76 | dummy.corresp_start_event = event.corresp_start_event |
77 | dummy.corresp_end_event = event | 77 | dummy.corresp_end_event = event |
78 | 78 | ||
79 | self._put_event_in_slot(TimeSlotArray.TASK_LIST, task_no, dummy.__class__, slot, dummy) | 79 | self._put_event_in_slot(TimeSlotArray.TASK_LIST, task_no, dummy.__class__, slot, dummy) |
80 | self._put_event_in_slot(TimeSlotArray.CPU_LIST, cpu, dummy.__class__, slot, dummy) | 80 | self._put_event_in_slot(TimeSlotArray.CPU_LIST, cpu, dummy.__class__, slot, dummy) |
81 | 81 | ||
82 | def fill_span_event_from_start(self, event): | 82 | def fill_span_event_from_start(self, event): |
83 | end_slot = None | 83 | end_slot = None |
84 | if event.corresp_end_event is None: | 84 | if event.corresp_end_event is None: |
@@ -86,44 +86,44 @@ class TimeSlotArray(object): | |||
86 | else: | 86 | else: |
87 | end_slot = self.get_time_slot(event.corresp_end_event.get_time()) | 87 | end_slot = self.get_time_slot(event.corresp_end_event.get_time()) |
88 | start_slot = self.get_time_slot(event.get_time()) | 88 | start_slot = self.get_time_slot(event.get_time()) |
89 | 89 | ||
90 | for slot in range(start_slot + 1, end_slot): | 90 | for slot in range(start_slot + 1, end_slot): |
91 | task_no = event.get_job().get_task().get_task_no() | 91 | task_no = event.get_job().get_task().get_task_no() |
92 | cpu = event.get_cpu() | 92 | cpu = event.get_cpu() |
93 | 93 | ||
94 | dummy = SPAN_START_EVENTS[event.__class__](task_no, cpu) | 94 | dummy = SPAN_START_EVENTS[event.__class__](task_no, cpu) |
95 | dummy.corresp_start_event = event | 95 | dummy.corresp_start_event = event |
96 | dummy.corresp_end_event = event.corresp_end_event | 96 | dummy.corresp_end_event = event.corresp_end_event |
97 | 97 | ||
98 | self._put_event_in_slot(TimeSlotArray.TASK_LIST, task_no, dummy.__class__, slot, dummy) | 98 | self._put_event_in_slot(TimeSlotArray.TASK_LIST, task_no, dummy.__class__, slot, dummy) |
99 | self._put_event_in_slot(TimeSlotArray.CPU_LIST, cpu, dummy.__class__, slot, dummy) | 99 | self._put_event_in_slot(TimeSlotArray.CPU_LIST, cpu, dummy.__class__, slot, dummy) |
100 | 100 | ||
101 | def iter_over_period(self, start, end, start_no, end_no, list_type, event_types): | 101 | def iter_over_period(self, start, end, start_no, end_no, list_type, event_types): |
102 | if self.array is None: | 102 | if self.array is None: |
103 | return # empty schedule | 103 | return # empty schedule |
104 | 104 | ||
105 | if start > end: | 105 | if start > end: |
106 | raise ValueError('Litmus is not a time machine') | 106 | raise ValueError('Litmus is not a time machine') |
107 | if start_no > end_no: | 107 | if start_no > end_no: |
108 | raise ValueError('start no should be less than end no') | 108 | raise ValueError('start no should be less than end no') |
109 | 109 | ||
110 | start_slot = self.get_time_slot(start) | 110 | start_slot = self.get_time_slot(start) |
111 | end_slot = self.get_time_slot(end) + 2 | 111 | end_slot = self.get_time_slot(end) + 2 |
112 | 112 | ||
113 | start_no = max(0, start_no) | 113 | start_no = max(0, start_no) |
114 | end_no = min(self.list_sizes[list_type] - 1, end_no) | 114 | end_no = min(self.list_sizes[list_type] - 1, end_no) |
115 | 115 | ||
116 | for no in range(start_no, end_no + 1): | 116 | for no in range(start_no, end_no + 1): |
117 | for type in event_types: | 117 | for type in event_types: |
118 | for slot in range(start_slot, end_slot): | 118 | for slot in range(start_slot, end_slot): |
119 | if slot in self.array[list_type][no][type]: | 119 | if slot in self.array[list_type][no][type]: |
120 | for event in self.array[list_type][no][type][slot]: | 120 | for event in self.array[list_type][no][type][slot]: |
121 | yield event | 121 | yield event |
122 | 122 | ||
123 | class Schedule(object): | 123 | class Schedule(object): |
124 | """The total schedule (task system), consisting of a certain number of | 124 | """The total schedule (task system), consisting of a certain number of |
125 | tasks.""" | 125 | tasks.""" |
126 | 126 | ||
127 | def __init__(self, name, num_cpus, task_list=[]): | 127 | def __init__(self, name, num_cpus, task_list=[]): |
128 | self.name = name | 128 | self.name = name |
129 | self.tasks = {} | 129 | self.tasks = {} |
@@ -134,41 +134,41 @@ class Schedule(object): | |||
134 | self.num_cpus = num_cpus | 134 | self.num_cpus = num_cpus |
135 | for task in task_list: | 135 | for task in task_list: |
136 | self.add_task(task) | 136 | self.add_task(task) |
137 | 137 | ||
138 | def get_selected(self): | 138 | def get_selected(self): |
139 | return self.selected | 139 | return self.selected |
140 | 140 | ||
141 | def set_selected(self, new_selected): | 141 | def set_selected(self, new_selected): |
142 | for event in self.selected: | 142 | for event in self.selected: |
143 | event.selected = False | 143 | event.selected = False |
144 | for event in new_selected: | 144 | for event in new_selected: |
145 | event.selected = True | 145 | event.selected = True |
146 | self.selected = new_selected | 146 | self.selected = new_selected |
147 | 147 | ||
148 | def get_selected(self): | 148 | def get_selected(self): |
149 | return copy.copy(self.selected) | 149 | return copy.copy(self.selected) |
150 | 150 | ||
151 | def set_time_params(self, time_per_maj=None): | 151 | def set_time_params(self, time_per_maj=None): |
152 | self.time_per_maj = time_per_maj | 152 | self.time_per_maj = time_per_maj |
153 | if self.time_per_maj is None: | 153 | if self.time_per_maj is None: |
154 | self.time_slot_array = TimeSlotArray() | 154 | self.time_slot_array = TimeSlotArray() |
155 | return | 155 | return |
156 | 156 | ||
157 | self.time_slot_array = TimeSlotArray(self.time_per_maj, \ | 157 | self.time_slot_array = TimeSlotArray(self.time_per_maj, \ |
158 | len(self.task_list), self.num_cpus) | 158 | len(self.task_list), self.num_cpus) |
159 | 159 | ||
160 | def get_time_slot_array(self): | 160 | def get_time_slot_array(self): |
161 | return self.time_slot_array | 161 | return self.time_slot_array |
162 | 162 | ||
163 | def get_time_bounds(self): | 163 | def get_time_bounds(self): |
164 | return (self.start, self.end) | 164 | return (self.start, self.end) |
165 | 165 | ||
166 | def scan(self, time_per_maj): | 166 | def scan(self, time_per_maj): |
167 | self.start = None | 167 | self.start = None |
168 | self.end = None | 168 | self.end = None |
169 | 169 | ||
170 | self.set_time_params(time_per_maj) | 170 | self.set_time_params(time_per_maj) |
171 | 171 | ||
172 | # we scan the graph task by task, and job by job | 172 | # we scan the graph task by task, and job by job |
173 | for task_no, task in enumerate(self.get_task_list()): | 173 | for task_no, task in enumerate(self.get_task_list()): |
174 | switches = {} | 174 | switches = {} |
@@ -176,12 +176,12 @@ class Schedule(object): | |||
176 | switches[event] = None | 176 | switches[event] = None |
177 | cur_cpu = [Event.NO_CPU] | 177 | cur_cpu = [Event.NO_CPU] |
178 | for job_no in sorted(task.get_jobs().keys()): | 178 | for job_no in sorted(task.get_jobs().keys()): |
179 | job = task.get_jobs()[job_no] | 179 | job = task.get_jobs()[job_no] |
180 | for event_time in sorted(job.get_events().keys()): | 180 | for event_time in sorted(job.get_events().keys()): |
181 | # could have multiple events at the same time (unlikely but possible) | 181 | # could have multiple events at the same time (unlikely but possible) |
182 | for event in job.get_events()[event_time]: | 182 | for event in job.get_events()[event_time]: |
183 | event.scan(cur_cpu, switches) | 183 | event.scan(cur_cpu, switches) |
184 | 184 | ||
185 | # What if one of the initial "span events" (switch to or inversion starting) never got a | 185 | # What if one of the initial "span events" (switch to or inversion starting) never got a |
186 | # corresponding end event? Well, then we assume that the end event was simply outside of | 186 | # corresponding end event? Well, then we assume that the end event was simply outside of |
187 | # the range of whatever we read in. So we need to fill dummies starting from the initial | 187 | # the range of whatever we read in. So we need to fill dummies starting from the initial |
@@ -191,7 +191,7 @@ class Schedule(object): | |||
191 | event = switches[span_event] | 191 | event = switches[span_event] |
192 | if event is not None: | 192 | if event is not None: |
193 | self.time_slot_array.fill_span_event_from_start(event) | 193 | self.time_slot_array.fill_span_event_from_start(event) |
194 | 194 | ||
195 | def add_task(self, task): | 195 | def add_task(self, task): |
196 | if task.name in self.tasks: | 196 | if task.name in self.tasks: |
197 | raise ValueError("task already in list!") | 197 | raise ValueError("task already in list!") |
@@ -200,23 +200,23 @@ class Schedule(object): | |||
200 | task.schedule = self | 200 | task.schedule = self |
201 | task.task_no = self.cur_task_no | 201 | task.task_no = self.cur_task_no |
202 | self.cur_task_no += 1 | 202 | self.cur_task_no += 1 |
203 | 203 | ||
204 | def get_tasks(self): | 204 | def get_tasks(self): |
205 | return self.tasks | 205 | return self.tasks |
206 | 206 | ||
207 | def get_task_list(self): | 207 | def get_task_list(self): |
208 | return self.task_list | 208 | return self.task_list |
209 | 209 | ||
210 | def get_name(self): | 210 | def get_name(self): |
211 | return self.name | 211 | return self.name |
212 | 212 | ||
213 | def get_num_cpus(self): | 213 | def get_num_cpus(self): |
214 | return self.num_cpus | 214 | return self.num_cpus |
215 | 215 | ||
216 | class Task(object): | 216 | class Task(object): |
217 | """Represents a task, including the set of jobs that were run under | 217 | """Represents a task, including the set of jobs that were run under |
218 | this task.""" | 218 | this task.""" |
219 | 219 | ||
220 | def __init__(self, name, job_list=[]): | 220 | def __init__(self, name, job_list=[]): |
221 | self.name = name | 221 | self.name = name |
222 | self.jobs = {} | 222 | self.jobs = {} |
@@ -224,25 +224,25 @@ class Task(object): | |||
224 | self.schedule = None | 224 | self.schedule = None |
225 | for job in job_list: | 225 | for job in job_list: |
226 | self.add_job(job) | 226 | self.add_job(job) |
227 | 227 | ||
228 | def add_job(self, job): | 228 | def add_job(self, job): |
229 | if job.job_no in self.jobs: | 229 | if job.job_no in self.jobs: |
230 | raise ScheduleError("a job is already being released at this time for this task") | 230 | raise ScheduleError("a job is already being released at this time for this task") |
231 | self.jobs[job.job_no] = job | 231 | self.jobs[job.job_no] = job |
232 | job.task = self | 232 | job.task = self |
233 | 233 | ||
234 | def get_schedule(self): | 234 | def get_schedule(self): |
235 | return self.schedule | 235 | return self.schedule |
236 | 236 | ||
237 | def get_jobs(self): | 237 | def get_jobs(self): |
238 | return self.jobs | 238 | return self.jobs |
239 | 239 | ||
240 | def get_task_no(self): | 240 | def get_task_no(self): |
241 | return self.task_no | 241 | return self.task_no |
242 | 242 | ||
243 | def get_name(self): | 243 | def get_name(self): |
244 | return self.name | 244 | return self.name |
245 | 245 | ||
246 | class Job(object): | 246 | class Job(object): |
247 | """Represents a job, including everything that happens related to the job""" | 247 | """Represents a job, including everything that happens related to the job""" |
248 | def __init__(self, job_no, event_list=[]): | 248 | def __init__(self, job_no, event_list=[]): |
@@ -251,19 +251,19 @@ class Job(object): | |||
251 | self.task = None | 251 | self.task = None |
252 | for event in event_list: | 252 | for event in event_list: |
253 | self.add_event(event) | 253 | self.add_event(event) |
254 | 254 | ||
255 | def add_event(self, event): | 255 | def add_event(self, event): |
256 | if event.time not in self.events: | 256 | if event.time not in self.events: |
257 | self.events[event.time] = [] | 257 | self.events[event.time] = [] |
258 | self.events[event.time].append(event) | 258 | self.events[event.time].append(event) |
259 | event.job = self | 259 | event.job = self |
260 | 260 | ||
261 | def get_events(self): | 261 | def get_events(self): |
262 | return self.events | 262 | return self.events |
263 | 263 | ||
264 | def get_task(self): | 264 | def get_task(self): |
265 | return self.task | 265 | return self.task |
266 | 266 | ||
267 | def get_job_no(self): | 267 | def get_job_no(self): |
268 | return self.job_no | 268 | return self.job_no |
269 | 269 | ||
@@ -279,61 +279,61 @@ class DummyEvent(object): | |||
279 | self.cpu = cpu | 279 | self.cpu = cpu |
280 | self.job = None | 280 | self.job = None |
281 | self.layer = None | 281 | self.layer = None |
282 | 282 | ||
283 | def __str__(self): | 283 | def __str__(self): |
284 | return '[Dummy Event]' | 284 | return '[Dummy Event]' |
285 | 285 | ||
286 | def get_time(self): | 286 | def get_time(self): |
287 | return self.time | 287 | return self.time |
288 | 288 | ||
289 | def get_cpu(self): | 289 | def get_cpu(self): |
290 | return self.cpu | 290 | return self.cpu |
291 | 291 | ||
292 | def get_job(self): | 292 | def get_job(self): |
293 | return self.job | 293 | return self.job |
294 | 294 | ||
295 | def get_layer(self): | 295 | def get_layer(self): |
296 | return self.layer | 296 | return self.layer |
297 | 297 | ||
298 | def render(self, graph, layer, prev_events, selectable=False): | 298 | def render(self, graph, layer, prev_events, selectable=False): |
299 | """Method that the visualizer calls to tell the event to render itself | 299 | """Method that the visualizer calls to tell the event to render itself |
300 | Obviously only implemented by subclasses (actual event types) | 300 | Obviously only implemented by subclasses (actual event types) |
301 | 301 | ||
302 | ``Rendering'' can mean either actually drawing the event or just | 302 | ``Rendering'' can mean either actually drawing the event or just |
303 | adding it as a selectable region. This is controlled by the | 303 | adding it as a selectable region. This is controlled by the |
304 | ``selectable'' parameter""" | 304 | ``selectable'' parameter""" |
305 | raise NotImplementdError | 305 | raise NotImplementdError |
306 | 306 | ||
307 | class Event(DummyEvent): | 307 | class Event(DummyEvent): |
308 | """Represents an event that occurs while a job is running (e.g. get scheduled | 308 | """Represents an event that occurs while a job is running (e.g. get scheduled |
309 | on a CPU, block, ...)""" | 309 | on a CPU, block, ...)""" |
310 | NO_CPU = -1 | 310 | NO_CPU = -1 |
311 | NUM_DEC_PLACES = 2 | 311 | NUM_DEC_PLACES = 2 |
312 | 312 | ||
313 | def __init__(self, time, cpu): | 313 | def __init__(self, time, cpu): |
314 | super(Event, self).__init__(time, cpu) | 314 | super(Event, self).__init__(time, cpu) |
315 | self.erroneous = False | 315 | self.erroneous = False |
316 | self.selected = False | 316 | self.selected = False |
317 | 317 | ||
318 | def __str__(self): | 318 | def __str__(self): |
319 | return '[Event]' | 319 | return '[Event]' |
320 | 320 | ||
321 | def _common_str(self): | 321 | def _common_str(self): |
322 | job = self.get_job() | 322 | job = self.get_job() |
323 | task = job.get_task() | 323 | task = job.get_task() |
324 | return ' for task ' + str(task.get_name()) + ': (TASK, JOB)=' + str((task.get_task_no(), \ | 324 | return ' for task ' + str(task.get_name()) + ': (TASK, JOB)=' + str((task.get_task_no(), \ |
325 | job.get_job_no())) + ', CPU=' + str(self.get_cpu()) | 325 | job.get_job_no())) + ', CPU=' + str(self.get_cpu()) |
326 | 326 | ||
327 | def is_erroneous(self): | 327 | def is_erroneous(self): |
328 | """An erroneous event is where something with the event is not quite right, | 328 | """An erroneous event is where something with the event is not quite right, |
329 | something significantly wrong that we don't have logical information telling | 329 | something significantly wrong that we don't have logical information telling |
330 | us how we should render the event.""" | 330 | us how we should render the event.""" |
331 | return self.erroneous | 331 | return self.erroneous |
332 | 332 | ||
333 | def is_selected(self): | 333 | def is_selected(self): |
334 | """Returns whether the event has been selected by the user. (needed for rendering)""" | 334 | """Returns whether the event has been selected by the user. (needed for rendering)""" |
335 | return self.selected | 335 | return self.selected |
336 | 336 | ||
337 | def scan(self, cur_cpu, switches): | 337 | def scan(self, cur_cpu, switches): |
338 | """Part of the procedure that walks through all the events and sets | 338 | """Part of the procedure that walks through all the events and sets |
339 | some parameters that are unknown at first. For instance, a SwitchAwayEvent | 339 | some parameters that are unknown at first. For instance, a SwitchAwayEvent |
@@ -348,26 +348,26 @@ class Event(DummyEvent): | |||
348 | sched.start = time | 348 | sched.start = time |
349 | if sched.end is None or time > sched.end: | 349 | if sched.end is None or time > sched.end: |
350 | sched.end = time | 350 | sched.end = time |
351 | 351 | ||
352 | sched.get_time_slot_array().add_event_to_time_slot(self) | 352 | sched.get_time_slot_array().add_event_to_time_slot(self) |
353 | 353 | ||
354 | class ErrorEvent(Event): | 354 | class ErrorEvent(Event): |
355 | pass | 355 | pass |
356 | 356 | ||
357 | class SuspendEvent(Event): | 357 | class SuspendEvent(Event): |
358 | def __init__(self, time, cpu): | 358 | def __init__(self, time, cpu): |
359 | super(SuspendEvent, self).__init__(time, cpu) | 359 | super(SuspendEvent, self).__init__(time, cpu) |
360 | self.layer = Canvas.MIDDLE_LAYER | 360 | self.layer = Canvas.MIDDLE_LAYER |
361 | 361 | ||
362 | def __str__(self): | 362 | def __str__(self): |
363 | return 'Suspend' + self._common_str() + ', TIME=' + util.format_float(self.get_time(), Event.NUM_DEC_PLACES) | 363 | return 'Suspend' + self._common_str() + ', TIME=' + util.format_float(self.get_time(), Event.NUM_DEC_PLACES) |
364 | 364 | ||
365 | def scan(self, cur_cpu, switches): | 365 | def scan(self, cur_cpu, switches): |
366 | if self.get_cpu() != cur_cpu[0]: | 366 | if self.get_cpu() != cur_cpu[0]: |
367 | self.erroneous = True | 367 | self.erroneous = True |
368 | #fprint "suspending on a CPU different from the CPU we are on!" | 368 | #fprint "suspending on a CPU different from the CPU we are on!" |
369 | super(SuspendEvent, self).scan(cur_cpu, switches) | 369 | super(SuspendEvent, self).scan(cur_cpu, switches) |
370 | 370 | ||
371 | def render(self, graph, layer, prev_events, selectable=False): | 371 | def render(self, graph, layer, prev_events, selectable=False): |
372 | if layer == self.layer: | 372 | if layer == self.layer: |
373 | prev_events[self] = None | 373 | prev_events[self] = None |
@@ -377,22 +377,22 @@ class SuspendEvent(Event): | |||
377 | else: | 377 | else: |
378 | graph.draw_suspend_triangle_at_time(self.get_time(), self.get_job().get_task().get_task_no(), | 378 | graph.draw_suspend_triangle_at_time(self.get_time(), self.get_job().get_task().get_task_no(), |
379 | self.get_cpu(), self.is_selected()) | 379 | self.get_cpu(), self.is_selected()) |
380 | 380 | ||
381 | 381 | ||
382 | class ResumeEvent(Event): | 382 | class ResumeEvent(Event): |
383 | def __init__(self, time, cpu): | 383 | def __init__(self, time, cpu): |
384 | super(ResumeEvent, self).__init__(time, cpu) | 384 | super(ResumeEvent, self).__init__(time, cpu) |
385 | self.layer = Canvas.MIDDLE_LAYER | 385 | self.layer = Canvas.MIDDLE_LAYER |
386 | 386 | ||
387 | def __str__(self): | 387 | def __str__(self): |
388 | return 'Resume' + self._common_str() + ', TIME=' + util.format_float(self.get_time(), Event.NUM_DEC_PLACES) | 388 | return 'Resume' + self._common_str() + ', TIME=' + util.format_float(self.get_time(), Event.NUM_DEC_PLACES) |
389 | 389 | ||
390 | def scan(self, cur_cpu, switches): | 390 | def scan(self, cur_cpu, switches): |
391 | if cur_cpu[0] != Event.NO_CPU and cur_cpu[0] != self.get_cpu(): | 391 | if cur_cpu[0] != Event.NO_CPU and cur_cpu[0] != self.get_cpu(): |
392 | self.erroneous = True | 392 | self.erroneous = True |
393 | #print "Resuming when currently scheduled on a CPU, but on a different CPU from the current CPU!" | 393 | #print "Resuming when currently scheduled on a CPU, but on a different CPU from the current CPU!" |
394 | super(ResumeEvent, self).scan(cur_cpu, switches) | 394 | super(ResumeEvent, self).scan(cur_cpu, switches) |
395 | 395 | ||
396 | def render(self, graph, layer, prev_events, selectable=False): | 396 | def render(self, graph, layer, prev_events, selectable=False): |
397 | if layer == self.layer: | 397 | if layer == self.layer: |
398 | prev_events[self] = None | 398 | prev_events[self] = None |
@@ -402,19 +402,19 @@ class ResumeEvent(Event): | |||
402 | else: | 402 | else: |
403 | graph.draw_resume_triangle_at_time(self.get_time(), self.get_job().get_task().get_task_no(), | 403 | graph.draw_resume_triangle_at_time(self.get_time(), self.get_job().get_task().get_task_no(), |
404 | self.get_cpu(), self.is_selected()) | 404 | self.get_cpu(), self.is_selected()) |
405 | 405 | ||
406 | 406 | ||
407 | class CompleteEvent(Event): | 407 | class CompleteEvent(Event): |
408 | def __init__(self, time, cpu): | 408 | def __init__(self, time, cpu): |
409 | super(CompleteEvent, self).__init__(time, cpu) | 409 | super(CompleteEvent, self).__init__(time, cpu) |
410 | self.layer = Canvas.TOP_LAYER | 410 | self.layer = Canvas.TOP_LAYER |
411 | 411 | ||
412 | def __str__(self): | 412 | def __str__(self): |
413 | return 'Complete' + self._common_str() + ', TIME=' + util.format_float(self.get_time(), Event.NUM_DEC_PLACES) | 413 | return 'Complete' + self._common_str() + ', TIME=' + util.format_float(self.get_time(), Event.NUM_DEC_PLACES) |
414 | 414 | ||
415 | def scan(self, cur_cpu, switches): | 415 | def scan(self, cur_cpu, switches): |
416 | super(CompleteEvent, self).scan(cur_cpu, switches) | 416 | super(CompleteEvent, self).scan(cur_cpu, switches) |
417 | 417 | ||
418 | def render(self, graph, layer, prev_events, selectable=False): | 418 | def render(self, graph, layer, prev_events, selectable=False): |
419 | if layer == Canvas.TOP_LAYER: | 419 | if layer == Canvas.TOP_LAYER: |
420 | prev_events[self] = None | 420 | prev_events[self] = None |
@@ -430,7 +430,7 @@ class SwitchToEvent(Event): | |||
430 | super(SwitchToEvent, self).__init__(time, cpu) | 430 | super(SwitchToEvent, self).__init__(time, cpu) |
431 | self.layer = Canvas.BOTTOM_LAYER | 431 | self.layer = Canvas.BOTTOM_LAYER |
432 | self.corresp_end_event = None | 432 | self.corresp_end_event = None |
433 | 433 | ||
434 | def __str__(self): | 434 | def __str__(self): |
435 | if self.corresp_end_event is None: | 435 | if self.corresp_end_event is None: |
436 | return 'Switch To (w/o Switch Away)' + self._common_str() + ', TIME=' \ | 436 | return 'Switch To (w/o Switch Away)' + self._common_str() + ', TIME=' \ |
@@ -438,19 +438,19 @@ class SwitchToEvent(Event): | |||
438 | return 'Scheduled' + self._common_str() + ', START=' \ | 438 | return 'Scheduled' + self._common_str() + ', START=' \ |
439 | + util.format_float(self.get_time(), Event.NUM_DEC_PLACES) \ | 439 | + util.format_float(self.get_time(), Event.NUM_DEC_PLACES) \ |
440 | + ', END=' + util.format_float(self.corresp_end_event.get_time(), Event.NUM_DEC_PLACES) | 440 | + ', END=' + util.format_float(self.corresp_end_event.get_time(), Event.NUM_DEC_PLACES) |
441 | 441 | ||
442 | def scan(self, cur_cpu, switches): | 442 | def scan(self, cur_cpu, switches): |
443 | old_cur_cpu = cur_cpu[0] | 443 | old_cur_cpu = cur_cpu[0] |
444 | cur_cpu[0] = self.get_cpu() | 444 | cur_cpu[0] = self.get_cpu() |
445 | switches[SwitchToEvent] = self | 445 | switches[SwitchToEvent] = self |
446 | self.corresp_end_event = None | 446 | self.corresp_end_event = None |
447 | 447 | ||
448 | if old_cur_cpu != Event.NO_CPU: | 448 | if old_cur_cpu != Event.NO_CPU: |
449 | self.erroneous = True | 449 | self.erroneous = True |
450 | #print "currently scheduled somewhere, can't switch to a CPU" | 450 | #print "currently scheduled somewhere, can't switch to a CPU" |
451 | 451 | ||
452 | super(SwitchToEvent, self).scan(cur_cpu, switches) | 452 | super(SwitchToEvent, self).scan(cur_cpu, switches) |
453 | 453 | ||
454 | def render(self, graph, layer, prev_events, selectable=False): | 454 | def render(self, graph, layer, prev_events, selectable=False): |
455 | if layer == self.layer: | 455 | if layer == self.layer: |
456 | end_time = None | 456 | end_time = None |
@@ -460,7 +460,7 @@ class SwitchToEvent(Event): | |||
460 | clip = AlignMode.RIGHT | 460 | clip = AlignMode.RIGHT |
461 | else: | 461 | else: |
462 | end_time = self.corresp_end_event.get_time() | 462 | end_time = self.corresp_end_event.get_time() |
463 | 463 | ||
464 | prev_events[self] = None | 464 | prev_events[self] = None |
465 | cpu = self.get_cpu() | 465 | cpu = self.get_cpu() |
466 | task_no = self.get_job().get_task().get_task_no() | 466 | task_no = self.get_job().get_task().get_task_no() |
@@ -471,30 +471,30 @@ class SwitchToEvent(Event): | |||
471 | graph.draw_bar_at_time(self.get_time(), end_time, | 471 | graph.draw_bar_at_time(self.get_time(), end_time, |
472 | task_no, cpu, self.get_job().get_job_no(), | 472 | task_no, cpu, self.get_job().get_job_no(), |
473 | clip, self.is_selected()) | 473 | clip, self.is_selected()) |
474 | 474 | ||
475 | class SwitchAwayEvent(Event): | 475 | class SwitchAwayEvent(Event): |
476 | def __init__(self, time, cpu): | 476 | def __init__(self, time, cpu): |
477 | super(SwitchAwayEvent, self).__init__(time, cpu) | 477 | super(SwitchAwayEvent, self).__init__(time, cpu) |
478 | self.layer = Canvas.BOTTOM_LAYER | 478 | self.layer = Canvas.BOTTOM_LAYER |
479 | self.corresp_start_event = None | 479 | self.corresp_start_event = None |
480 | 480 | ||
481 | def __str__(self): | 481 | def __str__(self): |
482 | if self.corresp_start_event is None: | 482 | if self.corresp_start_event is None: |
483 | return 'Switch Away (w/o Switch To)' + self._common_str() + 'TIME=' \ | 483 | return 'Switch Away (w/o Switch To)' + self._common_str() + 'TIME=' \ |
484 | + str(self.get_time()) | 484 | + str(self.get_time()) |
485 | return str(self.corresp_start_event) | 485 | return str(self.corresp_start_event) |
486 | 486 | ||
487 | def scan(self, cur_cpu, switches): | 487 | def scan(self, cur_cpu, switches): |
488 | old_cur_cpu = cur_cpu[0] | 488 | old_cur_cpu = cur_cpu[0] |
489 | 489 | ||
490 | self.corresp_start_event = switches[SwitchToEvent] | 490 | self.corresp_start_event = switches[SwitchToEvent] |
491 | 491 | ||
492 | cur_cpu[0] = Event.NO_CPU | 492 | cur_cpu[0] = Event.NO_CPU |
493 | switches[SwitchToEvent] = None | 493 | switches[SwitchToEvent] = None |
494 | 494 | ||
495 | if self.corresp_start_event is not None: | 495 | if self.corresp_start_event is not None: |
496 | self.corresp_start_event.corresp_end_event = self | 496 | self.corresp_start_event.corresp_end_event = self |
497 | 497 | ||
498 | if self.get_cpu() != old_cur_cpu: | 498 | if self.get_cpu() != old_cur_cpu: |
499 | self.erroneous = True | 499 | self.erroneous = True |
500 | #print "switching away from a CPU different from the CPU we are currently on" | 500 | #print "switching away from a CPU different from the CPU we are currently on" |
@@ -504,9 +504,9 @@ class SwitchAwayEvent(Event): | |||
504 | elif self.get_time() < self.corresp_start_event.get_time(): | 504 | elif self.get_time() < self.corresp_start_event.get_time(): |
505 | self.erroneous = True | 505 | self.erroneous = True |
506 | #print "switching away from a processor before we switched to it?!" | 506 | #print "switching away from a processor before we switched to it?!" |
507 | 507 | ||
508 | super(SwitchAwayEvent, self).scan(cur_cpu, switches) | 508 | super(SwitchAwayEvent, self).scan(cur_cpu, switches) |
509 | 509 | ||
510 | def render(self, graph, layer, prev_events, selectable=False): | 510 | def render(self, graph, layer, prev_events, selectable=False): |
511 | if self.corresp_start_event is None: | 511 | if self.corresp_start_event is None: |
512 | # We never found a corresponding start event. In that case, we can assume it lies | 512 | # We never found a corresponding start event. In that case, we can assume it lies |
@@ -528,18 +528,18 @@ class SwitchAwayEvent(Event): | |||
528 | if self.corresp_start_event in prev_events: | 528 | if self.corresp_start_event in prev_events: |
529 | return # already rendered the bar | 529 | return # already rendered the bar |
530 | self.corresp_start_event.render(graph, layer, prev_events, selectable) | 530 | self.corresp_start_event.render(graph, layer, prev_events, selectable) |
531 | 531 | ||
532 | class ReleaseEvent(Event): | 532 | class ReleaseEvent(Event): |
533 | def __init__(self, time, cpu): | 533 | def __init__(self, time, cpu): |
534 | super(ReleaseEvent, self).__init__(time, cpu) | 534 | super(ReleaseEvent, self).__init__(time, cpu) |
535 | self.layer = Canvas.TOP_LAYER | 535 | self.layer = Canvas.TOP_LAYER |
536 | 536 | ||
537 | def __str__(self): | 537 | def __str__(self): |
538 | return 'Release' + self._common_str() + ', TIME=' + util.format_float(self.get_time(), Event.NUM_DEC_PLACES) | 538 | return 'Release' + self._common_str() + ', TIME=' + util.format_float(self.get_time(), Event.NUM_DEC_PLACES) |
539 | 539 | ||
540 | def scan(self, cur_cpu, switches): | 540 | def scan(self, cur_cpu, switches): |
541 | super(ReleaseEvent, self).scan(cur_cpu, switches) | 541 | super(ReleaseEvent, self).scan(cur_cpu, switches) |
542 | 542 | ||
543 | def render(self, graph, layer, prev_events, selectable=False): | 543 | def render(self, graph, layer, prev_events, selectable=False): |
544 | prev_events[self] = None | 544 | prev_events[self] = None |
545 | if layer == Canvas.TOP_LAYER: | 545 | if layer == Canvas.TOP_LAYER: |
@@ -549,19 +549,19 @@ class ReleaseEvent(Event): | |||
549 | else: | 549 | else: |
550 | graph.draw_release_arrow_at_time(self.get_time(), self.get_job().get_task().get_task_no(), | 550 | graph.draw_release_arrow_at_time(self.get_time(), self.get_job().get_task().get_task_no(), |
551 | self.get_job().get_job_no(), self.is_selected()) | 551 | self.get_job().get_job_no(), self.is_selected()) |
552 | 552 | ||
553 | 553 | ||
554 | class DeadlineEvent(Event): | 554 | class DeadlineEvent(Event): |
555 | def __init__(self, time, cpu): | 555 | def __init__(self, time, cpu): |
556 | super(DeadlineEvent, self).__init__(time, cpu) | 556 | super(DeadlineEvent, self).__init__(time, cpu) |
557 | self.layer = Canvas.TOP_LAYER | 557 | self.layer = Canvas.TOP_LAYER |
558 | 558 | ||
559 | def __str__(self): | 559 | def __str__(self): |
560 | return 'Deadline' + self._common_str() + ', TIME=' + util.format_float(self.get_time(), Event.NUM_DEC_PLACES) | 560 | return 'Deadline' + self._common_str() + ', TIME=' + util.format_float(self.get_time(), Event.NUM_DEC_PLACES) |
561 | 561 | ||
562 | def scan(self, cur_cpu, switches): | 562 | def scan(self, cur_cpu, switches): |
563 | super(DeadlineEvent, self).scan(cur_cpu, switches) | 563 | super(DeadlineEvent, self).scan(cur_cpu, switches) |
564 | 564 | ||
565 | def render(self, graph, layer, prev_events, selectable=False): | 565 | def render(self, graph, layer, prev_events, selectable=False): |
566 | prev_events[self] = None | 566 | prev_events[self] = None |
567 | if layer == Canvas.TOP_LAYER: | 567 | if layer == Canvas.TOP_LAYER: |
@@ -571,14 +571,14 @@ class DeadlineEvent(Event): | |||
571 | else: | 571 | else: |
572 | graph.draw_deadline_arrow_at_time(self.get_time(), self.get_job().get_task().get_task_no(), | 572 | graph.draw_deadline_arrow_at_time(self.get_time(), self.get_job().get_task().get_task_no(), |
573 | self.get_job().get_job_no(), self.is_selected()) | 573 | self.get_job().get_job_no(), self.is_selected()) |
574 | 574 | ||
575 | 575 | ||
576 | class InversionStartEvent(ErrorEvent): | 576 | class InversionStartEvent(ErrorEvent): |
577 | def __init__(self, time): | 577 | def __init__(self, time): |
578 | super(InversionStartEvent, self).__init__(time, Event.NO_CPU) | 578 | super(InversionStartEvent, self).__init__(time, Event.NO_CPU) |
579 | self.layer = Canvas.BOTTOM_LAYER | 579 | self.layer = Canvas.BOTTOM_LAYER |
580 | self.corresp_end_event = None | 580 | self.corresp_end_event = None |
581 | 581 | ||
582 | def __str__(self): | 582 | def __str__(self): |
583 | if self.corresp_end_event is None: | 583 | if self.corresp_end_event is None: |
584 | return 'Inversion Start (w/o Inversion End)' + self._common_str() \ | 584 | return 'Inversion Start (w/o Inversion End)' + self._common_str() \ |
@@ -586,14 +586,14 @@ class InversionStartEvent(ErrorEvent): | |||
586 | return 'Priority Inversion' + self._common_str() + ', START=' \ | 586 | return 'Priority Inversion' + self._common_str() + ', START=' \ |
587 | + util.format_float(self.get_time(), Event.NUM_DEC_PLACES) \ | 587 | + util.format_float(self.get_time(), Event.NUM_DEC_PLACES) \ |
588 | + ', END=' + util.format_float(self.corresp_end_event.get_time(), Event.NUM_DEC_PLACES) | 588 | + ', END=' + util.format_float(self.corresp_end_event.get_time(), Event.NUM_DEC_PLACES) |
589 | 589 | ||
590 | def scan(self, cur_cpu, switches): | 590 | def scan(self, cur_cpu, switches): |
591 | switches[InversionStartEvent] = self | 591 | switches[InversionStartEvent] = self |
592 | self.corresp_end_event = None | 592 | self.corresp_end_event = None |
593 | 593 | ||
594 | # the corresp_end_event should already be set | 594 | # the corresp_end_event should already be set |
595 | super(InversionStartEvent, self).scan(cur_cpu, switches) | 595 | super(InversionStartEvent, self).scan(cur_cpu, switches) |
596 | 596 | ||
597 | def render(self, graph, layer, prev_events, selectable=False): | 597 | def render(self, graph, layer, prev_events, selectable=False): |
598 | if layer == self.layer: | 598 | if layer == self.layer: |
599 | end_time = None | 599 | end_time = None |
@@ -603,7 +603,7 @@ class InversionStartEvent(ErrorEvent): | |||
603 | clip = AlignMode.RIGHT | 603 | clip = AlignMode.RIGHT |
604 | else: | 604 | else: |
605 | end_time = self.corresp_end_event.get_time() | 605 | end_time = self.corresp_end_event.get_time() |
606 | 606 | ||
607 | if layer == self.layer: | 607 | if layer == self.layer: |
608 | prev_events[self] = None | 608 | prev_events[self] = None |
609 | cpu = self.get_cpu() | 609 | cpu = self.get_cpu() |
@@ -615,36 +615,36 @@ class InversionStartEvent(ErrorEvent): | |||
615 | graph.draw_mini_bar_at_time(self.get_time(), end_time, | 615 | graph.draw_mini_bar_at_time(self.get_time(), end_time, |
616 | task_no, cpu, self.get_job().get_job_no(), | 616 | task_no, cpu, self.get_job().get_job_no(), |
617 | clip, self.is_selected()) | 617 | clip, self.is_selected()) |
618 | 618 | ||
619 | 619 | ||
620 | class InversionEndEvent(ErrorEvent): | 620 | class InversionEndEvent(ErrorEvent): |
621 | def __init__(self, time): | 621 | def __init__(self, time): |
622 | super(InversionEndEvent, self).__init__(time, Event.NO_CPU) | 622 | super(InversionEndEvent, self).__init__(time, Event.NO_CPU) |
623 | self.layer = Canvas.BOTTOM_LAYER | 623 | self.layer = Canvas.BOTTOM_LAYER |
624 | self.corresp_start_event = None | 624 | self.corresp_start_event = None |
625 | 625 | ||
626 | def __str__(self): | 626 | def __str__(self): |
627 | if self.corresp_start_event is None: | 627 | if self.corresp_start_event is None: |
628 | return 'Inversion End (w/o Inversion Start)' + self._common_str() \ | 628 | return 'Inversion End (w/o Inversion Start)' + self._common_str() \ |
629 | + ', TIME=' + util.format_float(self.get_time(), Event.NUM_DEC_PLACES) | 629 | + ', TIME=' + util.format_float(self.get_time(), Event.NUM_DEC_PLACES) |
630 | 630 | ||
631 | return str(self.corresp_start_event) | 631 | return str(self.corresp_start_event) |
632 | 632 | ||
633 | def scan(self, cur_cpu, switches): | 633 | def scan(self, cur_cpu, switches): |
634 | self.corresp_start_event = switches[InversionStartEvent] | 634 | self.corresp_start_event = switches[InversionStartEvent] |
635 | 635 | ||
636 | cur_cpu[0] = Event.NO_CPU | 636 | cur_cpu[0] = Event.NO_CPU |
637 | switches[InversionStartEvent] = None | 637 | switches[InversionStartEvent] = None |
638 | 638 | ||
639 | if self.corresp_start_event is not None: | 639 | if self.corresp_start_event is not None: |
640 | self.corresp_start_event.corresp_end_event = self | 640 | self.corresp_start_event.corresp_end_event = self |
641 | 641 | ||
642 | if self.corresp_start_event is None: | 642 | if self.corresp_start_event is None: |
643 | self.erroneous = True | 643 | self.erroneous = True |
644 | print "inversion end was not matched by a corresponding inversion start" | 644 | print "inversion end was not matched by a corresponding inversion start" |
645 | 645 | ||
646 | super(InversionEndEvent, self).scan(cur_cpu, switches) | 646 | super(InversionEndEvent, self).scan(cur_cpu, switches) |
647 | 647 | ||
648 | def render(self, graph, layer, prev_events, selectable=False): | 648 | def render(self, graph, layer, prev_events, selectable=False): |
649 | if self.corresp_start_event is None: | 649 | if self.corresp_start_event is None: |
650 | # We never found a corresponding start event. In that case, we can assume it lies | 650 | # We never found a corresponding start event. In that case, we can assume it lies |
@@ -666,27 +666,27 @@ class InversionEndEvent(ErrorEvent): | |||
666 | if self.corresp_start_event in prev_events: | 666 | if self.corresp_start_event in prev_events: |
667 | return # already rendered the bar | 667 | return # already rendered the bar |
668 | self.corresp_start_event.render(graph, layer, prev_events, selectable) | 668 | self.corresp_start_event.render(graph, layer, prev_events, selectable) |
669 | 669 | ||
670 | class InversionDummy(DummyEvent): | 670 | class InversionDummy(DummyEvent): |
671 | def __init__(self, time, cpu): | 671 | def __init__(self, time, cpu): |
672 | super(InversionDummy, self).__init__(time, Event.NO_CPU) | 672 | super(InversionDummy, self).__init__(time, Event.NO_CPU) |
673 | self.layer = Canvas.BOTTOM_LAYER | 673 | self.layer = Canvas.BOTTOM_LAYER |
674 | 674 | ||
675 | def render(self, graph, layer, prev_events, selectable=False): | 675 | def render(self, graph, layer, prev_events, selectable=False): |
676 | if self.corresp_start_event is None: | 676 | if self.corresp_start_event is None: |
677 | if self.corresp_end_event in prev_events: | 677 | if self.corresp_end_event in prev_events: |
678 | return # we have already been rendered | 678 | return # we have already been rendered |
679 | self.corresp_end_event.render(graph, layer, prev_events, selectable) | 679 | self.corresp_end_event.render(graph, layer, prev_events, selectable) |
680 | else: | 680 | else: |
681 | if self.corresp_start_event in prev_events: | 681 | if self.corresp_start_event in prev_events: |
682 | return # we have already been rendered | 682 | return # we have already been rendered |
683 | self.corresp_start_event.render(graph, layer, prev_events, selectable) | 683 | self.corresp_start_event.render(graph, layer, prev_events, selectable) |
684 | 684 | ||
685 | class IsRunningDummy(DummyEvent): | 685 | class IsRunningDummy(DummyEvent): |
686 | def __init__(self, time, cpu): | 686 | def __init__(self, time, cpu): |
687 | super(IsRunningDummy, self).__init__(time, Event.NO_CPU) | 687 | super(IsRunningDummy, self).__init__(time, Event.NO_CPU) |
688 | self.layer = Canvas.BOTTOM_LAYER | 688 | self.layer = Canvas.BOTTOM_LAYER |
689 | 689 | ||
690 | def render(self, graph, layer, prev_events, selectable=False): | 690 | def render(self, graph, layer, prev_events, selectable=False): |
691 | if self.corresp_start_event is None: | 691 | if self.corresp_start_event is None: |
692 | if self.corresp_end_event in prev_events: | 692 | if self.corresp_end_event in prev_events: |
diff --git a/unit_trace/viz/viewer.py b/unit_trace/viz/viewer.py index 909da76..efc79a1 100644 --- a/unit_trace/viz/viewer.py +++ b/unit_trace/viz/viewer.py | |||
@@ -13,10 +13,10 @@ import copy | |||
13 | 13 | ||
14 | class GraphContextMenu(gtk.Menu): | 14 | class GraphContextMenu(gtk.Menu): |
15 | MAX_STR_LEN = 80 | 15 | MAX_STR_LEN = 80 |
16 | 16 | ||
17 | def __init__(self, selected): | 17 | def __init__(self, selected): |
18 | super(GraphContextMenu, self).__init__() | 18 | super(GraphContextMenu, self).__init__() |
19 | 19 | ||
20 | for event in selected: | 20 | for event in selected: |
21 | string = str(event) | 21 | string = str(event) |
22 | if len(string) > GraphContextMenu.MAX_STR_LEN - 3: | 22 | if len(string) > GraphContextMenu.MAX_STR_LEN - 3: |
@@ -24,100 +24,100 @@ class GraphContextMenu(gtk.Menu): | |||
24 | item = gtk.MenuItem(string) | 24 | item = gtk.MenuItem(string) |
25 | self.append(item) | 25 | self.append(item) |
26 | item.show() | 26 | item.show() |
27 | 27 | ||
28 | class GraphArea(gtk.DrawingArea): | 28 | class GraphArea(gtk.DrawingArea): |
29 | HORIZ_PAGE_SCROLL_FACTOR = 10.8 | 29 | HORIZ_PAGE_SCROLL_FACTOR = 10.8 |
30 | HORIZ_STEP_SCROLL_FACTOR = 0.8 | 30 | HORIZ_STEP_SCROLL_FACTOR = 0.8 |
31 | VERT_PAGE_SCROLL_FACTOR = 3.0 | 31 | VERT_PAGE_SCROLL_FACTOR = 3.0 |
32 | VERT_STEP_SCROLL_FACTOR = 0.5 | 32 | VERT_STEP_SCROLL_FACTOR = 0.5 |
33 | 33 | ||
34 | REFRESH_INFLATION_FACTOR = 20.0 | 34 | REFRESH_INFLATION_FACTOR = 20.0 |
35 | 35 | ||
36 | def __init__(self, renderer): | 36 | def __init__(self, renderer): |
37 | super(GraphArea, self).__init__() | 37 | super(GraphArea, self).__init__() |
38 | 38 | ||
39 | self.renderer = renderer | 39 | self.renderer = renderer |
40 | 40 | ||
41 | self.cur_x = 0 | 41 | self.cur_x = 0 |
42 | self.cur_y = 0 | 42 | self.cur_y = 0 |
43 | self.width = 0 | 43 | self.width = 0 |
44 | self.height = 0 | 44 | self.height = 0 |
45 | 45 | ||
46 | self.set_set_scroll_adjustments_signal('set-scroll-adjustments') | 46 | self.set_set_scroll_adjustments_signal('set-scroll-adjustments') |
47 | 47 | ||
48 | self.add_events(gtk.gdk.BUTTON_PRESS_MASK | gtk.gdk.POINTER_MOTION_MASK | gtk.gdk.POINTER_MOTION_HINT_MASK | | 48 | self.add_events(gtk.gdk.BUTTON_PRESS_MASK | gtk.gdk.POINTER_MOTION_MASK | gtk.gdk.POINTER_MOTION_HINT_MASK | |
49 | gtk.gdk.BUTTON_RELEASE_MASK | gtk.gdk.EXPOSURE_MASK) | 49 | gtk.gdk.BUTTON_RELEASE_MASK | gtk.gdk.EXPOSURE_MASK) |
50 | 50 | ||
51 | self.band_rect = None | 51 | self.band_rect = None |
52 | self.ctrl_clicked = False | 52 | self.ctrl_clicked = False |
53 | self.dirtied_regions = [] | 53 | self.dirtied_regions = [] |
54 | 54 | ||
55 | self.connect('expose-event', self.expose) | 55 | self.connect('expose-event', self.expose) |
56 | self.connect('size-allocate', self.size_allocate) | 56 | self.connect('size-allocate', self.size_allocate) |
57 | self.connect('set-scroll-adjustments', self.set_scroll_adjustments) | 57 | self.connect('set-scroll-adjustments', self.set_scroll_adjustments) |
58 | self.connect('button-press-event', self.button_press) | 58 | self.connect('button-press-event', self.button_press) |
59 | self.connect('button-release-event', self.button_release) | 59 | self.connect('button-release-event', self.button_release) |
60 | self.connect('motion-notify-event', self.motion_notify) | 60 | self.connect('motion-notify-event', self.motion_notify) |
61 | 61 | ||
62 | def expose(self, widget, expose_event, data=None): | 62 | def expose(self, widget, expose_event, data=None): |
63 | ctx = widget.window.cairo_create() | 63 | ctx = widget.window.cairo_create() |
64 | graph = self.renderer.get_graph() | 64 | graph = self.renderer.get_graph() |
65 | graph.update_view(self.cur_x, self.cur_y, self.width, self.height, ctx) | 65 | graph.update_view(self.cur_x, self.cur_y, self.width, self.height, ctx) |
66 | 66 | ||
67 | # We ourselves didn't update dirtied_regions, so this means that X or the | 67 | # We ourselves didn't update dirtied_regions, so this means that X or the |
68 | # window manager must have caused the expose event. So just update the | 68 | # window manager must have caused the expose event. So just update the |
69 | # expose_event's bounding area. | 69 | # expose_event's bounding area. |
70 | if not self.dirtied_regions or expose_event.send_event: | 70 | if not self.dirtied_regions or expose_event.send_event: |
71 | self.dirtied_regions = [(expose_event.area.x, expose_event.area.y, | 71 | self.dirtied_regions = [(expose_event.area.x, expose_event.area.y, |
72 | expose_event.area.width, expose_event.area.height)] | 72 | expose_event.area.width, expose_event.area.height)] |
73 | 73 | ||
74 | graph.render_surface(self.renderer.get_schedule(), self.dirtied_regions) | 74 | graph.render_surface(self.renderer.get_schedule(), self.dirtied_regions) |
75 | 75 | ||
76 | # render dragging band rectangle, if there is one | 76 | # render dragging band rectangle, if there is one |
77 | if self.band_rect is not None: | 77 | if self.band_rect is not None: |
78 | x, y, width, height = self.band_rect | 78 | x, y, width, height = self.band_rect |
79 | thickness = GraphFormat.BAND_THICKNESS | 79 | thickness = GraphFormat.BAND_THICKNESS |
80 | color = GraphFormat.BAND_COLOR | 80 | color = GraphFormat.BAND_COLOR |
81 | 81 | ||
82 | ctx.rectangle(x, y, width, height) | 82 | ctx.rectangle(x, y, width, height) |
83 | ctx.set_line_width(thickness) | 83 | ctx.set_line_width(thickness) |
84 | ctx.set_source_rgb(color[0], color[1], color[2]) | 84 | ctx.set_source_rgb(color[0], color[1], color[2]) |
85 | ctx.stroke() | 85 | ctx.stroke() |
86 | 86 | ||
87 | self.dirtied_regions = [] | 87 | self.dirtied_regions = [] |
88 | 88 | ||
89 | def get_renderer(self): | 89 | def get_renderer(self): |
90 | return self.renderer | 90 | return self.renderer |
91 | 91 | ||
92 | def get_graph(self): | 92 | def get_graph(self): |
93 | return self.renderer.get_graph() | 93 | return self.renderer.get_graph() |
94 | 94 | ||
95 | def set_scroll_adjustments(self, widget, horizontal, vertical, data=None): | 95 | def set_scroll_adjustments(self, widget, horizontal, vertical, data=None): |
96 | graph = self.renderer.get_graph() | 96 | graph = self.renderer.get_graph() |
97 | width = graph.get_width() | 97 | width = graph.get_width() |
98 | height = graph.get_height() | 98 | height = graph.get_height() |
99 | 99 | ||
100 | self.horizontal = horizontal | 100 | self.horizontal = horizontal |
101 | self.vertical = vertical | 101 | self.vertical = vertical |
102 | self.config_scrollbars(self.cur_x, self.cur_y) | 102 | self.config_scrollbars(self.cur_x, self.cur_y) |
103 | 103 | ||
104 | if self.horizontal is not None: | 104 | if self.horizontal is not None: |
105 | self.horizontal.connect('value-changed', self.horizontal_value_changed) | 105 | self.horizontal.connect('value-changed', self.horizontal_value_changed) |
106 | if self.vertical is not None: | 106 | if self.vertical is not None: |
107 | self.vertical.connect('value-changed', self.vertical_value_changed) | 107 | self.vertical.connect('value-changed', self.vertical_value_changed) |
108 | 108 | ||
109 | def horizontal_value_changed(self, adjustment): | 109 | def horizontal_value_changed(self, adjustment): |
110 | self.cur_x = min(adjustment.value, self.renderer.get_graph().get_width()) | 110 | self.cur_x = min(adjustment.value, self.renderer.get_graph().get_width()) |
111 | self.cur_x = max(adjustment.value, 0.0) | 111 | self.cur_x = max(adjustment.value, 0.0) |
112 | 112 | ||
113 | self._dirty(0, 0, self.width, self.height) | 113 | self._dirty(0, 0, self.width, self.height) |
114 | 114 | ||
115 | def vertical_value_changed(self, adjustment): | 115 | def vertical_value_changed(self, adjustment): |
116 | self.cur_y = min(adjustment.value, self.renderer.get_graph().get_height()) | 116 | self.cur_y = min(adjustment.value, self.renderer.get_graph().get_height()) |
117 | self.cur_y = max(adjustment.value, 0.0) | 117 | self.cur_y = max(adjustment.value, 0.0) |
118 | 118 | ||
119 | self._dirty(0, 0, self.width, self.height) | 119 | self._dirty(0, 0, self.width, self.height) |
120 | 120 | ||
121 | def size_allocate(self, widget, allocation): | 121 | def size_allocate(self, widget, allocation): |
122 | self.width = allocation.width | 122 | self.width = allocation.width |
123 | self.height = allocation.height | 123 | self.height = allocation.height |
@@ -127,21 +127,21 @@ class GraphArea(gtk.DrawingArea): | |||
127 | graph = self.renderer.get_graph() | 127 | graph = self.renderer.get_graph() |
128 | width = graph.get_width() | 128 | width = graph.get_width() |
129 | height = graph.get_height() | 129 | height = graph.get_height() |
130 | 130 | ||
131 | if self.horizontal is not None: | 131 | if self.horizontal is not None: |
132 | self.horizontal.set_all(hvalue, 0.0, width, graph.get_attrs().maj_sep * GraphArea.HORIZ_STEP_SCROLL_FACTOR, | 132 | self.horizontal.set_all(hvalue, 0.0, width, graph.get_attrs().maj_sep * GraphArea.HORIZ_STEP_SCROLL_FACTOR, |
133 | graph.get_attrs().maj_sep * GraphArea.HORIZ_PAGE_SCROLL_FACTOR, self.width) | 133 | graph.get_attrs().maj_sep * GraphArea.HORIZ_PAGE_SCROLL_FACTOR, self.width) |
134 | if self.vertical is not None: | 134 | if self.vertical is not None: |
135 | self.vertical.set_all(vvalue, 0.0, height, graph.get_attrs().y_item_size * GraphArea.VERT_STEP_SCROLL_FACTOR, | 135 | self.vertical.set_all(vvalue, 0.0, height, graph.get_attrs().y_item_size * GraphArea.VERT_STEP_SCROLL_FACTOR, |
136 | graph.get_attrs().y_item_size * GraphArea.VERT_PAGE_SCROLL_FACTOR, self.height) | 136 | graph.get_attrs().y_item_size * GraphArea.VERT_PAGE_SCROLL_FACTOR, self.height) |
137 | 137 | ||
138 | def _find_max_layer(self, regions): | 138 | def _find_max_layer(self, regions): |
139 | max_layer = Canvas.BOTTOM_LAYER | 139 | max_layer = Canvas.BOTTOM_LAYER |
140 | for event in regions: | 140 | for event in regions: |
141 | if event.get_layer() > max_layer: | 141 | if event.get_layer() > max_layer: |
142 | max_layer = event.get_layer() | 142 | max_layer = event.get_layer() |
143 | return max_layer | 143 | return max_layer |
144 | 144 | ||
145 | def _update_event_changes(self, list1, list2): | 145 | def _update_event_changes(self, list1, list2): |
146 | # if an event changed selected status, update the bounding area | 146 | # if an event changed selected status, update the bounding area |
147 | for event in list1: | 147 | for event in list1: |
@@ -152,12 +152,12 @@ class GraphArea(gtk.DrawingArea): | |||
152 | if event not in list1: | 152 | if event not in list1: |
153 | x, y, width, height = list2[event].get_dimensions() | 153 | x, y, width, height = list2[event].get_dimensions() |
154 | self._dirty_inflate(x - self.cur_x, y - self.cur_y, width, height, GraphFormat.BORDER_THICKNESS) | 154 | self._dirty_inflate(x - self.cur_x, y - self.cur_y, width, height, GraphFormat.BORDER_THICKNESS) |
155 | 155 | ||
156 | def motion_notify(self, widget, motion_event, data=None): | 156 | def motion_notify(self, widget, motion_event, data=None): |
157 | msg = None | 157 | msg = None |
158 | 158 | ||
159 | graph = self.renderer.get_graph() | 159 | graph = self.renderer.get_graph() |
160 | 160 | ||
161 | graph.render_surface(self.renderer.get_schedule(), [(motion_event.x, motion_event.y, | 161 | graph.render_surface(self.renderer.get_schedule(), [(motion_event.x, motion_event.y, |
162 | 0, 0)], True) | 162 | 0, 0)], True) |
163 | just_selected = graph.get_selected_regions(motion_event.x, motion_event.y, 0, 0) | 163 | just_selected = graph.get_selected_regions(motion_event.x, motion_event.y, 0, 0) |
@@ -166,62 +166,62 @@ class GraphArea(gtk.DrawingArea): | |||
166 | the_event = None | 166 | the_event = None |
167 | else: | 167 | else: |
168 | max_layer = self._find_max_layer(just_selected) | 168 | max_layer = self._find_max_layer(just_selected) |
169 | 169 | ||
170 | for event in just_selected: | 170 | for event in just_selected: |
171 | if event.get_layer() == max_layer: | 171 | if event.get_layer() == max_layer: |
172 | the_event = event | 172 | the_event = event |
173 | break | 173 | break |
174 | 174 | ||
175 | msg = str(the_event) | 175 | msg = str(the_event) |
176 | 176 | ||
177 | self.emit('update-event-description', the_event, msg) | 177 | self.emit('update-event-description', the_event, msg) |
178 | 178 | ||
179 | if self.band_rect is not None: | 179 | if self.band_rect is not None: |
180 | selected = {} | 180 | selected = {} |
181 | was_selected = self.renderer.get_schedule().get_selected() | 181 | was_selected = self.renderer.get_schedule().get_selected() |
182 | if self.ctrl_clicked: | 182 | if self.ctrl_clicked: |
183 | selected = copy.copy(was_selected) | 183 | selected = copy.copy(was_selected) |
184 | 184 | ||
185 | # dragging a rectangle | 185 | # dragging a rectangle |
186 | x = self.band_rect[0] | 186 | x = self.band_rect[0] |
187 | y = self.band_rect[1] | 187 | y = self.band_rect[1] |
188 | width = motion_event.x - self.band_rect[0] | 188 | width = motion_event.x - self.band_rect[0] |
189 | height = motion_event.y - self.band_rect[1] | 189 | height = motion_event.y - self.band_rect[1] |
190 | 190 | ||
191 | x_p, y_p, width_p, height_p = self._positivify(x, y, width, height) | 191 | x_p, y_p, width_p, height_p = self._positivify(x, y, width, height) |
192 | graph.render_surface(self.renderer.get_schedule(), [(x_p, y_p, width_p, height_p)], True) | 192 | graph.render_surface(self.renderer.get_schedule(), [(x_p, y_p, width_p, height_p)], True) |
193 | selected.update(graph.get_selected_regions(x_p, y_p, width_p, height_p)) | 193 | selected.update(graph.get_selected_regions(x_p, y_p, width_p, height_p)) |
194 | self.renderer.get_schedule().set_selected(selected) | 194 | self.renderer.get_schedule().set_selected(selected) |
195 | 195 | ||
196 | old_x, old_y, old_width, old_height = self.band_rect | 196 | old_x, old_y, old_width, old_height = self.band_rect |
197 | self.band_rect = (x, y, width, height) | 197 | self.band_rect = (x, y, width, height) |
198 | 198 | ||
199 | self._dirty_rect_border(old_x, old_y, old_width, old_height, GraphFormat.BAND_THICKNESS) | 199 | self._dirty_rect_border(old_x, old_y, old_width, old_height, GraphFormat.BAND_THICKNESS) |
200 | self._dirty_rect_border(x, y, width, height, GraphFormat.BAND_THICKNESS) | 200 | self._dirty_rect_border(x, y, width, height, GraphFormat.BAND_THICKNESS) |
201 | 201 | ||
202 | self._update_event_changes(was_selected, selected) | 202 | self._update_event_changes(was_selected, selected) |
203 | 203 | ||
204 | def button_press(self, widget, button_event, data=None): | 204 | def button_press(self, widget, button_event, data=None): |
205 | graph = self.renderer.get_graph() | 205 | graph = self.renderer.get_graph() |
206 | 206 | ||
207 | self.ctrl_clicked = button_event.state & gtk.gdk.CONTROL_MASK | 207 | self.ctrl_clicked = button_event.state & gtk.gdk.CONTROL_MASK |
208 | 208 | ||
209 | if button_event.button == 1: | 209 | if button_event.button == 1: |
210 | self.left_button_start_coor = (button_event.x, button_event.y) | 210 | self.left_button_start_coor = (button_event.x, button_event.y) |
211 | graph.render_surface(self.renderer.get_schedule(), \ | 211 | graph.render_surface(self.renderer.get_schedule(), \ |
212 | [(button_event.x, button_event.y, 0, 0)], True) | 212 | [(button_event.x, button_event.y, 0, 0)], True) |
213 | 213 | ||
214 | just_selected = graph.get_selected_regions(button_event.x, button_event.y, 0, 0) | 214 | just_selected = graph.get_selected_regions(button_event.x, button_event.y, 0, 0) |
215 | 215 | ||
216 | max_layer = self._find_max_layer(just_selected) | 216 | max_layer = self._find_max_layer(just_selected) |
217 | 217 | ||
218 | new_now_selected = None | 218 | new_now_selected = None |
219 | was_selected = self.renderer.get_schedule().get_selected() | 219 | was_selected = self.renderer.get_schedule().get_selected() |
220 | if self.ctrl_clicked: | 220 | if self.ctrl_clicked: |
221 | new_now_selected = copy.copy(was_selected) | 221 | new_now_selected = copy.copy(was_selected) |
222 | else: | 222 | else: |
223 | new_now_selected = {} | 223 | new_now_selected = {} |
224 | 224 | ||
225 | # only select those events which were in the top layer (it's | 225 | # only select those events which were in the top layer (it's |
226 | # not intuitive to click something and then have something | 226 | # not intuitive to click something and then have something |
227 | # below it get selected). Also, clicking something that | 227 | # below it get selected). Also, clicking something that |
@@ -237,43 +237,43 @@ class GraphArea(gtk.DrawingArea): | |||
237 | elif event in new_now_selected: | 237 | elif event in new_now_selected: |
238 | del new_now_selected[event] | 238 | del new_now_selected[event] |
239 | break # only pick one event when just clicking | 239 | break # only pick one event when just clicking |
240 | 240 | ||
241 | self.renderer.get_schedule().set_selected(new_now_selected) | 241 | self.renderer.get_schedule().set_selected(new_now_selected) |
242 | #self.last_selected = new_now_selected | 242 | #self.last_selected = new_now_selected |
243 | 243 | ||
244 | self._update_event_changes(new_now_selected, was_selected) | 244 | self._update_event_changes(new_now_selected, was_selected) |
245 | 245 | ||
246 | if self.band_rect is None: | 246 | if self.band_rect is None: |
247 | self.band_rect = (button_event.x, button_event.y, 0, 0) | 247 | self.band_rect = (button_event.x, button_event.y, 0, 0) |
248 | 248 | ||
249 | elif button_event.button == 3: | 249 | elif button_event.button == 3: |
250 | self._release_band() | 250 | self._release_band() |
251 | self.emit('request-context-menu', button_event, self.renderer.get_schedule().get_selected()) | 251 | self.emit('request-context-menu', button_event, self.renderer.get_schedule().get_selected()) |
252 | 252 | ||
253 | def button_release(self, widget, button_event, data=None): | 253 | def button_release(self, widget, button_event, data=None): |
254 | self.ctrl_clicked = False | 254 | self.ctrl_clicked = False |
255 | #self.last_selected = copy.copy(self.renderer.get_schedule().get_selected()) | 255 | #self.last_selected = copy.copy(self.renderer.get_schedule().get_selected()) |
256 | 256 | ||
257 | if button_event.button == 1: | 257 | if button_event.button == 1: |
258 | self._release_band() | 258 | self._release_band() |
259 | 259 | ||
260 | def _release_band(self): | 260 | def _release_band(self): |
261 | if self.band_rect is not None: | 261 | if self.band_rect is not None: |
262 | x, y, width, height = self.band_rect | 262 | x, y, width, height = self.band_rect |
263 | self._dirty_rect_border(x, y, width, height, GraphFormat.BAND_THICKNESS) | 263 | self._dirty_rect_border(x, y, width, height, GraphFormat.BAND_THICKNESS) |
264 | self.band_rect = None | 264 | self.band_rect = None |
265 | 265 | ||
266 | def _dirty(self, x, y, width, height): | 266 | def _dirty(self, x, y, width, height): |
267 | x = max(int(math.floor(x)), 0) | 267 | x = max(int(math.floor(x)), 0) |
268 | y = max(int(math.floor(y)), 0) | 268 | y = max(int(math.floor(y)), 0) |
269 | width = min(int(math.ceil(width)), self.width) | 269 | width = min(int(math.ceil(width)), self.width) |
270 | height = min(int(math.ceil(height)), self.height) | 270 | height = min(int(math.ceil(height)), self.height) |
271 | 271 | ||
272 | self.dirtied_regions.append((x, y, width, height)) | 272 | self.dirtied_regions.append((x, y, width, height)) |
273 | 273 | ||
274 | rect = gtk.gdk.Rectangle(x, y, width, height) | 274 | rect = gtk.gdk.Rectangle(x, y, width, height) |
275 | self.window.invalidate_rect(rect, True) | 275 | self.window.invalidate_rect(rect, True) |
276 | 276 | ||
277 | def _dirty_inflate(self, x, y, width, height, thickness): | 277 | def _dirty_inflate(self, x, y, width, height, thickness): |
278 | t = thickness * GraphArea.REFRESH_INFLATION_FACTOR | 278 | t = thickness * GraphArea.REFRESH_INFLATION_FACTOR |
279 | x -= t / 2.0 | 279 | x -= t / 2.0 |
@@ -281,17 +281,17 @@ class GraphArea(gtk.DrawingArea): | |||
281 | width += t | 281 | width += t |
282 | height += t | 282 | height += t |
283 | self._dirty(x, y, width, height) | 283 | self._dirty(x, y, width, height) |
284 | 284 | ||
285 | def _dirty_rect_border(self, x, y, width, height, thickness): | 285 | def _dirty_rect_border(self, x, y, width, height, thickness): |
286 | # support rectangles with negative width and height (i.e. -width = width, but going leftwards | 286 | # support rectangles with negative width and height (i.e. -width = width, but going leftwards |
287 | # instead of rightwards) | 287 | # instead of rightwards) |
288 | x, y, width, height = self._positivify(x, y, width, height) | 288 | x, y, width, height = self._positivify(x, y, width, height) |
289 | 289 | ||
290 | self._dirty_inflate(x, y, width, 0, thickness) | 290 | self._dirty_inflate(x, y, width, 0, thickness) |
291 | self._dirty_inflate(x, y, 0, height, thickness) | 291 | self._dirty_inflate(x, y, 0, height, thickness) |
292 | self._dirty_inflate(x, y + height, width, 0, thickness) | 292 | self._dirty_inflate(x, y + height, width, 0, thickness) |
293 | self._dirty_inflate(x + width, y, 0, height, thickness) | 293 | self._dirty_inflate(x + width, y, 0, height, thickness) |
294 | 294 | ||
295 | def _positivify(self, x, y, width, height): | 295 | def _positivify(self, x, y, width, height): |
296 | if width < 0: | 296 | if width < 0: |
297 | x += width | 297 | x += width |
@@ -299,28 +299,28 @@ class GraphArea(gtk.DrawingArea): | |||
299 | if height < 0: | 299 | if height < 0: |
300 | y += height | 300 | y += height |
301 | height = -height | 301 | height = -height |
302 | 302 | ||
303 | return x, y, width, height | 303 | return x, y, width, height |
304 | 304 | ||
305 | class GraphWindow(gtk.ScrolledWindow): | 305 | class GraphWindow(gtk.ScrolledWindow): |
306 | def __init__(self, renderer): | 306 | def __init__(self, renderer): |
307 | super(GraphWindow, self).__init__(None, None) | 307 | super(GraphWindow, self).__init__(None, None) |
308 | 308 | ||
309 | self.add_events(gtk.gdk.KEY_PRESS_MASK) | 309 | self.add_events(gtk.gdk.KEY_PRESS_MASK) |
310 | 310 | ||
311 | self.ctr = 0 | 311 | self.ctr = 0 |
312 | self.connect('key-press-event', self.key_press) | 312 | self.connect('key-press-event', self.key_press) |
313 | 313 | ||
314 | self.garea = GraphArea(renderer) | 314 | self.garea = GraphArea(renderer) |
315 | self.add(self.garea) | 315 | self.add(self.garea) |
316 | self.garea.show() | 316 | self.garea.show() |
317 | 317 | ||
318 | def key_press(self, widget, key_event): | 318 | def key_press(self, widget, key_event): |
319 | hadj = self.get_hadjustment() | 319 | hadj = self.get_hadjustment() |
320 | vadj = self.get_vadjustment() | 320 | vadj = self.get_vadjustment() |
321 | if hadj is None or vadj is None: | 321 | if hadj is None or vadj is None: |
322 | return | 322 | return |
323 | 323 | ||
324 | hupper = hadj.get_upper() | 324 | hupper = hadj.get_upper() |
325 | hlower = hadj.get_lower() | 325 | hlower = hadj.get_lower() |
326 | hpincr = hadj.get_page_increment() | 326 | hpincr = hadj.get_page_increment() |
@@ -333,9 +333,9 @@ class GraphWindow(gtk.ScrolledWindow): | |||
333 | vpincr = vadj.get_page_increment() | 333 | vpincr = vadj.get_page_increment() |
334 | vsincr = vadj.get_step_increment() | 334 | vsincr = vadj.get_step_increment() |
335 | vpsize = vadj.get_page_size() | 335 | vpsize = vadj.get_page_size() |
336 | 336 | ||
337 | ctrl_clicked = key_event.state & gtk.gdk.CONTROL_MASK | 337 | ctrl_clicked = key_event.state & gtk.gdk.CONTROL_MASK |
338 | 338 | ||
339 | adj_tuple = {'up' : (vadj, -vsincr, 0, vval, max), | 339 | adj_tuple = {'up' : (vadj, -vsincr, 0, vval, max), |
340 | 'ctrl-up' : (vadj, -vpincr, 0, vval, max), | 340 | 'ctrl-up' : (vadj, -vpincr, 0, vval, max), |
341 | 'down' : (vadj, vsincr, vupper - vpsize, vval, min), | 341 | 'down' : (vadj, vsincr, vupper - vpsize, vval, min), |
@@ -344,78 +344,78 @@ class GraphWindow(gtk.ScrolledWindow): | |||
344 | 'ctrl-left' : (hadj, -hpincr, 0, hval, max), | 344 | 'ctrl-left' : (hadj, -hpincr, 0, hval, max), |
345 | 'right' : (hadj, hsincr, hupper - hpsize, hval, min), | 345 | 'right' : (hadj, hsincr, hupper - hpsize, hval, min), |
346 | 'ctrl-right' : (hadj, hpincr, hupper - hpsize, hval, min)} | 346 | 'ctrl-right' : (hadj, hpincr, hupper - hpsize, hval, min)} |
347 | 347 | ||
348 | keystr = None | 348 | keystr = None |
349 | keymap = {gtk.keysyms.Up : 'up', gtk.keysyms.Down : 'down', | 349 | keymap = {gtk.keysyms.Up : 'up', gtk.keysyms.Down : 'down', |
350 | gtk.keysyms.Left : 'left', gtk.keysyms.Right : 'right'} | 350 | gtk.keysyms.Left : 'left', gtk.keysyms.Right : 'right'} |
351 | if key_event.keyval in keymap: | 351 | if key_event.keyval in keymap: |
352 | keystr = keymap[key_event.keyval] | 352 | keystr = keymap[key_event.keyval] |
353 | 353 | ||
354 | if ctrl_clicked: | 354 | if ctrl_clicked: |
355 | keystr = 'ctrl-' + keystr | 355 | keystr = 'ctrl-' + keystr |
356 | 356 | ||
357 | if keystr is not None: | 357 | if keystr is not None: |
358 | adj, inc, lim, val, extr = adj_tuple[keystr] | 358 | adj, inc, lim, val, extr = adj_tuple[keystr] |
359 | adj.set_value(extr(val + inc, lim)) | 359 | adj.set_value(extr(val + inc, lim)) |
360 | 360 | ||
361 | return True | 361 | return True |
362 | 362 | ||
363 | def get_graph_area(self): | 363 | def get_graph_area(self): |
364 | return self.garea | 364 | return self.garea |
365 | 365 | ||
366 | class MainWindow(gtk.Window): | 366 | class MainWindow(gtk.Window): |
367 | WINDOW_WIDTH_REQ = 500 | 367 | WINDOW_WIDTH_REQ = 500 |
368 | WINDOW_HEIGHT_REQ = 300 | 368 | WINDOW_HEIGHT_REQ = 300 |
369 | 369 | ||
370 | def __init__(self): | 370 | def __init__(self): |
371 | super(MainWindow, self).__init__(gtk.WINDOW_TOPLEVEL) | 371 | super(MainWindow, self).__init__(gtk.WINDOW_TOPLEVEL) |
372 | 372 | ||
373 | self.connect('delete_event', self.delete_event) | 373 | self.connect('delete_event', self.delete_event) |
374 | self.connect('destroy', self.die) | 374 | self.connect('destroy', self.die) |
375 | 375 | ||
376 | self.file_menu = gtk.Menu() | 376 | self.file_menu = gtk.Menu() |
377 | self.quit_item = gtk.MenuItem('_Quit', True) | 377 | self.quit_item = gtk.MenuItem('_Quit', True) |
378 | self.quit_item.connect('activate', self.quit_item_activate) | 378 | self.quit_item.connect('activate', self.quit_item_activate) |
379 | self.quit_item.show() | 379 | self.quit_item.show() |
380 | self.file_menu.append(self.quit_item) | 380 | self.file_menu.append(self.quit_item) |
381 | 381 | ||
382 | self.file_item = gtk.MenuItem('_File', True) | 382 | self.file_item = gtk.MenuItem('_File', True) |
383 | self.file_item.set_submenu(self.file_menu) | 383 | self.file_item.set_submenu(self.file_menu) |
384 | self.file_item.show() | 384 | self.file_item.show() |
385 | 385 | ||
386 | self.menu_bar = gtk.MenuBar() | 386 | self.menu_bar = gtk.MenuBar() |
387 | self.menu_bar.append(self.file_item) | 387 | self.menu_bar.append(self.file_item) |
388 | 388 | ||
389 | self.menu_bar.show() | 389 | self.menu_bar.show() |
390 | 390 | ||
391 | self.vbox = gtk.VBox(False, 0) | 391 | self.vbox = gtk.VBox(False, 0) |
392 | 392 | ||
393 | self.notebook = gtk.Notebook() | 393 | self.notebook = gtk.Notebook() |
394 | 394 | ||
395 | self.notebook.last_page = -1 | 395 | self.notebook.last_page = -1 |
396 | self.notebook.connect('switch-page', self.switch_page) | 396 | self.notebook.connect('switch-page', self.switch_page) |
397 | 397 | ||
398 | self.notebook.show() | 398 | self.notebook.show() |
399 | 399 | ||
400 | self.desc_label = gtk.Label('') | 400 | self.desc_label = gtk.Label('') |
401 | self.desc_label.set_justify(gtk.JUSTIFY_LEFT) | 401 | self.desc_label.set_justify(gtk.JUSTIFY_LEFT) |
402 | self.desc_label.show() | 402 | self.desc_label.show() |
403 | 403 | ||
404 | self.vbox.pack_start(self.menu_bar, False, False, 0) | 404 | self.vbox.pack_start(self.menu_bar, False, False, 0) |
405 | self.vbox.pack_start(self.notebook, True, True, 0) | 405 | self.vbox.pack_start(self.notebook, True, True, 0) |
406 | self.vbox.pack_start(self.desc_label, False, False, 0) | 406 | self.vbox.pack_start(self.desc_label, False, False, 0) |
407 | self.vbox.show() | 407 | self.vbox.show() |
408 | 408 | ||
409 | self.add(self.vbox) | 409 | self.add(self.vbox) |
410 | 410 | ||
411 | self.set_size_request(MainWindow.WINDOW_WIDTH_REQ, MainWindow.WINDOW_HEIGHT_REQ) | 411 | self.set_size_request(MainWindow.WINDOW_WIDTH_REQ, MainWindow.WINDOW_HEIGHT_REQ) |
412 | 412 | ||
413 | self.show() | 413 | self.show() |
414 | 414 | ||
415 | def connect_widgets(self, garea): | 415 | def connect_widgets(self, garea): |
416 | garea.connect('update-event-description', self.update_event_description) | 416 | garea.connect('update-event-description', self.update_event_description) |
417 | garea.connect('request-context-menu', self.request_context_menu) | 417 | garea.connect('request-context-menu', self.request_context_menu) |
418 | 418 | ||
419 | def set_renderers(self, renderers): | 419 | def set_renderers(self, renderers): |
420 | for i in range(0, self.notebook.get_n_pages()): | 420 | for i in range(0, self.notebook.get_n_pages()): |
421 | self.notebook.remove_page(0) | 421 | self.notebook.remove_page(0) |
@@ -424,7 +424,7 @@ class MainWindow(gtk.Window): | |||
424 | self.connect_widgets(gwindow.get_graph_area()) | 424 | self.connect_widgets(gwindow.get_graph_area()) |
425 | gwindow.show() | 425 | gwindow.show() |
426 | self.notebook.append_page(gwindow, gtk.Label(title)) | 426 | self.notebook.append_page(gwindow, gtk.Label(title)) |
427 | 427 | ||
428 | def switch_page(self, widget, page, page_num): | 428 | def switch_page(self, widget, page, page_num): |
429 | if self.notebook.get_nth_page(self.notebook.last_page) is not None: | 429 | if self.notebook.get_nth_page(self.notebook.last_page) is not None: |
430 | old_value = self.notebook.get_nth_page(self.notebook.last_page).get_hadjustment().get_value() | 430 | old_value = self.notebook.get_nth_page(self.notebook.last_page).get_hadjustment().get_value() |
@@ -432,27 +432,27 @@ class MainWindow(gtk.Window): | |||
432 | new_ofs = self.notebook.get_nth_page(page_num).get_graph_area().get_graph().get_origin()[0] | 432 | new_ofs = self.notebook.get_nth_page(page_num).get_graph_area().get_graph().get_origin()[0] |
433 | new_value = old_value - old_ofs + new_ofs | 433 | new_value = old_value - old_ofs + new_ofs |
434 | self.notebook.get_nth_page(page_num).get_hadjustment().set_value(new_value) | 434 | self.notebook.get_nth_page(page_num).get_hadjustment().set_value(new_value) |
435 | 435 | ||
436 | self.notebook.last_page = page_num | 436 | self.notebook.last_page = page_num |
437 | 437 | ||
438 | def update_event_description(self, widget, event, msg): | 438 | def update_event_description(self, widget, event, msg): |
439 | self.desc_label.set_text(msg) | 439 | self.desc_label.set_text(msg) |
440 | 440 | ||
441 | def request_context_menu(self, widget, gdk_event, selected): | 441 | def request_context_menu(self, widget, gdk_event, selected): |
442 | button = 0 | 442 | button = 0 |
443 | if hasattr(gdk_event, 'button'): | 443 | if hasattr(gdk_event, 'button'): |
444 | button = gdk_event.button | 444 | button = gdk_event.button |
445 | time = gdk_event.time | 445 | time = gdk_event.time |
446 | 446 | ||
447 | menu = GraphContextMenu(selected) | 447 | menu = GraphContextMenu(selected) |
448 | menu.popup(None, None, None, button, time) | 448 | menu.popup(None, None, None, button, time) |
449 | 449 | ||
450 | def quit_item_activate(self, widget): | 450 | def quit_item_activate(self, widget): |
451 | self.destroy() | 451 | self.destroy() |
452 | 452 | ||
453 | def delete_event(self, widget, event, data=None): | 453 | def delete_event(self, widget, event, data=None): |
454 | return False | 454 | return False |
455 | 455 | ||
456 | def die(self, widget, data=None): | 456 | def die(self, widget, data=None): |
457 | gtk.main_quit() | 457 | gtk.main_quit() |
458 | 458 | ||
diff --git a/unit_trace/viz/visualizer.py b/unit_trace/viz/visualizer.py index d739736..63594bd 100755 --- a/unit_trace/viz/visualizer.py +++ b/unit_trace/viz/visualizer.py | |||
@@ -13,13 +13,13 @@ TIME_PER_MAJ = 10000000 | |||
13 | def visualizer(stream): | 13 | def visualizer(stream): |
14 | sched = convert.convert_trace_to_schedule(stream) | 14 | sched = convert.convert_trace_to_schedule(stream) |
15 | sched.scan(TIME_PER_MAJ) | 15 | sched.scan(TIME_PER_MAJ) |
16 | 16 | ||
17 | task_renderer = renderer.Renderer(sched) | 17 | task_renderer = renderer.Renderer(sched) |
18 | task_renderer.prepare_task_graph(attrs=format.GraphFormat(time_per_maj=TIME_PER_MAJ)) | 18 | task_renderer.prepare_task_graph(attrs=format.GraphFormat(time_per_maj=TIME_PER_MAJ)) |
19 | cpu_renderer = renderer.Renderer(sched) | 19 | cpu_renderer = renderer.Renderer(sched) |
20 | cpu_renderer.prepare_cpu_graph(attrs=format.GraphFormat(time_per_maj=TIME_PER_MAJ)) | 20 | cpu_renderer.prepare_cpu_graph(attrs=format.GraphFormat(time_per_maj=TIME_PER_MAJ)) |
21 | 21 | ||
22 | window = viewer.MainWindow() | 22 | window = viewer.MainWindow() |
23 | window.set_renderers({'Tasks' : task_renderer, 'CPUs' : cpu_renderer}) | 23 | window.set_renderers({'Tasks' : task_renderer, 'CPUs' : cpu_renderer}) |
24 | 24 | ||
25 | gtk.main() | 25 | gtk.main() |