# Copyright (C) 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 Rickard Lindberg, Roger Lindberg
#
# This file is part of Timeline.
#
# Timeline is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Timeline is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Timeline. If not, see <http://www.gnu.org/licenses/>.
"""Contains the class NumTimeType."""
import math
import re
from timelinelib.calendar.num.time import NumDelta
from timelinelib.calendar.num.time import NumTime
from timelinelib.calendar.timetype import TimeType
from timelinelib.canvas.data import TimePeriod
from timelinelib.canvas.data import time_period_center
from timelinelib.calendar.num.timetype.strips.numstrip import NumStrip
from timelinelib.wxgui.dialogs.timeeditor.view import open_time_editor_dialog
[docs]class NumTimeType(TimeType):
"""The class."""
DURATION_TYPE_1 = _('Divide by 1')
DURATION_TYPE_2 = _('Divide by 10')
DURATION_TYPE_3 = _('Divide by 100')
DURATION_TYPE_4 = _('Divide by 1000')
DURATION_TYPE_5 = _('Divide by 10000')
[docs] def __eq__(self, other):
return isinstance(other, NumTimeType)
[docs] def __ne__(self, other):
return not (self == other)
[docs] def time_string(self, time):
return "%s" % time.value
[docs] def parse_time(self, time_string):
match = re.search(r"^([-]?\d+(.\d+)?(e[+]\d+)?)$", time_string)
if match:
if '.' in time_string or 'e' in time_string:
time = float(match.group(1))
else:
time = int(match.group(1))
try:
return NumTime(time)
except ValueError:
raise ValueError("Invalid time, time string = '%s'" % time_string)
else:
raise ValueError("Time not on correct format = '%s'" % time_string)
[docs] def get_navigation_functions(self):
return [
(_("Go to &Zero") + "\tCtrl+Z", go_to_zero_fn),
(_("Go to &Time") + "\tCtrl+T", go_to_time_fn),
("SEP", None),
(_("Backward") + "\tPgUp", backward_fn),
(_("Forward") + "\tPgDn", forward_fn),
]
[docs] def get_min_time(self):
return None
[docs] def get_max_time(self):
return None
[docs] def choose_strip(self, metrics, appearance):
# Choose an exponent that will make the minor strip just larger than
# the displayed period:
#
# 10**x > period_delta =>
# x > log(period_delta)
exponent = int(math.log(metrics.time_period.delta().value, 10)) + 1
# Keep decreasing the exponent until the minor strip is small enough.
while True:
if exponent == 0:
break
next_minor_strip_with_px = metrics.calc_exact_width(
TimePeriod(
NumTime(0),
NumTime(10 ** (exponent - 1))
)
)
if next_minor_strip_with_px > 30:
exponent -= 1
else:
break
return NumStrip(10 ** (exponent + 1)), NumStrip(10 ** exponent)
[docs] def get_default_time_period(self):
return time_period_center(NumTime(0), NumDelta(100))
[docs] def now(self):
return NumTime(0)
[docs] def get_min_zoom_delta(self):
return NumDelta(5), _("Can't zoom deeper than 5")
[docs] def get_name(self):
return "numtime"
[docs] def get_duplicate_functions(self):
return [
(_("1-period"), lambda p, d: move_period(p, d)),
(_("10-period"), lambda p, d: move_period(p, d * 10)),
(_("100-period"), lambda p, d: move_period(p, d * 100)),
(_("1000-period"), lambda p, d: move_period(p, d * 1000)),
]
[docs] def get_duration_types(self):
return [
self.DURATION_TYPE_1,
self.DURATION_TYPE_2,
self.DURATION_TYPE_3,
self.DURATION_TYPE_4,
self.DURATION_TYPE_5]
[docs] def get_duration_divisor(self, duration_type, weekday_length):
return {
self.DURATION_TYPE_1: 1,
self.DURATION_TYPE_2: 10,
self.DURATION_TYPE_3: 100,
self.DURATION_TYPE_4: 1000,
self.DURATION_TYPE_5: 10000,
}[duration_type]
[docs] def supports_saved_now(self):
return False
[docs] @staticmethod
def create_time_picker(parent, *args, **kwargs):
from timelinelib.calendar.num.timepicker import NumTimePicker
return NumTimePicker(parent, *args, **kwargs)
[docs] @staticmethod
def create_period_picker(parent, *args, **kwargs):
from timelinelib.calendar.num.periodpicker import NumPeriodPicker
return NumPeriodPicker(parent, *args, **kwargs)
[docs]def go_to_zero_fn(main_frame, current_period, navigation_fn):
navigation_fn(lambda tp: tp.center(NumTime(0)))
[docs]def go_to_time_fn(main_frame, current_period, navigation_fn):
def navigate_to(time):
navigation_fn(lambda tp: tp.center(time))
open_time_editor_dialog(main_frame, NumTimeType(), current_period.mean_time(), navigate_to, _("Go to Time"))
[docs]def backward_fn(main_frame, current_period, navigation_fn):
delta = current_period.start_time - current_period.end_time
navigation_fn(lambda tp: tp.move_delta(delta))
[docs]def forward_fn(main_frame, current_period, navigation_fn):
delta = current_period.end_time - current_period.start_time
navigation_fn(lambda tp: tp.move_delta(delta))
[docs]def move_period(period, num):
delta = NumDelta(num)
start_time = period.start_time + delta
end_time = period.end_time + delta
return TimePeriod(start_time, end_time)