updating_scroll_(false),
sticky_scrolling_(false), // Default setting is set in MainWindow::setup_ui()
always_zoom_to_fit_(false),
- tick_period_(0.0),
+ tick_period_(0),
tick_prefix_(pv::util::SIPrefix::yocto),
tick_precision_(0),
time_unit_(util::TimeUnit::Time),
}
}
-double View::tick_period() const
+const pv::util::Timestamp& View::tick_period() const
{
return tick_period_;
}
-void View::set_tick_period(double tick_period)
+void View::set_tick_period(const pv::util::Timestamp& tick_period)
{
if (tick_period_ != tick_period) {
tick_period_ = tick_period;
const double min_period = scale_ * min_width;
const int order = (int)floorf(log10f(min_period));
- const double order_decimal = pow(10.0, order);
+ const pv::util::Timestamp order_decimal =
+ pow(pv::util::Timestamp(10), order);
// Allow for a margin of error so that a scale unit of 1 can be used.
// Otherwise, for a SU of 1 the tick period will almost always be below
unsigned int unit = 0;
do {
- tp_with_margin = order_decimal * (ScaleUnits[unit++] + tp_margin);
+ tp_with_margin = order_decimal.convert_to<double>() *
+ (ScaleUnits[unit++] + tp_margin);
} while (tp_with_margin < min_period && unit < countof(ScaleUnits));
set_tick_period(order_decimal * ScaleUnits[unit - 1]);
// Precision is the number of fractional digits required, not
// taking the prefix into account (and it must never be negative)
- set_tick_precision(std::max((int)ceil(log10f(1 / tick_period_)), 0));
+ set_tick_precision(std::max(
+ ceil(log10(1 / tick_period_)).convert_to<int>(), 0));
- tick_period_width = tick_period_ / scale_;
+ tick_period_width = (tick_period_ / scale_).convert_to<double>();
const QString label_text =
format_time(max_time, tick_prefix_, time_unit_, tick_precision_);
MinValueSpacing;
min_width += SpacingIncrement;
-
} while (tick_period_width < label_width);
}
get_scroll_layout(length, offset);
length = max(length - areaSize.width(), 0.0);
- int major_tick_distance = tick_period_ / scale_;
+ int major_tick_distance = (tick_period_ / scale_).convert_to<int>();
horizontalScrollBar()->setPageStep(areaSize.width() / 2);
horizontalScrollBar()->setSingleStep(major_tick_distance);
--- /dev/null
+/*
+ * This file is part of the PulseView project.
+ *
+ * Copyright (C) 2015 Jens Steinhauser <jens.steinhauser@gmail.com>
+ *
+ * This program 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <boost/test/unit_test.hpp>
+#include <boost/test/floating_point_comparison.hpp>
+
+#include "pv/view/ruler.hpp"
+#include "test/test.hpp"
+
+using namespace pv::view;
+
+namespace {
+ QString format(const pv::util::Timestamp& t)
+ {
+ return pv::util::format_si_value(t, "s", pv::util::SIPrefix::none, 6);
+ }
+
+ const double e = 0.0001;
+};
+
+BOOST_AUTO_TEST_SUITE(RulerTest)
+
+BOOST_AUTO_TEST_CASE(tick_position_test_0)
+{
+ const pv::util::Timestamp major_period("0.1");
+ const pv::util::Timestamp offset("0");
+ const double scale(0.001);
+ const int width(500);
+
+ const Ruler::TickPositions ts = Ruler::calculate_tick_positions(
+ major_period, offset, scale, width, format);
+
+ BOOST_REQUIRE_EQUAL(ts.major.size(), 6);
+
+ BOOST_CHECK_CLOSE(ts.major[0].first, 0, e);
+ BOOST_CHECK_CLOSE(ts.major[1].first, 100, e);
+ BOOST_CHECK_CLOSE(ts.major[2].first, 200, e);
+ BOOST_CHECK_CLOSE(ts.major[3].first, 300, e);
+ BOOST_CHECK_CLOSE(ts.major[4].first, 400, e);
+ BOOST_CHECK_CLOSE(ts.major[5].first, 500, e);
+
+ BOOST_CHECK_EQUAL(ts.major[0].second, "0.000000 s");
+ BOOST_CHECK_EQUAL(ts.major[1].second, "+0.100000 s");
+ BOOST_CHECK_EQUAL(ts.major[2].second, "+0.200000 s");
+ BOOST_CHECK_EQUAL(ts.major[3].second, "+0.300000 s");
+ BOOST_CHECK_EQUAL(ts.major[4].second, "+0.400000 s");
+ BOOST_CHECK_EQUAL(ts.major[5].second, "+0.500000 s");
+
+ BOOST_REQUIRE_EQUAL(ts.minor.size(), 16);
+
+ BOOST_CHECK_CLOSE(ts.minor[ 0], -25, e);
+ BOOST_CHECK_CLOSE(ts.minor[ 1], 25, e);
+ BOOST_CHECK_CLOSE(ts.minor[ 2], 50, e);
+ BOOST_CHECK_CLOSE(ts.minor[ 3], 75, e);
+ BOOST_CHECK_CLOSE(ts.minor[ 4], 125, e);
+ BOOST_CHECK_CLOSE(ts.minor[ 5], 150, e);
+ BOOST_CHECK_CLOSE(ts.minor[ 6], 175, e);
+ BOOST_CHECK_CLOSE(ts.minor[ 7], 225, e);
+ BOOST_CHECK_CLOSE(ts.minor[ 8], 250, e);
+ BOOST_CHECK_CLOSE(ts.minor[ 9], 275, e);
+ BOOST_CHECK_CLOSE(ts.minor[10], 325, e);
+ BOOST_CHECK_CLOSE(ts.minor[11], 350, e);
+ BOOST_CHECK_CLOSE(ts.minor[12], 375, e);
+ BOOST_CHECK_CLOSE(ts.minor[13], 425, e);
+ BOOST_CHECK_CLOSE(ts.minor[14], 450, e);
+ BOOST_CHECK_CLOSE(ts.minor[15], 475, e);
+}
+
+BOOST_AUTO_TEST_CASE(tick_position_test_1)
+{
+ const pv::util::Timestamp major_period("0.1");
+ const pv::util::Timestamp offset("-0.463");
+ const double scale(0.001);
+ const int width(500);
+
+ const Ruler::TickPositions ts = Ruler::calculate_tick_positions(
+ major_period, offset, scale, width, format);
+
+ BOOST_REQUIRE_EQUAL(ts.major.size(), 5);
+
+ BOOST_CHECK_CLOSE(ts.major[0].first, 63, e);
+ BOOST_CHECK_CLOSE(ts.major[1].first, 163, e);
+ BOOST_CHECK_CLOSE(ts.major[2].first, 263, e);
+ BOOST_CHECK_CLOSE(ts.major[3].first, 363, e);
+ BOOST_CHECK_CLOSE(ts.major[4].first, 463, e);
+
+ BOOST_CHECK_EQUAL(ts.major[0].second, "-0.400000 s");
+ BOOST_CHECK_EQUAL(ts.major[1].second, "-0.300000 s");
+ BOOST_CHECK_EQUAL(ts.major[2].second, "-0.200000 s");
+ BOOST_CHECK_EQUAL(ts.major[3].second, "-0.100000 s");
+ BOOST_CHECK_EQUAL(ts.major[4].second, "0.000000 s");
+
+ BOOST_REQUIRE_EQUAL(ts.minor.size(), 17);
+ BOOST_CHECK_CLOSE(ts.minor[ 0], -12, e);
+ BOOST_CHECK_CLOSE(ts.minor[ 1], 13, e);
+ BOOST_CHECK_CLOSE(ts.minor[ 2], 38, e);
+ BOOST_CHECK_CLOSE(ts.minor[ 3], 88, e);
+ BOOST_CHECK_CLOSE(ts.minor[ 4], 113, e);
+ BOOST_CHECK_CLOSE(ts.minor[ 5], 138, e);
+ BOOST_CHECK_CLOSE(ts.minor[ 6], 188, e);
+ BOOST_CHECK_CLOSE(ts.minor[ 7], 213, e);
+ BOOST_CHECK_CLOSE(ts.minor[ 8], 238, e);
+ BOOST_CHECK_CLOSE(ts.minor[ 9], 288, e);
+ BOOST_CHECK_CLOSE(ts.minor[10], 313, e);
+ BOOST_CHECK_CLOSE(ts.minor[11], 338, e);
+ BOOST_CHECK_CLOSE(ts.minor[12], 388, e);
+ BOOST_CHECK_CLOSE(ts.minor[13], 413, e);
+ BOOST_CHECK_CLOSE(ts.minor[14], 438, e);
+ BOOST_CHECK_CLOSE(ts.minor[15], 488, e);
+ BOOST_CHECK_CLOSE(ts.minor[16], 513, e);
+}
+
+BOOST_AUTO_TEST_CASE(tick_position_test_2)
+{
+ const pv::util::Timestamp major_period("20");
+ const pv::util::Timestamp offset("8");
+ const double scale(0.129746);
+ const int width(580);
+
+ const Ruler::TickPositions ts = Ruler::calculate_tick_positions(
+ major_period, offset, scale, width, format);
+
+ const double mp = 5;
+ const int off = 8;
+
+ BOOST_REQUIRE_EQUAL(ts.major.size(), 4);
+
+ BOOST_CHECK_CLOSE(ts.major[0].first, ( 4 * mp - off) / scale, e);
+ BOOST_CHECK_CLOSE(ts.major[1].first, ( 8 * mp - off) / scale, e);
+ BOOST_CHECK_CLOSE(ts.major[2].first, (12 * mp - off) / scale, e);
+ BOOST_CHECK_CLOSE(ts.major[3].first, (16 * mp - off) / scale, e);
+
+ BOOST_CHECK_EQUAL(ts.major[0].second, "+20.000000 s");
+ BOOST_CHECK_EQUAL(ts.major[1].second, "+40.000000 s");
+ BOOST_CHECK_EQUAL(ts.major[2].second, "+60.000000 s");
+ BOOST_CHECK_EQUAL(ts.major[3].second, "+80.000000 s");
+
+ BOOST_REQUIRE_EQUAL(ts.minor.size(), 13);
+
+ BOOST_CHECK_CLOSE(ts.minor[ 0], ( 1 * mp - off) / scale, e);
+ BOOST_CHECK_CLOSE(ts.minor[ 1], ( 2 * mp - off) / scale, e);
+ BOOST_CHECK_CLOSE(ts.minor[ 2], ( 3 * mp - off) / scale, e);
+ BOOST_CHECK_CLOSE(ts.minor[ 3], ( 5 * mp - off) / scale, e);
+ BOOST_CHECK_CLOSE(ts.minor[ 4], ( 6 * mp - off) / scale, e);
+ BOOST_CHECK_CLOSE(ts.minor[ 5], ( 7 * mp - off) / scale, e);
+ BOOST_CHECK_CLOSE(ts.minor[ 6], ( 9 * mp - off) / scale, e);
+ BOOST_CHECK_CLOSE(ts.minor[ 7], (10 * mp - off) / scale, e);
+ BOOST_CHECK_CLOSE(ts.minor[ 8], (11 * mp - off) / scale, e);
+ BOOST_CHECK_CLOSE(ts.minor[ 9], (13 * mp - off) / scale, e);
+ BOOST_CHECK_CLOSE(ts.minor[10], (14 * mp - off) / scale, e);
+ BOOST_CHECK_CLOSE(ts.minor[11], (15 * mp - off) / scale, e);
+ BOOST_CHECK_CLOSE(ts.minor[12], (17 * mp - off) / scale, e);
+}
+
+BOOST_AUTO_TEST_SUITE_END()