wxIshiko/wxCharts

Legend for StackedColumnChart

Opened this issue · 12 comments

When I add a legend to my stacked column chart it only uses the 2 default colors. I assume there is a default theme similar to my previous issue that needs to be modified.

StackedBarChart

It's similar but a bit more tricky. wxChartsLegendCtrl doesn't have own theme it's only use theme from wxLineChartCtrl.
So to use it properly one should update one of those themes (or made LineChartDatasetOptions as in wxStackedColumnChartDatasetOptions or vice versa).
For example(paste this code after updating default theme):

    for (int i = 0; i < nDatasets; i++) //nDatasets - amount of datasets
    {
        auto color = wxChartsDefaultTheme->GetDatasetTheme(wxChartsDatasetId::CreateImplicitId(i))->GetStackedColumnChartDatasetOptions()->GetBrushOptions().GetColor();
        wxChartsDefaultTheme->GetDatasetTheme(wxChartsDatasetId::CreateImplicitId(i))->SetLineChartDatasetOptions(
            wxLineChartDatasetOptions(
                color,
                color,
                color
            )
        );
    }

I'm getting the same shared pointer error that I got on the previous issue. The chartData has 1 categorical data sets and 5 double datasets so I set nDatasets = 7 and I get the shared pointer error. I tried setting nDatasets to 8 and the app closed on execcution.

`
void AcornFrame::OnButtonGraphClick(wxCommandEvent& event)
{

wxChartsDatasetTheme* datasettheme = new wxChartsDatasetTheme();
datasettheme->SetStackedColumnChartDatasetOptions(wxStackedColumnChartDatasetOptions(
wxChartsPenOptions(*wxGREEN, 2),
wxChartsBrushOptions(*wxGREEN)

));

wxChartsDefaultTheme->SetDatasetTheme(wxChartsDatasetId::CreateImplicitId(3), wxSharedPtr<wxChartsDatasetTheme>(datasettheme));

wxChartsDatasetTheme* datasettheme1 = new wxChartsDatasetTheme();
datasettheme1->SetStackedColumnChartDatasetOptions(wxStackedColumnChartDatasetOptions(
    wxChartsPenOptions(*wxRED, 2),
    wxChartsBrushOptions(*wxRED)
));
wxChartsDefaultTheme->SetDatasetTheme(wxChartsDatasetId::CreateImplicitId(4), wxSharedPtr<wxChartsDatasetTheme>(datasettheme1));

int i,j;
wxWindow* ChartWindow = new wxWindow(Panel5,wxID_ANY,wxDefaultPosition, wxSize(1312,800));

// Create the data for the bar chart widget
double testno1;
double testno2;
double testno3;
double testno4;
double testno5;

 // Add the categorical dataset
wxVector<wxString> points0;
for(j=1;j<7;++j)
{
double testno=stumpdbh10table[0][j];
wxString teststring=wxString::Format(wxT("%4.1f"), testno);
points0.push_back(teststring);
}

    wxVector<wxString> labels;
labels.push_back("0.5");
labels.push_back("1.5");
labels.push_back("2.5");
labels.push_back("3.5");
labels.push_back("4.5");
labels.push_back("5.5");

//wxChartsCategoricalData::ptr chartData=(new wxChartsDoubleDataset("Dataset 0", points0));
 wxChartsCategoricalData::ptr chartData = wxChartsCategoricalData::make_shared(labels);


// Add the first dataset
wxVector<wxDouble> points1;
for(j=1;j<7;++j)
{

testno1=stumpdbh10table[6][j];
points1.push_back(testno1);
}
wxChartsDoubleDataset::ptr dataset1(new wxChartsDoubleDataset("MIXED HARDWOODS", points1));
chartData->AddDataset(dataset1);


// Add the second dataset
wxVector<wxDouble> points2;
for(j=1;j<7;++j)
{

testno2=stumpdbh10table[7][j];
points2.push_back(testno2);
}
wxChartsDoubleDataset::ptr dataset2(new wxChartsDoubleDataset("CONIFER SPECIES", points2));
chartData->AddDataset(dataset2);
//legenData->AddDataset(dataset2);

// Add the third dataset
    wxVector<wxDouble> points3;
for(j=1;j<7;++j)
{

testno3=stumpdbh10table[8][j];
points3.push_back(testno3);
}
wxChartsDoubleDataset::ptr dataset3(new wxChartsDoubleDataset("HICKORY SPECIES", points3));
chartData->AddDataset(dataset3);

// Add the fourth dataset
  wxVector<wxDouble> points4;
for(j=1;j<7;++j)
{

testno4=stumpdbh10table[10][j];
points4.push_back(testno4);
}
wxChartsDoubleDataset::ptr dataset4(new wxChartsDoubleDataset("GUM SPECIES", points4));
chartData->AddDataset(dataset4);


// Add the fifth dataset
wxVector<wxDouble> points5;
for(j=1;j<7;++j)
{
testno5=stumpdbh10table[5][j];
points5.push_back(testno5);
}
wxChartsDoubleDataset::ptr dataset5(new wxChartsDoubleDataset("WHITE OAK GROUP", points5));
chartData->AddDataset(dataset5);

// Create the legend widget

for (int i = 0; i < 7; i++) //nDatasets - amount of datasets
{
    auto color = wxChartsDefaultTheme->GetDatasetTheme(wxChartsDatasetId::CreateImplicitId(i))->GetStackedColumnChartDatasetOptions()->GetBrushOptions().GetColor();
    wxChartsDefaultTheme->GetDatasetTheme(wxChartsDatasetId::CreateImplicitId(i))->SetLineChartDatasetOptions(
        wxLineChartDatasetOptions(
            color,
            color,
            color
        )
    );
}





wxChartsLegendData legendData(chartData->GetDatasets());
wxChartsLegendCtrl* legendCtrl = new wxChartsLegendCtrl(ChartWindow, wxID_ANY, legendData,wxPoint(0,0),wxSize(150,100), wxSIMPLE_BORDER);

// Create the bar chart widget

wxStackedColumnChartCtrl* stackedColumnChartCtrl = new wxStackedColumnChartCtrl(ChartWindow,
wxID_ANY, chartData, wxPoint(151,0),wxSize(800,500));

}
`

