Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Axis refactor v2 - Do not interpolate hiding/showing legend #590

Merged
merged 3 commits into from
Nov 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,22 @@

## [Unreleased]

### Fixed

- Do not interpolate hiding/showing legend

## [0.15.0] - 2024-10-28

### Fixed

- Removed 'min' align property from the API which equivalent with the 'none'.
- Markers are the same even if new record added.
- Flying out marker label fixed.
- Axis line hide/show at same time with axis labels/ticks/title.
- Do not draw invisible axis line.

### Changed

- Removed 'min' align property from the API which equivalent with the 'none'.
- Changed MarkerId to be a string instead of a number.

### Added
Expand Down
11 changes: 7 additions & 4 deletions src/base/refl/auto_enum.h
Original file line number Diff line number Diff line change
Expand Up @@ -196,28 +196,31 @@ template <class E> constexpr E get_enum(const std::string_view &data)
template <class E, class V>
struct EnumArray : std::array<V, std::size(enum_names<E>)>
{
constexpr static auto first = Detail::from_to<E>().first;
using base_array = std::array<V, std::size(enum_names<E>)>;
[[nodiscard]] constexpr V &operator[](E value) noexcept
{
return base_array::operator[](
static_cast<std::size_t>(value));
static_cast<std::size_t>(value) - first);
}

[[nodiscard]] constexpr const V &operator[](
E value) const noexcept
{
return base_array::operator[](
static_cast<std::size_t>(value));
static_cast<std::size_t>(value) - first);
}

[[nodiscard]] constexpr V &at(E value)
{
return base_array::at(static_cast<std::size_t>(value));
return base_array::at(
static_cast<std::size_t>(value) - first);
}

[[nodiscard]] constexpr const V &at(E value) const
{
return base_array::at(static_cast<std::size_t>(value));
return base_array::at(
static_cast<std::size_t>(value) - first);
}

