Package Gnumed :: Package timelinelib :: Package canvas :: Package data :: Module timeperiod
[frames] | no frames]

Source Code for Module Gnumed.timelinelib.canvas.data.timeperiod

  1  # Copyright (C) 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018  Rickard Lindberg, Roger Lindberg 
  2  # 
  3  # This file is part of Timeline. 
  4  # 
  5  # Timeline is free software: you can redistribute it and/or modify 
  6  # it under the terms of the GNU General Public License as published by 
  7  # the Free Software Foundation, either version 3 of the License, or 
  8  # (at your option) any later version. 
  9  # 
 10  # Timeline is distributed in the hope that it will be useful, 
 11  # but WITHOUT ANY WARRANTY; without even the implied warranty of 
 12  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 13  # GNU General Public License for more details. 
 14  # 
 15  # You should have received a copy of the GNU General Public License 
 16  # along with Timeline.  If not, see <http://www.gnu.org/licenses/>. 
 17  from timelinelib.calendar.gregorian.gregorian import GregorianDateTime 
 18  from timelinelib.calendar.gregorian.time import GregorianTime 
19 20 21 -class TimePeriod(object):
22 23 """ 24 Represents a period in time using a start and end time. 25 26 This is used both to store the time period for an event and for storing the 27 currently displayed time period in the GUI. 28 """ 29
30 - def __init__(self, start_time, end_time):
31 self._start_time, self._end_time = self._update(start_time, end_time)
32 33 @property
34 - def start_time(self):
35 return self._start_time
36 37 @property
38 - def end_time(self):
39 return self._end_time
40 41 @property
42 - def start_and_end_time(self):
43 return self._start_time, self._end_time
44
45 - def __eq__(self, other):
46 return (isinstance(other, TimePeriod) and 47 self.start_time == other.start_time and 48 self.end_time == other.end_time)
49
50 - def __ne__(self, other):
51 return not (self == other)
52
53 - def __repr__(self):
54 return "TimePeriod<%s, %s>" % (self.start_time, self.end_time)
55
56 - def get_time_at_percent(self, percent):
57 return self.start_time + self.delta() * percent
58
59 - def get_start_time(self):
60 return self.start_time
61
62 - def get_end_time(self):
63 return self.end_time
64
65 - def set_start_time(self, time):
66 return self.update(time, self.end_time)
67
68 - def set_end_time(self, time):
69 return self.update(self.start_time, time)
70
71 - def start_to_start(self, time_period):
73
74 - def start_to_end(self, time_period):
76
77 - def end_to_start(self, time_period):
79
80 - def end_to_end(self, time_period):
82
83 - def update(self, start_time, end_time, 84 start_delta=None, end_delta=None):
85 new_start, new_end = self._update(start_time, end_time, start_delta, end_delta) 86 return TimePeriod(new_start, new_end)
87
88 - def _update(self, start_time, end_time, start_delta=None, end_delta=None):
89 """ 90 Change the time period data. 91 92 Optionally add the deltas to the times like this: time + delta. 93 94 If data is invalid, it will not be set, and a ValueError will be raised 95 instead. Data is invalid if or if the start time is larger than the end 96 time. 97 """ 98 new_start = self._calc_new_time(start_time, start_delta) 99 new_end = self._calc_new_time(end_time, end_delta) 100 self._assert_period_is_valid(new_start, new_end) 101 return (new_start, new_end)
102
103 - def _assert_period_is_valid(self, new_start, new_end):
104 if new_start is None: 105 raise ValueError(_("Invalid start time")) 106 if new_end is None: 107 raise ValueError(_("Invalid end time")) 108 if new_start > new_end: 109 raise ValueError(_("Start time can't be after end time. Start:%s End:%s" % 110 (new_start.to_str(), new_end.to_str())))
111
112 - def inside(self, time):
113 """ 114 Return True if the given time is inside this period or on the border, 115 otherwise False. 116 """ 117 return time >= self.start_time and time <= self.end_time
118
119 - def distance_to(self, time_period):
120 if time_period.starts_after(self.end_time): 121 return self.end_to_start(time_period).delta() 122 elif time_period.ends_before(self.start_time): 123 return time_period.end_to_start(self).delta() 124 else: 125 return None
126
127 - def overlaps(self, time_period):
130
131 - def outside_period(self, time_period):
134
135 - def inside_period(self, time_period):
136 return not self.outside_period(time_period)
137
138 - def starts_after(self, time):
139 return self.start_time > time
140
141 - def starts_before(self, time):
142 return self.start_time < time
143
144 - def ends_before(self, time):
145 return self.end_time < time
146
147 - def ends_after(self, time):
148 return self.end_time > time
149
150 - def ends_at(self, time):
151 return self.end_time == time
152
153 - def is_period(self):
154 """ 155 Return True if this time period is longer than just a point in time, 156 otherwise False. 157 """ 158 return self.start_time != self.end_time
159
160 - def mean_time(self):
161 """ 162 Return the time in the middle if this time period is longer than just a 163 point in time, otherwise the point in time for this time period. 164 """ 165 return self.start_time + (self.delta() / 2)
166
167 - def zoom(self, times, ratio=0.5):
168 start_delta = self.delta() * (times * ratio / 5.0) 169 end_delta = self.delta() * (-times * (1.0 - ratio) / 5.0) 170 return self.update(self.start_time, self.end_time, start_delta, end_delta)
171
172 - def move(self, direction):
173 """ 174 Move this time period one 10th to the given direction. 175 176 Direction should be -1 for moving to the left or 1 for moving to the 177 right. 178 """ 179 delta = self.delta() * (direction / 10.0) 180 return self.move_delta(delta)
181
182 - def move_delta(self, delta):
183 return self.update(self.start_time, self.end_time, delta, delta)
184
185 - def delta(self):
186 """Return the length of this time period as a timedelta object.""" 187 return self.end_time - self.start_time
188
189 - def center(self, time):
190 return self.move_delta(time - self.mean_time())
191
192 - def _calc_new_time(self, time, delta):
193 if delta is None: 194 return time 195 return time + delta
196
197 198 -class TimeOutOfRangeLeftError(ValueError):
199 pass
200
201 202 -class TimeOutOfRangeRightError(ValueError):
203 pass
204
205 206 -def time_period_center(time, length):
207 """ 208 TimePeriod factory method. 209 210 Return a time period with the given length (represented as a timedelta) 211 centered around `time`. 212 """ 213 half_length = length * 0.5 214 start_time = time - half_length 215 end_time = time + half_length 216 return TimePeriod(start_time, end_time)
217