nDatasets is 5 in your case because you have 5 values on legend.

You got shared pointer error because you created chart before updating theme.
All theme updates should be done before creating any chart control.

Thanks again for all your help. Worked like a charm. One last question is there a way to specify colors by rbg values?

Yes, just use wxColour object:

    datasettheme->SetStackedColumnChartDatasetOptions(wxStackedColumnChartDatasetOptions(
        wxChartsPenOptions(*wxBLACK, 2),
        wxChartsBrushOptions(wxColour(208,208,28))
    ));

I think the LineChartDatasetOptions stays in memory. If I build it after rebooting it executes and makes the changes fine. But if I rebuild it again it dies on execution. If I then drop your linechart loop out and recompile on execution it runs but without the changes the loop makes. Then if I recompile again with the loop in it makes the changes and looks fine

Yeah I added event.Skip(); at the end and it all works fine. Thanks for your help and patienc.e

In the stacked bars the first data set is at the bottom of the bar but it's at the top of the legend. Is there a way to reverse the order of the legend so that the first data set is at the bottom of the legend so that the order of the legend matches the order on the bars?

You can construct data for legend in any order, just put them in separate wxVector and pass to the wxChartsLegendData constructor instead of chartData->GetDatasets().

So I added the data set to a new data set in reverse order of the data used to make the chart:

`
reverseChartdata->AddDataset(dataset13);
reverseChartdata->AddDataset(dataset12);
reverseChartdata->AddDataset(dataset11);
reverseChartdata->AddDataset(dataset10);
reverseChartdata->AddDataset(dataset9);
reverseChartdata->AddDataset(dataset8);
reverseChartdata->AddDataset(dataset7);
reverseChartdata->AddDataset(dataset6);
reverseChartdata->AddDataset(dataset5);
reverseChartdata->AddDataset(dataset4);
reverseChartdata->AddDataset(dataset3);
reverseChartdata->AddDataset(dataset2);
reverseChartdata->AddDataset(dataset1);

// Create the legend widget

wxChartsLegendData legendData(reverseChartdata->GetDatasets());
wxChartsLegendCtrl* legendCtrl = new wxChartsLegendCtrl(ChartWindow, wxID_ANY, legendData,wxPoint(991,30),wxSize(130,300), wxSIMPLE_BORDER);`

but the colors in the legend are still in the same order though the names are in the correct order. I need to flip the order of the colors in the legend.

Right it won't work.

As we "transfer" colors from StackedColumnChartDataset (main chart) into LineChartDataset(legend) in usual order (0-0, 1-1, ...) so for flipping we should do it in reverse order (0-nDatasets-1, 1 - nDatasets-2,...).
So loop above become:

    for (int i = 0; i < nDatasets; i++)
    {
        auto color = wxChartsDefaultTheme->GetDatasetTheme(wxChartsDatasetId::CreateImplicitId(nDatasets-i-1))->GetStackedColumnChartDatasetOptions()->GetBrushOptions().GetColor();
        wxChartsDefaultTheme->GetDatasetTheme(wxChartsDatasetId::CreateImplicitId(i))->SetLineChartDatasetOptions(
            wxLineChartDatasetOptions(
                color,
                color,
                color
            )
        );
    }

Got it thanks