bool operator==(const EnumArray &) const = default;
Expand Down
13 changes: 8 additions & 5 deletions src/base/refl/auto_struct.h
Original file line number Diff line number Diff line change
Expand Up @@ -593,6 +593,13 @@ template <class T, class Visitor> struct Applier
[[maybe_unused]] Visitor &v) noexcept
{
if constexpr (!std::is_empty_v<U>) {
constexpr auto members =
Members::get_member_functors<U>(nullptr);

static_assert(
std::tuple_size_v<bases_t<U>> > 0
|| std::tuple_size_v<decltype(members)> > 0,
"Unable to run reflection");
if constexpr (std::tuple_size_v<bases_t<U>> > 0) {
std::invoke(
[&v]<class... Bases>(std::tuple<Bases...> *)
Expand All @@ -604,11 +611,7 @@ template <class T, class Visitor> struct Applier
},
std::add_pointer_t<bases_t<U>>{});
}

if constexpr (constexpr auto members =
Members::get_member_functors<U>(
nullptr);
std::tuple_size_v<decltype(members)> > 0) {
if constexpr (std::tuple_size_v<decltype(members)> > 0) {
std::apply(
[&v]<class... MF>(MF...)
{
Expand Down
22 changes: 6 additions & 16 deletions src/chart/animator/planner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -351,12 +351,10 @@ bool Planner::positionMorphNeeded() const

bool Planner::needColor() const
{
return (isAnyLegend(Gen::ChannelId::color)
&& source->axises.at(Gen::ChannelId::color)
!= target->axises.at(Gen::ChannelId::color))
|| (isAnyLegend(Gen::ChannelId::lightness)
&& source->axises.at(Gen::ChannelId::lightness)
!= target->axises.at(Gen::ChannelId::lightness))
return source->axises.at(Gen::ChannelId::color)
!= target->axises.at(Gen::ChannelId::color)
|| source->axises.at(Gen::ChannelId::lightness)
!= target->axises.at(Gen::ChannelId::lightness)
|| anyMarker(+[](const Gen::Marker &source,
const Gen::Marker &target) -> bool
{
Expand Down Expand Up @@ -406,9 +404,8 @@ bool Planner::needVertical() const
!= target->axises.at(Gen::AxisId::y)
|| source->guides.at(Gen::AxisId::y)
!= target->guides.at(Gen::AxisId::y)
|| (isAnyLegend(Gen::ChannelId::size)
&& source->axises.at(Gen::ChannelId::size)
!= target->axises.at(Gen::ChannelId::size))
|| source->axises.at(Gen::ChannelId::size)
!= target->axises.at(Gen::ChannelId::size)
|| (source->markerConnectionOrientation
!= target->markerConnectionOrientation
&& (source->markerConnectionOrientation.value_or(
Expand Down Expand Up @@ -461,13 +458,6 @@ bool Planner::needHorizontal() const
});
}

bool Planner::isAnyLegend(Gen::ChannelId type) const
{
const auto &src = source->getOptions()->legend.get();
const auto &trg = target->getOptions()->legend.get();
return (src && *src == type) || (trg && *trg == type);
}

void Planner::addMorph(SectionId sectionId,
::Anim::Duration duration,
::Anim::Duration delay,
Expand Down
2 changes: 0 additions & 2 deletions src/chart/animator/planner.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,6 @@ class Planner : public ::Anim::Group
static size_t dimensionCount(const Gen::Plot *plot,
Gen::AxisId type);

[[nodiscard]] bool isAnyLegend(Gen::ChannelId type) const;

::Anim::Options getOptions(SectionId sectionId,
::Anim::Duration duration,
::Anim::Duration delay = ::Anim::Duration(0),
Expand Down
53 changes: 36 additions & 17 deletions src/chart/generator/plotbuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -357,9 +357,12 @@ void PlotBuilder::normalizeXY()

void PlotBuilder::calcMeasureAxises(const Data::DataTable &dataTable)
{
for (const Channel &ch :
plot->getOptions()->getChannels().getChannels())
calcMeasureAxis(dataTable, ch.type);
for (const ChannelId &ch :
{ChannelId::x, ChannelId::y, ChannelId::label})
calcMeasureAxis(dataTable, ch);

if (auto &&legend = plot->options->legend.get())
calcMeasureAxis(dataTable, asChannel(*legend));
}

void PlotBuilder::calcMeasureAxis(const Data::DataTable &dataTable,
Expand Down Expand Up @@ -395,9 +398,11 @@ void PlotBuilder::calcMeasureAxis(const Data::DataTable &dataTable,

void PlotBuilder::calcDimensionAxises()
{
for (const Channel &ch :
plot->getOptions()->getChannels().getChannels())
calcDimensionAxis(ch.type);
for (const ChannelId &ch : {ChannelId::x, ChannelId::y})
calcDimensionAxis(ch);

if (auto &&legend = plot->options->legend.get())
calcDimensionAxis(asChannel(*legend));
}

void PlotBuilder::calcDimensionAxis(ChannelId type)
Expand Down Expand Up @@ -590,17 +595,31 @@ void PlotBuilder::normalizeColors()
cbase.setPos(color.rescale(cbase.getPos()));
}

plot->axises.at(ChannelId::color).measure.range = color;
plot->axises.at(ChannelId::lightness).measure.range = lightness;

for (auto &value : plot->axises.at(ChannelId::color).dimension)
value.second.colorBase =
ColorBase(static_cast<uint32_t>(value.second.value), 0.5);

for (auto &value :
plot->axises.at(ChannelId::lightness).dimension) {
value.second.value = lightness.rescale(value.second.value);
value.second.colorBase = ColorBase(0U, value.second.value);
if (auto &&legend = plot->options->legend.get()) {
switch (*legend) {
case Options::LegendId::color:
plot->axises.at(ChannelId::color).measure.range = color;

for (auto &value :
plot->axises.at(ChannelId::color).dimension)
value.second.colorBase = ColorBase(
static_cast<uint32_t>(value.second.value),
0.5);
break;
case Options::LegendId::lightness:
plot->axises.at(ChannelId::lightness).measure.range =
lightness;

for (auto &value :
plot->axises.at(ChannelId::lightness).dimension) {
value.second.value =
lightness.rescale(value.second.value);
value.second.colorBase =
ColorBase(0U, value.second.value);
}
break;
default:;
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/chart/main/events.h
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ class Events

struct LegendProperties
{
Gen::ChannelId channel;
Gen::Options::LegendId channel;
double scrollTop{};
double scrollHeight{};
};
Expand Down
17 changes: 3 additions & 14 deletions src/chart/options/options.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,6 @@ ChannelExtrema operator"" _perc(long double percent)
}
}

[[nodiscard]] bool operator==(const Options::LegendId &l,
const ChannelId &c)
{
return Options::toChannel(l) == c;
}

void Options::reset()
{
channels.reset();
Expand Down Expand Up @@ -283,14 +277,14 @@ std::optional<Options::LegendId> Options::getAutoLegend() const
series.erase(*id);

for (auto channelId : {LegendId::color, LegendId::lightness})
if (channels.at(toChannel(channelId))
if (channels.at(asChannel(channelId))
.dimensions()
.contains_any(series.begin(), series.end()))
return channelId;

for (auto channelId :
{LegendId::color, LegendId::lightness, LegendId::size})
if (auto &&mid = channels.at(toChannel(channelId)).measureId)
if (auto &&mid = channels.at(asChannel(channelId)).measureId)
if (series.contains(*mid)) return channelId;

return std::nullopt;
Expand Down Expand Up @@ -341,7 +335,7 @@ bool Options::labelsShownFor(const Data::SeriesIndex &series) const
return channels.at(AxisId::x).labelSeries() == series
|| channels.at(AxisId::y).labelSeries() == series
|| (legend.get()
&& channels.at(toChannel(*legend.get())).labelSeries()
&& channels.at(asChannel(*legend.get())).labelSeries()
== series);
}

Expand All @@ -365,9 +359,4 @@ void Options::showTooltip(std::optional<MarkerIndex> marker)
}
}

[[nodiscard]] ChannelId Options::toChannel(const LegendId &l)
{
return static_cast<ChannelId>(l);
}

}
16 changes: 12 additions & 4 deletions src/chart/options/options.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,6 @@ class Options
using Orientation = ::Anim::Interpolated<OrientationType>;
using MarkersInfoMap = std::map<MarkerInfoId, MarkerIndex>;

friend bool operator==(const LegendId &, const ChannelId &);

[[nodiscard]] static ChannelId toChannel(const LegendId &);

Options() = default;

[[nodiscard]] const Channels &getChannels() const
Expand Down Expand Up @@ -193,6 +189,18 @@ class Options
ChannelExtrema max);
};

[[nodiscard]] constexpr ChannelId asChannel(
const Options::LegendId &l)
{
return static_cast<ChannelId>(l);
}

[[nodiscard]] constexpr bool operator==(const Options::LegendId &l,
const ChannelId &c)
{
return asChannel(l) == c;
}

using PlotOptionsPtr = std::shared_ptr<Options>;

}
Expand Down
2 changes: 1 addition & 1 deletion src/chart/rendering/drawchart.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ void DrawChart::drawLegend(Gfx::ICanvas &canvas,
if (legend.value)
legendObj.draw(canvas,
bounds,
Gen::Options::toChannel(*legend.value),
*legend.value,
legend.weight);
});
}
Expand Down
13 changes: 7 additions & 6 deletions src/chart/rendering/drawlegend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
#include "base/text/smartstring.h"
#include "chart/generator/plot.h" // NOLINT(misc-include-cleaner)
#include "chart/main/events.h"
#include "chart/options/channel.h"
#include "chart/options/options.h"
#include "chart/rendering/colorbuilder.h"
#include "chart/rendering/drawbackground.h"
#include "chart/rendering/drawlabel.h"
Expand All @@ -31,7 +31,7 @@ namespace Vizzu::Draw

void DrawLegend::draw(Gfx::ICanvas &canvas,
const Geom::Rect &legendLayout,
Gen::ChannelId channelType,
Gen::Options::LegendId channelType,
double weight) const
{
auto markerWindowRect =
Expand All @@ -58,8 +58,9 @@ void DrawLegend::draw(Gfx::ICanvas &canvas,
.weight = weight,
.itemHeight = itemHeight,
.markerSize = markerSize,
.measure = plot->axises.at(channelType).measure,
.dimension = plot->axises.at(channelType).dimension,
.measure = plot->axises.at(asChannel(channelType)).measure,
.dimension =
plot->axises.at(asChannel(channelType)).dimension,
.properties = {.channel = channelType},
.fadeBarGradient = {markerWindowRect.leftSide(),
{.line = {},
Expand Down Expand Up @@ -120,7 +121,7 @@ const Gfx::LinearGradient &DrawLegend::FadeBarGradient::operator()(

void DrawLegend::drawTitle(const Info &info) const
{
plot->axises.at(info.properties.channel)
plot->axises.at(asChannel(info.properties.channel))
.title.visit(
[this,
&info,
Expand Down Expand Up @@ -286,7 +287,7 @@ void DrawLegend::drawMeasure(const Info &info) const

auto bar = getBarRect(info);

using ST = Gen::ChannelId;
using ST = Gen::Options::LegendId;
switch (info.properties.channel) {
case ST::color: colorBar(info, bar); break;
case ST::lightness: lightnessBar(info, bar); break;
Expand Down
2 changes: 1 addition & 1 deletion src/chart/rendering/drawlegend.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class DrawLegend : public DrawingContext
public:
void draw(Gfx::ICanvas &canvas,
const Geom::Rect &legendLayout,
Gen::ChannelId channelType,
Gen::Options::LegendId channelType,
double weight) const;

const Events::DrawEvents::Legend &events = rootEvents.draw.legend;
Expand Down
Loading
Loading