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() |
