Project

General

Profile

Improvements #12495 » WChartJSOptions.C

Mark Travis, 07/09/2026 07:46 PM

 
//
// 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_;
}
(5-5/9)