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

# Source Code for Module Gnumed.timelinelib.canvas.data.eras

      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
     18
     19  from timelinelib.canvas.data.timeperiod import TimePeriod
     20
     21
     22 -class Eras(object):
     23      """
     24      The list of all eras defined for a timeline.
     25
     26      Contains function for cloning of the whole list which is a
     27      necessary operation for undo/redo operations.
     28      """
     29
     30 -    def __init__(self, now_func, eras=None):
     31          self.now_func = now_func
     32          if eras is None:
     33              self._eras = []
     34          else:
     35              self._eras = eras
     36
     37 -    def get_all(self):
     38          return sorted(self._eras)
     39
     40 -    def get_all_periods(self):
     41
     42          def get_key(e):
     43              return e.get_time_period().start_time
     44
     45          def merge_colors(c1, c2):
     46              return ((c1[0] + c2[0]) / 2, (c1[1] + c2[1]) / 2, (c1[2] + c2[2]) / 2)
     47
     48          def create_overlapping_era(e0, e1, start, end):
     49              era = e1.duplicate()
     50              era.set_time_period(TimePeriod(start, end))
     51              era.set_color(merge_colors(e0.get_color(), e1.get_color()))
     52              era.set_name("%s + %s" % (e0.get_name(), e1.get_name()))
     53              return era
     54
     55          def get_start_and_end_times(e0, e1):
     56              e0start = e0.get_time_period().start_time
     57              e0end = e0.get_time_period().end_time
     58              e1start = e1.get_time_period().start_time
     59              e1end = e1.get_time_period().end_time
     60              return e0start, e0end, e1start, e1end
     61
     62          def return_era_for_overlapping_type_1(e0, e1):
     63              e0start, e0end, e1start, e1end = get_start_and_end_times(e0, e1)
     64              era = create_overlapping_era(e0, e1, e1start, e0end)
     65              e0.set_time_period(TimePeriod(e0start, e1start))
     66              e1.set_time_period(TimePeriod(e0end, e1end))
     67              return era
     68
     69          def return_era_for_overlapping_type_2(e0, e1):
     70              e0start, e0end, _, e1end = get_start_and_end_times(e0, e1)
     71              era = create_overlapping_era(e0, e1, e0start, e0end)
     72              self.all_eras.remove(e0)
     73              e1.set_time_period(TimePeriod(e0end, e1end))
     74              return era
     75
     76          def return_era_for_overlapping_type_3(e0, e1):
     77              return return_era_for_overlapping_type_2(e1, e0)
     78
     79          def return_era_for_overlapping_type_4(e0, e1):
     80              _, _, e1start, e1end = get_start_and_end_times(e0, e1)
     81              era = create_overlapping_era(e0, e1, e1start, e1end)
     82              self.all_eras.remove(e0)
     83              self.all_eras.remove(e1)
     84              return era
     85
     86          def return_era_for_overlapping_type_5(e0, e1):
     87              e0start, _, e1start, e1end = get_start_and_end_times(e0, e1)
     88              era = create_overlapping_era(e0, e1, e1start, e1end)
     89              e0.set_time_period(TimePeriod(e0start, e1start))
     90              self.all_eras.remove(e1)
     91              return era
     92
     93          def return_era_for_overlapping_type_6(e0, e1):
     94              e0start, e0end, e1start, e1end = get_start_and_end_times(e0, e1)
     95              era = create_overlapping_era(e0, e1, e1start, e1end)
     96              e0.set_time_period(TimePeriod(e0start, e1start))
     97              e1.set_time_period(TimePeriod(e1end, e0end))
     98              e1.set_name(e0.get_name())
     99              e1.set_color(e0.get_color())
    100              return era
    101
    102          def clone_all_eras():
    103              return [e.duplicate() for e in self.get_all()]
    104
    105          overlap_func = (None,
    106                          return_era_for_overlapping_type_1,
    107                          return_era_for_overlapping_type_2,
    108                          return_era_for_overlapping_type_3,
    109                          return_era_for_overlapping_type_4,
    110                          return_era_for_overlapping_type_5,
    111                          return_era_for_overlapping_type_6)
    112
    113          def create_overlapping_era_and_remove_hidden_eras():
    114              """
    115              self.all_eras is always sorted by Era start time.
    116              This method finds the first pair of Era's that overlaps.
    117              If such a pair is found, a overlapping Era is created and added
    118              to the the self.all_eras list. If any or both of the original
    119              Era's are hidden by the overlapping Era, they are removed from
    120              the self.all_eras list.
    121              When one overlapping pair has been found and processed the
    122              function returns False, after updating the self.all_eras list
    123              If no overlapping pairs of Era's are found the function retuns
    124              True.
    125              """
    126              e0 = self.all_eras[0]
    127              for e1 in self.all_eras[1:]:
    128                  strategy = e0.overlapping(e1)
    129                  if strategy > 0:
    130                      self.all_eras.append(overlap_func[strategy](e0, e1))
    131                      self.all_eras = sorted(self.all_eras, key=get_key)
    132                      return False
    133                  else:
    134                      e0 = e1
    135              return True
    136
    137          def adjust_all_eras_for_ends_today():
    138              for era in self.all_eras:
    139                  if era.ends_today():
    140                      era.set_time_period(TimePeriod(era.get_time_period().start_time, self.now_func()))
    141
    142          self.all_eras = clone_all_eras()
    143          adjust_all_eras_for_ends_today()
    144          if self.all_eras == []:
    145              return []
    146          while True:
    147              if len(self.all_eras) > 0:
    148                  done = create_overlapping_era_and_remove_hidden_eras()
    149              else:
    150                  done = True
    151              if done:
    152                  return self.all_eras
    153