|
//
|
|
// Created by mark on 6/6/25.
|
|
//
|
|
|
|
#include <ReportsAndCharts/WChartJSOptions.h>
|
|
#include <Wt/Json/Value.h>
|
|
|
|
// --- Nested Structs toJsonObject() Implementations ---
|
|
|
|
WChartJSOptions::WChartJSOptions(ChartJSType type) : chartType_(type), devicePixelRatio_(0) {}
|
|
|
|
|
|
Wt::Json::Object WChartJSOptions::LegendOptions::toJsonObject() const {
|
|
Wt::Json::Object obj;
|
|
if (display) {
|
|
obj["display"] = Wt::Json::Value(display);
|
|
obj["position"] = Wt::Json::Value(position);
|
|
if (reverse) {
|
|
obj["reverse"] = Wt::Json::Value(reverse);
|
|
}
|
|
}
|
|
return obj;
|
|
}
|
|
|
|
Wt::Json::Object WChartJSOptions::TitleOptions::toJsonObject() const {
|
|
Wt::Json::Object obj;
|
|
if (display) {
|
|
obj["display"] = Wt::Json::Value(display);
|
|
obj["text"] = Wt::Json::Value(text);
|
|
obj["position"] = Wt::Json::Value(position);
|
|
obj["font"] = Wt::Json::Object{{"size", Wt::Json::Value(fontSize)}};
|
|
}
|
|
return obj;
|
|
}
|
|
|
|
Wt::Json::Object WChartJSOptions::TooltipOptions::toJsonObject() const {
|
|
Wt::Json::Object obj;
|
|
if (enabled) {
|
|
obj["enabled"] = Wt::Json::Value(enabled);
|
|
obj["mode"] = Wt::Json::Value(mode);
|
|
obj["intersect"] = Wt::Json::Value(intersect);
|
|
if (reverse) { // <-- ADD THIS BLOCK
|
|
obj["reverse"] = Wt::Json::Value(reverse);
|
|
}
|
|
if (!freeFormOptions.empty()) { // <-- Add this block
|
|
obj.insert(freeFormOptions.begin(), freeFormOptions.end());
|
|
}
|
|
}
|
|
return obj;
|
|
}
|
|
|
|
Wt::Json::Object WChartJSOptions::ZoomAndPanOptions::toJsonObject() const {
|
|
Wt::Json::Object zoomAndPanObj;
|
|
if (enabled) {
|
|
Wt::Json::Object enabledTrue;
|
|
Wt::Json::Object zoomOptions;
|
|
Wt::Json::Object panOptions;
|
|
Wt::Json::Object zoomObj;
|
|
Wt::Json::Object panObj;
|
|
enabledTrue["enabled"] = Wt::Json::Value(true);
|
|
|
|
if (wheelEnabled)
|
|
zoomOptions["wheel"] = Wt::Json::Value(enabledTrue);
|
|
if (pinchEnabled)
|
|
zoomOptions["pinch"] = Wt::Json::Value(enabledTrue);
|
|
zoomOptions["mode"] = Wt::Json::Value(mode);
|
|
|
|
if (panEnabled)
|
|
panOptions["enabled"] = Wt::Json::Value(true);
|
|
|
|
panOptions["mode"] = Wt::Json::Value(mode);
|
|
|
|
zoomAndPanObj["pan"] = Wt::Json::Value(panOptions);
|
|
zoomAndPanObj["zoom"] = Wt::Json::Value(zoomOptions);
|
|
}
|
|
return zoomAndPanObj;
|
|
}
|
|
|
|
Wt::Json::Object WChartJSOptions::PluginOptions::toJsonObject() const {
|
|
Wt::Json::Object obj;
|
|
obj["legend"] = legend.toJsonObject();
|
|
obj["title"] = title.toJsonObject();
|
|
obj["tooltip"] = tooltip.toJsonObject();
|
|
obj["zoom"] = zoomAndPan.toJsonObject();
|
|
return obj;
|
|
}
|
|
|
|
Wt::Json::Object WChartJSOptions::TickOptions::toJsonObject() const {
|
|
Wt::Json::Object obj;
|
|
|
|
// Explicitly output the boolean, whether true or false
|
|
obj["display"] = Wt::Json::Value(display);
|
|
|
|
if (!color.empty()) {
|
|
obj["color"] = Wt::Json::Value(color);
|
|
}
|
|
if (autoSkip) {
|
|
obj["autoSkip"] = Wt::Json::Value(autoSkip);
|
|
}
|
|
// Free form options must always be evaluated, independent of the display flag
|
|
if (!freeFormOptions.empty()) {
|
|
obj.insert(freeFormOptions.begin(), freeFormOptions.end());
|
|
}
|
|
|
|
return obj;
|
|
}
|
|
|
|
Wt::Json::Object WChartJSOptions::ScaleTitleOptions::toJsonObject() const {
|
|
Wt::Json::Object obj;
|
|
if (display) {
|
|
obj["display"] = Wt::Json::Value(display);
|
|
obj["text"] = Wt::Json::Value(text);
|
|
}
|
|
return obj;
|
|
}
|
|
|
|
Wt::Json::Object WChartJSOptions::GridOptions::toJsonObject() const {
|
|
Wt::Json::Object obj;
|
|
|
|
// Explicitly output the boolean, whether true or false
|
|
obj["display"] = Wt::Json::Value(display);
|
|
|
|
if (!color.empty()) {
|
|
obj["color"] = Wt::Json::Value(color);
|
|
}
|
|
if (!freeFormOptions.empty()) {
|
|
obj.insert(freeFormOptions.begin(), freeFormOptions.end());
|
|
}
|
|
|
|
return obj;
|
|
}
|
|
|
|
Wt::Json::Object WChartJSOptions::AxisOptions::toJsonObject() const {
|
|
Wt::Json::Object obj = freeFormOptions;
|
|
obj["display"] = Wt::Json::Value(display);
|
|
obj["type"] = Wt::Json::Value(type);
|
|
obj["stacked"] = Wt::Json::Value(stacked);
|
|
obj["ticks"] = ticks.toJsonObject();
|
|
obj["title"] = title.toJsonObject();
|
|
obj["grid"] = grid.toJsonObject();
|
|
return obj;
|
|
}
|
|
|
|
Wt::Json::Object WChartJSOptions::ScalesOptions::toJsonObject() const {
|
|
Wt::Json::Object obj;
|
|
if (axisOptions.display) obj[axisOptions.axis] = axisOptions.toJsonObject();
|
|
return obj;
|
|
}
|
|
|
|
Wt::Json::Object WChartJSOptions::LayoutOptions::toJsonObject() const {
|
|
Wt::Json::Object obj;
|
|
if (std::holds_alternative<int>(padding)) {
|
|
obj["padding"] = Wt::Json::Value(std::get<int>(padding));
|
|
} else if (std::holds_alternative<Wt::Json::Object>(padding)) {
|
|
obj["padding"] = std::get<Wt::Json::Object>(padding);
|
|
}
|
|
return obj;
|
|
}
|
|
|
|
Wt::Json::Object WChartJSOptions::InteractionOptions::toJsonObject() const {
|
|
Wt::Json::Object obj;
|
|
obj["mode"] = Wt::Json::Value(mode);
|
|
obj["intersect"] = Wt::Json::Value(intersect);
|
|
obj["axis"] = Wt::Json::Value(axis);
|
|
return obj;
|
|
}
|
|
|
|
|
|
// --- Main Options Class Method Implementations ---
|
|
|
|
void WChartJSOptions::setResponsive(bool isResponsive) {
|
|
responsive_ = isResponsive;
|
|
options_["responsive"] = Wt::Json::Value(responsive_);
|
|
options_["onResize"] = Wt::Json::Value("handleResize");
|
|
}
|
|
|
|
void WChartJSOptions::setMaintainAspectRatio(bool maintain) {
|
|
maintainAspectRatio_ = maintain;
|
|
options_["maintainAspectRatio"] = Wt::Json::Value(maintainAspectRatio_);
|
|
}
|
|
|
|
void WChartJSOptions::setAspectRatio(double ratio) {
|
|
aspectRatio_ = ratio;
|
|
options_["aspectRatio"] = Wt::Json::Value(aspectRatio_);
|
|
}
|
|
|
|
void WChartJSOptions::setDevicePixelRatio(int ratio) {
|
|
devicePixelRatio_ = ratio;
|
|
options_["devicePixelRatio"] = Wt::Json::Value(devicePixelRatio_);
|
|
}
|
|
|
|
void WChartJSOptions::setLocale(const std::string& locale) {
|
|
locale_ = locale;
|
|
options_["locale"] = Wt::Json::Value(locale_);
|
|
}
|
|
|
|
void WChartJSOptions::setIndexAxis(const std::string& axis) {
|
|
options_["indexAxis"] = Wt::Json::Value(axis);
|
|
}
|
|
|
|
void WChartJSOptions::setPlugins(const PluginOptions& plugins) {
|
|
plugins_ = plugins;
|
|
options_["plugins"] = plugins_.toJsonObject();
|
|
}
|
|
|
|
void WChartJSOptions::setXScales(const ScalesOptions& scales) {
|
|
Wt::Json::Object scalesObj;
|
|
// Check if scales already exist (e.g., from setYScales)
|
|
if (options_.find("scales") != options_.end()) {
|
|
scalesObj = options_.get("scales");
|
|
}
|
|
|
|
if (scales.axisOptions.display) {
|
|
// Force the object key to "x"
|
|
scalesObj["x"] = scales.axisOptions.toJsonObject();
|
|
}
|
|
options_["scales"] = scalesObj;
|
|
}
|
|
|
|
void WChartJSOptions::setYScales(const ScalesOptions& scales) {
|
|
Wt::Json::Object scalesObj;
|
|
// Check if scales already exist (e.g., from setXScales)
|
|
if (options_.find("scales") != options_.end()) {
|
|
scalesObj = options_.get("scales");
|
|
}
|
|
|
|
if (scales.axisOptions.display) {
|
|
// Force the object key to "y"
|
|
scalesObj["y"] = scales.axisOptions.toJsonObject();
|
|
}
|
|
options_["scales"] = scalesObj;
|
|
}
|
|
void WChartJSOptions::setRScales(const ScalesOptions& scales) {
|
|
scales_ = scales;
|
|
options_["scales"] = scales_.toJsonObject();
|
|
}
|
|
|
|
void WChartJSOptions::setLayout(const LayoutOptions& layout) {
|
|
layout_ = layout;
|
|
// The layout object might be empty, so we reconstruct it
|
|
Wt::Json::Object layoutObj = layout.toJsonObject();
|
|
if (!layoutObj.empty()) {
|
|
options_["layout"] = layoutObj;
|
|
}
|
|
}
|
|
|
|
void WChartJSOptions::setInteraction(const InteractionOptions& interaction) {
|
|
interaction_ = interaction;
|
|
options_["interaction"] = interaction_.toJsonObject();
|
|
}
|
|
|
|
const Wt::Json::Object& WChartJSOptions::getOptions() const {
|
|
return options_;
|
|
}
|